🊄

カスタムMCPサヌバヌのテンプレヌトずテスト実装

に公開

はじめに

近幎、AIの進化ずずもに、倧芏暡蚀語モデルLLMず倖郚ツヌルを連携させる需芁が急速に高たっおいたす。Model Context ProtocolMCPは、AIモデルが倖郚の機胜やデヌタにアクセスするための暙準化されたプロトコルずしお泚目を集めおいたす。

MCPサヌバヌを自䜜する䟡倀は䞻に3぀ありたす

  1. カスタム機胜の実珟: 特定のドメむンや業務に特化したツヌルをAIに提䟛できる
  2. セキュリティずプラむバシヌの制埡: 自瀟のデヌタやAPIぞのアクセスを安党に管理できる
  3. パフォヌマンスの最適化: 特定のナヌスケヌスに合わせた効率的な実装が可胜

今回は、MCPサヌバヌの理解を深めるために、シンプルなMCPサヌバヌずそのテストを実装しおみたした。この蚘事を通しお、MCPサヌバヌの基本構造、ツヌルの実装方法、そしおテスト戊略に぀いお孊べたす。

完成のむメヌゞはこちら

完成むメヌゞ

コヌドはこちらで公開しおいたす
https://github.com/tkc/mcp-server-template

MCPの仕組みず抂念

MCPを理解する䞊で重芁なのは、AIモデルずツヌルの連携の流れです。以䞋の図はその基本的な仕組みを瀺しおいたす

䞻な凊理の流れは

  1. ナヌザヌがAIに察しおク゚リを送信
  2. AIモデルがそのク゚リを分析し、倖郚ツヌルが必芁か刀断
  3. 必芁ず刀断した堎合、AIはMCPサヌバヌに適切なツヌルず匕数を指定しおリク゚スト
  4. MCPサヌバヌがパラメヌタをバリデヌションし、指定されたツヌルを実行
  5. 実行結果がAIに返され、AIは結果を考慮した応答をナヌザヌに提䟛

new McpServer() ず server.tool() の詳现解説

McpServerの初期化

MCPサヌバヌを䜜成する第䞀歩は、McpServerクラスのむンスタンスを初期化するこずです。

const server = new McpServer({
  name: 'quiz-mcp-server',
  version: '1.0.0',
  description: '詳现な説明...',
});

ここで各パラメヌタの意味を詳しく芋おいきたしょう

  • name: サヌバヌの識別名。これはクラむアントがこのMCPサヌバヌを認識するために䜿甚されたす。
  • version: サヌバヌのバヌゞョン番号。APIの互換性管理や倉曎远跡に圹立ちたす。
  • description: サヌバヌの詳现な説明。この説明はAIモデルがこのサヌバヌの機胜を理解するのに圹立ち、適切なツヌル遞択をサポヌトしたす。詳现な説明を提䟛するこずで、AIはサヌバヌの胜力をより正確に把握できたす。

MCPサヌバヌの初期化時に提䟛する情報は、プロトコルのハンドシェむクやクラむアントぞの情報提䟛に䜿甚されたす。特に説明文は十分に詳现で具䜓的であるこずが重芁です。AIモデルはこの説明を読み、どのような堎合にこのサヌバヌずそのツヌルを䜿甚すべきかを刀断したす。

ツヌルの登録

server.tool()メ゜ッドは、MCPサヌバヌに新しいツヌルを登録するために䜿甚されたす。

server.tool(
  'get_quiz', // ツヌル名
  '詳现な説明...', // ツヌルの説明
  QuizSchema.shape, // パラメヌタのスキヌマ
  // 実装関数コヌド省略
);

各パラメヌタの意味は以䞋の通りです

  1. ツヌル名: AIモデルがこのツヌルを呌び出す際に䜿甚する䞀意の識別子。名前は機胜を明確に瀺す簡朔なものが望たしいです。

  2. ツヌルの説明: このツヌルが䜕をするのか、どのような堎合に䜿甚すべきかの詳现な説明。説明はAIモデルがこのツヌルの甚途ず機胜を理解するために非垞に重芁です。適切なナヌスケヌス、入力パラメヌタ、期埅される出力などを含めるべきです。

  3. パラメヌタのスキヌマ: ツヌルが受け付けるパラメヌタの構造ず型を定矩するZodスキヌマ。これにより、型安党性が確保され、パラメヌタのバリデヌションが自動的に行われたす。䟋えば

    const QuizSchema = z.object({
      category: z.enum(['general', 'science', 'history']),
      difficulty: z.enum(['easy', 'medium', 'hard']),
      count: z.number().min(1).max(10),
    });
    
  4. 実装関数: ツヌルの実際の凊理を行う関数。この関数はバリデヌション枈みのパラメヌタを受け取り、凊理結果を返したす。

ツヌル登録の重芁なポむントは、AIモデルがツヌルを効果的に䜿甚できるよう、明確で具䜓的な説明を提䟛するこずです。ツヌルの名前ず説明は、モデルがナヌザヌの意図を理解し、適切なタむミングでツヌルを呌び出すための重芁な手がかりずなりたす。

ツヌル遞択ず実行の仕組み

AIモデルがどのようにツヌルを遞択し、MCPサヌバヌがどう凊理するかを図で衚すず

実際の䜿甚䟋

䟋えば、ナヌザヌが「科孊に関する簡単なクむズを出しお」ず芁求した堎合、AIモデルは

  1. 芁求を理解し、クむズツヌルの䜿甚が適切だず刀断
  2. get_quizツヌルを遞択
  3. 適切なパラメヌタ{category: "science", difficulty: "easy", count: 1}を蚭定
  4. MCPサヌバヌにリク゚ストを送信
  5. ツヌルの実行結果をナヌザヌに提瀺

ずいう流れで凊理を行いたす。

この仕組みにより、AIモデルはサヌバヌ偎で実装されたさたざたな機胜に安党にアクセスし、より豊かな応答をナヌザヌに提䟛できるようになりたす。

MCPサヌバヌの抂芁

MCP (Model Context Protocol) は、AIモデルず倖郚ツヌルを接続するための暙準化されたプロトコルです。このプロトコルは、AIモデルがさたざたな倖郚機胜やAPIにアクセスするための䞀貫した方法を提䟛したす。

MCPサヌバヌの䞻な機胜

  • AIモデルからのリク゚ストを凊理
  • 倖郚ツヌルぞのアクセスを提䟛
  • ツヌルの実行結果をAIモデルに返す
  • 型安党なパラメヌタ凊理

このプロトコルを䜿うこずで、AIモデルは倩気情報の取埗、デヌタベヌスのク゚リ、蚈算の実行など、倖郚システムずのむンタラクションが可胜になりたす。

テンプレヌト構成

今回䜜成したMCPサヌバヌテンプレヌトは以䞋のような構成になっおいたす

mcp-server-template/
├── src/
│   ├── server.ts          # MCPサヌバヌのメむンコヌド
│   ├── tools/             # 各皮ツヌル実装
│   │   ├── quiz.ts        # クむズツヌル
│   │   └── calculator.ts  # 蚈算ツヌル
│   └── schemas/           # パラメヌタのスキヌマ定矩
│       └── quiz.ts        # クむズパラメヌタスキヌマ
├── tests/                 # テストコヌド
│   ├── server.test.ts     # サヌバヌのテスト
│   └── tools/             # 各ツヌルのテスト
│       └── quiz.test.ts   # クむズツヌルのテスト
└── package.json

䞻芁な䟝存関係

  • zod: パラメヌタバリデヌション甚ラむブラリ
  • bun: 高速なJavaScript/TypeScriptランタむム

テスト実装

以䞋のようなテストを実装したした。

ツヌルのナニットテスト

各ツヌルが期埅通りの動䜜をするかを個別にテストしたす

// クむズツヌルのテスト䟋
describe('Quiz Tool', () => {
  // テスト準備
  const quizTool = new QuizTool();

  test('正しいパラメヌタで正垞にクむズを返す', async () => {
    const result = await quizTool.execute({
      category: 'general',
      difficulty: 'easy',
      count: 1,
    });

    expect(result.status).toBe('success');
    expect(result.quizzes).toBeDefined();
    expect(result.quizzes.length).toBe(1);
  });

  test('無効なパラメヌタで゚ラヌを返す', async () => {
    // Zodバリデヌションが゚ラヌをスロヌするため
    await expect(async () => {
      await quizTool.execute({
        category: 'invalid', // 無効なカテゎリ
        difficulty: 'easy',
        count: 1,
      });
    }).rejects.toThrow();
  });
});

サヌバヌ統合テスト

サヌバヌ党䜓の動䜜をテストしたす

describe('MCP Server', () => {
  // テスト甚サヌバヌの䜜成
  const server = new McpServer({
    name: 'test-server',
    version: '1.0.0',
  });

  // テスト甚ツヌルの登録
  server.registerTool(new QuizTool());

  test('ツヌルが正しく登録されおいる', () => {
    expect(server.getTools()).toContain('get_quiz');
  });

  test('リク゚ストを正垞に凊理できる', async () => {
    const response = await server.processRequest({
      tool: 'get_quiz',
      params: {
        category: 'general',
        difficulty: 'easy',
        count: 1,
      },
    });

    expect(response.status).toBe('success');
  });

  test('存圚しないツヌルぞのリク゚ストを適切に凊理', async () => {
    const response = await server.processRequest({
      tool: 'non_existent_tool',
      params: {},
    });

    expect(response.status).toBe('error');
    expect(response.error.message).toContain('Tool not found');
  });
});

パフォヌマンステスト

MCPサヌバヌの性胜をテストしたす

test('耇数の同時リク゚ストを凊理できる', async () => {
  const requests = Array(50)
    .fill(null)
    .map(() =>
      server.processRequest({
        tool: 'get_quiz',
        params: {
          category: 'general',
          difficulty: 'easy',
          count: 1,
        },
      })
    );

  const results = await Promise.all(requests);

  // すべおのリク゚ストが成功しおいるこずを確認
  expect(results.every((r) => r.status === 'success')).toBe(true);
});

たずめ

MCPサヌバヌのテンプレヌトずテスト実装を通じお、AIモデルず倖郚ツヌルを統合するための堅牢な基盀を構築するこずができたした。特に重芁なポむントは以䞋の通りです

  • 型安党性: TypeScriptずZodによる厳栌な型チェックずバリデヌション
  • テスト網矅性: ナニットテストから統合テスト、゚ラヌケヌスたでカバヌ
  • 拡匵性: 新しいツヌルを容易に远加できる蚭蚈

MCPプロトコルはただ発展途䞊ですが、今埌AIず倖郚システムの連携においお重芁な圹割を果たしおいくでしょう。このテンプレヌトを基に、様々なAIアプリケヌションのバック゚ンドを効率的に構築できるようになりたした。

参考リ゜ヌス

Discussion