概要
Model Context Protocol(MCP)は、生成AIエージェントと外部リソース間の通信を標準化するプロトコルです。
しかし、標準入出力(stdio)で通信するMCPサーバーをコンテナ環境(特にCloud Run)で運用するには課題があります。
本記事では、Cloud Runのマルチコンテナ機能を使ったサイドカーパターンを採用し、FastAPI×LINE Messaging APIアプリケーションにおいて複数のMCPサーバーを効率よく動作させた実践例を解説します。
親記事:マルチエージェントと対話できるLINE botを開発しよう
サンプルコード:https://github.com/MokonaSato/line-multi-agent-sample
参考文献
Agent Development Kit (ADK) と MCP サーバー を Cloud Run で動かすための実践ガイド
環境・ライブラリなど
開発環境
- Python: 3.12
- フレームワーク: FastAPI 0.115.12
- クラウドリソース: Google Cloud Run + Cloud Build
使用ライブラリ
- LINE連携: line-bot-sdk 3.17.1
- AI連携: google-adk 0.5.0, litellm 1.69.2
- MCP(Model Context Protocol): mcp 1.8.1
インフラ・デプロイ構成
- メインアプリ: Cloud Run
- サイドカー構成: Filesystem MCP Server, Notion MCP Server
- CI/CD: Cloud Build
- シークレット管理: Secret Manager
Supergatewayとは
Supergateway は、MCP サーバー(通常は stdio ベース)とクライアントとの通信手段を変換する ライブラリ/CLI ツールです。
stdio を SSE(Server-Sent Events)や WebSocket(WS)に変換したり、逆に SSE を stdio に変換するためのトランスポート・ブリッジとして機能します。
Notion MCP ServerはSSE対応していなさそうだったため、今回はSupergatewayを利用します。
実装ポイント
1. Cloud Run マルチコンテナ構成例
現状、下記の設定で快適に動作しています。
-
メインコンテナ(line-multi-agent)
は1CPU、1.5GB RAM。 -
MCPサイドカー(Filesystem, Notion)
はそれぞれ0.25CPU、256MB RAM。
spec:
template:
spec:
containers:
- name: line-multi-agent
image: gcr.io/PROJECT_ID/line-multi-agent:BUILD_ID
ports:
- containerPort: 8080
name: http1
env:
- name: NOTION_MCP_URL
value: "http://localhost:3001/sse"
- name: FILESYSTEM_MCP_URL
value: "http://localhost:8000/sse"
resources:
limits:
cpu: "1"
memory: "1.5Gi"
2. supergatewayによるプロトコル変換
stdioベースのMCPサーバーをHTTP(SSE)対応させるためにsupergatewayを使用します。
Filesystem MCP サーバーの設定
spec:
template:
spec:
containers:
# 中略
- name: filesystem-mcp-server
image: node:20-alpine
env:
- name: PORT
value: "8000"
command: ["/bin/sh"]
args:
- -c
- |
set -e
npm install -g @modelcontextprotocol/server-filesystem supergateway
exec npx supergateway --stdio "npx @modelcontextprotocol/server-filesystem /tmp" --port 8000 --healthEndpoint /health
Notion MCP サーバーの設定
spec:
template:
spec:
containers:
# 中略
- name: notion-mcp-server
image: node:20-alpine
env:
- name: PORT
value: "3001"
- name: NOTION_TOKEN
valueFrom:
secretKeyRef:
name: notion-api-key
key: latest
args:
- -c
- |
set -e
npm install -g @notionhq/notion-mcp-server supergateway
CLEAN_TOKEN=$(echo "$NOTION_TOKEN" | tr -d '\n\r' | xargs)
export OPENAPI_MCP_HEADERS="{\"Authorization\":\"Bearer ${CLEAN_TOKEN}\",\"Notion-Version\":\"2022-06-28\"}"
exec npx supergateway --stdio "npx @notionhq/notion-mcp-server" --port 3001 --healthEndpoint /health
3. MCP統合モジュールの実装 (Python)
async def get_tools_async() -> Tuple[
Optional[MCPToolset],
Optional[MCPToolset],
AsyncExitStack,
]:
"""Cloud Run上のMCPサイドカーからツールを取得する
Google ADKのサンプルコードに基づいて、FilesystemとNotionの
MCPサーバーからツールを取得します。タイムアウト機能付き。
Returns:
Tuple[Optional[MCPToolset], Optional[MCPToolset], AsyncExitStack]:
(Filesystemツール, Notionツール, exitスタック)
"""
exit_stack = AsyncExitStack()
filesystem_tools = None
notion_tools = None
# MCP機能が無効化されている場合はスキップ
if not MCP_ENABLED:
return filesystem_tools, notion_tools, exit_stack
# Filesystem MCP (supergateway@localhost:8000) へSSEで接続
try:
filesystem_tools, fs_exit_stack = await asyncio.wait_for(
MCPToolset.from_server(
connection_params=SseServerParams(url=FILESYSTEM_MCP_URL)
),
timeout=MCP_TIMEOUT_SECONDS,
)
await exit_stack.enter_async_context(fs_exit_stack)
except asyncio.TimeoutError:
# 省略
# Notion MCP (localhost:3001) へSSEで接続
try:
notion_tools, notion_exit_stack = await asyncio.wait_for(
MCPToolset.from_server(
connection_params=SseServerParams(url=NOTION_MCP_URL)
),
timeout=MCP_TIMEOUT_SECONDS,
)
await exit_stack.enter_async_context(notion_exit_stack)
except asyncio.TimeoutError:
# 省略
return filesystem_tools, notion_tools, exit_stack