Python または TypeScript 開発者の方で、Claude・GPT・Cursor 上の AI にデータベースアクセス、API 呼び出し、ファイル読み書きをさせたい一方、大規模言語モデル単体では外部操作の「手足」がないという制約に直面している方へ向けた記事です。学習データにはカットオフがあり、リアルタイム操作はできません。本稿では空白プロジェクトから本番投入可能な MCP Serverを書き上げます。Tools / Resources / Prompts 三大機能、stdio と HTTP+SSE 二種のトランスポート、デバッグから Docker デプロイまでを一通りカバーし、読了後に Cursor または Claude Desktop へ自前ツールチェーンを接続できる状態を目指します。ノードとプランは NOVAKVM 料金ページをご確認ください。
[ SECTION_01 ] // WHAT_IS_MCP MCP とは:Function Calling から統一ツールプロトコルへ
AI ツール統合は三段階で進化してきました。Function Calling(OpenAI 2023)がモデル出力を構造化 JSON 呼び出しに変換し、Plugins / GPT Actions が HTTP エンドポイントを会話プラグイン化し、MCP(Model Context Protocol) は Anthropic が 2024 年 11 月にオープンソース化したプロトコルとして「モデルがツールをどう発見・記述・呼び出すか」を標準化しました。一度実装すれば Claude Desktop、Cursor、VS Code Continue など複数のホストで再利用できます。
- LLM の能力境界:リアルタイムデータへ直接アクセスできず、ファイルシステムやデータベースも操作できません。外部ツールが「感覚器官と手足」を補います。
- フォーマットの分断:OpenAI Function Calling、Claude Tool Use、LangChain Agent はそれぞれ異なるツール schema を持ち、モデルや IDE を変えるたびにアダプタ層の書き直しが発生します。
- 発見メカニズムの欠如:従来の REST API は AI に「何ができるか」を能動的に伝えません。MCP ランタイムは
tools/listで能力一覧を動的に公開します。 - セッションとコンテキスト:MCP は永続接続を維持し、多段 Agent ワークフローに適します。REST の無状態リクエストでは複雑タスクの連鎖が困難です。
- セキュリティと権限:Server 側で書き込み可能ツールと読み取り専用リソースを細かく制御し、モデルによる本番データへの越権操作を防ぎます。
Client-Server JSON-RPC アーキテクチャは次の流れに整理できます。
- Host(ホスト):Claude Desktop、Cursor、VS Code などユーザーインターフェースを提供します。
- MCP Client:Host 内蔵で、各 Server と 1:1 セッションを維持します。
- MCP Server(自前実装):Tools(実行可能操作)、Resources(読み取り専用データ)、Prompts(再利用プロンプトテンプレート)の三大原語を公開します。
- トランスポート層:ローカル開発は stdio(子プロセス stdin/stdout)、リモートデプロイは HTTP + SSE(Server-Sent Events プッシュ)を使います。
- プロトコル層:全メッセージは JSON-RPC 2.0 に従い、
initialize→tools/list→tools/call→notifications/cancelledという流れになります。 - ライフサイクル:ハンドシェイク → 能力交渉 → 通常稼働 → グレースフルシャットダウン。Client は
pingでキープアライブできます。
| 次元 | MCP | OpenAI FC | LangChain Tools |
|---|---|---|---|
| 標準化 | オープンプロトコル、ベンダー横断 | OpenAI API に依存 | フレームワーク内部形式 |
| ツール発見 | ランタイム tools/list |
リクエスト時 schema 埋め込み | コード登録、静的 |
| Resources / Prompts | ネイティブ対応 | 非対応 | 独自ラッパーが必要 |
| トランスポート | stdio / HTTP+SSE | HTTPS API | プロセス内呼び出し |
| IDE ネイティブ統合 | Cursor、Claude Desktop 等 | ChatGPT プラグイン | 追加ブリッジ層が必要 |
MCP が解くのは「API を呼べるか」ではなく「AI がツールを統一的に発見・選択・正しく呼び出す方法」です。これが Agent 時代の中核課題です。
[ SECTION_02 ] // DEV_ENV 開発環境の構築:Python mcp SDK と TypeScript SDK の選定
公式は Python の mcp パッケージ(FastMCP 高レベル API 含む)と TypeScript の @modelcontextprotocol/sdk の二系統を提供しています。Python はプロトタイプとデータ/ML 向き、TypeScript は Node.js エコシステムとフロントエンドチーム向きです。以降は Python FastMCP を主軸に解説しますが、TypeScript 側の構造は対称です。
mkdir my-mcp-server && cd my-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" httpx pydantic python-dotenv
npm install -g @modelcontextprotocol/inspector
推奨プロジェクト構成は次のとおりです。
my-mcp-server/
├── server.py
├── tools/
├── resources/
├── prompts/
├── tests/
├── Dockerfile
├── requirements.txt
└── .env
デバッグと接続に必要な三要素は次のとおりです。
- MCP Inspector:公式ビジュアルデバッガー。tools/resources/prompts を一覧し、手動呼び出しができます。
- Claude Desktop:macOS では
~/Library/Application Support/Claude/claude_desktop_config.jsonを編集し stdio Server を登録します。 - Cursor:Settings → MCP から Server 設定を追加します。stdio とリモート HTTP エンドポイントの両方に対応しています。
[ SECTION_03 ] // HELLO_WORLD Hello World:10 行で最初の MCP Server を起動する
FastMCP で最小構成の Server を作り、say_hello ツールを公開します。
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hello-server")
@mcp.tool()
def say_hello(name: str) -> str:
return f"Hello, {name}! MCP Server is running."
if __name__ == "__main__":
mcp.run()
Inspector で起動検証します。
npx @modelcontextprotocol/inspector python server.py
ブラウザで Inspector UI を開き、Tools パネルから say_hello に {"name": "NOVAKVM"} を渡すと、挨拶メッセージが返ることを確認できます。
Claude Desktop 設定(claude_desktop_config.json):
{
"mcpServers": {
"hello-server": {
"command": "/path/to/my-mcp-server/.venv/bin/python",
"args": ["/path/to/my-mcp-server/server.py"]
}
}
}
Cursor MCP 設定:プロジェクトルートに .cursor/mcp.json を作成するか、Cursor Settings → MCP で同等の JSON を追加します。Cursor を再起動すると Agent モードで say_hello ツールが表示されます。
[ SECTION_04 ] // TOOLS Tools 深度開発:5 種類のツールとエラーハンドリングのベストプラクティス
MCP ツールの関数シグネチャがそのままドキュメントになります。パラメータ名、型アノテーション、docstring が JSON Schema に変換され、モデルが理解します。複雑な入力は Pydantic モデルで制約します。
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(..., description="検索キーワード")
limit: int = Field(10, ge=1, le=100, description="返却件数上限")
@mcp.tool()
async def search_docs(input: SearchInput) -> list[dict]:
...
本番級 Server では次の五種類のツールを実装することが多いです。
- calculator:安全な数式評価。
evalの裸実行は禁止し、astまたは専用ライブラリで解析します。 - file_read / file_write:ルートディレクトリを限定(chroot 思想)し、パストラバーサルを防ぎます。書き込みは二次確認または拡張子ホワイトリストを設けます。
- fetch_url:非同期 HTTP リクエスト。実装例は下記のとおりです。
- db_query:読み取り専用 SQL(
SELECT)のみ。パラメータ化クエリでインジェクションを防ぎます。書き込みは別ツールに分離し監査ログを残します。 - get_current_time:ISO 8601 タイムスタンプを返し、モデルが「現在時刻を知らない」問題を解消します。
import httpx
@mcp.tool()
async def fetch_url(url: str, timeout: int = 30) -> str:
async with httpx.AsyncClient(timeout=timeout) as client:
resp = await client.get(url)
resp.raise_for_status()
return resp.text[:50000]
エラーハンドリングのベストプラクティスは次のとおりです。
- ツール内で例外を捕捉し、構造化エラーテキストを返します。プロセスをクラッシュさせず、Client がモデルへ結果を渡して retry や戦略変更を促します。
- 外部 API にはタイムアウトとリトライ上限を設定し、モデルの無限ループ呼び出しを防ぎます。
- API Key や接続文字列などの機密情報は環境変数から読み取り、tool 戻り値や Resources へ書き込みません。
- 書き込み操作ツールは変更内容と影響行数のサマリーを返し、モデルがユーザーへ確認しやすくします。
[ SECTION_05 ] // RESOURCES Resources リソースプロトコル:読み取り専用データと実行可能ツールの違い
Resource と Tool の本質的差異:Resource は読み取り専用のコンテキストデータ(設定ファイル、ユーザープロファイル、ログ断片)で、モデルは resources/read で取得します。Tool は実行可能な操作(クエリ、書き込み、リクエスト送信)です。Resource は「AI が参照すべきだが変更しない」情報に適しています。
URI スキーム(scheme)の慣例は次のとおりです。
config://app/settings— 起動時に登録する静的設定リソースです。user://{id}/profile— 動的テンプレート。Client が id を渡すと Server がリアルタイム生成します。file://— ローカルファイルシステムへのマッピング(パスサンドボックス必須)です。
Resource は text/plain、application/json、バイナリ blob(Base64 エンコード返却)、stream(大ファイルのチャンク配信)の四種 MIME に対応します。
@mcp.resource("config://app/settings")
def get_app_settings() -> str:
return json.dumps({"env": "production", "version": "1.2.0"})
@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
profile = db.fetch_user(user_id)
return json.dumps(profile)
ファイルシステム Resource Server はディレクトリ配下のファイルを再帰登録でき、AI がコーディング時にプロジェクト構造と主要設定を直接「見る」ことができます。read tool をファイルごとに呼ぶ必要がありません。
[ SECTION_06 ] // PROMPTS Prompts プロンプトテンプレート:再利用可能な多段会話の足場
MCP Prompt は事前定義されたプロンプトテンプレートです。Host が一覧表示し、ワンクリックで会話コンテキストへ注入できます。コードレビュー、インシデント振り返り、API 設計レビューなど反復ワークフローに適しています。プレースホルダパラメータと複数ターン message 構造をサポートします。
from mcp.types import PromptMessage, TextContent
@mcp.prompt()
def code_review_prompt(language: str, focus: str = "security") -> list[PromptMessage]:
return [
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"以下の {language} コードを {focus} の観点でレビューし、問題点と改善案を列挙してください:\n\n"
)
)
]
多段テンプレート例:第一ターンでロールと制約を注入し、第二ターンでレビュー対象コードのプレースホルダを渡し、第三ターンで構造化 JSON(severity / file / line / suggestion)の出力を要求します。チームのベストプラクティスを Prompt として固定化すれば、新メンバーが system prompt を毎回書く必要がなくなります。
[ SECTION_07 ] // HTTP_TRANSPORT HTTP トランスポートデプロイ:stdio から Streamable HTTP リモートサービスへ
| 次元 | stdio | HTTP + SSE |
|---|---|---|
| デプロイ位置 | ローカル子プロセス | リモートサーバー / コンテナ |
| ネットワーク要件 | 不要 | 公網または社内網到達性が必要 |
| 水平スケール | 単一マシン | ロードバランサ + session affinity |
| 認証 | プロセス分離 | Bearer Token / API Key |
| 適用シナリオ | 個人開発、Claude Desktop | チーム共有、7×24 クラウド常駐 |
FastMCP は streamable-http トランスポートをサポートし、一行で切り替えられます。
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)
本番 HTTP デプロイでは次を必ず整備します。
- Bearer Token / API Key:リバースプロキシまたは middleware 層で
Authorizationヘッダーを検証します。 - CORS:ブラウザ版 Inspector からクロスオリジンアクセスする場合、許可オリジンを設定します。
- Rate Limiting:IP または API Key 単位でレート制限し、モデルのループ呼び出しによるバックエンド過負荷を防ぎます。
- TLS:公網公開時は HTTPS 必須です。Caddy / Nginx で SSL 終端する構成が一般的です。
[ SECTION_08 ] // DEBUG_TEST デバッグテストとトラブルシューティング:Inspector、pytest と六ステップデプロイチェックリスト
MCP Inspector の使い方:起動後、左側に Server 能力ツリーが表示されます。Tools パネルで JSON パラメータを入力して手動トリガーでき、Notifications パネルで Server プッシュを、Logs パネルで stderr 出力を確認できます。コード変更後は Inspector が子プロセスを自動再起動します。
import pytest
from server import say_hello
def test_say_hello():
result = say_hello("World")
assert "Hello, World!" in result
@pytest.mark.asyncio
async def test_fetch_url():
result = await fetch_url("https://httpbin.org/get")
assert "origin" in result
| 現象 | 想定原因 | 対処 |
|---|---|---|
| ツールが表示されない | デコレーター漏れ、Server 起動失敗 | stderr ログ確認、Inspector 再接続 |
| JSON シリアライズ失敗 | datetime/Decimal 等の非シリアライズ型 | 手動 json.dumps または str 変換 |
| 呼び出しタイムアウト | 外部 API 遅延、timeout 未設定 | ツール内 timeout 設定、Client 側 limit 拡大 |
| 権限拒否 | ファイルパスがサンドボックス外、DB 認証エラー | ALLOWED_PATHS と .env 設定を確認 |
六ステップ本番デプロイチェックリストは次のとおりです。
- 依存バージョン固定:
pip freeze > requirements.txtを実行し、CI で Python と mcp SDK バージョンを固定します。上流 breaking change を防ぎます。 - Dockerfile 作成:マルチステージビルドで最終イメージはランタイム依存のみ。非 root ユーザーで Server プロセスを実行します。
- 環境変数設定:API Key、DB 接続文字列、ALLOWED_PATHS は secrets 管理経由とし、ハードコードしません。
- ホスティング選定:Railway / Render は MVP 向き。AWS Lambda + HTTP adapter は低頻度向き。Cloud Run / VPS は 7×24 常駐向きです。
- 監視導入:構造化ログ(JSON)、
/healthエンドポイント、Prometheus metrics または Sentry 例外報告を整備します。 - Cursor / Claude 接続検証:リモート URL + Bearer Token を MCP 設定へ書き込み、
tools/listでツール一覧が完全であることを確認してから本番トラフィックを流します。
[ SECTION_09 ] // PRODUCTION 本番環境へのデプロイ:Docker、ホスティング選定と可観測性
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER nobody
EXPOSE 8080
CMD ["python", "server.py"]
ホスティングプラットフォーム選定の目安は次のとおりです。
- Railway / Render:Git push 自動デプロイ。無料 tier は MVP 向きです。コールドスタートが SSE 長接続に影響する点に注意します。
- AWS Lambda:呼び出し課金。HTTP-to-stdio アダプタ層が必要です。低頻度内部ツール向きです。
- Google Cloud Run:コンテナネイティブ、自動スケール。SSE には min-instances ≥ 1 でキープアライブが必要です。
- VPS / ベアメタル:ネットワークとディスクを完全制御。機密データを社内に留める MCP Server に適しています。
可観測性三要素は次のとおりです。
- Logging:structlog または python-json-logger。各 tool call に name、duration_ms、status を記録します。
- Prometheus:
mcp_tool_calls_total、mcp_tool_duration_seconds等のメトリクスを公開します。 - Sentry:未処理例外を捕捉し、Server バージョン tag でロールバック判断を支援します。
バージョン互換性:MCP 仕様 2025-03-26 で Streamable HTTP が導入されました。デプロイ前に Client(Cursor バージョン、Claude Desktop バージョン)と Server SDK が同一トランスポートをサポートするか確認してください。README に mcp>=1.2.0 等の最低要件を明記することを推奨します。
[ SECTION_10 ] // ECOSYSTEM 実践:ChromaDB ナレッジベース MCP と 2026 エコシステム
総合実践プロジェクトとしてナレッジベース MCP Serverを挙げます。ChromaDB または Qdrant でドキュメントベクトルを保存し、watchfiles でディレクトリ変更を監視して自動 re-index します。search_knowledge と write_note の二ツールを公開すれば、Cursor 接続後に Agent がチーム内部ドキュメントを検索でき、学習データだけに頼らなくなります。
@mcp.tool()
async def search_knowledge(query: str, top_k: int = 5) -> list[dict]:
embedding = await embed(query)
results = collection.query(query_embeddings=[embedding], n_results=top_k)
return [{"text": doc, "score": score} for doc, score in zip(...)]
@mcp.tool()
async def write_note(title: str, content: str) -> str:
doc_id = collection.add(documents=[content], metadatas=[{"title": title}])
return f"Note saved: {doc_id}"
再利用推奨のコミュニティ MCP Serverは次のとおりです。
- @modelcontextprotocol/server-filesystem — サンドボックス付きファイル読み書き
- server-github — Issue、PR、コード検索
- server-brave-search — リアルタイム Web 検索
- server-postgres — 読み取り専用 SQL クエリ
- server-slack — チャンネルメッセージと通知
2026 年 MCP エコシステムの主要データは次のとおりです。
- エコシステム規模:2026 年時点で公開 MCP Server は 10,000 件超、GitHub modelcontextprotocol 組織リポジトリの Star 合計は 50,000 超と報告されています。
- ベンダー採用:2026 年 Q1 に OpenAI、Q2 に Google Gemini と Microsoft Copilot がネイティブ MCP サポートを発表。ガバナンスは Linux Foundation 傘下 AAIF へ移管されました。
- エンタープライズ統合コスト:MCP 標準インターフェース採用後、AI ツールチェーン統合開発コストが約 38–55% 削減されたという業界調査結果があります。
学習パスは次の六段階を推奨します。
- 公式仕様を読み、JSON-RPC メッセージフローを理解する
- FastMCP で Hello World + Inspector デバッグを完了する
- ファイル、HTTP、DB の三種以上の実ツールを実装する
- Resources と Prompts を追加し、三大原語の差異を体験する
- HTTP トランスポートへ切り替え、Docker でクラウドへデプロイする
- Cursor へ接続し、ナレッジベースまたは GitHub 統合の実践を完了する
以下の公開資料は仕様と SDK の検証入口として利用できます。上流リポジトリが更新された場合はリンク先を正としてください。
Model Context Protocol — 公式仕様とドキュメント
modelcontextprotocol/python-sdk — Python MCP SDK
modelcontextprotocol/typescript-sdk — TypeScript MCP SDK
modelcontextprotocol/inspector — MCP Inspector デバッグツール
スリープするノート PC 上で MCP Server を動かすと、tools/list セッション中断、OAuth 期限切れ、ディスク満杯によるベクトル DB 破損、ネットワーク切替後の SSE 断線などが日常の障害になります。「どのモデルを選ぶか」より実開発体験への影響が大きいケースが多いです。ラップトップ上の Docker でもホストのスリープ問題は残り、無料 tier PaaS のコールドスタートは長接続を頻繁に切断し、Lambda は SSE 常駐シナリオに向きません。
7×24 常駐 MCP ツールチェーン、安定 SSH、予測可能な Apple Silicon 算力が必要な場合、Cursor Agent と自前 Server を専用ベアメタルへ移す方が合理的です。NOVAKVM は多リージョンの Mac Mini M4 / M4 Pro 柔軟なレンタルを提供し、Cursor MCP、Claude Desktop リモート開発、ベクトル DB 同機デプロイに適しています。プランは 料金ページ、注文は 注文ページ、デプロイに関する質問は ヘルプセンターをご参照ください。