MCP Server を
ゼロから構築
バックエンドエンジニアや Agent プラットフォーム担当者が「AI に社内 API を触らせたい」と言われても、curl スクリプトの寄せ集めしかない——そんな状況にいる方へ向けた実践ガイドです。Python と FastMCP を使い、環境構築から Tools / Resources / Prompts の全実装、Function Calling との比較表、ChromaDB ベクトル知識ベース、Mac 隔離開発 5 ステップまで順を追って解説します。対照表・コピペ可能なコード・よくあるエラー表を含み、本番投入前の判断材料になります。
📋 目次
01 · はじめに:MCP とは何か
2026 年の Agent はコード生成や多段推論が得意ですが、外部ツールなしでは閉じた箱のままです。Git の最新 PR 状態を知らず、SELECT * FROM orders WHERE status='pending' を実行できず、Slack で同僚にメンションも送れません。従来は各モデル Host が独自の Function Calling を実装し、各 SaaS が Claude・GPT・Gemini 向けにアダプタを書く——統合コストが N×M で爆発します。
MCP(Model Context Protocol) は Anthropic が 2024 年 11 月にオープンソース化した規格で、「大規模モデルと外部世界をつなぐ USB-C」と形容されます。規格準拠の Server を 1 つ書けば、Cursor、Claude Desktop、OpenClaw など複数 Host が読み込めます。すでに MCP が AI 時代の HTTP プロトコルになる理由 を読んだ方には、本記事がハンズオン版です。pip install mcp から Docker 本番まで、そのまま手を動かせます。
構成は 三つの開発課題 → JSON-RPC ライフサイクル → 比較表 → Hello World → Tools → Resources → Prompts → HTTP+SSE → ChromaDB → Mac 隔離検収 の順です。
02 · 開発の三つの壁
1. Host ごとに異なるツール方言。 OpenAI の tools 配列、Anthropic の tool_use、Google の Function Declaration——Schema 名やエラー形式がバラバラです。「注文照会」を 3 Host に載せるだけで 3 層のラッパーが必要になります。MCP は JSON-RPC で登録・説明・呼び出しを統一し、Write Once, Run Everywhere を実現します。
2. ローカル資格情報と権限境界の曖昧さ。 MCP Server はファイルシステム、社内 API、OAuth Token に触れます。メイン Mac に十数 Server と複数 IDE を混在させると、本番 Key がテスト cron に紛れ込む事故が起きます。捨てられるサンドボックスで先に検収するのが鉄則です。
3. デバッグチェーンが長い。 Host → Client → STDIO または HTTP のどこか 1 箇所でも設定ミスが「ツールが見えない」「Connection closed」に見えます。Inspector と単体テストなしでは当て推量になりがちです。
03 · アーキテクチャと進化
Function Calling から MCP への三段階
第一段階(2023):Function Calling。 GPT-4 でツール呼び出しが登場。JSON で関数名と引数を返しアプリが実行。Schema が Prompt や SDK に埋め込まれ、Host 横断で再利用不可でした。
第二段階(2024 初):Plugins / Actions。 ChatGPT Plugins 等が HTTP エンドポイントをツール化。門戸は下がったもののHost 私有で、実行時に新 Server を動的発見できません。
第三段階(2024 11 月〜):MCP。 オープン仕様と SDK 公開。Host / Client / Server 分離。10,000+ コミュニティ Server が 18 か月で出現。2026 年には OpenAI・Google・Microsoft が本格追随しています。
Client-Server と三大能力
┌─────────────────────────────────────────────────────────────┐
│ Host(Cursor / Claude Desktop / OpenClaw) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ MCP Client │ │ MCP Client │ │ MCP Client │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼─────────────────┘
│ JSON-RPC │ JSON-RPC │ JSON-RPC
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MCP Server A │ │ MCP Server B │ │ MCP Server C │
│ Tools │ │ Resources │ │ Prompts │
└──────────────┘ └──────────────┘ └──────────────┘
- Tools:モデルが能動的に呼ぶ関数(
read_file、query_database等)。JSON Schema で入力を記述。 - Resources:モデルが受動的に読むコンテキスト(設定、ログ、schema)。URI で識別。
- Prompts:コードレビュー等の多ターン会話テンプレート。Host がワンクリック注入。
JSON-RPC 2.0 とトランスポート
メッセージはすべて JSON-RPC 2.0。initialize、tools/list、tools/call、resources/read、prompts/get などが基本です。
// ライフサイクル:initialize → initialized → 業務 → 終了{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "clientInfo": { "name": "cursor" } } }{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "say_hello", "arguments": { "name": "MacDate" } } }
トランスポートは STDIO(子プロセス、ローカル開発向け)と HTTP + SSE(リモート・マルチテナント)。2026 年仕様では Streamable HTTP が双方向ストリームを簡素化しています。
04 · MCP vs OpenAI FC vs LangChain 対照表
| 観点 | OpenAI FC | LangChain Tools | MCP |
|---|---|---|---|
| 位置づけ | 単一 Host 内蔵 | Python フレーム抽象 | クロス Host オープン規格 |
| 発見 | 静的 Schema | コード内登録 | tools/list 動的 |
| Host 横断 | OpenAI のみ | アダプタ再実装 | 1 実装・多 Host |
| Resources/Prompts | 非対応 | Retriever 等で模倣 | 第一級 |
| トランスポート | API 内蔵 | プロセス内 | STDIO / HTTP+SSE / Streamable HTTP |
| 規模(2026 中) | 私有 | PyPI 数千 | 10,000+ Server |
| 向く場面 | OpenAI 単体 PoC | 自社 Agent 内 | 多 Host・Enterprise Catalog |
数値スナップショット: MCP 統一層を採用したチームは統合コスト 38%–55% 削減を報告。同一 Server を Cursor と Claude Desktop に載せる重複工数は約 70% 減。公網スキャンでは未認証暴露 Server が 1,000+——隔離環境での権限検証が必須です。
05 · 開発環境のセットアップ
Python vs TypeScript
公式 SDK は Python(mcp) と TypeScript(@modelcontextprotocol/sdk)。Python の FastMCP はデコレータが簡潔でデータ系に向きます。本記事は Python 中心ですが、概念は TS にそのまま移植できます。
venv とディレクトリ構成
mkdir my-mcp-server && cd my-mcp-serverpython3 -m venv .venvsource .venv/bin/activatepip install "mcp[cli]" pydantic httpx chromadb
my-mcp-server/├── server.py├── tools/├── resources/├── prompts/├── tests/└── Dockerfile
MCP Inspector と Host 設定
npx @modelcontextprotocol/inspector python server.py
Cursor は ~/.cursor/mcp.json、Claude Desktop は macOS で ~/Library/Application Support/Claude/claude_desktop_config.json に Server を登録します。
06 · Hello World:最初の Server
# server.pyfrom mcp.server.fastmcp import FastMCPmcp = FastMCP("hello-server")@mcp.tool()def say_hello(name: str = "World") -> str: """指定名に挨拶。""" return f"Hello, {name}! MCP Server is running."if __name__ == "__main__": mcp.run()
Inspector で Connect → List Tools → say_hello に {"name": "MacDate"} を渡し、挨拶が返ることを確認してください。
Cursor 設定例
// ~/.cursor/mcp.json{ "mcpServers": { "hello-server": { "command": "/path/to/.venv/bin/python", "args": ["/path/to/server.py"]} } }
07 · Tools:5 種類の実装例
Pydantic による入力検証
from pydantic import BaseModel, Fieldclass CalcInput(BaseModel): expression: str = Field(description="式、例 2+3*4")@mcp.tool()def calculator(input: CalcInput) -> str: import re if not re.match(r'^[\d\s+\-*/().]+$', input.expression): raise ValueError("不正文字") return str(eval(input.expression))
| ツール | 用途 | 実装の要点 |
|---|---|---|
calculator | 安全な四則演算 | 正規表現ホワイトリスト |
read_file | ワークスペース読取 | パス正規化・ルート拘束 |
http_get | HTTP プロキシ | httpx 非同期・タイムアウト |
query_db | 読取専用 SQL | パラメータ化クエリ |
current_time | タイムゾーン時刻 | zoneinfo + ISO 8601 |
@mcp.tool()async def http_get(url: str) -> str: import httpx async with httpx.AsyncClient(timeout=5.0) as c: resp = await c.get(url) return resp.text[:8000]
エラーはモデルが説明できる読みやすい文字列で返すのがベストプラクティスです(パラメータ検証失敗を除く)。
08 · Resources:読み取り専用コンテキスト
Tool は副作用のある能動的操作。Resource は設定や schema など読み取り専用コンテキストです。会話開始時に Host が先読みすると Token を節約できます。
@mcp.resource("config://app/settings")def get_settings() -> str: import json return json.dumps({"env": "production"})@mcp.resource("schema://db/{table_name}")def get_table_schema(table_name: str) -> str: return f"CREATE TABLE {table_name} (...);"
09 · Prompts:再利用テンプレート
Prompts は Host がワンクリックで多ターン構造を注入します。Cursor の Agent Skill が「いつ何を使うか」を orchestrate するのに対し、MCP Prompt は会話の骨格を提供します。
@mcp.prompt()def code_review_prompt(language: str = "Python") -> str: return f"""あなたは {language} のシニアレビュアーです。1. セキュリティ 2. 性能 3. 可読性 4. テスト提案各行に行番号と修正案を付けて日本語で出力。"""
10 · HTTP トランスポートとセキュリティ
| 観点 | STDIO | HTTP+SSE | Streamable HTTP |
|---|---|---|---|
| 配置 | ローカル子プロセス | リモートサーバー | 単一エンドポイント双方向 |
| 共有 | Host ごと独立 | 複数 Client 共有可 | 同左 |
| 認証 | 起動者責任 | Bearer / mTLS / OAuth | 同左 |
| 用途 | デスクトップ Host | 社内 SaaS ゲートウェイ | 新規デプロイ推奨 |
mcp run server.py --transport streamable-http --port 8080
公網公開時は Bearer Token または OAuth 2.1 必須。ドメインホワイトリスト・パスサンドボックス・SQL 読取専用をツール層で実施。監査ログに tools/call 引数を記録してください。
11 · デバッグ・テスト・エラー対処
- Connect:
initialize成功を確認。 - List:Schema が期待通りか検証。
- Call Tool:手動パラメータで応答確認。
- Export Log:JSON-RPC transcript をチーム共有。
- pytest:
tools/callを CI に組み込む。
def test_calculator_basic(): result = calculator(CalcInput(expression="2+3*4")) assert result == "14"
| 症状 | 原因 | 対処 |
|---|---|---|
| ツールが見えない | パス誤り・venv 未使用 | mcp.json 絶対パス・Inspector 先行 |
| Connection closed | 起動クラッシュ | 単体で python server.py |
| タイムアウト | 同期ブロック IO | async + timeout 設定 |
| HTTP 401 | Token 失効 | Authorization ヘッダ確認 |
| Schema 失敗 | Pydantic 不一致 | tools/list の inputSchema 確認 |
12 · 本番デプロイ
FROM python:3.12-slimWORKDIR /appCOPY . .RUN pip install --no-cache-dir .EXPOSE 8080CMD ["mcp", "run", "server.py", "--transport", "streamable-http", "--port", "8080"]
- Railway / Render:MVP・PoC 向け従量課金。
- Cloud Run:SSE 長接続に比較的寛容。
- VPS:mTLS 内網ゲートウェイ向け、監視は自前。
serverInfo.version で SemVer 管理。Prometheus 等で tools/call P99 を記録し、カナリアで新旧 Server を並走させてから切替えます。
13 · 知識ベース実践:ChromaDB
企業 Agent で最も多い MCP 用途はベクトル知識ベースです。内部文書を embedding しモデルが検索します。
import chromadbclient = chromadb.PersistentClient(path="./chroma_data")collection = client.get_or_create_collection("docs")@mcp.tool()def search_knowledge(query: str, top_k: int = 5) -> str: results = collection.query(query_texts=[query], n_results=top_k) return "\n---\n".join(results["documents"][0] or [])
Embedding は OpenAI text-embedding-3-small(1536 次元)またはローカル sentence-transformers。ChromaDB デフォルト all-MiniLM-L6-v2(384 次元)。512 token チャンクが一般的。10 万ページ索引で2–4 GB ディスク・8 GB メモリ目安。本番は Qdrant クラスタ、PoC は ChromaDB 単体が現実的です。
14 · エコシステムと学習ロードマップ
@modelcontextprotocol/server-filesystem— ファイル Resource@modelcontextprotocol/server-postgres— 読取 SQL@modelcontextprotocol/server-slack— Slack 連携@modelcontextprotocol/server-github— Issue / PRmcp-server-fetch— HTTP 取得
2026 トレンド: Streamable HTTP が新デプロイのデフォルト化。OAuth 2.1 デバイスフロー普及。Enterprise Catalog と Server 署名がコンプライアンス標準。MCP と A2A の共存。
- MCP プロトコル解説で三層を理解。
- Hello World → Tools 五種を Inspector 検収。
- Cursor 接続で実業務シナリオを通す。
- ChromaDB Server で検索精度を比較。
- Railway + Bearer 認証で HTTP デプロイ。
- 隔離 Mac で Catalog リハーサル → ADR → 本番。
15 · まとめ:隔離 Mac で慣れてから本番へ
WSL や Linux コンテナでも MCP Server は開発できますが、メイン Mac に OAuth・本番 API Key・複数 Host 設定を混在させると、背景 cron で tools/call が社内 API を叩く事故が起きます。公網には 1,000+ の未認証 Server が存在——本番資格情報を汚す前に、隔離環境でホワイトリスト候補を検証するのが健全なエンジニアリングです。
MCP は Write Once を実現しますが、開発体験も macOS ネイティブが有利です。Cursor / Claude Desktop の設定パス、STDIO 子プロセス、Keychain 資格情報は Apple エコシステムと一体です。監査可能な「多 Server × 多 Host」実測が必要なら、独立 macOS レンタルノードで 1–3 日のリハーサルを経て Enterprise Catalog に進む方が、日常 Mac に Server を積み増すより安全で、裸コンテナより Host 挙動に近いです。
Mac 隔離 MCP 開発 5 ステップ
- 隔離 macOS をレンタル:Mac mini M4 から。SSH 接続。Apple ID / OAuth はメイン機と分離。M シリーズ料金参照。
- 開発環境:Python 3.12、Node(Inspector)、Cursor。独立 venv。
- 複数 Server 並行:Hello World、Tools 五種、ChromaDB。Inspector で tools/list スナップショット。
- Host 連携:STDIO 登録、固定タスクで遅延・越権を記録。
- ADR 出力・解放:Server ホワイトリスト・OAuth スコープを ADR に記録。テスト Key 失効・レンタル終了。