MCPサーバー実装まとめ

MCPサーバーの基本概念と初期設定

8日前


Model Context Protocol(MCP)は、AIアシスタントと外部ツールを連携させるためのプロトコルだ。MCPサーバーを構築することで、WindsurfやCursorなどのAIアシスタントから外部サービスを操作できるようになる。

初期設定には以下が必要:

  1. Node.js環境(v20以上推奨)
  2. MCP SDKのインストール
  3. TypeScriptの設定
  4. 対象サービス(今回はPaPut)のAPIキー

基本的なプロジェクト構成は以下の通り:

  • package.json:依存関係の管理
  • tsconfig.json:TypeScriptの設定
  • src/index.ts:エントリーポイント

MCPサーバーのプロジェクト構造設計

8日前


効率的なMCPサーバー開発のためのプロジェクト構造:

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サーバーの基本実装(サーバー部分)

8日前


MCPサーバーの中核となるサーバー部分の実装例:

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ツールの定義と実装

8日前


MCPサーバーでツールを定義する方法:

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ハンドラーの実装パターン

8日前


効果的なハンドラー関数の実装パターン:

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サーバーのデバッグとテスト

8日前


MCPサーバーのデバッグとテストのベストプラクティス:

  1. ローカルテスト
# 環境変数を設定してサーバーを起動 API_KEY=your_key npm run dev
  1. AIアシスタントとの統合テスト Windsurfの場合は~/.codeium/windsurf/mcp_config.jsonに設定を追加

  2. デバッグログの活用

console.error('デバッグ:', JSON.stringify(data, null, 2));
  1. エラーケースのテスト
  • 無効なパラメータ
  • APIキーなしでの起動
  • ネットワークエラー
  • APIレスポンスエラー
  1. 手動テストコマンド例
echo '{"jsonrpc":"2.0","id":"test","method":"mcp.listTools","params":{}}' | node dist/index.js

MCPサーバーのコード分割と責務分離

8日前


MCPサーバーのコードを適切に分割するためのガイドライン:

  1. 関心の分離

    • サーバー設定(server.ts)
    • ツール定義(tool.ts)
    • ハンドラー実装(handlers/*.ts)
    • API通信(services/*.ts)
    • 型定義(types/*.ts)
  2. ファイル分割の利点

    • コードの可読性向上
    • 単体テストの容易化
    • 並行開発の促進
    • 変更の影響範囲の限定
  3. モジュール間の依存関係

    • 循環依存を避ける
    • インターフェースを通じた疎結合
    • 共通ユーティリティの抽出
  4. 拡張性の確保

    • 新機能追加時に既存コードへの変更を最小化
    • プラグイン的な拡張ポイントの提供

MCPサーバーのエラーハンドリング戦略

8日前


堅牢なMCPサーバーのためのエラーハンドリング戦略:

  1. サーバーレベルのエラーハンドリング
server.onerror = (error) => { console.error('[MCP Error]', error); }; process.on('uncaughtException', (error) => { console.error('未捕捉の例外:', error); });
  1. ハンドラーレベルのエラーハンドリング
  • パラメータ検証エラー
  • APIリクエストエラー
  • 予期せぬ例外
  1. エラーレスポンスの構造
{ content: [{ type: 'text', text: 'エラーメッセージ' }], isError: true }
  1. デバッグ情報の提供
  • 開発環境では詳細なエラー情報
  • 本番環境ではユーザーフレンドリーなメッセージ
  1. リトライ戦略
  • 一時的なネットワークエラーに対するリトライ
  • 指数バックオフの実装

AIアシスタントとMCPサーバーの連携設定

8日前


各AIアシスタントとMCPサーバーを連携させる設定方法:

  1. Windsurf ~/.codeium/windsurf/mcp_config.jsonに以下を追加:
"mcpServers": { "service_name": { "command": "node", "args": ["path/to/dist/index.js"], "env": { "API_KEY": "your_api_key" } } }
  1. Cursor 設定から「AI: MCP Servers」に追加:
"ai.mcpServers": [ { "name": "service_name", "command": "node", "args": ["path/to/dist/index.js"], "env": { "API_KEY": "your_api_key" } } ]
  1. Claude Desktop 設定から「拡張機能」→「MCP サーバー」に追加:
  • 名前: service_name
  • コマンド: npx
  • 引数: -y your-package-name
  • 環境変数: API_KEY=your_api_key