MCP.so
ログイン
ブログに戻る

MCP Client(MCP クライアント)ガイド:仕組み・主要クライアント・実装方法

2026年10月15日MCP.so TeamMCP.so Team

MCP クライアントとは何か、ホストとの違い、主要な MCP クライアントが対応するトランスポートと機能、そして TypeScript/Python で最小限のクライアントを作る方法を解説します。

MCP クライアントとは、AI アプリケーションの内部でちょうど 1 つの MCP サーバーとの接続を保持するコネクタです。そのサーバーへのリクエスト(ツール一覧の取得、ツールの呼び出し、リソースの読み取り)を送り、結果をアプリに返します。モデルと UI を動かしているアプリケーション側はホストと呼ばれます。Claude Code、Cursor、VS Code のようなホストは、設定したサーバーごとにクライアントを 1 つずつ作成します。日常会話ではアプリ全体を「MCP クライアント」と呼ぶことも多く、それで困ることはありませんが、自分で実装するときにはこの区別が重要になります。

このガイドでは、クライアントがプロトコル上で実際に何をしているのか、2026 年 10 月時点で主要クライアントが何に対応しているのか、そして公式の TypeScript/Python SDK で最小限のクライアントを書く方法を解説します。プロトコルの基礎から知りたい場合はまず MCP とは? を、メッセージ単位の流れは MCP はどう動くのか? を参照してください。

ホスト・クライアント・サーバーの違い

MCP アーキテクチャ仕様は 3 つの役割を定義しています:

役割内容例
ホストユーザーが直接やり取りする AI アプリ。モデルを動かし、同意を管理し、どのコンテキストを共有するかを決めるClaude Code、Cursor、VS Code、ChatGPT
クライアントホストが生成するコネクタで、1 つのサーバーと 1:1 で結び付くVS Code で Sentry サーバーを追加したときに VS Code が生成するオブジェクト
サーバーtools・resources・prompts を公開するプログラムGitHub、Filesystem、Playwright

つまり Cursor に 3 つのサーバーを接続すると、ホスト 1 つとクライアント 3 つになります。サーバーごとにクライアントを分けるのはセキュリティモデルの一部です。サーバーは会話全体を見ることも、他のサーバーの中を「覗く」こともできず、何がその境界を越えるかはホストが決めます。(サーバー側の説明は MCP サーバーとは? を参照してください。)

MCP クライアントが実際にやっていること

現在の仕様リビジョン 2026-07-28 では、MCP はステートレスです。古いチュートリアルは initialize ハンドシェイクから始まりますが、今のクライアントの仕事はそれとは異なります。モダンなクライアントは次のことを行います:

  1. **すべてのリクエストにメタデータを付ける。**各 JSON-RPC リクエストの _meta には io.modelcontextprotocol/protocolVersion と io.modelcontextprotocol/clientCapabilities(いずれも必須)、通常は io.modelcontextprotocol/clientInfo も含まれます。Streamable HTTP では、同じ値の MCP-Protocol-Version ヘッダーも送ります(仕様)。
  2. 必要に応じてサーバーを探索する。server/discover は、対応バージョン・機能・サーバーの利用指示を 1 回で返します。呼び出しは任意ですが、stdio で相手がハンドシェイク方式の古いサーバーかもしれない場合は、最初にこれで確認することが推奨されています。
  3. プリミティブを一覧・呼び出しする。tools/list・resources/list・prompts/list を送ってツール定義をモデルに渡し、モデルがツールを選んだら tools/call を送ります。
  4. 入力リクエストに応える。サーバーがユーザーからの情報を必要とするとき、サーバー側から独自のリクエストを送ることはもうありません。代わりに InputRequiredResult(resultType: "input_required")を返します。たとえば elicitation のフォームです。クライアントはフォームを表示し、inputResponses を付けて元のリクエストを再送します。このパターンは Multi Round-Trip Requests(MRTR) と呼ばれます。
  5. **変更を購読する。**ツール一覧の変更やリソースの更新を知るために、クライアントは長時間開いたままの subscriptions/listen リクエストを送り、必要な通知の種類を指定して購読します。
  6. **認証を扱う。**リモートの HTTP サーバーに対しては、認可仕様の OAuth フローを実行します。stdio サーバーは代わりに環境変数から認証情報を受け取ります。詳しくは MCP 認証ガイド を参照してください。

Roots・Sampling・Logging は今も動作しますが、2026-07-28 版で非推奨になったため、新しく作るクライアントで実装する必要はありません。

主要な MCP クライアントの比較

下表の各セルは、各ベンダーの現行の公式ドキュメントに基づいています。「記載なし」は公式ドキュメントで見つけられなかったという意味で、機能が存在しないという意味ではありません。

クライアントローカル(stdio)リモートのトランスポートサーバーの設定場所ドキュメント記載のプリミティブ/拡張
Claude Code対応Streamable HTTP(推奨)、SSE(非推奨)claude mcp add、~/.claude.json、プロジェクトの .mcp.jsonTools、resources、prompts、elicitation、list-changed による自動更新、OAuth
Claude Desktop / claude.ai対応(Desktop)リモートサーバーは Custom Connectors として追加claude_desktop_config.json、Settings → ConnectorsTools、resources、prompts
Cursor対応SSE、Streamable HTTP.cursor/mcp.json、~/.cursor/mcp.jsonTools、prompts、resources、roots、elicitation、MCP Apps、OAuth
VS Code(Copilot)対応HTTP、SSEワークスペースの .mcp.json、ユーザーの mcp.jsonTools、resources、prompts、MCP Apps
ChatGPT非対応(トンネルが必要)SSE、streaming HTTPPlugins → Add custom MCP server(Web 版)Tools(読み取り・書き込み)、OAuth
Codex対応Streamable HTTPcodex mcp add、~/.codex/config.tomlTools、OAuth ログイン

ドキュメントからの補足:

  • Claude Code には 3 つのスコープ(local、project、user)があります。探索時に prompts/list と resources/list を要求し、サーバーから list-changed 通知が届くと一覧を更新します(ドキュメント)。設定方法は Claude Code MCP ガイド を参照してください。
  • Claude Desktop はローカルサーバーを claude_desktop_config.json から読み込みます。macOS では ~/Library/Application Support/Claude/、Windows では %APPDATA%\Claude\ にあります。リモートサーバーは Settings → Connectors から Custom Connector として追加します(ドキュメント)。Claude Desktop MCP 設定 を参照してください。
  • Cursor はドキュメントに記載された機能が最も多いクライアントの 1 つで、roots・elicitation・MCP Apps がすべて対応済みとされています(ドキュメント)。Cursor MCP 設定 を参照してください。
  • VS Code は現在、ワークスペースの .mcp.json(キーは mcpServers)を推奨しています。従来の .vscode/mcp.json(キーは servers)は新規サーバーには非推奨です。Prompts は /<server>.<prompt> の形で呼び出します(ドキュメント)。VS Code MCP 設定 を参照してください。
  • ChatGPT はリモートサーバーにのみ接続でき、Web 版の Plugins から追加します(ドキュメント)。ChatGPT MCP 設定 を参照してください。
  • Codex は CLI、IDE 拡張、ChatGPT デスクトップアプリ内の Codex で同じ config.toml を共有します。Codex MCP 設定 を参照してください。

Windsurf、Zed、Cline、Goose などを含む一覧は MCP.so クライアントディレクトリ をご覧ください。

最小限の MCP クライアントを作る

クライアントを自作する必要があるのは、エージェント、チャットボット、テストハーネス、ゲートウェイなど、独自のホストを作る場合だけです。Tier 1 の 2 つの SDK は 2026 年に v2 になり、ステートレスな新リビジョンに対応しています。

TypeScript(@modelcontextprotocol/client v2)

npm install @modelcontextprotocol/client
import {
  Client,
  StreamableHTTPClientTransport,
} from '@modelcontextprotocol/client';

const client = new Client(
  { name: 'my-client', version: '1.0.0' },
  { versionNegotiation: { mode: 'auto' } }
);

await client.connect(
  new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'))
);
console.log(client.getProtocolEra()); // 'modern' or 'legacy'

const { tools } = await client.listTools();
console.log(tools.map((t) => t.name));

const result = await client.callTool({
  name: 'greet',
  arguments: { name: 'Ada' },
});
if (result.isError) {
  console.error('Tool failed:', result.content);
} else {
  console.log(result.content);
}

await client.close();

SDK ドキュメントには見落としやすいポイントが 3 つあります:

  • **versionNegotiation。**指定しないと、connect() は 2025 年の旧来の initialize ハンドシェイクを使います。mode: 'auto' はまず server/discover で確認し、相手が古いサーバーならハンドシェイクにフォールバックします。mode: { pin: '2026-07-28' } はフォールバックしません。
  • **ツールのエラーも通常の結果として返る。**失敗したツールは例外を投げずに isError: true を返すので、content を使う前に必ず確認してください。例外になるのは、未知のツールやタイムアウトといったプロトコルレベルの失敗だけです。
  • **listTools() はすべてのページを辿る。**ページネーションを自動で処理し、上限は listMaxPages(既定値 64)です。

ローカルサーバーを起動したい場合は、トランスポートだけを差し替えます:

import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';

await client.connect(
  new StdioClientTransport({ command: 'node', args: ['server.js'] })
);

elicitation に対応するには、コンストラクタで機能を宣言し(capabilities: { elicitation: { form: {} } })、client.setRequestHandler('elicitation/create', ...) でハンドラーを登録します。MRTR の再送は SDK が処理します。

Python(mcp v2)

uv add "mcp[cli]"
import asyncio

from mcp import Client


async def main() -> None:
    async with Client("http://localhost:8000/mcp") as client:
        tools = await client.list_tools()
        print([t.name for t in tools.tools])

        result = await client.call_tool("add", {"a": 1, "b": 2})
        print(result.structured_content)


asyncio.run(main())

URL を渡すと、Client は Streamable HTTP を使います。ローカルサーバーには stdio トランスポートを渡します:Client(stdio_client(StdioServerParameters(command="python", args=["server.py"])))。これらは mcp と mcp.client.stdio からインポートします(Python SDK)。async with ブロックがライフサイクル全体をカバーし、入るときに接続してプロトコルバージョンを合意し、抜けるときにすべてを終了します。

モデルとつなぐ

実用的なクライアントは、MCP のツール定義を使っている LLM のツール形式に変換します。name・description・inputSchema を対応付け、モデルのツール呼び出しを callTool に渡し、結果を会話に追加します。公式の build-a-client チュートリアルでは、Anthropic SDK を使った一連の流れを紹介しています。実際のサーバーに接続する前に、MCP Inspector でテストしておきましょう。

MCP クライアントの選び方

  • **ターミナルで使うコーディングエージェント:**Claude Code か Codex。どちらもサーバー追加と OAuth ログインのための CLI コマンドがあります。
  • **IDE:**Cursor か VS Code。Cursor はオプション機能(roots、elicitation、Apps)の記載が多く、VS Code はすでに Copilot を使っているチームに向いています。
  • **開発者以外向けのチャット:**claude.ai か ChatGPT で、リモートサーバーのみ対応です。Notion や Sentry のように、ホスト型の HTTPS エンドポイントを提供しているサーバーを選びましょう。
  • **自社プロダクト:**SDK のクライアントを使い、versionNegotiation: 'auto'(または Python v2 の Client)を有効にすれば、新旧どちらのサーバーにも接続できます。あわせて MCP セキュリティのベストプラクティス に従い、特にツール呼び出しをユーザーに見せ、副作用のある操作は実行前に確認を取りましょう。

機能の対応状況はリリースごとに変わります。resources、prompts、elicitation に依存する前に、対象クライアントのドキュメントに記載があるか確認してください。記載がなければ、同じ機能をツールとしても公開しておきましょう。ツールはすべてのクライアントが対応しています。

次のステップ

クライアントが決まったら、接続するサーバーを探しましょう。MCP.so サーバーディレクトリで数千のサーバーを探したり、クライアントディレクトリでアプリを比較したり、まずはおすすめ MCP サーバーの一覧から始めることもできます。

すべてを手元のマシンで動かしたい場合は、ローカルの Ollama モデルで MCP ツールを使う方法をご覧ください。

よくある質問

MCP クライアントとは何ですか?

MCP クライアントは、AI アプリ内部で 1 つの MCP サーバーと 1 対 1 の接続を保持するコネクタです。ホストアプリに代わって tools/list や tools/call などのリクエストを送り、結果をアプリに返します。

MCP ホストと MCP クライアントの違いは何ですか?

ホストは Claude Code、Cursor、VS Code など、ユーザーが直接操作する AI アプリです。ホストは設定されたサーバーごとに MCP クライアントを 1 つ作成し、各クライアントは 1 つのサーバーとだけ通信します。

どのアプリが MCP クライアントですか?

代表的な MCP 対応アプリには Claude Code、Claude Desktop、Cursor、Copilot 付きの VS Code、ChatGPT、Codex があります。トランスポートや機能はそれぞれ異なり、たとえば ChatGPT はリモートサーバーにのみ接続でき、Cursor は roots、elicitation、MCP Apps への対応もドキュメントに記載しています。

自分で MCP クライアントを作るには?

TypeScript の @modelcontextprotocol/client や Python の mcp パッケージなど、公式 SDK を使います。Client を作成して Streamable HTTP か stdio で接続し、listTools と callTool を呼び出してツールを LLM に渡します。