開発実践 2026-06-16

MCP Server を
ゼロから構築

バックエンドエンジニアや Agent プラットフォーム担当者が「AI に社内 API を触らせたい」と言われても、curl スクリプトの寄せ集めしかない——そんな状況にいる方へ向けた実践ガイドです。Python と FastMCP を使い、環境構築から Tools / Resources / Prompts の全実装Function Calling との比較表ChromaDB ベクトル知識ベースMac 隔離開発 5 ステップまで順を追って解説します。対照表・コピペ可能なコード・よくあるエラー表を含み、本番投入前の判断材料になります。

2026 FastMCP で MCP Server をゼロから構築するアーキテクチャと AI ツール呼び出しの実践図

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 → PromptsHTTP+SSEChromaDBMac 隔離検収 の順です。

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_filequery_database 等)。JSON Schema で入力を記述。
  • Resources:モデルが受動的に読むコンテキスト(設定、ログ、schema)。URI で識別。
  • Prompts:コードレビュー等の多ターン会話テンプレート。Host がワンクリック注入。

JSON-RPC 2.0 とトランスポート

メッセージはすべて JSON-RPC 2.0initializetools/listtools/callresources/readprompts/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 FCLangChain ToolsMCP
位置づけ単一 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-server
python3 -m venv .venv
source .venv/bin/activate
pip 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.jsonClaude Desktop は macOS で ~/Library/Application Support/Claude/claude_desktop_config.json に Server を登録します。

06 · Hello World:最初の Server

# server.py
from mcp.server.fastmcp import FastMCP

mcp = 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 で ConnectList Toolssay_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, Field

class 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_getHTTP プロキシ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 トランスポートとセキュリティ

観点STDIOHTTP+SSEStreamable 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 · デバッグ・テスト・エラー対処

  1. Connectinitialize 成功を確認。
  2. List:Schema が期待通りか検証。
  3. Call Tool:手動パラメータで応答確認。
  4. Export Log:JSON-RPC transcript をチーム共有。
  5. pytesttools/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
タイムアウト同期ブロック IOasync + timeout 設定
HTTP 401Token 失効Authorization ヘッダ確認
Schema 失敗Pydantic 不一致tools/list の inputSchema 確認

12 · 本番デプロイ

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir .
EXPOSE 8080
CMD ["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 chromadb
client = 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 / PR
  • mcp-server-fetch — HTTP 取得

2026 トレンド: Streamable HTTP が新デプロイのデフォルト化。OAuth 2.1 デバイスフロー普及。Enterprise Catalog と Server 署名がコンプライアンス標準。MCP と A2A の共存。

  1. MCP プロトコル解説で三層を理解。
  2. Hello World → Tools 五種を Inspector 検収。
  3. Cursor 接続で実業務シナリオを通す。
  4. ChromaDB Server で検索精度を比較。
  5. Railway + Bearer 認証で HTTP デプロイ。
  6. 隔離 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 ステップ

  1. 隔離 macOS をレンタル:Mac mini M4 から。SSH 接続。Apple ID / OAuth はメイン機と分離。M シリーズ料金参照。
  2. 開発環境:Python 3.12、Node(Inspector)、Cursor。独立 venv。
  3. 複数 Server 並行:Hello World、Tools 五種、ChromaDB。Inspector で tools/list スナップショット。
  4. Host 連携:STDIO 登録、固定タスクで遅延・越権を記録。
  5. ADR 出力・解放:Server ホワイトリスト・OAuth スコープを ADR に記録。テスト Key 失効・レンタル終了。