この回のゴール
- 公式
mcpPython SDK で MCP サーバーを書けるようになる - FastMCP デコレータでツール/リソース/プロンプトを登録できる
- サーバーを subprocess で実際に起動 して JSON-RPC 対話する
- 次回(Claude Desktop 連携)のための 動くサーバー を用意する
1. 使うライブラリ
pip install mcp # 公式 Python SDK
公式 SDK のクラス:
- FastMCP — サーバーの簡易定義(推奨)
- mcp.client.stdio.stdio_client — stdio 経由でサーバーに繋ぐクライアント
- mcp.ClientSession — クライアントの会話管理
2. 最小 MCP サーバーの全コード
server.py にこれだけ書けばサーバー 1 つが完成します:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("demo-server")
@mcp.tool()
def calculator(expression: str) -> str:
"""数式を評価して結果を返す電卓ツール。
Args:
expression: Python で評価可能な数式。例: '2 * (3 + 4)'
"""
import re
if not re.match(r"^[\d\s\+\-\*\/\(\)\.\%]+$", expression):
return f"Error: 不正な式 {expression!r}"
try:
return str(eval(expression, {"__builtins__": {}}, {}))
except Exception as e:
return f"Error: {e}"
@mcp.tool()
def echo(message: str) -> str:
"""受け取ったメッセージをそのまま返すデバッグ用ツール。"""
return f"echo: {message}"
if __name__ == "__main__":
mcp.run() # stdio transport で起動
ポイント
FastMCP("名前")でサーバーのインスタンスを作成@mcp.tool()デコレータで関数をツールとして 自動登録- 関数の docstring が
descriptionに、型ヒント がinput_schemaになる mcp.run()で stdio transport で起動(デフォルト)
これで Claude API で書いていた TOOL_DEFINITION = {...} が 不要 になります。
3. リソースとプロンプトも登録できる
@mcp.resource("handbook://chapter/{chapter_num}")
def read_chapter(chapter_num: int) -> str:
"""指定章のハンドブック本文を返す。"""
return HANDBOOK_CHAPTERS[chapter_num]
@mcp.prompt()
def review_prompt(code: str) -> str:
"""コードレビュー用のプロンプトテンプレート。"""
return f"以下のコードをレビューしてください:\n\n```\n{code}\n```"
- Resource: ファイル/DB 等の 参照データ (URI でアドレス可能)
- Prompt: 再利用可能なプロンプトテンプレ
4. サーバーの起動方法
方法 A: 直接コマンドライン
python server.py
# → stdio 経由で待機開始
方法 B: mcp CLI
mcp dev server.py # 開発モード、ブラウザ UI で inspector
方法 C: Claude Desktop から自動起動
次回 (s4) で扱う。claude_desktop_config.json にパスを書くと Claude が subprocess として自動起動する。
5. 動作確認の 2 通り
(a) mcp-inspector (CLI/GUI)
npx @modelcontextprotocol/inspector python server.py
ブラウザで ツール一覧を確認・実行 できる公式 GUI。開発時の定番。
(b) 自作クライアント
Python のクライアント SDK でサーバーに繋ぎ、JSON-RPC 往復を可視化 できます:
from mcp.client.stdio import stdio_client, StdioServerParameters
from mcp import ClientSession
async def main():
params = StdioServerParameters(command="python", args=["server.py"])
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
result = await session.call_tool("calculator", {"expression": "2+3"})
print(result.content[0].text) # "5"
6. 第 6 章のツールを MCP 化する
第 6 章の calculator や search_handbook を MCP サーバーに移植すれば、同じロジック が:
- Claude API から使える(今まで通り)
- Claude Desktop から使える(次回)
- 他の MCP 対応 LLM (GPT-4 等) から使える
- 他の開発者が自分のエージェントから使える
一度書けば、あらゆる所で使える。これが MCP の威力。
7. デバッグのコツ
ログ確認
import logging
logging.basicConfig(level=logging.DEBUG)
手動テスト
# stdio で手動操作(テスト用)
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}' | python server.py
よくあるハマリポイント
| 症状 | 原因 | 対策 |
|---|---|---|
| サーバー起動しない | 依存関係不足 | pip install mcp |
| ツールが見えない | @mcp.tool() 忘れ |
デコレータ必須 |
| 引数エラー | 型ヒント不足 | 明示的な型を付ける |
| Claude Desktop で読まれない | 設定ミス | config.json のパス確認 |
まとめ
- 公式
mcpPython SDK + FastMCP で 30 行 の MCP サーバーが作れる @mcp.tool()のデコレータ + docstring + 型ヒントで自動的にツール登録される- 3 プリミティブ: Tools / Resources / Prompts いずれもデコレータで宣言
- 検証は mcp-inspector(公式 GUI) か 自作クライアント で
この回の限界(次への動機)
サーバーは動いた。次は Claude Desktop に登録して、Claude の純正 UI からこのツールを呼ばせる。 👉 次回「Claude Desktop と繋ぐ」で、本シリーズの集大成として「第 5 章 RAG を MCP 化して Claude が自動検索する」を実現します。