この記事のポイント
- MCPサーバーはPythonやTypeScriptで数十行から動くが、2026年の本番水準はStreamable HTTP + OAuth 2.1で決まる。
- stdioはローカル開発向けで、リモートや水平スケールが必要になった瞬間にStreamable HTTPへ移行するのがデファクトだ。
- 主要な攻撃ベクトルはtool poisoning、rug-pull、confused deputy、ツール出力経由の間接プロンプトインジェクションで、設計段階から対策が必要になる。
MCPサーバー構築が「趣味」から「インフラ実装業務」に変わった
MCPサーバーの数は、わずか1年半で異常なスピードで増え続けています。2026年4月時点でGlamaは約20,249件、mcp.soは約18,998件、PulseMCPは約12,770件、Smitheryは7,000件を超えるMCPサーバーをインデックスしています(TrueFoundryのレジストリ比較)。Linux FoundationのAgentic AI Foundationへの寄贈時点で、月間SDKダウンロードは9,700万回。この数字を見ると、「MCPサーバーを作る」という作業が、もはやホビープロジェクトではなくAIインフラの実装業務になったことが分かります。
本記事では、MCPサーバーを2026年の本番水準で実装するために必要なことを、SDK選定からデプロイ・セキュリティまで一気通貫で解説します。MCPそのものの設計思想や歴史的経緯はMCPとは何かの解説記事で扱っているので、本稿は「手を動かす開発者向け」の実装ガイドに振り切ります。
MCPサーバーを作るという作業の輪郭
開発者視点で見ると、MCPサーバーを作るという作業は3つの問いに答えることに集約されます。
1つ目は「このサーバーは何を提供するのか」です。MCPにはTools(実行可能なアクション)、Resources(参照可能なデータ)、Prompts(再利用可能なテンプレート)という3つのサーバー側プリミティブがあります。たとえば「在庫を調べる」「注文を作る」はToolsであり、「商品カタログ」「FAQの本文」はResourcesに該当します。この3種の使い分けを間違えると、後から必ず実装がねじれるので、最初に紙の上で分類してから書き始めるのが定石です。
2つ目は「どのトランスポートで話すのか」です。ローカル実行ならstdio、リモート実行ならStreamable HTTP——選択肢はこの2つしかありません。stdioは標準入出力でJSON-RPCを流すだけなので認証もネットワークも不要ですが、Claude DesktopやCursorといったローカルクライアント限定です。ChatGPT Apps SDK、Claudeのリモートコネクタ、ホスト型クライアントはすべてStreamable HTTPを要求します。
3つ目は「誰が呼び出せるのか」です。stdioではOSが信頼境界になりますが、Streamable HTTPに出た瞬間、認証・認可・監査という一連の課題が発生します。ここでの正解は公式仕様が定めている通り、OAuth 2.1 + PKCE + Protected Resource Metadataという組み合わせです。
SDKの選び方 — 2026年4月時点のTier分類
公式ドキュメントは、SDKを3つのTierに分けて扱っています。Tier 1はMCPコアチームまたは主要ベンダーが共同メンテナンスするもので、TypeScript、Python、C#(Microsoft)、Go(Google)が該当します。Tier 2はSpring AIによるJavaやコミュニティ主導のRust、Tier 3はSwift・Ruby・PHPといった位置づけです。
迷ったらPythonかTypeScriptを選んでください。PythonのmcpパッケージにはFastMCPというデコレータベースの高レベルAPIがあり、数行でサーバーが動きます。データサイエンスや既存のバックエンド資産を呼び出すならPython一択です。エッジ実行やCloudflare Workers・Vercelへのデプロイが前提なら、TypeScript SDKが最も摩擦が少ない選択肢になります。
| SDK | Tier | インストール | 向いている用途 |
|---|---|---|---|
| Python | 1 | uv add "mcp[cli]" | データ・ML系バックエンド、ローカル統合 |
| TypeScript | 1 | npm i @modelcontextprotocol/sdk | エッジ・サーバーレス・Workers |
| C# | 1 | dotnet add package ModelContextProtocol | .NETエンタープライズ |
| Go | 1 | go get github.com/modelcontextprotocol/go-sdk | 高スループットインフラ |
| Java | 2 | Spring AI spring-ai-starter-mcp-server | Springエコシステム |
| Rust | 2 | cargo add rmcp | システムレベル、組込 |
最小のMCPサーバー — PythonのFastMCPで10行
言葉よりコードの方が早いので、まず動く最小サンプルを見ます。以下は天気警報を返すget_alertsツールと、挨拶を返すResourceを提供するFastMCPのサーバーです。
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
# 実際にはここでAPIを叩く
return f"Active alerts for {state}: none"
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
return f"Hello, {name}."
if __name__ == "__main__":
mcp.run(transport="stdio")
このコードをweather.pyとして保存し、uv run weather.pyで起動するだけで、もう立派なMCPサーバーです。@mcp.tool()のdocstringがそのままツールの説明として扱われ、型アノテーションからJSON Schemaが自動生成されます。LLMはこのdocstringを読んで「どのツールを呼ぶべきか」を判断するので、説明文は設計ドキュメントのつもりで書くのが鉄則です。曖昧な説明は誤選択(いわゆるtool confusion)の直接原因になります。
ここで1つ重要な注意があります。stdioモードのMCPサーバーでは絶対にprint()で標準出力に書いてはいけません。標準出力はJSON-RPCフレーミング専用で、ログを混ぜると即座にプロトコルが破綻します。Pythonならsys.stderr、TypeScriptならconsole.errorを使ってください。これは初心者が必ず踏む最初の地雷です。
TypeScriptで書く — Cloudflare Workersを意識した構成
TypeScript SDKは@modelcontextprotocol/sdkとしてnpmで提供されています。最小サンプルは次のようになります。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "weather", version: "1.0.0" });
server.registerTool(
"get_alerts",
{
description: "Get weather alerts for a US state",
inputSchema: {
state: z.string().length(2).describe("Two-letter state code"),
},
},
async ({ state }) => ({
content: [{ type: "text", text: `Alerts for ${state}...` }],
}),
);
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Weather MCP running on stdio");
TypeScriptはZodによるスキーマ定義が強力で、入力バリデーションを仕様と一元化できます。Workers対応を視野に入れるなら、最初からトランスポートを差し替えられる構造で書いておくと後で楽です。Cloudflareが公開しているcreate-cloudflareテンプレート(npm create cloudflare@latest -- my-mcp-server --template=cloudflare/ai/demos/remote-mcp-authless)を使えば、雛形がほぼそのままStreamable HTTP対応のリモートMCPサーバーになります(Cloudflareの解説記事)。
Claude DesktopとInspectorで動作確認
サーバーができたら、すぐに2種類のクライアントで動作確認します。1つはClaude Desktopへの登録、もう1つはMCP Inspectorです。
Claude Desktopの設定ファイルは、macOSなら~/Library/Application Support/Claude/claude_desktop_config.jsonにあります。次のように絶対パスで登録するだけです。
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["--directory", "/abs/path/weather", "run", "weather.py"]
}
}
}
ここでもう1つの定番の罠があります。パスは必ず絶対パスで書いてください。相対パスはClaude Desktopの起動ディレクトリ基準になり、高確率で動きません。
MCP Inspectorの方が開発体験は圧倒的に上です。npx @modelcontextprotocol/inspector uv run weather.pyと叩くだけで、ブラウザUIが立ち上がり、ツール一覧・リソース一覧・呼び出し結果・JSON-RPCの生メッセージがすべて見えます。Bearer Tokenの注入やコンフィグファイルによる複数サーバーの切り替えもサポートしていて、CLIモードもあるのでCIに組み込むこともできます。print()の事故もここで一瞬で気付けます。
stdioからStreamable HTTPへ — プロダクション運用の分水嶺
開発はstdioで十分ですが、本番は違います。2026年時点でPulseMCPの「検索上位」の8割以上は既にリモートのStreamable HTTPサーバーです。ChatGPT Apps SDK、Claudeのリモートコネクタ、そして企業のAIゲートウェイ配下で動くサーバーは、例外なくStreamable HTTPを要求します。
Streamable HTTPは、HTTP POSTベースのリクエスト応答に加えて、必要に応じてServer-Sent Eventsを使って部分的なストリーミングを返せる設計です。かつて存在したHTTP+SSEのみの古い方式は既に置き換えられています。
実装上の最大のポイントはセッション設計です。Streamable HTTPは可能な限りステートレスで書きましょう。セッション状態をメモリに持つと、複数インスタンスにロードバランシングした瞬間に壊れます。2026年のMCPロードマップでも「ステートフルなセッションはロードバランサと喧嘩する」と明言されており、水平スケール前提ならステートはRedisや外部ストアに逃がす設計が必須です。もう1つ、セッションIDは暗号学的にランダムな値を使い、決して認証の代わりとして扱ってはいけません。これは仕様上のMUST要件です。
OAuth 2.1でMCPサーバーを保護する
リモート化した瞬間、認証・認可が必要になります。MCPの公式仕様は2025年3月の更新でOAuth 2.1を採用しました。以下が最低限押さえるべきポイントです。
- PKCEは必須で、
plainメソッドは禁止。S256のみが許容されます。 .well-known/oauth-protected-resourceを公開し、MCPサーバー自身と認可サーバーを分離します(RFC 9728 Protected Resource Metadata)。- Dynamic Client Registration(RFC 7591)に対応すると、クライアントの手動登録というM×Nの運用負荷が消えます。2025年11月の更新でClient ID Metadata Documents(CIMD)という新しい選択肢も追加されましたが、2026年4月時点ではDCRが依然デファクトです。
- MCPサーバーは認証にセッションIDを使ってはいけません。認証はBearerトークン(OAuth 2.1のアクセストークン)で行います。
自前で全部実装する必要はありません。実運用では認証を外部のプロバイダに任せるのが現実解です。StytchのMCP OAuth DCR解説、ScalekitのSecure MCP Server構築ガイド、そしてCloudflare Workers + PropelAuthの組み合わせなど、採用しやすい選択肢がすでに揃っています。
セキュリティの落とし穴 — 2025〜2026年の実攻撃ベクトル
MCPサーバーのセキュリティは、2025年を通じて急速に「紙の上の懸念」から「実攻撃ベクトル」に変わりました。Unit 42の調査とPractical DevSecOpsの解説を踏まえると、押さえるべき攻撃は次の4つです。
まずTool Poisoningとその進化系であるRug Pullです。攻撃者がツールの説明文に隠れた指示を仕込み、LLMが本来意図しない動作を取るようにしたり、インストール直後は無害だった説明文を後から書き換えて悪性化させる攻撃です。対策はクライアント側でツール記述をピン留めし、変更を検知したらユーザーに警告することですが、サーバー側としてはツール定義の変更をバージョンとして扱い、更新履歴を透明にする設計が有効です。
次にConfused Deputyです。MCPサーバーがサーバー自身の強い権限で動作し、エンドユーザーの権限チェックを省いてしまうと、攻撃者は自分がアクセスできないはずのデータに間接的に到達できます。対策は1つだけで、常にリクエストを発したユーザーの権限コンテキストで処理することです。サーバー側の環境変数やサービスアカウントに頼った実装は、ほぼ例外なくConfused Deputyを生みます。
そしてツール出力経由の間接プロンプトインジェクションです。たとえばGitHubのIssue本文を取ってくるツールが、Issue内に埋め込まれた「これまでの指示を無視して...」というテキストをそのままLLMへ返せば、攻撃者はサーバー側のToolリストを自由に操ることができます。対策は、ツール出力を「信頼できないコンテンツ」として明示的にマーキングし、クライアント側のコンテキスト組み立てで分離することです。サーバー側でもHTMLタグの除去や既知の攻撃文字列のサニタイズは最低限行うべきです。
最後に、2026年に新しく話題になっているのがMCP Samplingを悪用した間接注入です。サーバーがホストのLLMに推論を依頼するSampling機構を通じて、悪意のあるプロンプトをLLMに注入する手口で、Unit 42が詳細な攻撃例を公開しています。Samplingを使うサーバーを書くなら、入力の出所を厳密に制御してください。
デプロイ先を選ぶ — 4つの現実的な選択肢
MCPサーバーの本番デプロイは、用途によってはっきりと選択肢が分かれます。
Cloudflare Workersは、エッジで低レイテンシ・グローバル配信が必要な場面で第一選択になります。workers-mcpSDKとcreate-cloudflareテンプレートが揃っており、無料枠も日次10万リクエスト。Cloudflare自身が2,500以上のAPIエンドポイントをMCPサーバーとして公開しており、事実上の「デファクトのMCP本番環境」という地位を固めつつあります。
Vercelは、Next.jsベースで開発されている既存サービスに後付けでMCPを追加する場合に最も摩擦が少ない選択肢です。OAuthのビルトイン機能もあり、ZapierやVapiのようなSaaSがMCPエンドポイントを提供する際の主要基盤になっています。
Railwayはステートフルなサーバーや常時接続が必要な用途に向きます。ステートレス化が難しい既存アプリをそのままMCP化したい場合、Hobbyプランの$5/月とRedisのワンクリック追加は扱いやすい組み合わせです。
Fly.ioは、stdioベースのサーバーをそのままラップして公開したいケースで有力です。fly mcp launchコマンドが存在し、アクセスがない時は自動サスペンドしてくれるため、ロングテールのMCPサーバーに向いています。
より網羅的な比較はMCP Playgroundのデプロイ先ガイドが参考になります。
コマース特化MCPから学ぶ実装パターン
実装パターンを学ぶなら、すでに本番投入されているコマース系MCPサーバーを読むのが最短です。
ShopifyはDev MCP、Storefront MCP、Customer Account MCP、Checkout MCPという4種類のMCPサーバーを提供しており、それぞれ読み取り権限・ユーザーコンテキスト・決済権限が明確に分離されています。この「1つの大きなMCPサーバー」ではなく「役割ごとに分割した複数のMCPサーバー」という設計判断は、権限境界とスキャンサーフェスを小さく保つための教科書的な選択です。commercetoolsも同じく役割分離型で、Commerce MCPをVS Code・Claude Desktop・LangChain・Vercel AI SDKと繋ぐ統合パターンを公式ドキュメント化しています。Shopifyの4層構造や各サーバーのToolセットの詳細はCommerce MCPの実装解説を参照してください。
もう1つ、コマースMCPから読み取るべきパターンは「最初は読み取り中心に絞る」という意思決定です。2025年を通じてほとんどのコマースMCPはRead-Only操作に留まっていました。2026年に入って初めて返金や注文修正のような副作用のある操作が本格化してきた段階です。これは時間を稼ぐための保守的な判断ではなく、副作用のあるツールは承認UX・監査・取消可能性をセットで設計する必要があるという現実的な制約から来ています。あなたが最初のMCPサーバーを書く場合も、まずは読み取り系から始めて、副作用系は慎重に追加するほうが安全です。MCPはプロトコル単独では閉じず、その上にUCPやACP、AP2といったコマース特化レイヤーが乗る前提なので、どこまでを自前のMCPでカバーし、どこを上位プロトコルに委ねるかの整理も同時に必要です。この層構造についてはMCP・A2A・UCPのプロトコル整理やエージェンティックコマースとは何かが参考になります。
レジストリに公開する — 配布までが実装の一部
MCPサーバーを書き切ったら、最後の工程はレジストリへの公開です。ここまでやって初めて、世界中のクライアントから発見・利用される状態になります。
現在の中心は公式レジストリです。2025年後半にLinux Foundation配下で正式リリースされ、各クライアントは徐々にここを一次参照に切り替えつつあります。併せてSmithery、Glama、mcp.so、PulseMCPといった第三者レジストリにも登録しておけば、検索経路を最大化できます。Smitheryは「verified」ステータスとホスティング機能も提供しているので、公開と運用を一体で済ませたい場合に便利です。
登録時に最もよく見られるのはREADME・説明文・ツール一覧の3点です。LLMがツールを選ぶときに頼る情報と、人間の開発者がサーバーを選ぶときに頼る情報は、ほぼ重なっています。Tool descriptionには何ができて何ができないかを正直に書き、既知の制限事項も含めておくのが結果的に採用率を上げます。
まとめ — MCPサーバー実装はインフラ実装に近づいた
MCPサーバーを作るという作業は、2024年の「Claude Desktop用の便利スクリプトを書く」から、2026年の「認証・スケール・セキュリティ・配布まで面倒を見る分散システムの一部品を作る」へと、大きく輪郭を変えました。
最小のPythonサーバーは10行で動きます。しかし10行のサーバーが本番で使われることはありません。本番はStreamable HTTP + OAuth 2.1 + ステートレス設計 + セキュリティ対策 + レジストリ登録の合わせ技で初めて成立します。この記事で扱った観点を1つずつチェックリスト化しておけば、書き始めから配布までの作業が迷子になりません。
MCPはもはや配管です。あなたが書くサーバーはその配管の蛇口の1つで、業界が期待しているのは「蛇口の数」ではなく「信頼できる蛇口の数」です。最初の1本を小さく、正しく書くところから始めてみてください。




