Chuyển đến nội dung chính
友田 陽大
本番LLMアプリ実装(信頼できるAI)
MCP
Model Context Protocol
生成AI
LLM
AIエージェント
TypeScript
セキュリティ
OAuth
アーキテクチャ設計
技術選定

MCP(Model Context Protocol)本番サーバー実装ガイド 2026|アーキテクチャ・トランスポート・認可・セキュリティ

Model Context Protocol(MCP)で本番に耐えるサーバーを実装するための実践ガイド。host/client/serverアーキテクチャ、stdio/Streamable HTTPトランスポート、公式TypeScript SDK(v1)の正しいAPI、OAuth 2.1認可(RFC 9728/8707・PKCE・トークンaudience検証)、ツール安全設計と公式セキュリティベストプラクティスまで、一次情報準拠のTypeScript実コードで解説します。

Published
Reading time
12 min read
Author
友田 陽大
Chia sẻ

生成AIを「賢いチャット」から「実際に業務を動かすシステム」に変える鍵は、モデルを外部のツール・データ・業務ロジックに安全に繋ぐことです。その接続を標準化したのが MCP(Model Context Protocol) ——AIモデルとツールの間の“共通端子”です。ツールごとに独自連携を作らず、1つのプロトコルで繋ぐ。だからこそ2025年以降、主要なAIクライアントとプラットフォームが一斉に採用しました。

しかしMCPサーバーを本番に載せるときの勝負どころは、プロトコルの物珍しさではありません。 「アーキテクチャの理解」「トランスポートの選択」「OAuth 2.1認可」、そして何より「ツール=任意コード実行という前提に立ったセキュリティ設計」です。この記事は、現行の安定仕様(2025-11-25)と公式TypeScript SDK(v1系)に厳密準拠し、本番で効く実装だけを実コードで示します。

本記事のバージョン・API・セキュリティ要件は、すべて公式仕様(modelcontextprotocol.io)で確認した一次情報に基づきます。仕様は日付リビジョンで更新されるため、実装前に必ず出典を確認してください。

MCPの全体像:host / client / server と3つのプリミティブ

MCPは JSON-RPC 2.0 をベースにした、ステートフルな接続プロトコルです。登場人物は3者。

役割責務(公式定義の要約)
Hostコンテナ兼コーディネータ。複数のクライアントを生成・管理し、接続許可とライフサイクル、セキュリティポリシーと同意(ユーザー認可)を強制、LLM連携とコンテキスト集約を担う
ClientHostが生成し、1つのサーバーと1:1のステートフルなセッションを張る。プロトコル交渉と双方向メッセージのルーティングを担当
Server特化した機能を提供。Tools / Resources / Prompts を公開し、独立して動作。セキュリティ制約を尊重しなければならない

サーバーが公開する3つのプリミティブ(ここが実装の中心):

  • Tools(ツール) — 「AIモデルが実行する関数」。副作用を伴う操作の入口。最も注意が必要
  • Resources(リソース) — 「ユーザーやAIが使うコンテキスト・データ」。ファイルやDBレコードなど。
  • Prompts(プロンプト) — 「ユーザー向けのテンプレート化されたメッセージ/ワークフロー」。

さらにクライアント側が提供する機能(サーバーから要求できる)として Sampling(サーバー起点のLLM呼び出し)・Roots(操作範囲のURI/ファイル境界)・Elicitation(ユーザーへの追加入力要求) があります。どの機能が使えるかは、初期化時の能力ネゴシエーション(capability negotiation) で双方が明示的に宣言して決まります。

トランスポートの選択:stdio か Streamable HTTP か

MCPの標準トランスポートは2つだけです。用途で選びます。

トランスポートいつ使う要点
stdioローカル。クライアントがサーバーをサブプロセスとして起動JSON-RPCをstdin/stdoutで改行区切り送受信(メッセージに改行を含めない)。stderrはログ専用。クライアントは可能な限りstdioを優先すべき
Streamable HTTPリモート。独立プロセスが複数接続をHTTPで処理POST/GETの単一エンドポイント。必要に応じSSEでストリーム。認証・Origin検証が必須級

⚠️ 旧 HTTP+SSE トランスポート(2024-11-05版)は非推奨で、Streamable HTTP に置き換えられました。新規実装で選ぶ理由はありません。

Streamable HTTP のセキュリティは“任意”ではありません(公式のMUST/SHOULD):

  • サーバーは全接続で Origin ヘッダを検証し、不正なら 403 を返す(DNSリバインディング対策)。
  • ローカル実行時は 0.0.0.0 ではなく 127.0.0.1 にバインドする。
  • セッションIDは MCP-Session-Id ヘッダで扱い、**暗号的に安全(安全に生成したUUID等)**でなければならない。
  • HTTPクライアントは全リクエストに MCP-Protocol-Version を付ける。
// Streamable HTTP: DNS リバインディング対策として Origin を必ず検証する(公式MUST)
const ALLOWED_ORIGINS = new Set(["https://app.example.com"]);

function assertTrustedOrigin(req: Request): void {
  const origin = req.headers.get("origin");
  // Origin が付く(=ブラウザ由来)のに許可リストに無ければ拒否
  if (origin && !ALLOWED_ORIGINS.has(origin)) {
    throw new HttpError(403, "forbidden origin");
  }
}
// セッションIDは推測不能に。認証をセッションに依存させない(後述の session hijacking 対策)。
const sessionId = crypto.randomUUID();

最小の本番MCPサーバー(公式SDK v1・TypeScript)

まず“動く最小形”です。本番は安定版 @modelcontextprotocol/sdk(v1系) を使います(@modelcontextprotocol/server v2 はベータでAPIが異なるため、本番採用は時期尚早)。ツールは server.registerTool で登録し、inputSchema には Zodの「生シェイプ」z.object(...) で包まないオブジェクト)を渡すのが v1 の作法です。

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: "acme-tools", version: "1.0.0" });

// inputSchema は「生の Zod シェイプ」。境界で入力を型と値域で締める。
server.registerTool(
  "search-orders",
  {
    title: "注文検索",
    description: "テナント内の注文を検索する(読み取り専用)",
    inputSchema: { tenantId: z.string().uuid(), query: z.string().min(1).max(200) },
  },
  async ({ tenantId, query }) => {
    // 認可は「MCPの外」の決定的コードで強制する。プロンプトに委ねない。
    const orders = await searchOrders(tenantId, query);
    return { content: [{ type: "text", text: JSON.stringify(orders) }] };
  },
);

const transport = new StdioServerTransport();
await server.connect(transport);

registerTool(name, config, handler)・生シェイプのinputSchema{ content: [{ type: "text", text }] } の戻り値・server.connect(transport) は、いずれもv1.29.0の公式ドキュメントで確認した現行APIです。構造化出力が必要なら outputSchemastructuredContent を併用できます。LLM出力の検証設計は structured output の信頼性設計 と同じ発想です。

ツールを“安全に”設計する:任意コード実行という前提

MCPで最も誤解されるのが Tools です。公式仕様は明言します——「ツールは任意コード実行を表し、相応の注意をもって扱わねばならない」。つまり、MCPツールを開けることは、LLM(と、それを操作しうる攻撃者)に、あなたのシステムの関数を呼ばせることです。

だから設計原則は、LLMアプリのセキュリティ(OWASP LLM06「過剰なエージェンシー」)と完全に地続きです——破壊的な操作は、ツールに「実行」させず「提案」だけを返させる

// ツール = 任意コード実行。破壊的操作は「提案」を返し、その場では実行しない。
server.registerTool(
  "propose-refund",
  {
    title: "返金の提案",
    description: "返金の提案レコードを作成する(実行はしない・人間承認が必要)",
    inputSchema: { orderId: z.string().uuid(), amountJpy: z.number().int().positive() },
  },
  async ({ orderId, amountJpy }) => {
    // 副作用は「提案の作成」のみ(最小権限)。実際の返金は承認済みのコード経路だけ。
    const proposalId = await createRefundProposal({ orderId, amountJpy });
    return {
      content: [{ type: "text", text: `提案を作成しました: ${proposalId}(承認待ち)` }],
    };
  },
);

実際の返金は、MCPの外側で、決定的な業務ルール検証+人間承認+冪等キーを通して行います。この「提案と実行の分離+冪等性」は、私が決済基盤で本番二重課金0件を保つために使ってきた信頼性・冪等性の設計そのものです。加えて公式は、**「ツールの説明(annotation)は、信頼できるサーバー由来でない限り信頼しない」**とも述べています。つまりツールのメタデータ自体が攻撃面になり得ます。ツールの並べ方・権限設計は AIエージェントのツール実行設計 も参照してください。

リモートMCPの認可:OAuth 2.1(token passthrough は禁止)

認可はHTTPトランスポートに限った任意機能です(stdioは環境から資格情報を取得するため、通常は認可を使いません)。リモートMCPを公開するなら、公式の認可モデルに厳密に従います。

  • MCPサーバー = OAuth 2.1 の「リソースサーバー」、MCPクライアント = OAuthクライアント、別に認可サーバー(AS)が存在。
  • RFC 9728(Protected Resource Metadata) をサーバーは実装必須。401時の WWW-Authenticate/.well-known/oauth-protected-resource でASを発見させる。
  • RFC 8707(Resource Indicators) — クライアントは認可・トークン両リクエストで、MCPサーバーの正規URIresource に必ず送る。
  • PKCE(S256)必須。ASのメタデータで対応を確認できなければ続行しない。
  • トークンの検証は妥協できない(公式のMUST):
// リモートMCP = OAuth 2.1 の resource server。
// 受け取ったトークンは「自分向け(aud)」だけ受理する。
function verifyAccessToken(rawToken: string): Claims {
  const claims = verifyJwt(rawToken, JWKS); // 署名・iss・exp を検証
  // aud に自分の正規URIが無いトークンは拒否(他サービス向けの流用を防ぐ)
  if (!claims.aud?.includes(MCP_SERVER_CANONICAL_URI)) {
    throw new HttpError(401, "token audience mismatch");
  }
  return claims;
  // ★ このトークンを下流の外部APIへ「素通し」してはならない(公式で明確に禁止)。
  //   下流呼び出しは、MCPサーバー自身の資格情報/別トークンで行う。
}

**token passthrough(受領トークンをそのまま下流へ横流しする)は、認可仕様で明確に禁止された“アンチパターン”**です。監査証跡を壊し、信頼境界を越えさせ、セキュリティ制御を回避させます。

本番セキュリティ設計:公式ベストプラクティスの脅威と対策

公式の Security Best Practices が名指しする代表的な脅威と、対策の要点です。

脅威何が起きる対策の要点
Confused Deputyプロキシが静的client_id+動的登録+同意Cookieを持つと、Cookie再利用で同意を飛ばして認可コードを窃取プロキシはクライアントごとの同意(per-client consent)を必須実装。承認済みclient_idを都度確認、redirect_uriは完全一致
Token Passthrough自分向けでないトークンを受理し下流へ素通し自分向け以外のトークンを受理しない。仕様で明確に禁止
Session HijackingセッションIDの推測・なりすましセッションを認証に使わない。推測不能なセッションID(安全なUUID)。全受信リクエストを検証。IDはユーザーに束ねる
SSRF発見用フィールドに内部URL(例:クラウドメタデータ169.254.169.254)を仕込むHTTPSを強制、プライベートIP帯をブロック、リダイレクト先を検証(自作IP判定は符号化バイパスに注意)
ローカルサーバー起動悪意ある起動コマンドで任意コード実行クライアントは起動コマンドを明示し明示的同意を要求、サンドボックス化
過剰スコープadmin:* 等の広すぎるスコープで被害が拡大最小権限のスコープを段階的に。ワイルドカード/万能スコープを避ける

これらは特別な話ではなく、**「MCPサーバーを、信頼できないクライアント(と、その先のLLM)に晒される普通のWeb APIとして防御する」**ことに尽きます。

可観測性・回復性・冪等性:本番運用の三点

MCPツールは外部システムを叩くため、可観測性が欠かせません。ツール呼び出し名・引数(PIIはマスク)・レイテンシ・成否・拒否をユーザー/セッション単位で記録し、異常を検知します(土台は OpenTelemetryによる本番可観測性)。加えて、外部呼び出しにはタイムアウトとリトライ(指数バックオフ)、副作用のある操作には冪等キーを必ず入れます。LLMは同じ意図でツールを複数回呼ぶことがあり、冪等でない実行は二重課金・二重発送に直結します。

バージョニングと将来への備え

MCPの版は日付ベース(後方非互換な変更があった日付)。現行の安定版は 2025-11-252026-07-28 はリリース候補(RC)で未確定です。SDKも過渡期で、安定版 @modelcontextprotocol/sdk(v1)と、APIの異なるベータ @modelcontextprotocol/server(v2)が並存します。本番はv1に固定し、MCP-Protocol-Version によるネゴシエーションで版差を吸収、破壊的変更に備えます。

導入チェックリスト(本番公開前)

  • トランスポート — ローカルはstdio、リモートはStreamable HTTP(旧HTTP+SSEは使わない)。
  • Origin検証 — Streamable HTTPでOriginを検証し不正は403。ローカルは127.0.0.1バインド。
  • セッション — 推測不能なセッションID。認証をセッションに依存させない。全受信を検証。
  • 認可(リモート) — OAuth 2.1、RFC 9728/8707、PKCE(S256)。トークンのaudを検証し自分向けのみ受理。
  • token passthrough禁止 — 受領トークンを下流へ横流ししない。下流は別資格情報で。
  • ツール最小権限 — 破壊的操作は「提案」に留め、実行は人間承認+冪等キー付きのコード経路で。
  • 入力検証inputSchema(Zod)で型・値域を締め、認可は決定的コードで再確認。
  • 可観測性 — ツール呼び出しのログ/トレース、タイムアウト、リトライ、異常検知。
  • SDK/仕様の固定 — v1安定SDK、仕様版を明示、更新は一次情報で追う。

まとめ

MCPは、AIを業務システムに繋ぐための強力な標準です。しかし本番の成否を分けるのは、プロトコルの新しさではなく——「ツール=任意コード実行」「LLM=確率的で信頼できないコンポーネント」という前提に立ち、その周りを決定的なアーキテクチャで囲えるかです。

  • アーキテクチャ:host/client/server と3プリミティブ、能力ネゴシエーションを理解する。
  • トランスポート:stdio(ローカル)/ Streamable HTTP(リモート)を用途で選び、Origin・セッションを守る。
  • 認可:OAuth 2.1のリソースサーバーとして、audを検証し token passthrough を禁じる
  • ツール安全性:最小権限・提案/実行分離・人間承認・冪等性で、被害半径を封じ込める。

MCPサーバーのセキュリティは、LLMアプリのセキュリティの一部です。「速く繋ぐ」ことと「安全に運用する」ことは、正しく設計すれば両立します。

Câu hỏi thường gặp

MCP(Model Context Protocol)とは何ですか?
AIモデル(LLM)を外部のツール・データ・プロンプトに接続するためのオープンな標準プロトコルです。host / client / server の3者が JSON-RPC 2.0 でやり取りし、サーバーは Tools / Resources / Prompts を公開します。各ツールを個別に実装するのではなく、標準インターフェースで繋げる『AIのための共通端子』のような役割です。
stdio と Streamable HTTP、どちらのトランスポートを使うべき?
ローカルで動かす(クライアントがサーバーをサブプロセスとして起動する)なら stdio、ネットワーク越しのリモートサーバーなら Streamable HTTP です。旧来の HTTP+SSE トランスポートは非推奨となり、Streamable HTTP に置き換えられました。
MCPサーバーのセキュリティで最も重要な点は?
3点です。①ツールは『任意コード実行』として最小権限で設計し、破壊的操作は人間承認を通す。②リモートは OAuth 2.1 で、受領した access token の aud(audience)を検証して自分向けのみ受理し、下流へ素通ししない(公式で禁止)。③Streamable HTTP は Origin ヘッダを検証(DNSリバインディング対策)し、ローカルは 0.0.0.0 ではなく 127.0.0.1 にバインドする。
公式のTypeScript SDKはどれを使えばいい?
本番は安定版の @modelcontextprotocol/sdk(v1系)を使います。ツールは server.registerTool で登録し、inputSchema には Zod の『生シェイプ』(z.object(...) で包まないオブジェクト)を渡します。@modelcontextprotocol/server(v2)はまだベータで、Zodの渡し方などAPIが異なるため、本番では避けます。
MCPの仕様バージョンはどう管理されていますか?
日付ベースのリビジョン(YYYY-MM-DD)で管理され、後方非互換な変更があった日付が版名になります。現行の安定仕様は 2025-11-25 です(2026-07-28 はリリース候補で未確定)。HTTPクライアントは MCP-Protocol-Version ヘッダで版を明示し、初期化時に能力ネゴシエーションを行います。
プロンプトインジェクションでMCPツールが悪用される危険はありますか?
あります。公式仕様も『ツールは任意コード実行を表し、相応の注意が必要』『信頼できるサーバー由来でなければツールの説明(annotation)は信頼できないものとして扱うべき』と警告しています。防御はLLMアプリ全体のセキュリティ設計(出力のゼロトラスト検証・ツール最小権限・人間承認)と同じで、詳細は本文末尾のセキュリティ記事に集約しています。

Tài liệu tham khảo

友田

友田 陽大

Người phát triển sản phẩm đoạt Giải thưởng Bộ trưởng (METI). Với TypeScript + Python + AWS, tôi một mình triển khai trọn gói SaaS, chuyển đổi số công nghiệp và AI tạo sinh (RAG) sẵn sàng cho production — từ phân tích yêu cầu đến hạ tầng và vận hành.

I can take on the implementation from this article as an engagement

Security engineering, from design to implementation and operations

Design reviews via threat modeling, correct implementation of crypto and authn/authz, log design and detection (detection engineering), and building an incident-response capability. With experience building — solo × generative AI — a METI Minister's Award B2B SaaS and a payments platform with zero double charges in production, I help get your product to a state where it ships fast and can be defended. Vertical risks that only design can address, I also take on as an audit.

Nhận cả dự án trọn gói lẫn vai trò cố vấn kỹ thuật. Hãy bắt đầu bằng buổi tư vấn miễn phí 30 phút.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

Cũng đáng đọc