MCPの基本的な仕組み

n-ozawan

皆さん、こんにちは。LP開発グループのn-ozawanです。
イラン文化圏では春分の日をノウルーズと言い、イラン暦の元日に該当します。

本題です。
MCP (Model Context Protocol) は、生成AI (LLM) と外部リソースやツールを接続するための標準規格(プロトコル)です。その仕組みはどうなっているのでしょうか?今回はMCPの仕組みについてのお話です。

MCPの仕組み

サーバーとクライアント

MCPはクライアント・サーバー型で動作します。厳密に言うならば、MCPホスト、MCPクライアント、MCPサーバーの3つの構造となっています。

MCPホストは生成AIが動作する環境(アプリ)であり、VS CodeやClaude Desktopなどが該当します。MCPホストはユーザーからの指示を受け取り、MCPクライアントを通じて、MCPサーバーが提供する各種サービスを実行させます。通信するMCPサーバーは複数あり、MCPホストはMCPサーバーごとにMCPクライアントを作成し、それらを管理します。

MCPクライアントはMCPホストとMCPサーバーを橋渡しするコンポーネントです。生成AIからの命令を受けて、MCPサーバーを通して外部APIやローカルファイルへアクセスし、結果をAIへ返します。

MCPサーバーは生成AIにリソースや機能を提供するコンポーネントです。MCPサーバーは対応する外部システムごとに構築します。例えばGitHubへのアクセスや操作を可能するためのMCPサーバー、などです。また、「サーバー」と聞くとクラウド上に構築されたものと想像しますが、実際の多くはローカル環境でMCPサーバーを動作させます。前回、draw.ioのMCPを使ってみましたが、あれはローカル環境にdraw.io用のMCPサーバーが動作しています。

JSON-RPC

MCPクライアントとMCPサーバーはJSON-RPCという規格で通信を行います。RPCとは、Remote Procedure Call の略で、ネットワーク上の別のコンピュータで動作するプログラム(関数やメソッド)を、手元のプログラムから直接呼び出して実行させるプロトコルです。JSON-PRCとは、そんなRPCをJSONで通信するプロトコルです。

例えば、MCPクライアントは以下のようなJSONを、MCPサーバーへ送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "Id": 1,                  // 識別子
  "method": "tools/call",   // ツールの実行
  "params": {               // 引数
    "name": "example",
    "arguments": {
      "query": "hello world!"
    }
  }
}

MCPサーバーは受け取ったJSONの内容を元に処理を実行します。そしてその処理が成功した場合、以下のようなレスポンスをMCPクライアントへ返却します。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子(リクエストと同じ番号が設定される)
  "result": {               // 処理が成功した場合の結果
    "content": [
      {
        "type": "text", 
        "text": "hello world!", 
      }
    ]
  }
}

MCPサーバーの基本機能

MCPサーバーにはプリミティブと呼ばれる3つの基本機能があります。

ツール

ツールは、生成AIが外部システムと連携して、何かしらの処理を実行するための機能です。

MCPクライアントは、MCPサーバーがどんなツールを提供しているのかを問い合わせます。その際は、"method": "tools/list"のリクエストを送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "id": 1,                  // 識別子
  "method": "tools/list",   // MCPサーバーが提供するツールの一覧を取得
  "params": {}              // 引数
}

MCPサーバーは"method": "tools/list"のリクエストに対して、利用可能なツールの情報をレスポンスします。以下のレスポンスでは、fetch_pageというツールが提供されていることが分かります。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子
  "result": {               // ツールの一覧を返却する
    "tools": [
      {
        "name": "fetch_page",  // ツール名
        "inputSchema": { 
          "type": "object",
          "required": ["url"] 
        }
      }
    ]
  }
}

そのレスポンスから、生成AIは使用するツールを判断して、MCPクライアントがそのツールを実行するリクエストを送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "id": 1,                  // 識別子
  "method": "tools/call",   // MCPサーバーが提供するツールを実行
  "params": {               // 引数
    "name": "fetch_page",   // 実行したいツール名
    "arguments": {
      "url": "https://www.ios-net.co.jp"
    }
  }
}

リソース

リソースは、生成AIが外部システムが持つリソースを取得するための機能です。

MCPクライアントは、MCPサーバーからどのようなリソースを取得できるのかを問い合わせます。その際は、"method": "resources/list"のリクエストを送信します。

{
  "jsonrpc": "2.0",             // JSONRPC のバージョン
  "id": 1,                      // 識別子
  "method": "resources/list",   // リソースの一覧を取得
  "params": {}                  // 引数
}

MCPサーバーは"method": "resources/list"のリクエストに対して、取得可能なリソースをレスポンスします。以下のレスポンスでは、file:///example/README.mdというリソースが取得可能であることがわかります。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子
  "result": {               // リソースの一覧を返却する
    "resources": [
      {
        "uri": "file:///example/README.md",
        "mimeType": "text/markdown"
      }
    ]
  }
}

そのレスポンスから、生成AIはMCPクライアントを通して、外部システムのリソースを取得するリクエストを送信します。

{
  "jsonrpc": "2.0",             // JSONRPC のバージョン
  "id": 1,                      // 識別子
  "method": "resources/read",   // リソースの取得
  "params": {                   // 引数
    "uri": "file:///example/README.md"
  }
}

プロンプト

プロンプトは、よく使う指示や質問(プロンプト)の形式を予め用意しておく「テンプレート」です。処理した結果や取得したリソースを生成AIが有効活用するためには、それに適したプロンプトが必要です。そのようなプロンプトをMCPサーバーから取得することができます。プロンプトのあり/なしや、その内容によっては生成AIの精度が大きく変わってきますので、MCPサーバーからプロンプトを提供することで、安定した精度を確保します。

MCPクライアントとの通信はツールやリソースとほぼ同じで、"method": "prompts/list"でプロンプトの一覧を取得し、"method": "prompts/get"でプロンプトを取得します。

おわりに

MCPはAIに関係するプロトコルですので、複雑で難しい印象を受けていましたが、意外とシンプルな仕様でした。

今回はMCPクライアントからMCPサーバーへの通信をあげましたが、その逆で、MCPサーバーからMCPクライアントへの通信もあります。ファイルの削除など、本当にその操作をしても良いのか?とユーザーに確認するために、MCPサーバーからMCPクライアントへ問い合わせます。

ではまた。

Recommendおすすめブログ