(2025/04/27 追記) この記事のupdate版がこちらです
シェルで一連のJSONを送るよりも、MCPサーバを起動して標準入力で送る方が実行できるリクエストが多いです(特にtools/call
)
(追記終わり)
はじめに
七尾百合子さん、お誕生日 17日目 おめでとうございます! nikkieです。
久しぶりのMCPの話題です。
目次
MCPサーバは一体何をやっている?
Quickstartに沿ってお天気のMCPサーバを作りました。
作る中で試しに、MCPサーバのスクリプトをPython処理系で実行してみたのですが、何も起こりません。
% uv run weather.py # Ctrl+C連打で抜けます
しかしMCPクライアントにMCPサーバのスクリプトを渡すと動きます。
% uv run client.py ../weather/weather.py
一体何をやっているのでしょうか? 私、気になります!
結論:stdio transportを覗き見
この記事の結論です。
% echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"bash-client","version":"1.0.0"}}}' | uv run weather.py {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"weather","version":"1.3.0"}}}
% uv run weather.py <<EOF {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"bash-client","version":"1.0.0"}}} {"jsonrpc":"2.0","method":"notifications/initialized","params":{}} {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} EOF [04/03/25 22:24:05] INFO Processing request of type server.py:534 ListToolsRequest {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"get_alerts","description":"Get weather alerts for a US state.\n\n Args:\n state: Two-letter US state code (e.g. CA, NY)\n ","inputSchema":{"properties":{"state":{"title":"State","type":"string"}},"required":["state"],"title":"get_alertsArguments","type":"object"}},{"name":"get_forecasts","description":"Get weather forecasts for a location.\n\n Args:\n latitude: Latitude of the location\n longitude: Longitude of the location\n ","inputSchema":{"properties":{"latitude":{"title":"Latitude","type":"number"},"longitude":{"title":"Longitude","type":"number"}},"required":["latitude","longitude"],"title":"get_forecastsArguments","type":"object"}}]}}
お天気MCPサーバのtool一覧が取得できました!
今の理解:MCPサーバにはクライアントからJSONが送られる
MCPのpython-sdkをClaude Codeにチャットしながら少し読みました。
https://modelcontextprotocol.io/llms-full.txt もFetchさせた上で
このリポジトリにはstdio transportのMCP serverの実装があります。JSON RPCを使うようですが、toolの一覧を取得するためにサーバ・クライアント間でどのような通信が行われているか示してください
パイプラインでクライアントからサーバの呼び出しはbashのコマンドで再現できるのでしょうか?できる場合は例を示してください
全文はこちらに控えました
https://gist.github.com/ftnext/fdefed4500e3eddf08ccc4e9f44111a2
Claude Codeでのセッションと上記覗き見を元に、ドキュメントを見ていきます。
MCPではクライアントとサーバのtransportには2つあります。
https://modelcontextprotocol.io/docs/concepts/architecture#transport-layer
- Stdio transport
- HTTP with SSE transport
All transports use JSON-RPC 2.0 to exchange messages.
JSON-RPCを使っているとのこと。
だからMCPサーバにJSONを送るわけですね!
stdio transportの仕様1を見ていくと
https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio
体験したものが言語化されているように思われます。
また、なぜ3つのJSONを順番に送ったかの説明がライフサイクルにありました
- initialize
- notifications/initialized
- tools/list
ここを読み込んでいけば、JSONを送ってtoolを呼び出すこともできそうです!
終わりに
MCPサーバを実装したPythonスクリプトを処理系で実行しても何も起こらなかったために、クライアントとMCPはどのような通信をしているかが気になりました。
Claude Codeを使ってMCP Python SDKのソースコードを読み、一連のJSONを送ってサーバからリストの一覧を取得できました。
MCPサーバはPythonに限らず、TypeScriptやDockerイメージでの提供とバリエーション豊富ですが、stdio transportはこの記事で見たのと共通ととらえています。
stdio transportを理解する一歩目は踏み出せました!
- 執筆時点で最新の仕様は2025-03-26ですが、素振りは1つ前の2024-11-05だったので、素振りと同じバージョンを見ています↩