sdk-implementation-examples.json•23.6 kB
{
  "schema": "memory_document_v2",
  "metadata": {
    "id": "sdk-implementation-examples",
    "title": "SDK実装サンプル集",
    "documentType": "code_examples",
    "path": "sdk-implementation-examples.json",
    "tags": [
      "e2e-test",
      "implementation",
      "code-samples",
      "sdk"
    ],
    "lastModified": "2025-04-06T11:25:00.000Z",
    "createdAt": "2025-04-06T11:25:00.000Z",
    "version": 1
  },
  "content": {
    "overview": "E2Eテスト実装で使用する@modelcontextprotocol/sdkの主要クラスとその具体的な実装例のコレクションです。この文書は、CodeQueenモードでの実装フェーズで参照するためのガイドラインとして役立てることができます。",
    "sdkClasses": {
      "InMemoryTransport": {
        "description": "メモリ内でのクライアント-サーバー間通信をシミュレートするためのトランスポート実装",
        "importStatement": "import { InMemoryTransport } from '@modelcontextprotocol/sdk';",
        "keyMethods": [
          {
            "name": "createLinkedPair()",
            "description": "クライアントとサーバー用のリンクされたトランスポートペアを作成する静的メソッド",
            "returnValue": "[clientTransport, serverTransport]のペア",
            "example": "const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();"
          },
          {
            "name": "start()",
            "description": "トランスポートの処理を開始し、キューに入っているメッセージの配信を開始する",
            "returnValue": "Promise<void>",
            "example": "await transport.start();"
          },
          {
            "name": "send(message)",
            "description": "相手側のトランスポートにJSONRPCメッセージを送信する",
            "parameters": [
              {
                "name": "message",
                "type": "JSONRPCMessage",
                "description": "送信するJSON-RPCメッセージ"
              }
            ],
            "returnValue": "Promise<void>",
            "example": "await clientTransport.send({ jsonrpc: '2.0', method: 'ping', id: 1 });"
          },
          {
            "name": "close()",
            "description": "トランスポート接続を閉じる",
            "returnValue": "Promise<void>",
            "example": "await transport.close();"
          }
        ],
        "callbacks": [
          {
            "name": "onmessage",
            "description": "メッセージを受信したときに呼び出されるコールバック",
            "parameters": [
              {
                "name": "message",
                "type": "JSONRPCMessage",
                "description": "受信したJSON-RPCメッセージ"
              }
            ],
            "example": "transport.onmessage = (message) => { console.log('Received message:', message); };"
          },
          {
            "name": "onclose",
            "description": "接続が閉じられたときに呼び出されるコールバック",
            "example": "transport.onclose = () => { console.log('Connection closed'); };"
          },
          {
            "name": "onerror",
            "description": "エラーが発生したときに呼び出されるコールバック",
            "parameters": [
              {
                "name": "error",
                "type": "Error",
                "description": "発生したエラー"
              }
            ],
            "example": "transport.onerror = (error) => { console.error('Transport error:', error); };"
          }
        ]
      },
      "Client": {
        "description": "MCP(Model Context Protocol)クライアントの実装",
        "importStatement": "import { Client } from '@modelcontextprotocol/sdk';",
        "keyMethods": [
          {
            "name": "constructor(transport)",
            "description": "指定されたトランスポートを使用してクライアントを初期化する",
            "parameters": [
              {
                "name": "transport",
                "type": "Transport",
                "description": "使用するトランスポート(InMemoryTransportなど)"
              }
            ],
            "example": "const client = new Client(clientTransport);"
          },
          {
            "name": "initialize(options)",
            "description": "クライアントを初期化し、サーバーへの接続を確立する",
            "parameters": [
              {
                "name": "options",
                "type": "Object",
                "description": "初期化オプション(プロトコルバージョン、機能、クライアント情報など)"
              }
            ],
            "returnValue": "Promise<InitializeResult>",
            "example": "const result = await client.initialize({\n  protocolVersion: '2024-11-05',\n  capabilities: {},\n  clientInfo: {\n    name: 'TestClient',\n    version: '1.0.0'\n  }\n});"
          },
          {
            "name": "callTool(name, args)",
            "description": "サーバー側のツールを呼び出す",
            "parameters": [
              {
                "name": "name",
                "type": "string",
                "description": "呼び出すツールの名前"
              },
              {
                "name": "args",
                "type": "Object",
                "description": "ツールに渡す引数"
              }
            ],
            "returnValue": "Promise<CallToolResult>",
            "example": "const result = await client.callTool('read_branch_memory_bank', {\n  branch: 'feature/test',\n  path: 'test-document.json',\n  docs: '/path/to/docs'\n});"
          }
        ]
      },
      "Server": {
        "description": "MCP(Model Context Protocol)サーバーの実装",
        "importStatement": "import { Server } from '@modelcontextprotocol/sdk';",
        "keyMethods": [
          {
            "name": "constructor(transport, options)",
            "description": "指定されたトランスポートとオプションを使用してサーバーを初期化する",
            "parameters": [
              {
                "name": "transport",
                "type": "Transport",
                "description": "使用するトランスポート(InMemoryTransportなど)"
              },
              {
                "name": "options",
                "type": "Object",
                "description": "サーバーオプション(プロトコルバージョン、機能、サーバー情報など)"
              }
            ],
            "example": "const server = new Server(serverTransport, {\n  protocolVersion: '2024-11-05',\n  capabilities: {},\n  serverInfo: {\n    name: 'TestServer',\n    version: '1.0.0'\n  }\n});"
          },
          {
            "name": "registerTool(name, callback)",
            "description": "クライアントが呼び出せるツールを登録する",
            "parameters": [
              {
                "name": "name",
                "type": "string",
                "description": "ツールの名前"
              },
              {
                "name": "callback",
                "type": "Function",
                "description": "ツールが呼び出されたときに実行されるコールバック関数"
              }
            ],
            "example": "server.registerTool('read_branch_memory_bank', async (params) => {\n  // ツールの実装\n  return { document: { ... } };\n});"
          }
        ]
      }
    },
    "implementationExamples": {
      "MCPInMemoryClient": {
        "description": "MCPサーバーと通信するためのインメモリクライアント実装",
        "fullImplementation": [
          "import { InMemoryTransport, Client, JSONRPCMessage } from '@modelcontextprotocol/sdk';",
          "",
          "/**",
          " * MCPサーバーと通信するためのインメモリクライアント",
          " */",
          "export class MCPInMemoryClient {",
          "  private client: Client;",
          "  private transport: InMemoryTransport;",
          "  private isConnected: boolean = false;",
          "",
          "  /**",
          "   * クライアントを作成する",
          "   * @param clientTransport クライアント側のトランスポート",
          "   */",
          "  constructor(clientTransport: InMemoryTransport) {",
          "    this.transport = clientTransport;",
          "    this.client = new Client(this.transport);",
          "  }",
          "",
          "  /**",
          "   * クライアントを初期化し、サーバーに接続する",
          "   */",
          "  async initialize(): Promise<void> {",
          "    if (this.isConnected) {",
          "      return;",
          "    }",
          "",
          "    await this.transport.start();",
          "    await this.client.initialize({",
          "      protocolVersion: '2024-11-05',",
          "      capabilities: {},",
          "      clientInfo: {",
          "        name: 'MCPInMemoryClient',",
          "        version: '1.0.0'",
          "      }",
          "    });",
          "",
          "    this.isConnected = true;",
          "  }",
          "",
          "  /**",
          "   * サーバーとの接続を閉じる",
          "   */",
          "  async close(): Promise<void> {",
          "    await this.transport.close();",
          "    this.isConnected = false;",
          "  }",
          "",
          "  /**",
          "   * ブランチメモリバンクからドキュメントを読み込む",
          "   * @param branch ブランチ名",
          "   * @param path ドキュメントパス",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async readBranchMemoryBank(branch: string, path: string, docs: string): Promise<any> {",
          "    return this.client.callTool('read_branch_memory_bank', {",
          "      branch,",
          "      path,",
          "      docs",
          "    });",
          "  }",
          "",
          "  /**",
          "   * ブランチメモリバンクにドキュメントを書き込む",
          "   * @param branch ブランチ名",
          "   * @param path ドキュメントパス",
          "   * @param content ドキュメントの内容",
          "   * @param docs ドキュメントルート",
          "   * @param tags タグ(オプション)",
          "   */",
          "  async writeBranchMemoryBank(",
          "    branch: string,",
          "    path: string,",
          "    content: string,",
          "    docs: string,",
          "    tags?: string[]",
          "  ): Promise<any> {",
          "    return this.client.callTool('write_branch_memory_bank', {",
          "      branch,",
          "      path,",
          "      content,",
          "      docs,",
          "      tags",
          "    });",
          "  }",
          "",
          "  /**",
          "   * ブランチメモリバンクのドキュメントにJSONパッチを適用する",
          "   * @param branch ブランチ名",
          "   * @param path ドキュメントパス",
          "   * @param patches JSONパッチ操作の配列",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async patchBranchMemoryBank(",
          "    branch: string,",
          "    path: string,",
          "    patches: any[],",
          "    docs: string",
          "  ): Promise<any> {",
          "    return this.client.callTool('write_branch_memory_bank', {",
          "      branch,",
          "      path,",
          "      patches,",
          "      docs",
          "    });",
          "  }",
          "",
          "  /**",
          "   * グローバルメモリバンクからドキュメントを読み込む",
          "   * @param path ドキュメントパス",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async readGlobalMemoryBank(path: string, docs: string): Promise<any> {",
          "    return this.client.callTool('read_global_memory_bank', {",
          "      path,",
          "      docs",
          "    });",
          "  }",
          "",
          "  /**",
          "   * グローバルメモリバンクにドキュメントを書き込む",
          "   * @param path ドキュメントパス",
          "   * @param content ドキュメントの内容",
          "   * @param docs ドキュメントルート",
          "   * @param tags タグ(オプション)",
          "   */",
          "  async writeGlobalMemoryBank(",
          "    path: string,",
          "    content: string,",
          "    docs: string,",
          "    tags?: string[]",
          "  ): Promise<any> {",
          "    return this.client.callTool('write_global_memory_bank', {",
          "      path,",
          "      content,",
          "      docs,",
          "      tags",
          "    });",
          "  }",
          "",
          "  /**",
          "   * グローバルメモリバンクのドキュメントにJSONパッチを適用する",
          "   * @param path ドキュメントパス",
          "   * @param patches JSONパッチ操作の配列",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async patchGlobalMemoryBank(",
          "    path: string,",
          "    patches: any[],",
          "    docs: string",
          "  ): Promise<any> {",
          "    return this.client.callTool('write_global_memory_bank', {",
          "      path,",
          "      patches,",
          "      docs",
          "    });",
          "  }",
          "",
          "  /**",
          "   * コンテキスト情報を読み込む",
          "   * @param branch ブランチ名",
          "   * @param language 言語コード",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async readContext(branch: string, language: string, docs: string): Promise<any> {",
          "    return this.client.callTool('read_context', {",
          "      branch,",
          "      language,",
          "      docs",
          "    });",
          "  }",
          "",
          "  /**",
          "   * タグでドキュメントを検索する",
          "   * @param tags 検索するタグの配列",
          "   * @param match マッチング方法('and'または'or')",
          "   * @param scope 検索範囲('branch'、'global'、または'all')",
          "   * @param branch ブランチ名(scopeが'branch'または'all'の場合に必要)",
          "   * @param docs ドキュメントルート",
          "   */",
          "  async searchDocumentsByTags(",
          "    tags: string[],",
          "    match: 'and' | 'or',",
          "    scope: 'branch' | 'global' | 'all',",
          "    branch: string | undefined,",
          "    docs: string",
          "  ): Promise<any> {",
          "    return this.client.callTool('search_documents_by_tags', {",
          "      tags,",
          "      match,",
          "      scope,",
          "      branch,",
          "      docs",
          "    });",
          "  }",
          "}"
        ]
      },
      "E2ETestSetup": {
        "description": "E2Eテスト環境のセットアップユーティリティ",
        "fullImplementation": [
          "import { InMemoryTransport, Server } from '@modelcontextprotocol/sdk';",
          "import { setupTestEnv, TestEnv } from './test-env';",
          "import { MCPInMemoryClient } from './MCPInMemoryClient';",
          "",
          "/**",
          " * E2Eテスト環境をセットアップする",
          " */",
          "export async function setupE2ETestEnv(): Promise<{",
          "  testEnv: TestEnv;",
          "  client: MCPInMemoryClient;",
          "  cleanup: () => Promise<void>;",
          "}> {",
          "  // テスト環境のセットアップ",
          "  const testEnv = await setupTestEnv();",
          "",
          "  // InMemoryTransportのペアを作成",
          "  const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();",
          "",
          "  // MCPサーバーをインメモリトランスポートで初期化",
          "  const server = new Server(serverTransport, {",
          "    protocolVersion: '2024-11-05',",
          "    capabilities: {},",
          "    serverInfo: {",
          "      name: 'MemoryBankMCPServer',",
          "      version: '2.4.0'",
          "    }",
          "  });",
          "",
          "  // サーバーツールの登録(実際のMCPサーバーの処理を呼び出す)",
          "  const { DIContainer, setupContainer } = require('../../../src/main/di/providers');",
          "  const container = await setupContainer({ docsRoot: testEnv.docRoot });",
          "",
          "  // ブランチコントローラーの取得",
          "  const branchController = await container.get('branchController');",
          "  ",
          "  // サーバーにツールを登録",
          "  server.registerTool('read_branch_memory_bank', async (params) => {",
          "    const { branch, path } = params;",
          "    const result = await branchController.readDocument(branch, path);",
          "    return result;",
          "  });",
          "",
          "  server.registerTool('write_branch_memory_bank', async (params) => {",
          "    const { branch, path, content, patches, tags } = params;",
          "    const result = await branchController.writeDocument({",
          "      branchName: branch,",
          "      path,",
          "      content,",
          "      patches,",
          "      tags",
          "    });",
          "    return result;",
          "  });",
          "",
          "  // グローバルコントローラーの取得",
          "  const globalController = await container.get('globalController');",
          "",
          "  server.registerTool('read_global_memory_bank', async (params) => {",
          "    const { path } = params;",
          "    const result = await globalController.readDocument(path);",
          "    return result;",
          "  });",
          "",
          "  server.registerTool('write_global_memory_bank', async (params) => {",
          "    const { path, content, patches, tags } = params;",
          "    const result = await globalController.writeDocument({",
          "      path,",
          "      content,",
          "      patches,",
          "      tags",
          "    });",
          "    return result;",
          "  });",
          "",
          "  // コンテキストコントローラーの取得",
          "  const contextController = await container.get('contextController');",
          "",
          "  server.registerTool('read_context', async (params) => {",
          "    const { branch, language } = params;",
          "    const result = await contextController.readContext(branch, language);",
          "    return result;",
          "  });",
          "",
          "  server.registerTool('search_documents_by_tags', async (params) => {",
          "    const { tags, match, scope, branch } = params;",
          "    const result = await contextController.searchDocumentsByTags({",
          "      tags,",
          "      match,",
          "      scope,",
          "      branch",
          "    });",
          "    return result;",
          "  });",
          "",
          "  // トランスポートを開始",
          "  await serverTransport.start();",
          "",
          "  // MCPクライアントを作成して初期化",
          "  const client = new MCPInMemoryClient(clientTransport);",
          "  await client.initialize();",
          "",
          "  // クリーンアップ関数",
          "  const cleanup = async () => {",
          "    await client.close();",
          "    await testEnv.cleanup();",
          "  };",
          "",
          "  return { testEnv, client, cleanup };",
          "}"
        ]
      },
      "BasicTest": {
        "description": "基本的な接続確立のE2Eテスト",
        "fullImplementation": [
          "import { setupE2ETestEnv } from './helpers/e2e-test-env';",
          "",
          "describe('MCP E2E Initialization Tests', () => {",
          "  let testEnv;",
          "  let client;",
          "  let cleanup;",
          "",
          "  beforeEach(async () => {",
          "    const setup = await setupE2ETestEnv();",
          "    testEnv = setup.testEnv;",
          "    client = setup.client;",
          "    cleanup = setup.cleanup;",
          "  });",
          "",
          "  afterEach(async () => {",
          "    await cleanup();",
          "  });",
          "",
          "  it('should establish connection successfully', async () => {",
          "    // クライアントは既に初期化されているので、接続が確立されているはず",
          "    // いくつかの基本的な操作を試してみる",
          "    const branchName = 'feature/test-branch';",
          "    const documentPath = 'test-document.json';",
          "    const docContent = JSON.stringify({",
          "      schema: \"memory_document_v2\",",
          "      metadata: {",
          "        id: \"test-e2e-doc\",",
          "        title: \"E2Eテスト用ドキュメント\",",
          "        documentType: \"test\",",
          "        path: documentPath,",
          "        tags: [\"test\", \"e2e\"],",
          "        lastModified: new Date().toISOString(),",
          "        createdAt: new Date().toISOString(),",
          "        version: 1",
          "      },",
          "      content: {",
          "        value: \"E2Eテスト用のドキュメント内容\"",
          "      }",
          "    }, null, 2);",
          "",
          "    // ドキュメントを書き込む",
          "    const writeResult = await client.writeBranchMemoryBank(",
          "      branchName,",
          "      documentPath,",
          "      docContent,",
          "      testEnv.docRoot",
          "    );",
          "",
          "    expect(writeResult.success).toBe(true);",
          "    expect(writeResult.data).toBeDefined();",
          "",
          "    // ドキュメントを読み込む",
          "    const readResult = await client.readBranchMemoryBank(",
          "      branchName,",
          "      documentPath,",
          "      testEnv.docRoot",
          "    );",
          "",
          "    expect(readResult.success).toBe(true);",
          "    expect(readResult.data).toBeDefined();",
          "    expect(readResult.data.document).toBeDefined();",
          "    expect(typeof readResult.data.document.content).toBe('string');",
          "",
          "    const parsed = JSON.parse(readResult.data.document.content);",
          "    expect(parsed.metadata.id).toBe('test-e2e-doc');",
          "    expect(parsed.content.value).toBe('E2Eテスト用のドキュメント内容');",
          "  });",
          "});"
        ]
      }
    }
  }
}