Skip to main content
Glama
mcp-demo-server

mcp-demo-server

by mhamzanadeem

MCP Demo — Python エージェントツールをゼロから


MCP とは?

MCP (Model Context Protocol) は、AI アプリケーションが外部の ツール、リソース、プロンプト を一貫したインターフェースを通じて発見・利用できるようにする標準化されたプロトコルです。

すべての AI フレームワークがデータベース、API、ファイルシステム、内部サービスごとに異なる統合を考案する代わりに、MCP ホストは MCP サーバーに接続し、同じプロトコルサーフェスを使用できます。

MCP が解決する問題

問題

MCP による解決策

ベンダーロックイン

統合は、単一のモデルプロバイダーやエージェントフレームワークに縛られるのではなく、MCP を通じて機能を公開します

一貫性のないツール呼び出し

ツールは機械可読なスキーマと標準化された発見・呼び出しセマンティクスを持ちます

コンテキストの永続化がない

MCP はコンテキスト/ツールプロバイダーをモデルから分離し、長期間の接続を可能にします

動的データソース

データベース、API、ファイル、内部システムを、実装をモデルランタイムに埋め込むことなく MCP リソース/ツールとしてラップします

ワイヤ上では、MCP は stdio や HTTP ベースのトランスポート (SSE/Streamable HTTP) などのトランスポートを介して JSON-RPC 2.0 メッセージ を使用します。このリポジトリは stdio を使用します。クライアントはサーバーをサブプロセスとして起動し、stdin を通じてプロトコルメッセージを送信し、stdout を通じて応答を受信します。


Related MCP server: Weather MCP Server

アーキテクチャ

flowchart TD
    A[User: "What's the weather in London?"] --> B[AI Agent<br/>OpenAI Responses API]
    B --> C[1. Discovers MCP tools]
    B --> D[2. Decides whether to call]
    B --> E[3. Emits function call]
    E --> F[MCP Client<br/>ClientSession + stdio]
    F --> G[initialize]
    F --> H[tools/list]
    F --> I[tools/call]
    I --> J[JSON-RPC 2.0<br/>stdin/stdout]
    J --> K[MCP Server subprocess]
    K --> L[get_current_weather tool]
    K --> M[greeting://{name} resource]

公式 SDK を使う理由

このリポジトリは、プロトコルを再実装する代わりに公式 Python MCP SDK を使用しています。SDK は以下を提供します。

  • プロトコルのライフサイクルと検証

  • トランスポート抽象化 (stdio、HTTP/SSE)

  • 型付きクライアント/サーバー API

アプリケーションコードは、サーバー登録、ツールスキーマ、initialize、tools/list、tools/call、リソース読み取り、stdio プロセス管理など、重要な MCP の概念を明示的にしています。

現在の SDK の安定版 v2 API は、サーバー構築に MCPServer を、stdio クライアントに ClientSession/stdio_client を使用します。


プロジェクト構成

mcp-demo/
├── README.md
├── requirements.txt
├── .env.example
├── pyproject.toml
├── src/
│   ├── mcp_server/
│   │   ├── __init__.py
│   │   ├── server.py      # MCP server entry point
│   │   ├── tools.py       # Tool implementations
│   │   ├── handlers.py    # Request handlers
│   │   └── utils.py       # Shared utilities
│   ├── mcp_client/
│   │   ├── __init__.py
│   │   ├── client.py      # MCP client wrapper
│   │   ├── agent.py       # OpenAI agent integration
│   │   └── runner.py      # Demo runner
│   └── shared/
│       ├── __init__.py
│       └── types.py       # Shared Pydantic models
├── tests/
│   ├── test_server.py
│   └── test_client.py
├── examples/
│   └── demo.ipynb
└── scripts/
    └── run_demo.sh

必要条件

  • Python 3.10+

  • OpenAI API キー (AI エージェントデモ用)

  • 天気 API キーは不要 — 天気ツールは決定論的なサンプルデータを使用するため、MCP パスはオフラインで動作します


クイックスタート

1. 仮想環境を作成

python -m venv .venv
source .venv/bin/activate        # Linux/macOS
.venv\Scripts\Activate.ps1       # Windows PowerShell

2. 依存関係をインストール

python -m pip install --upgrade pip
pip install -r requirements.txt

3. OpenAI を設定

cp .env.example .env

.env をあなたの認証情報で編集してください:

OPENAI_API_KEY=your_api_key_here
OPENAI_MODEL=gpt-4.1-mini

サーバー自体は OpenAI キーを 必要としません。


デモを実行

リポジトリルートから

python src/mcp_client/runner.py

ランナーが行うこと:

ステップ

説明

1️⃣

src/mcp_server/server.py を子プロセスとして起動

2️⃣

MCP 初期化ハンドシェイクを実行

3️⃣

tools/list を呼び出し

4️⃣

発見した MCP スキーマを OpenAI 関数ツールに変換

5️⃣

モデルに自然言語の質問への回答を依頼

6️⃣

モデルが get_current_weather を選択した場合、MCP 経由で tools/call を送信

7️⃣

MCP の結果をモデルに返送

8️⃣

最終回答を出力

9️⃣

サーバーをクリーンにシャットダウン

代替: シェルラッパー

bash scripts/run_demo.sh

期待される出力

正確な文言はモデルによって異なりますが、ログの流れは次のようになります:

INFO mcp_client.client: -> MCP initialize
INFO mcp_client.client: <- MCP initialize: server=mcp-demo-server
INFO mcp_client.client: -> MCP tools/list
INFO mcp_client.client: <- MCP tools/list: ["get_current_weather"]
INFO mcp_client.agent: User: What's the weather in London?
INFO mcp_client.agent: OpenAI requested tool: get_current_weather {"city":"London","units":"metric"}
INFO mcp_client.client: -> MCP tools/call name=get_current_weather arguments={"city":"London","units":"metric"}
INFO mcp_server.tools: weather lookup city=London units=metric
INFO mcp_client.client: <- MCP tools/call result={"city":"London","temperature":18.0,...}
INFO mcp_client.agent: Final: London is 18°C and partly cloudy.

ログは、アプリケーション境界で MCP セマンティックメッセージを意図的に表示します。SDK は JSON-RPC フレーミングを内部的に処理します。


MCP サーバーを単独で実行

python src/mcp_server/server.py

stdio MCP サーバーは「ハング」しているように見えますが、これは 想定どおり です。stdin でプロトコルメッセージを待機します。ホスト/クライアントがそれを起動し、stdio パイプを所有する必要があります。

対話型プロトコル検査

pip install "mcp[cli]"
mcp dev src/mcp_server/server.py

実演される MCP メソッド

公式 SDK は JSON-RPC ライフサイクルを処理します:

メソッド

方向

目的

initialize

Client → Server

ハンドシェイクと機能ネゴシエーション

tools/list

Client → Server

利用可能なツールを発見

tools/call

Client → Server

ツールを呼び出し

resources/list

Client → Server

利用可能なリソースを発見

resources/read

Client → Server

リソースを読み取り

クライアントは、機能を一覧表示または呼び出す前に明示的に initialize() を呼び出します。サーバーのデコレータは、Python 型アノテーションからツール/リソーススキーマを生成します。


ツール: get_current_weather

get_current_weather(
    city: str,
    units: Literal["metric", "imperial"] = "metric"
) -> WeatherResponse

構造化された Pydantic ベースのペイロードを返します:

{
  "city": "London",
  "temperature": 18.0,
  "units": "metric",
  "condition": "partly cloudy",
  "humidity_percent": 72
}

不明な都市は、サーバーをクラッシュさせるのではなく、制御された MCP ツールエラーで失敗します。


エージェント統合フロー

エージェントは、デモをシンプルに保つために プレーンな OpenAI 関数呼び出し (追加フレームワークなし) を使用します:

flowchart LR
    A[MCP Tool Schema] --> B[OpenAI Function Tool]
    B --> C[Model Chooses Function]
    C --> D[MCP ClientSession.call_tool]
    D --> E[MCP Server Executes Tool]
    E --> F[Function Call Output]
    F --> G[Final Model Answer]

これはエージェントフレームワークがラップするのと同じパターンです: MCP ツールを発見 → モデルにスキーマを公開 → 選択した呼び出しを MCP 経由でルーティング → 結果を次のモデルターンにフィードします。


テスト

pytest -q

テストスイートの対象:

  • ✅ ツール実行 (メートル法の天気)

  • ✅ ツール実行 (ヤード・ポンド法の天気)

  • ✅ 検証/エラー動作 (不明な都市)

  • ✅ プロセス内 MCP クライアントの発見とツール呼び出し

テストは可能な限り SDK のインメモリクライアントを使用します。実際の MCP プロトコルレイヤーを実行しながら、サブプロセスの不安定さを回避します。


フォーマットとリンティング

このプロジェクトは Ruff を使用しています:

# Check
ruff check .
ruff format --check .

# Format
ruff format .

本番環境に関する注意点

このデモは意図的に小規模ですが、いくつかの本番環境の懸念事項を表しています:

懸念事項

実装

stdout の規律

サーバーはアプリログを stdout に出力しません (MCP に属します)。ログは logging を介して stderr に送られます。

型付き I/O

Pydantic モデルはアプリケーション境界でツールの入力/出力を検証します。

制御された障害

ツール例外はプロセスクラッシュではなく MCP エラー結果 (SDK) になります。

サブプロセスのライフサイクル

SDK の stdio コンテキストマネージャーがプロセスの起動/シャットダウンを管理します。

最小権限の環境

MCP stdio クライアントは、子プロセスに必要な環境変数を明示的に渡します。

動的発見

エージェントは天気ツールスキーマをハードコードせず、tools/list で発見します。

実際の外部データソースの場合: 決定論的な天気を認証付き API/データベース呼び出しに置き換え、タイムアウト、リトライ、レート制限、可観測性、シークレット管理を追加してください。


プロトコルのメンタルモデル

簡略化された JSON-RPC シーケンス:

// Client -> Server
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}

// Server -> Client
{"jsonrpc":"2.0","id":1,"result":{...}}

// Client -> Server
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

// Server -> Client
{"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}

// Client -> Server
{"jsonrpc":"2.0","id":3,"method":"tools/call",
 "params":{"name":"get_current_weather","arguments":{"city":"London"}}}

// Server -> Client
{"jsonrpc":"2.0","id":3,"result":{"content":[...],"structuredContent":{...}}}

正確なプロトコルスキーマは MCP 仕様 と SDK によって管理されています。上記は教育用に意図的に簡略化されています。


参考


Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables AI agents to retrieve real-time weather conditions and forecasts via OpenWeatherMap API. Supports interactive weather queries and travel planning through MCP tools, resources, and prompts.
    2
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides weather data from OpenWeatherMap API through MCP tools and a REST API with OpenAPI support. Enables LLM agents to retrieve current weather, forecasts, and temperature ranges by city or coordinates.
    4 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Wraps the OpenWeatherMap API to provide weather data through MCP, enabling AI agents to query current conditions, forecasts, and other weather information via natural language.
    452 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides weather data from WeatherAPI.com through MCP, enabling AI agents to query current conditions and forecasts via natural language.
    195 npm
    MIT