AIエージェント入門

MCP Streamable HTTP 完全実装ガイド2026|Python・TypeScript クライアント/サーバーをゼロから構築

MCP Streamable HTTP 完全実装ガイド2026|Python・TypeScript クライアント/サーバーをゼロから構築

この記事の結論

MCP 2025-11-25仕様の新標準トランスポートStreamable HTTPをPython SDK(mcp 1.27.2)とTypeScript SDK(v1.29.0)を使ってクライアント・サーバー両側からゼロ実装。stdio選択フローも解説。

Streamable HTTP とは何か — 旧 HTTP+SSE との違いを5分で理解する

MCP(Model Context Protocol)のトランスポート層は、2025年11月25日付けの仕様アップデートで大きく刷新された。旧仕様(2024-11-05)で使われていた HTTP+SSE トランスポートは廃止され、代わりに Streamable HTTP トランスポートが標準となった。

両者の違いを一言で言うと、「SSE 専用チャンネル(GET /sse)」を廃し、単一エンドポイント(例: https://example.com/mcp)に POST/GET/DELETE の3メソッドを集約した点にある。旧 HTTP+SSE では「POST で送信 → 別の GET /sse でストリーム受信」という2エンドポイント設計だったため、ロードバランサやリバースプロキシがセッションを別のノードに振り分けると接続が切れる問題があった。Streamable HTTP ではこの問題を根本的に解消している。

項目 旧 HTTP+SSE(2024-11-05) Streamable HTTP(2025-11-25)
エンドポイント数 2(POST 送信用 + GET SSE 受信用) 1(POST/GET/DELETE を集約)
レスポンス形式 常に SSE ストリーム SSE または JSON を選択可能
セッション管理 なし(ステートレス) MCP-Session-Id ヘッダーでステートフル管理
接続再開 非対応 Last-Event-ID ヘッダーで再接続・再配信対応
本番展開 スティッキーセッション必須 スティッキーセッション不要(基本構成)

現時点(2026年6月)では 2025-11-25 が安定仕様バージョンであり、Python SDK は mcp 1.27.2(2026年5月29日リリース)、TypeScript SDK は @modelcontextprotocol/sdk v1.29.0(2026年3月30日リリース)が最新安定版となっている。なお、v2.0.0a1(TypeScript)および Python 2.0 系のアルファが公開されているが、本記事では 本番推奨の v1.x 系を対象とする。

stdio vs Streamable HTTP — 選択フロー

実装に入る前に「なぜ Streamable HTTP が必要か」を整理しておく。

stdio トランスポートは、クライアントがサーバーをサブプロセスとして起動し、標準入出力で通信する。Claude Desktop や Claude Code との統合はほぼ stdio 一択でよい。ネットワーク設定ゼロで単一ユーザー・単一プロセスなら十分だ。

一方、以下のいずれかに該当する場合は Streamable HTTP を選ぶ。

  • 複数クライアントが同一サーバーを同時利用する(マルチテナント)
  • サーバーをクラウド(Cloudflare Workers / Vercel / AWS Lambda 等)にデプロイする
  • REST API エンドポイントとして外部公開し、OAuth 認証と組み合わせたい
  • ストリーミング通知をサーバーからクライアントへ非同期に送りたい
  • 接続断後に途中から再開(Resumability)したい

判断が迷う場合のシンプルなルール: 「開発・ローカル → stdio」「本番・クラウド → Streamable HTTP」と覚えておけばよい。

Python サーバーをゼロから実装する(mcp 1.27.2・FastMCP 経由)

Python SDK では FastMCP クラスを使うのが最も手軽だ。stateless_http=True にするとサーバーレス環境向けのステートレスモードになり、セッション管理が不要になる。長期接続やストリーミング通知が必要な場合は stateless_http=False(デフォルト)を使う。

# インストール
pip install "mcp[cli]"
# または uv を使う場合
uv add "mcp[cli]"
# server.py
from mcp.server.fastmcp import FastMCP

# ステートフルサーバー(セッション管理あり・デフォルト)
mcp = FastMCP("my-mcp-server")

@mcp.tool()
def calculate(expr: str) -> str:
    """数式を評価して結果を返す。例: '2 + 3 * 4'"""
    try:
        # 安全のため eval 対象を数値演算のみに限定する実装では
        # ast.literal_eval やサードパーティの safe-eval を使うこと
        result = eval(expr, {"__builtins__": {}}, {})
        return f"{expr} = {result}"
    except Exception as e:
        return f"エラー: {e}"

@mcp.tool()
def list_files(directory: str = ".") -> list[str]:
    """指定ディレクトリのファイル一覧を返す"""
    import os
    try:
        return os.listdir(directory)
    except Exception as e:
        return [f"エラー: {e}"]

@mcp.resource("config://settings")
def get_settings() -> str:
    """アプリケーション設定を返す"""
    return '{"version": "1.0", "env": "production"}'

if __name__ == "__main__":
    # Streamable HTTP で起動(デフォルトポート: 8000)
    mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)

起動コマンドは以下のいずれかで行える。

# Python で直接起動
python server.py

# mcp CLI 経由(開発時)
mcp run server.py --transport streamable-http

# Inspector UI でデバッグ(http://localhost:8000/mcp が確認できる)
mcp dev server.py

起動後、クライアントからは POST http://localhost:8000/mcp で接続初期化を行う。サーバーは InitializeResult レスポンスの HTTP ヘッダーに MCP-Session-Id を付与するため、以降のリクエストすべてにそのセッション ID を含める必要がある(MCP 公式仕様 – Transports)。

TypeScript クライアントから接続する(@modelcontextprotocol/sdk v1.29.0)

TypeScript SDK では StreamableHTTPClientTransport クラスが Streamable HTTP に対応したクライアントトランスポートを担う。Express ベースのサーバーと組み合わせて使う場合は NodeStreamableHTTPServerTransport を使う(これは公式 TypeScript SDK のサーバー側実装)。

# インストール
npm install @modelcontextprotocol/sdk
# TypeScript SDK では Express と node パッケージも必要
npm install @modelcontextprotocol/express @modelcontextprotocol/node @modelcontextprotocol/client
// client.ts
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';

async function main() {
  // サーバー URL を指定して接続
  const serverUrl = new URL('http://localhost:3000/mcp');

  const transport = new StreamableHTTPClientTransport(serverUrl);
  const client = new Client(
    { name: 'my-ts-client', version: '1.0.0' },
    { capabilities: { sampling: {}, elicitation: {} } }
  );

  // 接続初期化(サーバーから MCP-Session-Id を受け取る)
  await client.connect(transport);
  console.log('接続成功');

  // ツール一覧を取得
  const { tools } = await client.listTools();
  console.log('利用可能なツール:', tools.map(t => t.name));

  // ツールを呼び出す
  const result = await client.callTool({ name: 'greet', arguments: { name: 'World' } });
  console.log('ツール結果:', result.content);

  // セッションを明示的に終了(HTTP DELETE を送信)
  await client.close();
  console.log('切断完了');
}

main().catch(console.error);

接続断後の再接続(Resumability)を使う場合は、Last-Event-ID ヘッダーを付けて HTTP GET を送ると、サーバー側の InMemoryEventStore から途中のイベントが再配信される。これは接続が不安定なモバイル環境やサーバーレス環境で特に有用だ。

セッション管理と MCP-Protocol-Version ヘッダー

Streamable HTTP 仕様において、ヘッダーの扱いは実装品質を大きく左右する。以下の3種類を正しく理解しておく。

MCP-Session-Id(セッション識別子)
サーバーが InitializeResult レスポンスに付与するセッション識別子。以降のすべての HTTP リクエストに含める必要がある。暗号論的に安全な UUID や JWT が推奨される。セッションが存在しないリクエストに対してサーバーは HTTP 404 を返す。

MCP-Protocol-Version(プロトコルバージョン指定)
初期化完了後のすべての HTTP リクエストに MCP-Protocol-Version: 2025-11-25 を含める必要がある。これはサーバーが複数バージョンをサポートする際に正しい仕様でレスポンスを返すために使われる。未対応バージョンを送ると HTTP 400 が返る。

Last-Event-ID(再接続用イベント ID)
接続断後に再接続する際の SSE イベント ID。HTTP GET に含めることでサーバーはそのイベント ID 以降のメッセージを再配信する。このメカニズムは SSE 標準仕様(HTML Living Standard)に準拠している。

SSE を使う場面 vs POST 単発レスポンスの判断フロー

Streamable HTTP では、クライアントからの POST に対してサーバーが返すレスポンスが2通りある。

  • application/json(単発 JSON 応答): ツール呼び出しが即座に完了し、追加の通知も不要な場合。最もシンプルでサーバーレス環境に適している
  • text/event-stream(SSE ストリーム): レスポンスまでに時間がかかる処理、途中経過の通知(ログ送信等)、複数のメッセージを順次送りたい場合

クライアントは Accept ヘッダーに application/jsontext/event-stream の両方を指定する必要があり、サーバーがどちらを返しても処理できなければならない。Python SDK の json_response=True オプション(または --json-response フラグ)を使えば常に JSON 応答に強制できる。これはサーバーレスやエッジコンピューティング環境で SSE が扱えない場合に便利だ。

クロスランゲージ動作確認 — Python サーバーに TypeScript クライアントで接続する

MCP の重要な特性は言語非依存であることだ。Python で実装したサーバーに TypeScript クライアントが接続できる。以下は動作確認用の最小構成例だ。

# terminal 1: Python サーバー起動
python server.py
# ログ: MCP server running on http://0.0.0.0:8000
# terminal 2: TypeScript クライアントで接続確認
npx tsx client.ts
# 接続成功
# 利用可能なツール: [ 'calculate', 'list_files' ]
# ツール結果: [ { type: 'text', text: '2 + 3 * 4 = 14' } ]

接続が成功しない場合のデバッグは Python SDK の MCP Inspectormcp dev server.py)が最も手軽だ。ブラウザの開発者ツールでネットワークタブを開き、POST /mcp の HTTP 200 と MCP-Session-Id ヘッダーの存在を確認すること。

本番デプロイ前のセキュリティチェックリスト

MCP 公式仕様は Streamable HTTP における DNS リバインディング攻撃への対策を必須としている。本番環境に持ち出す前に以下を必ず確認する。

  • Origin ヘッダー検証: すべての受信リクエストで Origin ヘッダーを検証し、不正な場合は HTTP 403 を返す(仕様上 MUST)
  • ローカル開発時のバインドアドレス: ローカル開発では 0.0.0.0 ではなく 127.0.0.1 のみにバインドする(仕様上 SHOULD)
  • 認証の実装: 本番では必ず Bearer Token + OAuth 2.1 等の認証を実装する。詳細は MCP OAuth 認証実装ガイド を参照
  • CORS 設定: ブラウザ経由のアクセスが必要な場合、origin: '*' は開発専用。本番では許可オリジンを明示的に列挙する
  • セッション ID の安全な生成: randomUUID()crypto.randomBytes() を使い、予測可能な値を使わない

FastMCP との棲み分け — どちらを使うか

Python SDK には FastMCP(高レベル API)と Server(低レベル API)の2種類がある。基本的には FastMCP から始めてよい。FastMCP サーバー構築ガイドで詳しく解説しているが、簡単に棲み分けをまとめると以下の通りだ。

観点 FastMCP(高レベル) Server(低レベル)
コード量 少ない(デコレータベース) 多い(明示的なハンドラ定義)
カスタマイズ性 中程度 高い
推奨場面 新規プロジェクト・プロトタイプ 細かいプロトコル制御が必要な場合
Streamable HTTP 対応 あり(transport="streamable-http" あり(anyio.run() + transport 直接指定)

TypeScript 側でもサーバーとしては McpServer(高レベル)と Server(低レベル)があり、公式 examples では McpServer + NodeStreamableHTTPServerTransport の組み合わせが標準的な構成とされている。MCP Tool Annotations(ツールメタデータ)の詳細については Tool Annotations 設計ガイドも参照してほしい。

MCP レジストリ(Smithery)との連携

Streamable HTTP サーバーとして実装が完了したら、Smithery MCP レジストリへ公開することでほかのエージェントやクライアントから発見可能になる。Smithery は MCP サーバーのディレクトリサービスであり、サーバー URL・認証方法・提供ツール一覧のメタデータを登録することで、Claude.ai や各種 MCP 対応クライアントが自動的にサーバーを検出・利用できるようになる。

まとめ

Streamable HTTP トランスポートは、MCP をクラウドやマルチテナント環境に展開するための現行標準(spec 2025-11-25)だ。今回の記事で扱ったポイントを整理する。

  • 旧 HTTP+SSE に代わり、単一エンドポイント(POST/GET/DELETE)に集約されたことでロードバランサ問題が解消された
  • Python SDK(mcp 1.27.2)の FastMCP + transport="streamable-http" で最小構成のサーバーが数分で動く
  • TypeScript SDK(v1.29.0)の StreamableHTTPClientTransport でクロスランゲージ接続が可能
  • MCP-Session-Id / MCP-Protocol-Version / Last-Event-ID の3ヘッダーを正しく扱うことが実装品質の鍵
  • Origin ヘッダー検証・認証実装・CORS 設定は本番必須

この記事を読んで導入イメージが固まってきた方へ

UravationではAIエージェント導入の研修・コンサルを行っています。MCP を活用した社内ツール連携や AI エージェント基盤の設計相談もお気軽にどうぞ。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年6月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事