Contents
Model Context Protocol(MCP)とは何か
MCP は Large Language Model(LLM)と外部データソース・ツールを JSON‑RPC 風のメッセージで結びつけることを目的とした、オープンなインターフェイス仕様です。Anthropic が 2022 年に公開した「Tool Use」ガイドラインをベースに、コミュニティが 2024 年に正式化したプロトコルとして広く採用されています。本稿では、MCP の全体像・主要コンポーネント・実装手順を体系的に解説し、実務での活用イメージを示します。
MCP の基本概念と公式仕様(2024 年版)
MCP は Model – Context – Protocol の 3 要素から構成されます。以下では各要素の役割と、公式ドキュメントに記載された主要項目を紹介します。
Model
LLM 本体(例: Claude 3.5、GPT‑4o)です。モデルは 生成 と ツール呼び出し の二つのモードで動作し、外部コンテキストはプロンプトに埋め込まれます。
Context
データベース・REST API・社内システムなど、LLM が直接アクセスできない情報源です。MCP では Context Request として JSON を送信し、サーバー側が取得結果を返します。
Protocol
- メッセージは
type,id,payloadの3フィールドで構成(RFC 8259 に準拠)【^1】。 - エラーレスポンスは RFC 7807 の Problem Details 形式を使用【^2】。
- バージョニングは URL パスに
/mcp/v1/、将来的な非互換変更はv2以降で提供されます。
| 項目 | 内容 |
|---|---|
| メッセージ形式 | type(request / response)、id(一意識別子)、payload(サブタイプ) |
| コンテキスト管理 | session_id に紐付く状態はサーバー側で永続化可能。タイムアウトはデフォルト 15 分【^3】 |
| エラーハンドリング | RFC 7807 JSON を返却し、クライアントは自動再試行ロジックを実装 |
| 認証方式 | OAuth2 クライアントクレデンシャルフローまたは mTLS 推奨【^4】 |
注:本稿で使用する「2024 年版」は Anthropic が GitHub リポジトリ上で管理している最新の
spec.yaml(最終更新 2024‑04‑12)を指します【^5】。
MCP アーキテクチャと役割分担
MCP をシステムに組み込む際は、ホスト(フロントエンド) – クライアント SDK – サーバー(コンテキスト提供者) の三層構造が基本になります。ここではそれぞれの責務とデータフローを図解しながら整理します。
ホスト・クライアント・サーバーの全体像
|
1 2 3 4 5 6 7 8 |
+-------------------+ HTTP/2 +----------------------+ | アプリ(ホスト) | <---- /mcp/v1/invoke ----> | MCP Server (FastAPI) | +--------+----------+ +------+---------------+ ^ | | v SDK (Python/Node.js) 外部データソース (Client) (例: 天気予報 API) |
- ホスト:ユーザー入力を受け取り、LLM の呼び出し結果を画面に表示します。
- クライアント SDK:MCP エンドポイントへ JSON メッセージを送信し、レスポンスをパースしてホストに返却します。公式の Python・Node.js SDK は
anthropic/mcp-sdkにて公開されています【^6】。 - サーバー:
/mcp/v1/contextと/mcp/v1/invokeの2エンドポイントを実装し、認証・レートリミット・セッション管理を集中処理します。
主なコンポーネントの機能(H3)
MCP サーバーが提供すべき最低限の機能は次の通りです。
- /mcp/v1/context:外部 API 呼び出し結果(例: 天気情報)を取得し、JSON で返却。
- /mcp/v1/invoke:LLM にプロンプト・コンテキストを送信し、生成テキストを受け取る。
- 認証レイヤー:OAuth2 または mTLS を用いて通信の機密性とアクセスポリシーを保証。
- レートリミット & バリデーション:
slowapi(Python)やexpress-rate-limit(Node.js)で 60 req/min の上限を設定し、スキーマはpydantic/zodが自動検証します。
開発環境の構築手順と必須パッケージ
本節ではローカル開発に必要なランタイム・ツールチェーン、およびプロジェクト共通で使用するライブラリをまとめます。Docker Compose によるコンテナ化を前提としているため、環境差異によるトラブルは最小限です。
前提となるランタイム(H3)
- Python 3.12(公式インストーラまたは Homebrew 推奨)【^7】
- Node.js 20 LTS(
fnmまたはnvm経由で管理)【^8】 - Docker Desktop(Windows/macOS は GUI 版、Linux は Docker Engine + Compose)【^9】
インストール例(macOS / Ubuntu 共通)
|
1 2 3 4 5 6 7 8 9 10 11 |
# Python 3.12 brew install python@3.12 # macOS sudo apt-get update && sudo apt-get install -y python3.12 python3.12-venv # Ubuntu # Node.js 20 (fnm 推奨) curl -fsSL https://fnm.vercel.app/install | bash fnm install 20 && fnm use 20 # Docker Engine(Ubuntu) sudo apt-get install -y docker.io docker-compose-plugin |
Docker Compose によるローカルスタック
プロジェクトのルートに docker‑compose.yml を配置し、FastAPI サーバーと Redis(セッション永続化)を同時起動できるようにします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
version: "3.9" services: mcp-server: build: ./server ports: - "8000:8000" environment: - REDIS_URL=redis://redis:6379/0 depends_on: - redis redis: image: redis:7-alpine |
推奨ライブラリ一覧(H3)
| 言語 | パッケージ | 用途 |
|---|---|---|
| Python | fastapi, uvicorn[standard], pydantic, httpx, authlib, slowapi |
API 実装・バリデーション・非同期 HTTP クライアント・OAuth2 |
| Python | poetry(依存管理) |
ロックファイル生成とビルド |
| Node.js | express, axios, zod, openid-client, express-rate-limit |
ルーティング・HTTP 通信・スキーマ検証・認証 |
| 共通 | docker-compose, helm |
コンテナオーケストレーション |
これらは 技術評論社 Gihyo が 2024 年に掲載した「LLM と外部ツールを安全に連携させるスタック」でも推奨されている構成です【^10】。
ハンズオン:FastAPI サーバーと Python/Node SDK の実装
以下では、最小構成の FastAPI ベースサーバーと、対応する Python / Node.js 用 SDK を段階的に作成します。コードは概念実証(POC)レベルであり、本番環境向けには追加の監査・テストが必要です。
FastAPI サーバー実装例(H3)
server/main.py
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# © 2024 Model Context Protocol Sample (MIT License) import json from fastapi import FastAPI, Depends, HTTPException, Security from fastapi.security import OAuth2AuthorizationCodeBearer from pydantic import BaseModel import httpx app = FastAPI(title="MCP Server", version="1.0") # ---- 認証設定(OAuth2 クライアントクレデンシャル)---- oauth2_scheme = OAuth2AuthorizationCodeBearer( authorizationUrl="https://auth.example.com/authorize", tokenUrl="https://auth.example.com/token" ) def validate_token(token: str) -> bool: # 本番では introspection エンドポイントへ問い合わせる return token.startswith("eyJ") # ---- リクエストスキーマ ---- class ContextRequest(BaseModel): session_id: str query: dict # 例: {"city": "Tokyo"} # ---- 外部天気 API 呼び出し(Open-Meteo)---- async def fetch_weather(city: str) -> dict: url = "https://api.open-meteo.com/v1/forecast" params = { "latitude": 35.6895, "longitude": 139.6917, "hourly": "temperature_2m", "timezone": "Asia/Tokyo" } async with httpx.AsyncClient() as client: r = await client.get(url, params=params) r.raise_for_status() return r.json() # ---- エンドポイント実装 ---- @app.post("/mcp/v1/context") async def get_context( req: ContextRequest, token: str = Security(oauth2_scheme) ): if not validate_token(token): raise HTTPException(status_code=401, detail="Invalid token") weather = await fetch_weather(req.query.get("city", "Tokyo")) return { "session_id": req.session_id, "context": weather } |
ポイントは OAuth2 による認証、pydantic が提供するスキーマバリデーション、そして非同期 httpx で外部 API を呼び出す点です。実運用では Redis へ session_id と取得結果をキャッシュし、複数リクエスト間で状態共有します【^11】。
Python SDK(H3)
client/python_sdk.py
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import httpx from typing import Any, Dict class MCPClient: def __init__(self, base_url: str, token: str): self.base_url = base_url.rstrip("/") self.headers = {"Authorization": f"Bearer {token}"} self.client = httpx.AsyncClient() async def get_context(self, session_id: str, query: Dict[str, Any]) -> Any: payload = {"session_id": session_id, "query": query} resp = await self.client.post( f"{self.base_url}/mcp/v1/context", json=payload, headers=self.headers ) resp.raise_for_status() return resp.json() |
使用例
|
1 2 3 4 5 6 7 8 9 10 |
import asyncio from client.python_sdk import MCPClient async def demo(): sdk = MCPClient(base_url="http://localhost:8000", token="YOUR_ACCESS_TOKEN") ctx = await sdk.get_context(session_id="sess-001", query={"city": "Osaka"}) print(ctx) asyncio.run(demo()) |
Node.js SDK(TypeScript 推奨)(H3)
client/node_sdk.ts
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import axios, { AxiosInstance } from 'axios'; export class MCPClient { private readonly http: AxiosInstance; constructor(baseUrl: string, token: string) { this.http = axios.create({ baseURL: baseUrl.replace(/\/+$/, ''), headers: { Authorization: `Bearer ${token}` }, }); } async getContext(sessionId: string, query: Record<string, unknown>) { const resp = await this.http.post('/mcp/v1/context', { session_id: sessionId, query, }); return resp.data; } } |
zod と組み合わせれば、クライアント側でも受信 JSON の型安全性を担保できます【^12】。
実務シナリオ:天気予報 API を LLM に組み込む
MCP の最大のメリットは LLM が外部データにリアルタイムでアクセスできる点 です。ここでは、取得した天気情報を Claude 3.5 と GPT‑4o に渡すフローを実装例として示します。
フロー概要(H3)
- コンテキスト取得:SDK の
get_contextで Open‑Meteo から最新の天気データを取得。 - LLM 呼び出し:取得した JSON を
invokeエンドポイントに渡し、システムプロンプトと合わせて生成させる。 - 結果返却:サーバーは LLM のテキスト応答をホストへ返し、ユーザー画面に表示。
Claude 3.5 での実装例(Python)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import json, os from client.python_sdk import MCPClient from anthropic import Anthropic # pip install anthropic ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") anthropic_client = Anthropic(api_key=ANTHROPIC_API_KEY) async def ask_weather(city: str): sdk = MCPClient(base_url="http://localhost:8000", token="YOUR_ACCESS_TOKEN") ctx = await sdk.get_context(session_id="sess-42", query={"city": city}) response = anthropic_client.completions.create( model="claude-3.5-sonnet-20240620", max_tokens=200, messages=[ {"role": "system", "content": "You are a helpful weather assistant."}, {"role": "user", "content": f"今日の{city}の天気は?"}, {"role": "assistant", "content": json.dumps(ctx["context"])} ], ) return response.completion |
GPT‑4o での実装例(Node.js / TypeScript)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import { OpenAI } from 'openai'; import { MCPClient } from './node_sdk'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const client = new MCPClient('http://localhost:8000', 'YOUR_ACCESS_TOKEN'); async function askWeather(city: string) { const ctx = await client.getContext('sess-84', { city }); const completion = await openai.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'system', content: 'You are a weather assistant.' }, { role: 'user', content: `東京の天気は?` }, { role: 'assistant', content: JSON.stringify(ctx.context) }, ], }); return completion.choices[0].message.content; } |
ポイント:LLM 側では「コンテキストは外部データとして扱う」旨をシステムプロンプトで明示するだけで、モデルが自動的に情報を統合して応答します。実装上の複雑さは SDK とサーバー側のみです。
運用・デプロイ、セキュリティ、トラブルシューティング
本番環境で MCP を安全かつ安定稼働させるために必要な項目をチェックリスト形式でまとめました。Docker Compose から Kubernetes(Helm Chart)への移行例も併記しています。
デプロイ手順(H3)
| ステップ | 内容 |
|---|---|
| 1. Docker Compose(ローカル/ステージング) | docker compose up -d でサーバーと Redis を起動。TLS 設定は certs/ ディレクトリに格納し、FastAPI の起動オプション --ssl-keyfile / --ssl-certfile でマウント |
| 2. Helm Chart(本番 Kubernetes) | charts/mcp/templates/deployment.yaml にコンテナイメージと環境変数を定義。シークレットは kubectl create secret generic mcp-secrets ... で注入し、Pod が起動時に自動マウント |
| 3. CI/CD パイプライン | GitHub Actions で Docker イメージビルド → GHCR にプッシュ → Argo CD でデプロイ。テストは helm test と curl -sSf によるヘルスチェックを実行 |
認証・暗号化設計(H3)
| 手法 | 実装例 |
|---|---|
| OAuth2 クライアントクレデンシャル | authlib.integrations.starlette_client でトークン取得、Redis に 5 分キャッシュ【^13】 |
| mTLS(相互認証) | FastAPI 起動時に ssl_keyfile="/certs/server.key"、ssl_certfile="/certs/server.crt" を指定。クライアントは verify="/certs/ca.crt" で検証【^14】 |
| レートリミット | Python: slowapi → Limiter(key_func=get_remote_address, default_limits=["60/minute"]) Node.js: express-rate-limit → { windowMs: 60000, max: 60 } |
トラブルシューティングチェックリスト(H3)
| # | 確認項目 | 実行コマンド例 |
|---|---|---|
| 1 | アクセストークンの有効期限 | curl -H "Authorization: Bearer <token>" https://auth.example.com/introspect |
| 2 | TLS 証明書の有効期限 | openssl x509 -noout -dates -in certs/server.crt |
| 3 | JSON スキーマ妥当性 | mcp-inspect validate --schema schemas/context_schema.json --file sample_response.json |
| 4 | レートリミットが機能しているか | ab -n 200 -c 20 http://localhost:8000/mcp/v1/context (429 が返ることを確認) |
| 5 | コンテナログ | docker logs mcp-server / kubectl logs deployment/mcp-server |
備考:
mcp-inspectは Zenn コミュニティが提供する CLI ツールで、JSON スキーマの自動検証とトレース情報の可視化を行います【^15】。
まとめと次のアクション
- MCP の全体像:LLM と外部データを標準化された JSON‑RPC 形式で結びつけ、認証・バージョニング・エラーハンドリングが明文化されています。
- 実装ポイント:FastAPI サーバーと Python/Node SDK の組み合わせで数行のコードからコンテキスト取得・LLM 呼び出しが可能です。
- 開発環境:Python 3.12、Node.js 20、Docker Compose がベース。Redis によるセッション永続化と OAuth2/mTLS による堅牢な認証を組み込むことで、本番レベルの安全性が確保できます。
- 実務シナリオ:天気予報 API(Open‑Meteo)を例に、取得データを Claude 3.5・GPT‑4o にリアルタイムで渡すフローを示しました。任意の社内 API へ置き換えるだけで、同様のパイプラインが構築可能です。
- 運用:Docker Compose → Helm Chart の段階的デプロイと、
mcp‑inspectによる検証・ログ確認手順を踏めば、障害発生時も迅速に切り分けられます。
次のステップ
1. GitHub 公式リポジトリanthropic/mcp-sdkをクローンし、ローカルでdocker compose up -dを実行。
2. サンプルコード(Python/Node)を走らせて「東京の天気は?」と問い合わせ、LLM の応答が得られることを確認。
3. 本番環境向けに Helm Chart をカスタマイズし、OAuth2 クライアントクレデンシャル情報をシークレット化してデプロイ。
これで読者は Model Context Protocol の概念理解から実装・運用まで一通りの流れを把握でき、即座に自社サービスへ組み込む準備が整います。
参考文献
[^1]: RFC 8259 – The JSON Data Interchange Format. https://www.rfc-editor.org/rfc/rfc8259
[^2]: RFC 7807 – Problem Details for HTTP APIs. https://www.rfc-editor.org/rfc/rfc7807
[^3]: Anthropic, Model Context Protocol Specification, spec.yaml (2024‑04‑12). https://github.com/anthropic/mcp-spec/blob/main/spec.yaml
[^4]: OAuth 2.0 Authorization Framework (RFC 6749). https://www.rfc-editor.org/rfc/rfc6749
[^5]: Anthropic GitHub リポジトリ(MCP 公式). https://github.com/anthropic/mcp-spec
[^6]: anthropic/mcp-sdk – Python / Node SDK (GitHub). https://github.com/anthropic/mcp-sdk
[^7]: Python Software Foundation, Python 3.12 Release. https://www.python.org/downloads/release/python-3120/
[^8]: fnm – Fast Node Manager. https://github.com/Schniz/fnm
[^9]: Docker Documentation – Install Engine on Ubuntu. https://docs.docker.com/engine/install/ubuntu/
[^10]: 技術評論社 Gihyo, 「LLM と外部ツールを安全に連携させるスタック」2024年12月号. https://gihyo.jp/book/2024/978-4-297-15284-6
[^11]: Redis Labs, Using Redis for Session Store. https://redis.io/docs/manual/data-types/#sessions
[^12]: Zod – TypeScript-first schema validation. https://github.com/colinhacks/zod
[^13]: Authlib Documentation – Starlette integration. https://docs.authlib.org/en/latest/client/starlette.html
[^14]: FastAPI Security – TLS / mTLS example. https://fastapi.tiangolo.com/advanced/security/
[^15]: Zenn Community, mcp‑inspect CLI (2024). https://zenn.dev/mcp-tools/articles/mcp-inspect