Understanding MCP Architecture: Single-Server vs Multi-Server Clients について
LangGraph と GPT-4o で数学・天気ツールを使う Python のサンプルです。単一サーバーへの接続と、stdio・SSE を介した複数サーバーの並行利用を比較します。
主な機能
- 01加算・乗算ツールを備えた数学サーバー
- 02場所を指定する天気問い合わせ
- 03単一サーバークライアントの例
- 04複数サーバークライアントの例
- 05stdio と SSE のトランスポート
活用シーン
- 01MCP ツールで算術を実行
- 02計算と並行して天気を照会
- 03単一サーバー構成と複数サーバー構成の比較
MCP 対応
Math と Weather の MCP サーバー、および片方または両方に接続するクライアントスクリプトを含みます。stdio と SSE によるツールの読み込みと呼び出しを示します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP アーキテクチャを理解する:シングルサーバーとマルチサーバーのクライアント
現代の AI 駆動型アプリケーションでは、複数の外部サービスと連携するために、効率的でスケーラブルなアーキテクチャが必要です。Multi-Client Protocol(MCP) は、さまざまなツールサーバーと通信するための堅牢なフレームワークを提供し、AI モデルと外部計算処理のシームレスな連携を可能にします。このブログでは、シングルサーバー クライアントと マルチサーバー クライアントを比較し、MCP アーキテクチャの利点を見ていきます。
Math Server (math_server.py)
Math Server は、加算や乗算などの基本的な数学演算を提供する MCP ツールサーバーです。受信したリクエストを待ち受け、ツールの呼び出しを処理し、結果を返します。
コードの内訳
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Math")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""Multiply two numbers"""
return a * b
if __name__ == "__main__":
mcp.run(transport="stdio")
- Math という名前の MCP サーバーを定義します。
add(a, b)とmultiply(a, b)を利用可能なツールとして登録します。- stdio トランスポートで実行し、標準入力/出力を介した通信を可能にします。
シングルサーバークライアント
シングルサーバークライアント は、計算に使用する一連のツールを公開する 1 つの MCP サーバーに接続します。single_server_client.py スクリプトが math_server.py と連携して数学演算を実行する仕組みを見てみましょう。
動作の仕組み
- Math Server を起動する:
math_server.pyは MCP サーバーとして実行され、2 つのツールadd(a, b)とmultiply(a, b)を公開します。 - stdio 接続を初期化する:クライアントはサブプロセスを作成し、stdio トランスポートを介して Math Server と通信します。
- 利用可能なツールを読み込む:クライアントはサーバーから利用可能なツール(
add、multiply)を取得します。 - AI モデルを呼び出す:AI モデルの
GPT-4oは、LangGraph の ReAct(推論+行動)エージェントを使って、与えられた数式の解き方を判断します。 - 計算を実行する:モデルはツール呼び出しを生成し、最初に
add(3,5)、次にmultiply(8,12)を呼び出して、最後に計算結果を返します。
コードの内訳(single_server_client.py)
server_params = StdioServerParameters(
command="python",
args=["server/math_server.py"],
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
agent = create_react_agent(model, tools)
events = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
次のように出力されます:
----------------------------------------------------------------------------
The result is 96
MCP の通信フロー(シーケンス図)
sequenceDiagram
participant Client as Client Script
participant LangGraph as LangGraph React Agent
participant ClientSession as MCP ClientSession
participant stdio as stdio Transport Layer
participant MathServer as Math Server Process
participant Tools as Math Tools (add/multiply)
participant LLM as GPT-4o Model
Note over Client: Starts execution with asyncio.run()
Client->>MathServer: Launch as subprocess with stdio parameters
Client->>stdio: Create stdio client connection
stdio-->>Client: Return read/write streams
Client->>ClientSession: Initialize session
ClientSession->>stdio: Send initialize message
stdio->>MathServer: Forward initialize request
MathServer-->>stdio: Return server capabilities
stdio-->>ClientSession: Return initialization response
ClientSession-->>Client: Session initialized
Client->>ClientSession: load_mcp_tools()
ClientSession->>stdio: Request available tools
stdio->>MathServer: Forward tools request
MathServer->>Tools: Discover registered tools (add, multiply)
Tools-->>MathServer: Return tool descriptions
MathServer-->>stdio: Return tool descriptions
stdio-->>ClientSession: Return tool descriptions
ClientSession-->>Client: Return langchain-compatible tools
Client->>LangGraph: Create React agent with model and tools
LangGraph-->>Client: Return agent instance
Client->>LangGraph: agent.ainvoke("what's (3 + 5) x 12?")
LangGraph->>LLM: Generate reasoning and tool calls
Note over LLM: Decides to use add(3, 5) first
LLM-->>LangGraph: Return reasoning and add(3, 5) tool call
LangGraph->>ClientSession: Call add(3, 5)
ClientSession->>stdio: Send tool execution request
stdio->>MathServer: Forward tool execution request
MathServer->>Tools: Execute add(3, 5)
Tools-->>MathServer: Return result (8)
MathServer-->>stdio: Return tool execution result
stdio-->>ClientSession: Return tool execution result
ClientSession-->>LangGraph: Return add result (8)
LangGraph->>LLM: Generate next reasoning step with add result
Note over LLM: Decides to use multiply(8, 12) next
LLM-->>LangGraph: Return reasoning and multiply(8, 12) tool call
LangGraph->>ClientSession: Call multiply(8, 12)
ClientSession->>stdio: Send tool execution request
stdio->>MathServer: Forward tool execution request
MathServer->>Tools: Execute multiply(8, 12)
Tools-->>MathServer: Return result (96)
MathServer-->>stdio: Return tool execution result
stdio-->>ClientSession: Return tool execution result
ClientSession-->>LangGraph: Return multiply result (96)
LangGraph->>LLM: Generate final answer with all results
LLM-->>LangGraph: Return final answer "The result is 96"
LangGraph-->>Client: Return complete event trace and answer
Client->>Client: Print final answer
Weather Server (weather_server.py)
Weather Server は、リアルタイムの天気情報を提供するもう 1 つの MCP ツールサーバーです。天気に関するクエリを待ち受け、最新の天気データを返します。
サーバーを起動するコマンド:
python server/weather_server.py
コードの内訳
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Weather")
@mcp.tool()
async def get_weather(location: str) -> str:
"""Get weather for location."""
return "It's always sunny in New York"
if __name__ == "__main__":
mcp.run(transport="sse")
- Weather という名前の MCP サーバーを定義します。
get_weather(location)を利用可能なツールとして登録します。- SSE(Server-Sent Events) トランスポートで実行し、リアルタイムのイベントストリーミングを可能にします。
マルチサーバークライアント
マルチサーバークライアント は、複数の MCP サーバーと同時にやり取りできます。multi_server_client.py スクリプトでは、math_server.py と weather_server.py の両方と通信することで、その仕組みを示します。
動作の仕組み
- 複数のサーバーを初期化する:クライアントは
stdioを使って Math サーバーに接続し、SSE(Server-Sent Events) を介して Weather サーバーに接続します。 - 複数のサーバーからツールを読み込む:AI モデルは両方のサーバーのツールを利用できるようになります。
- 並列処理:クライアントは、1 回の実行内で異なるサーバーのツールを呼び出せるようになります。
- AI 駆動型の応答:モデルは複数の MCP サーバーを使って、数式と天気に関するクエリの両方を処理します。
コードの内訳(multi_server_client.py)
async with MultiServerMCPClient(
{
"math": {
"command": "python",
"args": ["server/math_server.py"],
"transport": "stdio",
},
"weather": {
"url": "http://localhost:8000/sse",
"transport": "sse",
},
}
) as client:
agent = create_react_agent(model, client.get_tools())
math_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
weather_response = await agent.ainvoke({"messages": "what is the weather in nyc?"})
マルチサーバークライアントの応答
マルチサーバークライアントの出力は次のようになります:
{
"math_response": "The result of (3 + 5) x 12 is 96.",
"weather_response": "The weather in NYC is currently sunny."
}
MCP アーキテクチャの利点
- スケーラビリティ:複数のサービスに簡単に拡張できます。
- 並列実行:異なるサーバーへのクエリを同時に実行できます。
- 柔軟な通信:複数のトランスポートレイヤー(
stdio、sseなど)をサポートします。 - AI との統合:AI モデルと外部計算サービスをシームレスに接続します。
コードのセットアップと実行
コードをクローンして実行するには、次の手順に従ってください:
git clone https://github.com/commitbyrajat/langgraph-mcp-integration.git
cd langgraph-mcp-integration
rye sync # Sync dependencies
rye run python server/weather_server.py &
rye run python client/single_server_client.py
rye run python client/multi_server_client.py
MCP アーキテクチャを活用すると、開発者は複数のサービスと効率的に連携する強力な AI 駆動型アプリケーションを構築できます。🚀
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。