MCPサーバー実装まとめ
MCPサーバーの基本概念と初期設定
約1年前
Model Context Protocol(MCP)は、AIアシスタントと外部ツールを連携させるためのプロトコルだ。MCPサーバーを構築することで、WindsurfやCursorなどのAIアシスタントから外部サービスを操作できるようになる。
初期設定には以下が必要:
- Node.js環境(v20以上推奨)
- MCP SDKのインストール
- TypeScriptの設定
- 対象サービス(今回はPaPut)のAPIキー
基本的なプロジェクト構成は以下の通り:
- package.json:依存関係の管理
- tsconfig.json:TypeScriptの設定
- src/index.ts:エントリーポイント
MCPサーバーのプロジェクト構造設計
約1年前
効率的なMCPサーバー開発のためのプロジェクト構造:
plaintext
src/
├── handlers/ # 各ツールのハンドラー関数
│ ├── create-memo.ts
│ └── index.ts
├── services/ # 外部APIとの通信を担当
│ ├── api-service.ts
│ └── index.ts
├── types/ # 型定義
│ ├── create-memo.ts
│ └── index.ts
├── utils/ # ユーティリティ関数
│ └── error-handler.ts
├── tool.ts # ツール定義
├── server.ts # サーバー設定
└── index.ts # エントリーポイントこの構造により、関心の分離が実現され、コードの保守性と拡張性が向上する。
MCPサーバーの基本実装(サーバー部分)
約1年前
MCPサーバーの中核となるサーバー部分の実装例:
typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
export class MCPServer {
private server: Server;
constructor() {
// 環境変数から設定を取得
const apiKey = process.env.API_KEY;
// サーバーの初期化
this.server = new Server(
{ name: 'my-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// ツールとエラーハンドリングのセットアップ
setupTools(this.server, apiKey);
setupErrorHandling(this.server);
}
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
}MCPツールの定義と実装
約1年前
MCPサーバーでツールを定義する方法:
typescript
server.setRequestHandler(
ListToolsRequestSchema,
async () => ({
tools: [{
name: "service_action_name",
description: "ツールの説明文",
inputSchema: {
type: "object",
properties: {
param1: {
type: "string",
description: "パラメータ1の説明"
},
// 他のパラメータ...
},
required: ["param1"]
}
}]
})
);
// ツール呼び出しハンドラー
server.setRequestHandler(
CallToolRequestSchema,
async (request) => {
switch (request.params.name) {
case "service_action_name":
return await handleAction(request.params.arguments);
default:
return { content: [{ type: "text", text: "未知のツール" }], isError: true };
}
}
);MCPハンドラーの実装パターン
約1年前
効果的なハンドラー関数の実装パターン:
typescript
async function handleAction(args: Record<string, unknown> | undefined) {
// 1. パラメータの検証
if (!args || typeof args.param1 !== 'string') {
return {
content: [{ type: 'text', text: "パラメータが不正です" }],
isError: true
};
}
// 2. パラメータの構築
const params = {
param1: args.param1,
// オプションパラメータの処理
param2: typeof args.param2 === 'boolean' ? args.param2 : false
};
try {
// 3. APIリクエスト
const result = await apiService.callAction(params);
// 4. 結果の処理
if (!result.success) {
return {
content: [{ type: 'text', text: `エラー: ${result.error}` }],
isError: true
};
}
// 5. 成功レスポンス
return {
content: [{ type: 'text', text: "処理が完了しました" }]
};
} catch (error) {
// 6. エラーハンドリング
return {
content: [{ type: 'text', text: `例外が発生: ${error.message}` }],
isError: true
};
}
}MCPサーバーのデバッグとテスト
約1年前
MCPサーバーのデバッグとテストのベストプラクティス:
- ローカルテスト
bash
# 環境変数を設定してサーバーを起動
API_KEY=your_key npm run dev-
AIアシスタントとの統合テスト Windsurfの場合は
~/.codeium/windsurf/mcp_config.jsonに設定を追加 -
デバッグログの活用
typescript
console.error('デバッグ:', JSON.stringify(data, null, 2));- エラーケースのテスト
- 無効なパラメータ
- APIキーなしでの起動
- ネットワークエラー
- APIレスポンスエラー
- 手動テストコマンド例
bash
echo '{"jsonrpc":"2.0","id":"test","method":"mcp.listTools","params":{}}' | node dist/index.jsMCPサーバーのコード分割と責務分離
約1年前
MCPサーバーのコードを適切に分割するためのガイドライン:
-
関心の分離
- サーバー設定(server.ts)
- ツール定義(tool.ts)
- ハンドラー実装(handlers/*.ts)
- API通信(services/*.ts)
- 型定義(types/*.ts)
-
ファイル分割の利点
- コードの可読性向上
- 単体テストの容易化
- 並行開発の促進
- 変更の影響範囲の限定
-
モジュール間の依存関係
- 循環依存を避ける
- インターフェースを通じた疎結合
- 共通ユーティリティの抽出
-
拡張性の確保
- 新機能追加時に既存コードへの変更を最小化
- プラグイン的な拡張ポイントの提供
MCPサーバーのエラーハンドリング戦略
約1年前
堅牢なMCPサーバーのためのエラーハンドリング戦略:
- サーバーレベルのエラーハンドリング
typescript
server.onerror = (error) => {
console.error('[MCP Error]', error);
};
process.on('uncaughtException', (error) => {
console.error('未捕捉の例外:', error);
});- ハンドラーレベルのエラーハンドリング
- パラメータ検証エラー
- APIリクエストエラー
- 予期せぬ例外
- エラーレスポンスの構造
typescript
{
content: [{ type: 'text', text: 'エラーメッセージ' }],
isError: true
}- デバッグ情報の提供
- 開発環境では詳細なエラー情報
- 本番環境ではユーザーフレンドリーなメッセージ
- リトライ戦略
- 一時的なネットワークエラーに対するリトライ
- 指数バックオフの実装
AIアシスタントとMCPサーバーの連携設定
約1年前
各AIアシスタントとMCPサーバーを連携させる設定方法:
- Windsurf
~/.codeium/windsurf/mcp_config.jsonに以下を追加:
json
"mcpServers": {
"service_name": {
"command": "node",
"args": ["path/to/dist/index.js"],
"env": {
"API_KEY": "your_api_key"
}
}
}- Cursor 設定から「AI: MCP Servers」に追加:
json
"ai.mcpServers": [
{
"name": "service_name",
"command": "node",
"args": ["path/to/dist/index.js"],
"env": { "API_KEY": "your_api_key" }
}
]- Claude Desktop 設定から「拡張機能」→「MCP サーバー」に追加:
- 名前:
service_name - コマンド:
npx - 引数:
-y your-package-name - 環境変数:
API_KEY=your_api_key