Node.js で作る MCP サーバー:実践的な実装手順とサンプルコード

現代の AI アプリケーション開発において、外部ツールやデータソースとの統合は不可欠な要素となっています。Model Context Protocol(MCP)は、この課題を解決するために設計された革新的なプロトコルです。Node.js での MCP サーバー実装は、その柔軟性と豊富なエコシステムにより、開発者にとって最も実用的な選択肢の一つです。この記事では、Node.js を使用した MCP サーバーの構築方法を、基本的な概念から実践的な実装まで、サンプルコードを交えながら詳しく解説いたします。
背景
Model Context Protocol の基本概念
Model Context Protocol(MCP)は、AI アプリケーションが外部のツールやデータソースと安全かつ効率的にやり取りするための標準化されたプロトコルです。従来の AI アプリケーションでは、各サービスとの個別統合が必要でしたが、MCP により統一されたインターフェースでの連携が可能になります。
MCP の核となる概念は以下の通りです:
ツール(Tools): AI が実行できる具体的な機能を定義したもの。ファイル操作、API コール、計算処理など様々な処理を抽象化します。
リソース(Resources): AI がアクセス可能なデータやコンテンツ。ファイル、データベースレコード、Web ページなどを指します。
プロンプト(Prompts): 再利用可能なテンプレート化されたプロンプト。特定のタスクに最適化された指示文を提供します。
サンプリング(Sampling): AI モデルとの対話を管理する機能。会話の流れを制御し、適切なレスポンスを生成します。
Node.js でのサーバー開発の利点
Node.js での MCP サーバー開発には、以下のような顕著な利点があります:
非同期処理の優位性
Node.js のイベント駆動型アーキテクチャは、MCP サーバーが要求する高い並行性と応答性に最適です。複数の AI クライアントからの同時リクエストを効率的に処理できます。
javascript// 非同期処理の例
async function handleMultipleRequests(requests) {
const results = await Promise.all(
requests.map((request) => processToolCall(request))
);
return results;
}
豊富なパッケージエコシステム
npm エコシステムには、MCP サーバー開発に必要な様々なライブラリが揃っています:
- WebSocket 通信:
ws
,socket.io
- HTTP 処理:
express
,fastify
- データベース連携:
mongodb
,mysql2
,pg
- ファイル操作:
fs-extra
,chokidar
- API 連携:
axios
,node-fetch
TypeScript との親和性
TypeScript を使用することで、MCP プロトコルの複雑な型定義を安全に扱えます。コンパイル時の型チェックにより、ランタイムエラーを大幅に削減できます。
他の実装方法との比較
MCP サーバーの実装方法として、Node.js 以外にも Python、Go、Rust などの選択肢があります。それぞれの特徴を比較してみましょう。
実装言語 | 学習コスト | 開発速度 | パフォーマンス | エコシステム | 適用場面 |
---|---|---|---|---|---|
Node.js | 中 | 高 | 中〜高 | 非常に豊富 | Web 統合、API 連携 |
Python | 低 | 高 | 中 | 豊富 | データ分析、ML 統合 |
Go | 中〜高 | 中 | 高 | 中程度 | 高パフォーマンス要求 |
Rust | 高 | 低〜中 | 非常に高 | 成長中 | システムレベル処理 |
Node.js は、開発効率とパフォーマンスのバランスが優れており、特に Web アプリケーションとの統合や REST API の構築において強力です。
準備
開発環境のセットアップ
MCP サーバー開発を始めるために、以下の環境をセットアップします。
Node.js のインストール
最新の LTS バージョン(v20 以上推奨)をインストールします:
bash# Node.js公式サイトからダウンロード、またはnvmを使用
nvm install --lts
nvm use --lts
# バージョン確認
node --version
npm --version
Yarn の導入
パッケージ管理には Yarn を使用します:
bashnpm install -g yarn
yarn --version
開発ツールの準備
効率的な開発のために以下のツールを準備します:
bash# TypeScript環境
yarn global add typescript ts-node
# 開発用ツール
yarn global add nodemon eslint prettier
必要なパッケージとツール
MCP サーバー開発に必要な主要パッケージを整理します。
核心ライブラリ
json{
"dependencies": {
"@modelcontextprotocol/sdk": "^0.5.0",
"express": "^4.19.2",
"ws": "^8.16.0",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.11.24",
"@types/express": "^4.17.21",
"@types/ws": "^8.5.10",
"@types/uuid": "^9.0.8",
"typescript": "^5.3.3",
"ts-node": "^10.9.2",
"nodemon": "^3.1.0"
}
}
パッケージの役割説明
- @modelcontextprotocol/sdk: MCP プロトコルの公式実装
- express: HTTP サーバー機能
- ws: WebSocket 通信
- uuid: 一意識別子生成
- zod: ランタイム型検証
プロジェクト構造の設計
拡張性とメンテナンス性を考慮したプロジェクト構造を設計します。
csharpmcp-server/
├── src/
│ ├── types/
│ │ ├── mcp.ts # MCP型定義
│ │ └── tools.ts # ツール型定義
│ ├── tools/
│ │ ├── base.ts # ツール基底クラス
│ │ ├── file-operations.ts # ファイル操作ツール
│ │ ├── web-api.ts # Web API連携ツール
│ │ └── database.ts # データベースツール
│ ├── resources/
│ │ ├── manager.ts # リソース管理
│ │ └── providers/ # リソースプロバイダー
│ ├── handlers/
│ │ ├── tool-handler.ts # ツールハンドラー
│ │ ├── resource-handler.ts # リソースハンドラー
│ │ └── error-handler.ts # エラーハンドラー
│ ├── utils/
│ │ ├── logger.ts # ログ機能
│ │ ├── config.ts # 設定管理
│ │ └── validation.ts # バリデーション
│ ├── server.ts # サーバーメイン
│ └── app.ts # アプリケーション初期化
├── tests/
│ ├── unit/ # 単体テスト
│ ├── integration/ # 統合テスト
│ └── fixtures/ # テストデータ
├── config/
│ ├── default.json # デフォルト設定
│ ├── development.json # 開発環境設定
│ └── production.json # 本番環境設定
├── docker/
│ ├── Dockerfile # コンテナ定義
│ └── docker-compose.yml # 開発環境
├── docs/ # ドキュメント
├── package.json
├── tsconfig.json
├── .eslintrc.js
├── .prettierrc
└── README.md
TypeScript 設定
tsconfig.json
の設定例:
json{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
基本実装
最小構成の MCP サーバー作成
まず、最もシンプルな MCP サーバーを作成して基本的な動作を確認します。
プロジェクト初期化
bashmkdir mcp-server
cd mcp-server
yarn init -y
yarn add @modelcontextprotocol/sdk express ws uuid zod
yarn add -D @types/node @types/express @types/ws @types/uuid typescript ts-node nodemon
基本的なサーバー実装
src/server.ts
:
typescriptimport { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
ListToolsRequestSchema,
CallToolRequestSchema,
ToolSchema,
} from '@modelcontextprotocol/sdk/types.js';
class BasicMCPServer {
private server: Server;
constructor() {
this.server = new Server(
{
name: 'basic-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupHandlers();
}
private setupHandlers(): void {
// ツール一覧の取得
this.server.setRequestHandler(
ListToolsRequestSchema,
async () => {
return {
tools: [
{
name: 'echo',
description: 'Echo back the input text',
inputSchema: {
type: 'object',
properties: {
text: {
type: 'string',
description: 'Text to echo back',
},
},
required: ['text'],
},
},
{
name: 'add',
description: 'Add two numbers',
inputSchema: {
type: 'object',
properties: {
a: {
type: 'number',
description: 'First number',
},
b: {
type: 'number',
description: 'Second number',
},
},
required: ['a', 'b'],
},
},
],
};
}
);
// ツール実行
this.server.setRequestHandler(
CallToolRequestSchema,
async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'echo':
return {
content: [
{
type: 'text',
text: `Echo: ${args.text}`,
},
],
};
case 'add':
const result =
(args.a as number) + (args.b as number);
return {
content: [
{
type: 'text',
text: `Result: ${args.a} + ${args.b} = ${result}`,
},
],
};
default:
throw new Error(`Unknown tool: ${name}`);
}
}
);
}
async start(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Basic MCP Server started');
}
}
// サーバー起動
const server = new BasicMCPServer();
server.start().catch(console.error);
起動スクリプトの設定
package.json
に起動スクリプトを追加:
json{
"scripts": {
"dev": "nodemon --exec ts-node src/server.ts",
"build": "tsc",
"start": "node dist/server.js",
"test": "jest"
}
}
TypeScript による型安全な実装
型安全性を向上させるために、詳細な型定義を作成します。
MCP 型定義
src/types/mcp.ts
:
typescriptimport { z } from 'zod';
// ツール定義のスキーマ
export const ToolDefinitionSchema = z.object({
name: z.string(),
description: z.string(),
inputSchema: z.object({
type: z.literal('object'),
properties: z.record(z.any()),
required: z.array(z.string()).optional(),
}),
});
export type ToolDefinition = z.infer<
typeof ToolDefinitionSchema
>;
// ツール実行結果のスキーマ
export const ToolResultSchema = z.object({
content: z.array(
z.object({
type: z.enum(['text', 'image', 'resource']),
text: z.string().optional(),
data: z.string().optional(),
mimeType: z.string().optional(),
})
),
isError: z.boolean().optional(),
});
export type ToolResult = z.infer<typeof ToolResultSchema>;
// ツール実行パラメータ
export interface ToolExecutionContext {
name: string;
arguments: Record<string, any>;
requestId?: string;
userId?: string;
}
// エラー情報
export interface MCPError {
code: number;
message: string;
data?: any;
}
ツール型定義
src/types/tools.ts
:
typescriptimport {
ToolDefinition,
ToolResult,
ToolExecutionContext,
} from './mcp.js';
// 抽象ツールクラス
export abstract class BaseTool {
abstract readonly name: string;
abstract readonly description: string;
abstract readonly inputSchema: ToolDefinition['inputSchema'];
// ツール定義の取得
getDefinition(): ToolDefinition {
return {
name: this.name,
description: this.description,
inputSchema: this.inputSchema,
};
}
// ツール実行(抽象メソッド)
abstract execute(
context: ToolExecutionContext
): Promise<ToolResult>;
// 入力検証
protected validateInput(args: Record<string, any>): void {
const required = this.inputSchema.required || [];
for (const field of required) {
if (!(field in args)) {
throw new Error(
`Required field '${field}' is missing`
);
}
}
}
}
// ツールレジストリ
export class ToolRegistry {
private tools = new Map<string, BaseTool>();
register(tool: BaseTool): void {
this.tools.set(tool.name, tool);
}
unregister(name: string): void {
this.tools.delete(name);
}
get(name: string): BaseTool | undefined {
return this.tools.get(name);
}
list(): ToolDefinition[] {
return Array.from(this.tools.values()).map((tool) =>
tool.getDefinition()
);
}
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
const tool = this.tools.get(context.name);
if (!tool) {
throw new Error(`Tool '${context.name}' not found`);
}
return await tool.execute(context);
}
}
基本的なツール定義とハンドラー
実用的なツールを実装して、MCP サーバーの機能を拡張します。
Echo ツール
src/tools/echo.ts
:
typescriptimport {
BaseTool,
ToolResult,
ToolExecutionContext,
} from '../types/tools.js';
export class EchoTool extends BaseTool {
readonly name = 'echo';
readonly description =
'Echo back the input text with optional formatting';
readonly inputSchema = {
type: 'object' as const,
properties: {
text: {
type: 'string',
description: 'Text to echo back',
},
format: {
type: 'string',
enum: [
'plain',
'uppercase',
'lowercase',
'reverse',
],
description: 'Text formatting option',
},
prefix: {
type: 'string',
description: 'Optional prefix to add',
},
},
required: ['text'],
};
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
this.validateInput(context.arguments);
const {
text,
format = 'plain',
prefix = '',
} = context.arguments;
let result = text as string;
// フォーマット適用
switch (format) {
case 'uppercase':
result = result.toUpperCase();
break;
case 'lowercase':
result = result.toLowerCase();
break;
case 'reverse':
result = result.split('').reverse().join('');
break;
}
// プレフィックス追加
if (prefix) {
result = `${prefix}: ${result}`;
}
return {
content: [
{
type: 'text',
text: result,
},
],
};
}
}
計算ツール
src/tools/calculator.ts
:
typescriptimport {
BaseTool,
ToolResult,
ToolExecutionContext,
} from '../types/tools.js';
export class CalculatorTool extends BaseTool {
readonly name = 'calculator';
readonly description =
'Perform mathematical calculations';
readonly inputSchema = {
type: 'object' as const,
properties: {
operation: {
type: 'string',
enum: [
'add',
'subtract',
'multiply',
'divide',
'power',
'sqrt',
],
description: 'Mathematical operation to perform',
},
a: {
type: 'number',
description: 'First operand',
},
b: {
type: 'number',
description:
'Second operand (not required for sqrt)',
},
},
required: ['operation', 'a'],
};
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
this.validateInput(context.arguments);
const { operation, a, b } = context.arguments;
let result: number;
let expression: string;
try {
switch (operation) {
case 'add':
if (b === undefined)
throw new Error(
'Second operand required for addition'
);
result = a + b;
expression = `${a} + ${b} = ${result}`;
break;
case 'subtract':
if (b === undefined)
throw new Error(
'Second operand required for subtraction'
);
result = a - b;
expression = `${a} - ${b} = ${result}`;
break;
case 'multiply':
if (b === undefined)
throw new Error(
'Second operand required for multiplication'
);
result = a * b;
expression = `${a} × ${b} = ${result}`;
break;
case 'divide':
if (b === undefined)
throw new Error(
'Second operand required for division'
);
if (b === 0)
throw new Error(
'Division by zero is not allowed'
);
result = a / b;
expression = `${a} ÷ ${b} = ${result}`;
break;
case 'power':
if (b === undefined)
throw new Error(
'Exponent required for power operation'
);
result = Math.pow(a, b);
expression = `${a}^${b} = ${result}`;
break;
case 'sqrt':
if (a < 0)
throw new Error(
'Square root of negative number is not allowed'
);
result = Math.sqrt(a);
expression = `√${a} = ${result}`;
break;
default:
throw new Error(
`Unknown operation: ${operation}`
);
}
return {
content: [
{
type: 'text',
text: `計算結果: ${expression}`,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `計算エラー: ${error.message}`,
},
],
isError: true,
};
}
}
}
改良されたサーバー実装
src/server.ts
を更新して、ツールレジストリを使用します:
typescriptimport { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
ListToolsRequestSchema,
CallToolRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { ToolRegistry } from './types/tools.js';
import { EchoTool } from './tools/echo.js';
import { CalculatorTool } from './tools/calculator.js';
class EnhancedMCPServer {
private server: Server;
private toolRegistry: ToolRegistry;
constructor() {
this.server = new Server(
{
name: 'enhanced-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.toolRegistry = new ToolRegistry();
this.registerTools();
this.setupHandlers();
}
private registerTools(): void {
this.toolRegistry.register(new EchoTool());
this.toolRegistry.register(new CalculatorTool());
}
private setupHandlers(): void {
// ツール一覧の取得
this.server.setRequestHandler(
ListToolsRequestSchema,
async () => {
return {
tools: this.toolRegistry.list(),
};
}
);
// ツール実行
this.server.setRequestHandler(
CallToolRequestSchema,
async (request) => {
try {
const result = await this.toolRegistry.execute({
name: request.params.name,
arguments: request.params.arguments || {},
});
return result;
} catch (error) {
console.error('Tool execution error:', error);
return {
content: [
{
type: 'text',
text: `Error: ${error.message}`,
},
],
isError: true,
};
}
}
);
}
async start(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Enhanced MCP Server started');
}
}
// サーバー起動
const server = new EnhancedMCPServer();
server.start().catch(console.error);
この基本実装により、拡張可能な MCP サーバーの土台が完成しました。次のセクションでは、さらに高度な機能を実装していきます。
機能拡張
カスタムツールの実装
より実用的なツールを実装して、MCP サーバーの機能を拡張します。
日時ツール
typescriptimport {
BaseTool,
ToolResult,
ToolExecutionContext,
} from '../types/tools.js';
export class DateTimeTool extends BaseTool {
readonly name = 'datetime';
readonly description =
'現在の日時を取得したり、日時を変換したりします';
readonly inputSchema = {
type: 'object' as const,
properties: {
operation: {
type: 'string',
enum: ['now', 'format', 'parse', 'add', 'diff'],
description: '実行する操作',
},
format: {
type: 'string',
description: 'フォーマット文字列',
},
timezone: {
type: 'string',
description: 'タイムゾーン(例: Asia/Tokyo)',
},
},
required: ['operation'],
};
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
const {
operation,
format = 'YYYY-MM-DD HH:mm:ss',
timezone = 'Asia/Tokyo',
} = context.arguments;
try {
switch (operation) {
case 'now':
const now = new Date();
return {
content: [
{
type: 'text',
text: `現在時刻: ${now.toLocaleString(
'ja-JP',
{ timeZone: timezone }
)}`,
},
],
};
default:
throw new Error(`未対応の操作: ${operation}`);
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `エラー: ${error.message}`,
},
],
isError: true,
};
}
}
}
リソース管理機能の追加
MCP サーバーにリソース管理機能を追加します。
typescriptimport {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
class ResourceManager {
private resources = new Map<string, any>();
addResource(
uri: string,
content: any,
mimeType?: string
): void {
this.resources.set(uri, { content, mimeType });
}
getResource(uri: string): any {
return this.resources.get(uri);
}
listResources(): Array<{
uri: string;
name: string;
mimeType?: string;
}> {
return Array.from(this.resources.entries()).map(
([uri, data]) => ({
uri,
name: uri.split('/').pop() || uri,
mimeType: data.mimeType,
})
);
}
}
エラーハンドリングの実装
堅牢なエラーハンドリングシステムを構築します。
typescriptexport class MCPErrorHandler {
static handleToolError(
error: any,
toolName: string
): ToolResult {
console.error(`Tool error in ${toolName}:`, error);
return {
content: [
{
type: 'text',
text: `ツール '${toolName}' でエラーが発生しました: ${error.message}`,
},
],
isError: true,
};
}
static isValidationError(error: any): boolean {
return (
error.name === 'ValidationError' ||
error.code === 'VALIDATION_ERROR'
);
}
}
実践例
ファイル操作ツールの作成
実用的なファイル操作ツールを実装します。
typescriptimport * as fs from 'fs/promises';
import * as path from 'path';
import {
BaseTool,
ToolResult,
ToolExecutionContext,
} from '../types/tools.js';
export class FileOperationTool extends BaseTool {
readonly name = 'file_operations';
readonly description =
'ファイルの読み書きや操作を行います';
readonly inputSchema = {
type: 'object' as const,
properties: {
operation: {
type: 'string',
enum: ['read', 'write', 'list', 'exists', 'delete'],
description: '実行する操作',
},
path: {
type: 'string',
description: 'ファイル・ディレクトリのパス',
},
content: {
type: 'string',
description: '書き込むコンテンツ(write操作時)',
},
},
required: ['operation', 'path'],
};
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
const {
operation,
path: filePath,
content,
} = context.arguments;
try {
switch (operation) {
case 'read':
const data = await fs.readFile(filePath, 'utf-8');
return {
content: [
{
type: 'text',
text: `ファイル内容:\n${data}`,
},
],
};
case 'write':
if (!content)
throw new Error(
'書き込み内容が指定されていません'
);
await fs.writeFile(filePath, content, 'utf-8');
return {
content: [
{
type: 'text',
text: `ファイルに書き込みました: ${filePath}`,
},
],
};
case 'list':
const files = await fs.readdir(filePath);
return {
content: [
{
type: 'text',
text: `ディレクトリ内容:\n${files.join(
'\n'
)}`,
},
],
};
default:
throw new Error(`未対応の操作: ${operation}`);
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `ファイル操作エラー: ${error.message}`,
},
],
isError: true,
};
}
}
}
Web API 連携機能の実装
外部 API との連携機能を実装します。
typescriptimport axios from 'axios';
import {
BaseTool,
ToolResult,
ToolExecutionContext,
} from '../types/tools.js';
export class WebAPITool extends BaseTool {
readonly name = 'web_api';
readonly description =
'Web API への HTTP リクエストを実行します';
readonly inputSchema = {
type: 'object' as const,
properties: {
method: {
type: 'string',
enum: ['GET', 'POST', 'PUT', 'DELETE'],
description: 'HTTP メソッド',
},
url: {
type: 'string',
description: 'リクエスト URL',
},
headers: {
type: 'object',
description: 'リクエストヘッダー',
},
data: {
type: 'object',
description: 'リクエストボディ',
},
},
required: ['method', 'url'],
};
async execute(
context: ToolExecutionContext
): Promise<ToolResult> {
const {
method,
url,
headers = {},
data,
} = context.arguments;
try {
const response = await axios({
method: method.toLowerCase(),
url,
headers,
data,
timeout: 10000,
});
return {
content: [
{
type: 'text',
text: `API レスポンス (${
response.status
}):\n${JSON.stringify(response.data, null, 2)}`,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `API リクエストエラー: ${error.message}`,
},
],
isError: true,
};
}
}
}
運用
テスト環境の構築
MCP サーバーのテスト環境を構築します。
typescriptimport {
describe,
it,
expect,
beforeEach,
} from '@jest/globals';
import { ToolRegistry } from '../src/types/tools.js';
import { EchoTool } from '../src/tools/echo.js';
describe('MCP Server Tools', () => {
let registry: ToolRegistry;
beforeEach(() => {
registry = new ToolRegistry();
registry.register(new EchoTool());
});
it('should execute echo tool correctly', async () => {
const result = await registry.execute({
name: 'echo',
arguments: { text: 'Hello, World!' },
});
expect(result.content[0].text).toBe('Hello, World!');
expect(result.isError).toBeFalsy();
});
});
デバッグとトラブルシューティング
効果的なデバッグ手法を紹介します。
typescriptimport winston from 'winston';
export const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: 'error.log',
level: 'error',
}),
new winston.transports.File({
filename: 'combined.log',
}),
new winston.transports.Console({
format: winston.format.simple(),
}),
],
});
本番環境での運用考慮事項
Docker 化
dockerfileFROM node:20-alpine
WORKDIR /app
COPY package*.json yarn.lock ./
RUN yarn install --production
COPY dist/ ./dist/
EXPOSE 3000
CMD ["node", "dist/server.js"]
環境変数管理
typescriptexport const config = {
port: process.env.PORT || 3000,
nodeEnv: process.env.NODE_ENV || 'development',
logLevel: process.env.LOG_LEVEL || 'info',
maxRequestSize: process.env.MAX_REQUEST_SIZE || '10mb',
};
まとめ
本記事では、Node.js を使用した MCP サーバーの実装について、基本的な概念から実践的な応用まで幅広く解説いたしました。
実装のポイント振り返り
型安全性の重要性: TypeScript と Zod を活用することで、ランタイムエラーを大幅に削減し、開発効率を向上させることができます。
拡張可能な設計: ツールレジストリパターンを採用することで、新しいツールの追加が容易になり、コードの保守性が向上します。
エラーハンドリング: 適切なエラーハンドリングにより、AI クライアントに有用なフィードバックを提供できます。
テスト駆動開発: 単体テストと統合テストを組み合わせることで、品質の高い MCP サーバーを構築できます。
次のステップとさらなる学習リソース
MCP サーバー開発をさらに深めるために、以下のリソースをご活用ください:
公式ドキュメント
コミュニティリソース
学習の次のステップ
- 複雑なツールの実装: データベース連携やファイルシステム操作
- パフォーマンス最適化: キャッシュ機能やバッチ処理の実装
- セキュリティ強化: 認証・認可機能の追加
- マイクロサービス化: 複数の MCP サーバーの連携
Node.js での MCP サーバー開発は、AI アプリケーションの可能性を大きく広げる技術です。本記事の内容を基に、ぜひ独自の MCP サーバーを構築し、AI との新しい連携を探求してください。実装過程で得られる学びは、必ず皆様の開発スキル向上に寄与することでしょう。
関連リンク
- review
もう「なんとなく」で決めない!『解像度を上げる』馬田隆明著で身につけた、曖昧思考を一瞬で明晰にする技術
- review
もう疲れ知らず!『最高の体調』鈴木祐著で手に入れた、一生モノの健康習慣術
- review
人生が激変!『苦しかったときの話をしようか』森岡毅著で発見した、本当に幸せなキャリアの築き方
- review
もう「何言ってるの?」とは言わせない!『バナナの魅力を 100 文字で伝えてください』柿内尚文著 で今日からあなたも伝え方の達人!
- review
もう時間に追われない!『エッセンシャル思考』グレッグ・マキューンで本当に重要なことを見抜く!
- review
プロダクト開発の悩みを一刀両断!『プロダクトマネジメントのすべて』及川 卓也, 曽根原 春樹, 小城 久美子