リモートサーバーで動かす Python MCP Server — Streamable HTTP 時代の始まり ~ uv / Docker / pytest を備えたミニマルテンプレート付き ~

## まず結論：Python 製 MCP Server がクラウドで動きます

従来、MCP サーバと言えば「ローカル用」というイメージが強く、Server-Sent Events (SSE) や補助的な WebSocket を組み合わせる構成に悩む声も少なくありませんでした。
しかし、**つい数日前の2025年5月8日**、[MCP Python SDK の v1.8.0 がリリース](https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.8.0)され、待望の **Streamable HTTP トランスポートが正式にサポート**されました。
このリリースノートでは、「This is the first release supporting the new Streamable HTTP transport from protocol version 2025-03-26, which supersedes the SSE transport from protocol version 2024-11-05. 🎉」と高らかに宣言されており、MCP の通信プロトコルにおける重要なマイルストーンであることが伺えます。

この Streamable HTTP により、1本の標準的な HTTP コネクションだけで双方向ストリーム通信を扱えるようになり、**VPS、Cloud Run、AWS Lambda といった一般的なクラウド環境で Python 製 MCP Server をそのまま公開・運用する道が大きく開かれました。**

> クラウドに配置し、既存の HTTP インフラストラクチャ（ロードバランサ、CDN、WAFなど）を活用しつつ、サーバ内部では Python の豊富なエコシステム（任意の機械学習ライブラリや LLM）を直接呼び出す——これにより、Python を使った MCP アプリケーション開発の柔軟性と拡張性が飛躍的に向上します。

### Streamable HTTP の技術的な魅力：少し深掘り

MCP の仕様における Streamable HTTP トランスポート ([公式仕様](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http)参照) は、単に「HTTPでストリーミングできる」以上の洗練された仕組みを提供し、従来のHTTP+SSE方式の課題解決を目指しています。主な特徴は以下の通りです。

*   **エンドポイントの統合と通信の簡素化**: 従来、SSE接続の確立用とメッセージ送信用に別々のエンドポイント（例: `/sse` と `/sse/messages`）を管理する必要がありましたが、Streamable HTTPではこれらが単一のエンドポイント（例: `/mcp`）に集約されました。クライアントからのメッセージ（リクエスト、通知、レスポンス）は常にHTTP POSTリクエストとしてこの単一エンドポイントに送信され、サーバーは必要に応じてその応答をSSEストリームとして返すか、単一のJSONレスポンスを返します。これにより、クライアント・サーバー双方の実装と運用が簡素化されます。
*   **柔軟な接続維持と効率的な双方向性**:
    *   接続は通常のHTTPリクエストとして開始され、サーバー側の判断で必要に応じてその接続上でSSEストリームに「アップグレード」されます。これにより、必ずしも常時接続を維持する必要がなくなり、特にサーバーレス環境などでのリソース効率が向上します。「最初は通常のHTTP接続で開始し、必要に応じて逐次データ送信へ切り替わるため、常時オープンな専用接続が不要」になる点は大きなメリットです。
    *   サーバーは確立されたSSEストリームを通じて、クライアントからのリクエストに対する応答だけでなく、任意のタイミングで通知や追加のリクエストをクライアントに送信できます。これにより、実質的な双方向通信が単一の論理的コネクション上で実現されます。
    *   クライアント側も、サーバーからの自発的なメッセージ（例：リソースの変更通知など）を受信するために、別途HTTP GETリクエストでSSEストリームを確立し、待ち受けることが可能です。
*   **セッション管理と将来的な堅牢性向上 (Resumability & Cancellability)**:
    *   MCP仕様では、`Mcp-Session-Id` HTTPヘッダを用いたステートフルなセッション管理の枠組みが定義されています。これにより、サーバーはクライアントごとの状態を保持し、複数のリクエストや接続にまたがる文脈を維持できます。
    *   また、SSEの標準機能である `Last-Event-ID` ヘッダを利用したストリームの再開（Resumability）や、クライアントからの明示的な操作キャンセル（Cancellability）といった、より堅牢な通信を実現するための高度な機能もMCP仕様には盛り込まれています。これらはSDKで順次対応が進められており、ネットワークが不安定な環境でも、通信の途中再開や不要な長時間処理の中止が可能になることが期待されます。
    *   MCP Python SDK v1.8.0時点では、これらの高度なセッション管理機能はまだ完全には実装されておらず、主に将来的な拡張のための基盤と位置づけられています。しかし、基本的なStreamable HTTPの送受信は仕様通り動作し、従来のSSE方式と同等の機能（機能パリティ）は達成されていると報告されています。
*   **後方互換性への配慮**: 旧来の HTTP+SSE トランスポート (protocol version 2024-11-05) との互換性を保つためのガイドラインも提供されており、既存システムからの段階的な移行も考慮されています。例えば、Cloudflareの実装では、旧来のSSE用パスと新しいStreamable HTTP用パスをサーバー側で併用することで、両方のバージョンのクライアントに対応する例が示されています。

これらの特性により、Streamable HTTP は、単なる一方向のストリーミングを超え、より効率的で柔軟、かつ将来的に堅牢性も向上する双方向通信基盤を、標準的なHTTPプロトコル上で実現していると言えるでしょう。

Cloudflare のブログ記事「[Bringing streamable HTTP transport and Python language support to MCP servers](https://blog.cloudflare.com/streamable-http-mcp-servers-python/)」(2025年4月30日付) でも、この新しいトランスポートのシンプルさが強調されています。以前のSSEベースのトランスポートでは、メッセージの送受信用に別々のエンドポイントを管理する必要がありましたが、Streamable HTTP では単一のエンドポイントでこれらが完結します。同記事ではこの変化を「以前はまるで2台の電話機（聞く用と話す用）で会話するようなものだった」と巧みに表現しており、Streamable HTTPがいかに開発者の負担を軽減するかが伺えます。

## 1. Python SDK の進化：Streamable HTTP 対応で広がる可能性

MCP Python SDK が Streamable HTTP に対応したことで、Python を用いた MCP サーバー開発の選択肢と可能性はどのように広がるのでしょうか。先行して Streamable HTTP に対応していた TypeScript SDK と比較しつつ、Python ならではの利点を見ていきましょう。

| 観点                      | TypeScript SDK (Node.jsベース)                                  | Python SDK (v1.8.0 以降)                                                                 |
| :------------------------ | :-------------------------------------------------------------- | :--------------------------------------------------------------------------------------- |
| **Streamable HTTP対応**   | 既にサポート済み                                                    | **v1.8.0 で正式サポート**                                                                  |
| **LLM・機械学習ライブラリ** | JavaScriptエコシステムに依存                                        | PyTorch, TensorFlow, Hugging Face Transformers など、**Pythonの豊富なエコシステムをフル活用可能** |
| **サーバーレスデプロイ**    | Cloud Functions, AWS Lambda (Node.jsランタイム) などで実績あり        | Cloud Run, AWS Lambda (Pythonランタイム) などで、**同様の容易さでデプロイ可能に**                  |
| **エコシステムの成熟度**    | 比較的早期からMCP対応が進み、関連ツールやサンプルも充実している傾向あり | Pythonコミュニティの強みを活かし、急速にキャッチアップ中。本テンプレートもその一助。                 |

この比較から見えてくるのは、Python SDK が Streamable HTTP に対応したことで、機能面で TypeScript SDK に追いつきつつ、Python が得意とする **LLM推論やデータサイエンス処理との親和性の高さ** を最大限に活かせるようになった点です。これにより、例えば以下のようなことがより容易になります。

*   MCPサーバー内部で直接、高度な自然言語処理や機械学習モデルを実行し、その結果をリアルタイムにクライアント（AIエージェントなど）に提供する。
*   既存のPythonベースの機械学習ワークフローやデータパイプラインとMCPサーバーをシームレスに連携させる。

つまり、Python 版の Streamable HTTP 対応は、単に新しい通信方式が使えるようになったというだけでなく、Python の強力なエコシステム全体を MCP の世界に本格的に持ち込む扉を開いたと言えるでしょう。


## 2. "公式サンプルが分かりづらい" を埋めるミニマルテンプレート

<https://github.com/akitana-airtanker/mcp-python-streamable-e2e-test-template>

| 目的 | 実装内容 |
| --- | --- |
| **すぐ動かしたい** | `mcp-server-demo` / `mcp-client-demo` を同梱 |
| **環境差異をなくしたい** | `Dockerfile` + VS Code **Dev Container** |
| **テスト前提で始めたい** | `pytest-asyncio` による E2E を初期搭載 |
| **整形・品質を保ちたい** | `pre-commit` + **Ruff** で lint / format 自動化 |
| **インストールを速く** | **uv** で `venv` と `pip` を高速化 |

テンプレートをクローン → `uv venv && uv pip install -e ".[dev,test]"` → `pytest` 実行まで *約 3 分*。Streamable HTTP が期待通りに往復することを確認できます。


## 3. クイックスタート と セットアップ詳細

このテンプレートを最大限に活用するためのセットアップ手順と、その背景にある仕組みを詳しく見ていきましょう。

### 3.1 基本的な起動手順

まずは、リポジトリをクローンしてからサーバを起動し、クライアントから接続するまでの基本的な流れです。

```bash
# 1. リポジトリをクローン
git clone https://github.com/akitana-airtanker/mcp-python-streamable-e2e-test-template.git my-mcp
cd my-mcp

# 2. uv で仮想環境を作成し、依存関係をインストール
uv venv  # .venv ディレクトリに仮想環境が作成されます
uv pip install -e ".[dev,test]" # 開発用・テスト用依存もまとめてインストール

# 3. 仮想環境を有効化
source .venv/bin/activate      # Linux / macOS の場合
# .venv\Scripts\activate         # Windows (Command Prompt) の場合
# .\.venv\Scripts\Activate.ps1 # Windows (PowerShell) の場合

# 4. MCPサーバを起動
mcp-server-demo
# デフォルトで http://0.0.0.0:8000/mcp でリクエストを待ち受けます
```

別のターミナルを開き、同様に仮想環境を有効化してからクライアントを実行します。

```bash
# (別ターミナルで仮想環境を有効化後)
# 5. MCPクライアントを実行
mcp-client-demo
# "Result of add(10, 5): 15" と表示されれば成功です

# 6. E2Eテストを実行
pytest
# すべてのテストがパス (緑色のOK) することを確認します
```

### 3.2 セットアップのポイント解説

#### `uv` による高速な環境構築：Pythonパッケージングの次世代エース

このテンプレートでは、Python の新しいパッケージマネージャである `uv` を全面的に採用しています。`uv` は、Python 界で今最も注目されているツールの一つと言っても過言ではありません。

*   **`uv` とは？**:
    *   高性能リンター `Ruff` の開発元としても知られる **Astral 社** によって開発されている、Rust 製の高速 Python パッケージングツールです。
    *   単に `pip` や `venv` の代替を目指すだけでなく、`pip-tools` のような依存関係固定（ロッキング）機能や、将来的には `Poetry` や `PDM` のようなプロジェクト管理機能までカバーすることを目指しています ([参考: Bite code! の記事](https://www.bitecode.dev/p/a-year-of-uv-pros-cons-and-should) や [Hacker News の議論](https://news.ycombinator.com/item?id=42415602))。
    *   その圧倒的な速度と野心的なスコープから、Python の標準ツールチェーンに大きな影響を与える可能性を秘めていると期待されています（ただし、`Poetry` や `PDM` の全ての機能を現時点で完全に代替するものではありません）。
*   **導入方法**: もし `uv` がシステムにインストールされていない場合は、[uv 公式ドキュメント](https://github.com/astral-sh/uv#installation) を参照してインストールしてください。`pipx install uv` や `cargo install uv` などの方法があります。
*   **本テンプレートでのメリット**:
    *   **`uv venv`**: 仮想環境の作成が文字通り一瞬で完了します。
    *   **`uv pip install`**: 複雑な依存関係を持つプロジェクトでも、解決とパッケージのダウンロード・インストールが劇的に高速化されます。従来の `pip` で数分かかっていた処理が数秒で終わることも珍しくありません。
    *   本テンプレートでは、`pyproject.toml` に定義された依存関係（通常版、開発用 `[dev]`、テスト用 `[test]`）を `uv pip install -e ".[dev,test]"` の一発で効率的にインストールできます。この速度は、CI/CD パイプラインの実行時間短縮にも大きく貢献します。

`uv` を採用することで、開発サイクルのあらゆる場面で時間的コストを削減し、より本質的な開発作業に集中できるようになります。

#### `pre-commit` と `Ruff` による品質維持：モダンPython開発のベストプラクティス

コードの品質を自動的に高く保つことは、現代的なソフトウェア開発において不可欠です。このテンプレートでは、`pre-commit` フックと `Ruff` を組み合わせることで、そのベストプラクティスを導入しています。

*   **`pre-commit`**: Git のコミット前に、あらかじめ定義されたチェック処理（フック）を自動的に実行するフレームワークです ([公式サイト](https://pre-commit.com/))。
    *   `uv pip install -e ".[dev,test]"` で `pre-commit` 本体も開発依存としてインストールされます。
    *   利用を開始するには、リポジトリのルートで `pre-commit install` を一度だけ実行します。これにより、Git のフックが設定され、以降のコミット時に自動でチェックが走るようになります。
*   **`Ruff`**: Astral 社が開発する、Rust 製の超高速 Python リンター兼フォーマッターです ([公式サイト](https://github.com/astral-sh/ruff))。
    *   驚異的なのはその速度だけでなく、従来 `Flake8`, `isort`, `pydocstyle`, `pyupgrade` など複数のツールで行っていたチェックやフォーマットの大部分を `Ruff` 単体でカバーできる点です。これにより、設定ファイルがシンプルになり、ツールの管理コストも大幅に削減されます。
    *   `.pre-commit-config.yaml` に `Ruff` のフックが定義されており、コミットしようとすると自動的にコードの静的解析（潜在的なバグや非推奨な書き方の検出）とフォーマット（コーディングスタイル統一）が実行されます。
    *   もし問題が見つかればコミットは中断され、修正を促されます。多くの場合、`Ruff` が自動で修正可能な問題は修正してくれます。

この `pre-commit` + `Ruff` の組み合わせは、Python コミュニティで急速にデファクトスタンダードとなりつつあり、チーム開発におけるコードの一貫性維持や、レビュー負荷の軽減に大きく貢献します。

#### VS Code Dev Container による環境再現性：よりスムーズな開発体験

VS Code をお使いの場合、Dev Container 機能を利用することで、開発環境構築の手間をさらに削減し、よりスムーズな開発体験を得られます。

*   **Dev Container とは？**: Docker コンテナ内に完全に隔離された開発環境を構築し、VS Code から直接利用できるようにする仕組みです。
*   **使い方**:
    1.  VS Code で本テンプレートプロジェクトを開きます。
    2.  [Dev Containers 拡張機能](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) がインストールされていれば、右下に「Reopen in Container」という通知が表示されるのでクリックします。
*   **メリット**:
    *   `.devcontainer/devcontainer.json` ファイルに、使用する Docker イメージ、インストールする VS Code 拡張機能、コンテナ作成後に実行するコマンド（`postCreateCommand` での `uv pip install` や `pre-commit install` など）が全て定義されています。
    *   ローカル環境に Python や `uv`、各種ツールを個別にインストールする必要が一切ありません。
    *   チームメンバー全員が全く同じツールと同じバージョンで開発でき、「私の環境では動いたのに」といった問題を撲滅できます。

## 4. テンプレートの中身を覗く (主要ファイル解説)

<https://github.com/akitana-airtanker/mcp-python-streamable-e2e-test-template>

このテンプレートは、Streamable HTTP 対応の MCP サーバを迅速に開発するための骨格を提供します。主要なファイルとその役割を見ていきましょう。

```
.
├── Dockerfile               # コンテナイメージ定義 (python:3.13-slim ベース、非root実行)
├── .devcontainer/
│   └── devcontainer.json    # VS Code Dev Container 設定
├── src/
│   └── mcp_python_streamable_e2e_test_template/
│       ├── __init__.py
│       ├── client.py        # サンプルMCPクライアント実装
│       ├── config.py        # 環境変数からの設定読み込み
│       └── server.py        # FastMCPサーバ本体とツール・リソース定義
├── tests/
│   ├── conftest.py        # pytestフィクスチャ (テスト用サーバ起動など)
│   └── test_client.py     # E2Eテストケース (Streamable HTTP経由でのツール呼び出し)
├── .pre-commit-config.yaml  # pre-commitフック定義 (Ruffなど)
├── pyproject.toml           # プロジェクト定義、依存関係 (uv用)
└── README.md                # プロジェクト詳細説明
```

### `src/server.py` - MCPサーバの心臓部

`FastMCP` を使って MCP サーバを定義し、ツールやリソースを登録します。

```python
import logging
import os
from mcp.server.fastmcp import FastMCP
from .config import Config

# 設定読み込み (環境変数 LOG_LEVEL, MCP_SERVER_PORT など)
cfg = Config()
# ... (ポート設定ロジック) ...

# FastMCPインスタンス生成 (サーバ名 "Demo" はログ等で使用)
server: FastMCP = FastMCP("Demo")
logging.basicConfig(level=cfg.log_level, format="...")
logger = logging.getLogger(server.name)

# 'add' ツール定義
@server.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    logger.debug(f"Tool 'add' called with a={a}, b={b}")
    result = a + b
    logger.debug(f"Tool 'add' result: {result}")
    return result

# 'greeting' リソース定義
@server.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting."""
    logger.debug(f"Resource 'greeting://{name}' accessed")
    greeting = f"Hello, {name}!"
    # ...
    return greeting

def main() -> None:
    """サーバ起動のエントリポイント"""
    transport = os.getenv("MCP_TRANSPORT", "streamable-http") # デフォルトでStreamable HTTP
    logger.info(f"Starting server '{server.name}' with transport '{transport}'...")
    server.run(transport=transport) # サーバ実行！

if __name__ == "__main__":
    main()
```

*   **`FastMCP("Demo")`**: 軽量な MCP サーバインスタンスを作成します。
*   **`@server.tool()`**: このデコレータを付けた関数が MCP ツールとして公開されます。型ヒントが引数と返り値のスキーマ定義に使われます。
*   **`@server.resource("greeting://{name}")`**: URI パターンにマッチするリソースを定義します。`{name}` の部分が関数の引数に渡されます。
*   **`server.run(transport="streamable-http")`**: これが Streamable HTTP でサーバを起動するコマンドです。

### `src/client.py` - サーバと対話するクライアント

Streamable HTTP を使ってサーバに接続し、ツールを呼び出すサンプルクライアントです。

```python
import asyncio
from mcp import ClientSession, types
from mcp.client.streamable_http import streamablehttp_client # Streamable HTTPクライアント

async def run_client(quiet: bool, verbose: bool) -> None:
    server_url: str = "http://localhost:8000/mcp" # 接続先

    try:
        async with streamablehttp_client(server_url) as (
            client_read_stream, client_write_stream, client_get_session_id_callback
        ):
            async with ClientSession(client_read_stream, client_write_stream) as current_session:
                session: ClientSession = current_session
                await session.initialize() # セッション初期化
                logger.info(f"Connected. Session ID: {client_get_session_id_callback()}")

                tool_name: str = "add"
                arguments: dict[str, Any] = {"a": 10, "b": 5}
                response_object: types.CallToolResult = await session.call_tool(
                    tool_name, arguments # 'add'ツール呼び出し
                )
                # ... (レスポンス処理) ...
    # ... (エラーハンドリング) ...

# ... (main関数とargparse) ...
```
*   **`streamablehttp_client(server_url)`**: 指定した URL に対して Streamable HTTP で接続を試みる非同期コンテキストマネージャです。成功すると読み書き用のストリームとセッションID取得コールバックを返します。
*   **`ClientSession(...)`**: ストリームを使って MCP セッションを管理します。
*   **`session.call_tool(...)`**: 指定したツール名と引数でサーバ側のツールを実行します。

### `Dockerfile` - 再現可能な実行環境

このファイルは、MCP サーバアプリケーションを実行するための Docker イメージをビルドする方法を定義します。

```dockerfile
# ベースイメージ (Python 3.13 slim版)
FROM python:3.13-slim

# ... (システムユーティリティ、uvインストール) ...

# 非rootユーザー作成 (セキュリティのため)
ARG APP_USER=appuser
RUN groupadd ${APP_USER} && useradd -ms /bin/bash -g ${APP_USER} ${APP_USER}

WORKDIR /app # 作業ディレクトリ

# 依存関係ファイルコピー & uvでインストール
COPY pyproject.toml uv.lock* ./
COPY src/ ./src
COPY README.md ./README.md
RUN uv venv .venv && \
    . .venv/bin/activate && \
    uv pip install --no-cache-dir -e ".[test,dev]"

COPY . . # 残りのコードをコピー
RUN chown -R ${APP_USER}:${APP_USER} /app # 所有権変更

USER ${APP_USER} # 非rootユーザーに切り替え

# venv内のコマンドを使えるようにPATH設定
ENV VIRTUAL_ENV="/app/.venv"
ENV PATH="/app/.venv/bin:$PATH"

EXPOSE 8000 # サーバがリッスンするポート
CMD ["mcp-server-demo"] # コンテナ起動時のデフォルトコマンド
```
*   **`FROM python:3.13-slim`**: 軽量な公式 Python イメージをベースにします。
*   **`uv venv` & `uv pip install`**: コンテナ内でも `uv` を使って高速に環境をセットアップします。
*   **非rootユーザー実行**: `USER ${APP_USER}` で、より安全な実行形態をとります。
*   **`CMD ["mcp-server-demo"]`**: コンテナ起動時に `mcp-server-demo` スクリプト（`src/server.py` の `main` 関数）が実行されます。

### `tests/` ディレクトリ - E2Eテストによる品質保証

`pytest` を使ったE2Eテストが、Streamable HTTP 通信の正しさを保証します。

**`tests/conftest.py` (テスト設定とフィクスチャ):**
```python
import pytest
import subprocess
import os
import time

@pytest.fixture(scope="session")
def mcp_server_url() -> str:
    # テスト用に別ポート(8001)でサーバを起動
    port = "8001"
    env = os.environ.copy()
    env["MCP_SERVER_PORT"] = port # 環境変数でポート指定
    env["LOG_LEVEL"] = "WARNING"  # テスト中はログを抑制

    # サーバをバックグラウンドプロセスとして起動
    process = subprocess.Popen(
        ["mcp-server-demo"],
        env=env,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    time.sleep(1) # サーバ起動待ち (より堅牢な待機処理が望ましい場合も)
    yield f"http://localhost:{port}/mcp" # テストケースにサーバURLを提供

    process.terminate() # テスト終了後にサーバを停止
    process.wait()
```
*   `mcp_server_url` フィクスチャは、セッション開始時に `mcp-server-demo` を **ポート 8001** で起動します。これは、`src/server.py` 内のロジックで `MCP_SERVER_PORT` 環境変数が `FASTMCP_PORT` に優先されるためです。これにより、開発用サーバ（デフォルト8000番）とテスト用サーバが衝突しません。

**`tests/test_client.py` (テストケース):**
```python
import pytest
from mcp import ClientSession, types
from mcp.client.streamable_http import streamablehttp_client

@pytest.mark.asyncio
async def test_add_tool_success(mcp_server_url: str) -> None: # フィクスチャからURL取得
    tool_name: str = "add"
    arguments: dict[str, Any] = {"a": 10, "b": 5}
    expected_result: int = 15

    async with streamablehttp_client(mcp_server_url) as ( # テスト用サーバに接続
        read_stream, write_stream, get_session_id_callback
    ):
        async with ClientSession(read_stream, write_stream) as session:
            await session.initialize()
            response: types.CallToolResult = await session.call_tool(tool_name, arguments)

            assert not response.isError
            # ... (結果の詳細な検証) ...
            content_list: list[types.Content] = response.content
            first_content: types.TextContent = content_list[0]
            assert int(first_content.text) == expected_result
```
*   テスト関数は `mcp_server_url` を引数に取り、実際にそのURLへ `streamablehttp_client` で接続します。
*   `add` ツールを呼び出し、返ってきた結果が期待通りであるかを `assert` で検証します。

これにより、「Streamable HTTP でツールを呼び出したら、ちゃんと期待した結果が返ってくる」という一連の流れを自動でテストできます。

## 5. さらに踏み込む活用例：クラウドへの展開

このテンプレートで作成した MCP サーバは、コンテナ化されているため、さまざまなクラウドプラットフォームへの展開が容易です。ここでは代表的な例をいくつか紹介します。

### 5.1 Google Cloud Run で手軽にサーバレス公開

Google Cloud Run は、コンテナイメージをアップロードするだけで、スケーラブルなサーバレス環境にアプリケーションをデプロイできるサービスです。

*   **デプロイ手順の概要**:
    1.  ローカルで Docker イメージをビルドします: `docker build -t gcr.io/YOUR_PROJECT_ID/mcp-server:latest .`
    2.  Google Container Registry (GCR) または Artifact Registry にイメージをプッシュします: `docker push gcr.io/YOUR_PROJECT_ID/mcp-server:latest`
    3.  `gcloud run deploy` コマンドでデプロイします:
        ```bash
        gcloud run deploy mcp-server \
            --image gcr.io/YOUR_PROJECT_ID/mcp-server:latest \
            --platform managed \
            --region YOUR_REGION \
            --allow-unauthenticated \ # 必要に応じて認証を設定
            --port 8000 # DockerfileでEXPOSEしたポート
        ```
        ([公式ドキュメント: Pythonサービスのビルドとデプロイ](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service) も参照)
*   **Streamable HTTP との相性**:
    *   Cloud Run はデフォルトで HTTP/2 をサポートしており、Streamable HTTP のような長時間持続するコネクションや双方向ストリーミングと技術的に相性が良いです。
    *   リクエスト数に応じた自動スケール（ゼロスケールも可能）により、コスト効率の高い運用が期待できます。
*   **考慮事項**:
    *   コールドスタート時間: 最小インスタンス数を1以上に設定することで緩和できます。
    *   タイムアウト設定: Streamable HTTP のセッションが意図せず切断されないよう、Cloud Run のリクエストタイムアウト設定（最大60分）を適切に調整する必要があります。
    *   Glamaプロジェクトによる[認証付きSSEサーバーのCloud Run運用事例](https://glama.ai/mcp/servers/@the-freetech-company/mcp-sse-authenticated-cloud-run)では、Cloud RunのIAM認証とローカルプロキシを組み合わせることで、セキュアなMCPサーバー公開を実現しています。
    *   Cloud Runは2020年10月よりHTTPストリーミング（SSE含む）を公式サポートしており、MCPサーバーのStreamable HTTPモードも技術的に動作可能です。ただし、Cloud Runのリクエストタイムアウト（最大15分、設定により最大60分）を超える長時間のSSE接続は切断される可能性があるため、MCPプロトコルの推奨（長時間処理の場合はレスポンス完了後にストリームを閉じる）や将来的なResumability機能が重要になります。

### 5.2 AWS Lambda と Function URL で柔軟なサーバレス体験

AWS Lambda もコンテナイメージをサポートしており、Function URL を使えば API Gateway を介さずに直接 HTTP エンドポイントを公開できます。

*   **デプロイ手順の概要**:
    1.  ローカルで Docker イメージをビルドします。
    2.  Amazon Elastic Container Registry (ECR) にイメージをプッシュします ([公式ドキュメント: コンテナイメージを使用した Lambda 関数の作成](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html))。
        ```bash
        # ECRリポジトリ作成 (初回のみ)
        aws ecr create-repository --repository-name mcp-server --image-scanning-configuration scanOnPush=true
        # Dockerログイン
        aws ecr get-login-password --region YOUR_REGION | docker login --username AWS --password-stdin YOUR_AWS_ACCOUNT_ID.dkr.ecr.YOUR_REGION.amazonaws.com
        # イメージにタグ付けしてプッシュ
        docker tag mcp-server:latest YOUR_AWS_ACCOUNT_ID.dkr.ecr.YOUR_REGION.amazonaws.com/mcp-server:latest
        docker push YOUR_AWS_ACCOUNT_ID.dkr.ecr.YOUR_REGION.amazonaws.com/mcp-server:latest
        ```
    3.  ECR イメージを指定して Lambda 関数を作成し、Function URL を有効化します。
        ```bash
        aws lambda create-function \
            --function-name mcp-server-lambda \
            --package-type Image \
            --code ImageUri=YOUR_AWS_ACCOUNT_ID.dkr.ecr.YOUR_REGION.amazonaws.com/mcp-server:latest \
            --role YOUR_LAMBDA_EXECUTION_ROLE_ARN \
            --timeout 300 \ # 必要に応じて調整 (最大900秒)
            --memory-size 512 # 必要に応じて調整
        
        aws lambda create-function-url-config \
            --function-name mcp-server-lambda \
            --auth-type NONE # または AWS_IAM
        ```
*   **Streamable HTTP との相性**:
    *   Function URL は HTTP/1.1 および HTTP/2 に対応しています。
    *   Lambda の実行時間制限（最大15分）とペイロードサイズ制限（リクエスト・レスポンス共に6MB）を考慮する必要があります。Streamable HTTP であっても、長時間のストリーミングや大きなデータ転送には、Lambda のこれらの制約内で動作するよう工夫が必要になる場合があります。
*   **考慮事項**:
    *   **イメージサイズ**: Lambda のコンテナイメージサイズ上限は 10GB です。本テンプレートの Dockerfile は slim イメージをベースにしているため、通常はこの範囲に収まりますが、大規模な機械学習ライブラリを追加する場合は注意が必要です。
    *   **コールドスタート**: Provisioned Concurrency を設定することで緩和できます。
    *   **重量モデルの実行**: `--memory-size` を増やすことで、PyTorch や TensorFlow などの大きなモデルも実行可能ですが、コストとのバランスを考慮する必要があります。

### 5.3 Kubernetes (K8s) で本格的な運用とスケーリング

より高度な制御やスケーラビリティが求められる場合は、Kubernetes (K8s) へのデプロイが選択肢となります。

*   **デプロイ手順の概要**:
    1.  Docker イメージをビルドし、任意のコンテナレジストリ (Docker Hub, GCR, ECRなど) にプッシュします。
    2.  Deployment と Service のマニフェストファイルを作成します。
        ```yaml
        # deployment.yaml (抜粋)
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: mcp-server-deployment
        spec:
          replicas: 2 # 初期レプリカ数
          selector:
            matchLabels:
              app: mcp-server
          template:
            metadata:
              labels:
                app: mcp-server
            spec:
              containers:
              - name: mcp-server-container
                image: YOUR_REGISTRY/mcp-server:latest # プッシュしたイメージ
                ports:
                - containerPort: 8000
        ---
        # service.yaml (抜粋)
        apiVersion: v1
        kind: Service
        metadata:
          name: mcp-server-service
        spec:
          selector:
            app: mcp-server
          ports:
            - protocol: TCP
              port: 80 # Serviceが公開するポート
              targetPort: 8000 # コンテナのポート
          type: LoadBalancer # または ClusterIP/NodePort + Ingress
        ```
    3.  `kubectl apply -f deployment.yaml` と `kubectl apply -f service.yaml` でデプロイします。
*   **スケーリングと可用性**:
    *   **Horizontal Pod Autoscaler (HPA)**: CPU使用率やカスタムメトリクスに基づいてPod数を自動でスケールさせることができます ([公式ウォークスルー](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/))。
        ```yaml
        # hpa.yaml (CPU使用率ベースの例)
        apiVersion: autoscaling/v2
        kind: HorizontalPodAutoscaler
        metadata:
          name: mcp-server-hpa
        spec:
          scaleTargetRef:
            apiVersion: apps/v1
            kind: Deployment
            name: mcp-server-deployment
          minReplicas: 1
          maxReplicas: 5
          metrics:
          - type: Resource
            resource:
              name: cpu
              target:
                type: Utilization
                averageUtilization: 70
        ```
    *   **Ingress**: Service を外部に公開し、ルーティング、SSL終端、HTTP/2サポートなどを提供します。Nginx Ingress Controller や Traefik など、多くの Ingress Controller が HTTP/2 をサポートしており、Streamable HTTP のパフォーマンス向上に寄与する可能性があります。Ingress の設定でバックエンドプロトコルを `HTTP2` (または `GRPC` など、コントローラがサポートする適切な値) に指定することで、Podまでの経路でHTTP/2が維持されるように構成できます（具体的なアノテーションはIngress Controllerのドキュメントをご確認ください）。
*   **考慮事項**:
    *   K8s は学習コストが高いですが、一度構築すれば非常に柔軟で堅牢な運用が可能です。
    *   マネージド Kubernetes サービス (GKE, EKS, AKSなど) を利用すると、コントロールプレーンの管理負担を軽減できます。

これらのクラウドプラットフォームを活用することで、「試してみる → クラウドに上げる → LLM/ML を組み込む」というステップを、このテンプレートを起点としてスムーズに進めることができます。

## 6. コミュニティの動向とMCPの将来性：活発な議論と進化

MCP および関連技術は、Anthropic による最初の発表（[Hacker News での議論: Model Context Protocol](https://news.ycombinator.com/item?id=42237424)参照、2024年12月頃）以来、開発者コミュニティで活発に議論され、進化を続けています。

*   **Streamable HTTP への道のり**: 当初、MCP はステートフルなプロトコルで長寿命コネクションを前提としていましたが、サーバーレス環境へのデプロイの難しさから、より柔軟な通信方式が求められていました。GitHub Discussions の「[State, and long-lived vs. short-lived connections](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/102)」では、Shopify や Automattic (WordPress.com) といった企業で実際に MCP を利用しようとしている開発者たちから、具体的な課題（PHPでのSSE実装の困難さ、サーバーレスでのスケーリング問題など）や、セッショントークン、ステートレス/ステートフル版の分岐、WebSocket の利用といった様々な解決策が提案・議論されました。この活発なフィードバックループを経て、最終的に現在の Streamable HTTP トランスポート（HTTP POST + オプションのSSE）が仕様として採用された経緯があります。これは、MCP がコミュニティと共に進化している証と言えるでしょう。
*   **Cloudflare Workers での Python MCP サーバ**: 前述の Cloudflare の記事では、Cloudflare Workers 上で Python を使って MCP サーバを構築・デプロイする方法も紹介されています。これは、エッジコンピューティング環境での MCP 活用という新たな可能性を示唆しています。特に、既存の FastAPI アプリケーションを `FastAPI-MCP` ライブラリを使って容易に MCP ツールとして公開できる点は、多くの Python 開発者にとって朗報でしょう。
*   **MCP 仕様の継続的な進化とロードマップ**:
    *   Cloudflare は、MCP 仕様で定義されている再接続性 (Resumability)、キャンセル可能性 (Cancellability)、セッション管理 (Session management) といった高度な機能を、自社の Agents SDK に積極的に取り込んでいく方針を示しています。
    *   MCPの公式ロードマップでは、「認証・認可の強化」「サービスレジストリと発見機能」「ストリーミングとサーバーレス対応のさらなる改善（Resumability、ステートレス動作サポートなど）」「マルチ言語SDKとテストの充実」などが優先項目として挙げられており、プロトコル自体がより堅牢でスケーラブルなものへと進化を続けていることが期待されます。
*   **MCPエコシステムの拡大と業界の採用動向**:
    *   **主要プレイヤーの参入が加速**: Anthropic提唱のMCPに対し、**OpenAIが2025年3月に自社製品へのMCP採用を公式表明**したことは特筆すべき動きです。Agents SDKを皮切りに、ChatGPTやAPIへの対応も計画されており、Sam Altman CEOも「MCPは人々に受け入れられており、我々の全プロダクトにサポートを加えることに興奮している」とコメントしています。この事実は、MCPが業界標準プロトコルへと発展する上で極めて大きな推進力となります。
    *   **クラウドベンダーのサポート**:
        *   **Microsoft**: 早くからMCPに関与し、公式C# SDK開発や、Copilot Studio、AutogenフレームワークへのMCP連携を実装。さらにPlaywright（Webテスト自動化ツール）向けのMCPサーバー拡張も公開し、Azure OpenAIサービスやGitHub領域でのサポートも進んでいます。
        *   **Google Cloud (DeepMind含む)**: 「MCP Toolbox for Databases」(旧Gen AI Toolbox for Databases) を発表し、データベースとAIエージェント連携の標準としてMCPをサポート。DeepMind CEOのDemis Hassabis氏も次世代Gemini SDKへのMCP対応を明言しています。また、GoogleのAgent2Agent (A2A) Protocolのマネージド展開先としてCloud Runをサポートし、MCPエージェントのCloud Run上での動作シナリオも推進しています。
        *   **AWS**: 2025年4月には、自社のAIコード支援サービス（CodeWhispererやCodeCatalyst関連と推測される）向けMCPサーバー群をオープンソースで公開。KubeCon EU 2025ではBedrockエージェントでのMCPサポートにも言及し、MCPを「AIとツールの橋渡し標準」として受け入れる姿勢を示しています。
        *   **Cloudflare**: 自社Workersエッジプラットフォーム上でのMCPサーバーホスティングを推進し、Python対応とStreamable HTTP対応のアップデートを2025年4月に発表。Agents SDKを通じて、新旧両トランスポートをサポートする実装を提供しています。
    *   **開発者ツールとスタートアップの動き**: Zed、Replit、Codeium、Sourcegraphといった開発者ツール企業がMCPを自社プラットフォームに統合する動きを見せています。また、Kubernetesベースのプラットフォームを提供するKubiyaや、APIゲートウェイOSS「Kgateway」を拡張した「MCP Gateway」をリリースしたSolo.ioなど、クラウドネイティブなスタートアップによる採用も活発です。
    *   **豊富なサーバー実装とコミュニティの熱量**: MCP公式サイトの事例紹介ページ ([modelcontextprotocol.io/examples](https://modelcontextprotocol.io/examples)) には、ファイルシステム操作、DB連携、開発ツール連携、ブラウザ自動化、コミュニケーションツール連携、AI特化ツールなど、公式・コミュニティ双方から多様なMCPサーバーがリストアップされています。Axiom、Browserbase、Stripe、Sentry、Prisma、Qdrant、Weaviateといった多くの先進企業が公式インテグレーションを提供しており、エコシステムの成長が加速しています。Python SDKのGitHubリポジトリはスター数約12,000件・フォーク1,300件以上（2025年5月時点）を集め、RedditのMCP関連コミュニティでも活発な情報交換が行われています。「数百のツールベンダーがMCP統合を進めている」との報道もあり、その注目度の高さが伺えます。
    *   **代替実装と技術デモ**: Blaxel のように、SSE の課題を解決するために WebSocket ベースの MCP 実装 (Supergateway のフォーク) を開発し、オープンソースで公開する動きも見られます。また、YouTubeチャンネル「the_context()」では、「[MCP - Can Lambda do it? - Streamable HTTP Model Context Protocol](https://www.youtube.com/watch?v=Ejua5LQTqek)」といった技術デモ動画が公開されるなど、Streamable HTTP とサーバーレスアーキテクチャの組み合わせに対する技術コミュニティの関心も高まっています。
    *   **Cloud Runデプロイ事例**: Mark W Kiehl氏によるMediumの記事「[Deploy Your Custom MCP AI Tool to Cloud Run](https://medium.com/@markwkiehl/deploy-your-custom-mcp-ai-tool-to-cloud-run-a4d443821e67)」(2025年5月1日付) では、`python-a2a`ライブラリを用いたカスタムMCPツールのCloud Runへのデプロイ手順が紹介されており、具体的な運用イメージを掴むのに役立ちます（ただし、SDK v1.8.0リリース前の記事のため、Streamable HTTPを直接利用しているかは不明です）。
*   **MCPの課題と展望**:
    *   ガートナーなどの分析では「現時点ではセキュリティモデルなど未成熟な部分もあり、主にデスクトップアプリ連携用途で使われている」といった指摘もあります。認証・認可の強化や、大規模分散環境での最適化は、今後の重要な課題です。
    *   しかし、「AI業界のUSB-Cポート」とも称されるMCPは、AnthropicやOpenAIといったAI先端企業だけでなく、主要クラウドベンダーまでもが急速に採用を進めるという異例の展開を見せています。この力強い動きは、MCPがAIエージェントと外部サービスを繋ぐデファクトスタンダードへと成長する大きな可能性を示唆しており、今後の動向から目が離せません。

## 7. まとめと次のステップ
本記事では、MCP Python SDK v1.8.0 で正式サポートされた Streamable HTTP トランスポートの登場により、Python 製 MCP サーバーをクラウド環境でより手軽かつ柔軟に運用できるようになったことを解説しました。また、その開発を加速するためのミニマルなE2Eテスト済みテンプレートを紹介し、主要な技術要素やクラウドへの展開例、そして活発なコミュニティの動向についても触れました。

このテンプレートが、あなたの MCP サーバー開発の一助となれば幸いです。
ぜひ、<https://github.com/akitana-airtanker/mcp-python-streamable-e2e-test-template> をクローンし、まずはローカルで Streamable HTTP の挙動を確かめてみてください。そして、その可能性をクラウドへと広げていきましょう。

## 8. 参考資料

*   **MCP (Model Context Protocol) 全般**
    *   MCP Python SDK v1.8.0 リリースノート: [https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.8.0](https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.8.0)
    *   FastMCP (SDK 内サーバ): [https://github.com/modelcontextprotocol/python-sdk/tree/main/mcp/server/fastmcp](https://github.com/modelcontextprotocol/python-sdk/tree/main/mcp/server/fastmcp)
    *   Model Context Protocol 公式サイト: [https://modelcontextprotocol.io/introduction](https://modelcontextprotocol.io/introduction)
    *   MCPサーバー事例集: [https://modelcontextprotocol.io/examples](https://modelcontextprotocol.io/examples)
    *   Awesome MCP Servers (コミュニティによるキュレーションリスト): [https://github.com/punkpeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers)
*   **本テンプレートで利用している主要技術**
    *   uv (Python Package Installer and Resolver): [https://github.com/astral-sh/uv](https://github.com/astral-sh/uv)
    *   Ruff (Python linter / formatter): [https://github.com/astral-sh/ruff](https://github.com/astral-sh/ruff)
    *   pre-commit (Gitフック管理): [https://pre-commit.com/](https://pre-commit.com/)
    *   VS Code Dev Containers: [https://code.visualstudio.com/docs/devcontainers/containers](https://code.visualstudio.com/docs/devcontainers/containers)
    *   pytest (Pythonテストフレームワーク): [https://docs.pytest.org/en/stable/](https://docs.pytest.org/en/stable/)
    *   pytest-asyncio (pytest用asyncioサポート): [https://pytest-asyncio.readthedocs.io/](https://pytest-asyncio.readthedocs.io/)
*   **関連技術**
    *   Docker: [https://docs.docker.com/](https://docs.docker.com/)
    *   Python `asyncio`: [https://docs.python.org/3/library/asyncio.html](https://docs.python.org/3/library/asyncio.html)