MCP サーバー アーキテクチャ全体像(v2)
概要
| 項目 | 内容 |
|---|---|
| ステータス | 🟡 設計中 |
| 親ドキュメント | 案件提案書 |
| 関連設計 | 認証・テナンシ / ツール一覧 / インフラ・実装計画 |
本ドキュメントは、H2T プロダクト群 MCP サーバーの機能設計の全体像を定義する。コンポーネント構成・責務分担・リクエストフロー・4 プロダクト振り分け方式・トランスポート方式・エラーハンドリング方針をここで確定し、後続の設計書(認証 / ツール / インフラ)の前提とする。
1. システム全体構成
1.1 アーキテクチャ図
1.2 コンポーネント責務
| コンポーネント | 主な責務 | 配置 |
|---|---|---|
| API Gateway HTTP API | MCP プロトコルの HTTP 受付、TLS 終端、Authorizer 起動、Dispatcher へのルーティング | 新規(AWS マネージド) |
| Lambda Authorizer | OAuth 2.1 access_token 検証、scope 確認、認証ユーザー解決(user_id + product の取り出し) | 新規 / VPC 外 Lambda |
| Lambda MCP Dispatcher | tool 呼び出しのルーティング、入力スキーマ検証、レスポンス整形、監査ログ書込、OAuth エンドポイント実装 | 新規 / VPC 外 Lambda |
| Lambda Data Fetcher | Aurora への SQL クエリ実行、4 プロダクト振り分けによる接続先 Aurora の切替 | 新規 / VPC 内 Lambda |
| DynamoDB | OAuth state(authorization_code / refresh_token / consents)、idempotency キャッシュ、監査ログのうち長期保管不要なもの | 新規(VPC 不要、IAM 経由) |
| Aurora MySQL | 各プロダクトの DB データ(読み取りのみ) | 既存リソース、変更なし |
1.3 配置の方針
- VPC 外 Lambda(Authorizer / Dispatcher): VPC ENI 作成のオーバーヘッドを避け、コールドスタートを最速化。DynamoDB / Secrets Manager / API Gateway 等のマネージドサービスにアクセスするだけで完結
- VPC 内 Lambda(Data Fetcher): Aurora は VPC 内のプライベートサブネットに配置されているため、Aurora 接続のためだけに VPC 内 Lambda を分離
- 責務分離の利点: 認証処理(高頻度・低レイテンシ要求)と DB アクセス処理(中頻度・コールドスタート許容)を分けることで、それぞれに最適なチューニングが可能
2. リクエストフロー
2.1 初回接続・認証フロー(OAuth 2.1 + PKCE)
詳細は 認証・テナンシ設計 を参照。
2.2 tool 呼び出しフロー(読取系・Phase 1)
3. 4 プロダクト振り分け方式
3.1 振り分けロジック
3.2 product の判定タイミング
- 認証時に確定: ユーザーが OAuth 認可フローのログイン画面でログインした際、入力された
login_id+ パスワードを 4 製品のいずれかのmappy_usersテーブルで照合 - どの製品の
mappy_usersテーブルで照合するかは、認可フローの開始時にクライアントが指定したproductクエリパラメータで決定(認証設計 §5.2 参照) - 以降のリクエストでは access_token に含まれた
productクレームから決定的に解決、tool 入力で上書き不可
3.3 Aurora 接続情報の管理
4 製品分の Aurora エンドポイント・認証情報は Secrets Manager に格納し、Lambda Data Fetcher の起動時に動的取得する。env テンプレートに平文コミットされている現状(既存問題)とは独立に管理する。
| Secret 名(仮) | 内容 |
|---|---|
mcp/db/gmac | gmac-db-production-cluster-1 の接続情報 |
mcp/db/gcor | gcor-db-production-cluster の接続情報 |
mcp/db/pipit | kingmeo-db-production-cluster の接続情報 |
mcp/db/kuchikomi_one | kuchikomi-one-db-production-cluster の接続情報 |
4. tool 命名規則
4.1 単一名前空間
<domain>.<action>| 部分 | 例 |
|---|---|
<domain> | location / review / ranking / insight |
<action> | list / get / summary |
例: location.list, review.list, ranking.list, insight.summary
4.2 プロダクト名を含めない理由
4 プロダクトは 同一 Laravel コードベース で動いており、DB スキーマ・カラム名も同一であることが本番調査で確認されている(env テンプレートで DB_DATABASE=gmac が全製品共通)。
そのため、tool 名にプロダクト名を含める必要がなく、1 つの tool(例: location.list)が認証情報から自動で適切な Aurora に振り分けられる設計とする。
これにより:
- 顧客 AI から見ると、製品が違ってもインターフェースが同じ で混乱しない
- MCP サーバー側のコード量が 1/4 になる
- 新しい tool を追加するたび 4 倍書く必要がない
- 命名空間衝突や混同のリスクが減る
4.3 顧客が複数製品を使う場合
1 顧客が複数製品(例: GMAC + GCOR)を併用する場合は、製品ごとに別の OAuth クライアントを登録する。MCP の利用側からは別のサーバーとして見える。
将来的に「1 つの接続で複数製品を切り替える」要件が出てきた時点で、tool 入力に product パラメータを追加することで拡張可能。Phase 1 では実装しない。
5. トランスポート方式
5.1 MCP Streamable HTTP(単発 request/response モード)
MCP 2025-03-26 仕様の Streamable HTTP には 2 つのモードがある:
| モード | 特徴 | Lambda 適合性 |
|---|---|---|
| 単発 request/response | クライアントが POST → サーバーが 1 回 JSON で応答 → 接続クローズ | ◎ API Gateway HTTP API 30 秒制限内に収まる |
| ストリーミング(SSE) | サーバーが長時間 SSE 接続を維持し、tool 実行中の進捗や非同期イベントを push | △ Lambda + Function URL 15 分まで可だが構成複雑化 |
本案件は単発 request/response モードに統一する。理由:
- Phase 1 は読取系のみ(数百 ms 〜 数秒で完了)、ストリーミング不要
- Phase 2 以降の書込系も
batch_idを返してクライアントがbatch.statusをポーリングする方式で対応可能(SSE 不要) - Lambda + API Gateway HTTP API の制約(30 秒)に収まるため、Lambda Function URL ではなく標準的な API Gateway を使える
- 状態管理を DynamoDB に寄せることで Lambda 自体は stateless 維持、スケール容易
5.2 エンドポイント仕様
| パス | メソッド | 用途 |
|---|---|---|
POST /mcp | POST | MCP プロトコルのメインエンドポイント(tools/list、tools/call 等) |
GET /oauth/authorize | GET | OAuth 認可エンドポイント |
POST /oauth/token | POST | アクセストークン発行・更新 |
POST /oauth/revoke | POST | トークン失効 |
POST /oauth/register | POST | 動的クライアント登録(RFC 7591) |
GET /.well-known/oauth-authorization-server | GET | OAuth メタデータ |
GET /health | GET | ヘルスチェック |
6. エラーハンドリング
6.1 エラー区分
| 区分 | HTTP ステータス | JSON-RPC code | 動作 |
|---|---|---|---|
| 認証エラー(トークン無効・期限切れ) | 401 | -32001 | クライアントに再認証を促す |
| 認可エラー(scope 不足、テナンシ違反) | 403 | -32004 | tool 結果を isError: true で返す |
| 入力スキーマエラー | 400 | -32602 | 詳細メッセージ付きで返却 |
| tool 見つからない | 404 | -32601 | tools/list で確認を促す |
| Aurora 接続エラー | 502 | -32603 | リトライ可、監査ログに記録 |
| タイムアウト(API Gateway 30 秒超過) | 504 | -32603 | クライアントに通知 |
| レート制限超過 | 429 | -32003 | retry_after ヘッダ付き |
6.2 エラーレスポンス形式
MCP プロトコルの仕様に従い、JSON-RPC エラー or tool result の isError: true:
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"content": [
{
"type": "text",
"text": "{\"error_code\":\"FORBIDDEN_LOCATION\",\"message\":\"指定された店舗へのアクセス権限がありません\",\"details\":{\"location_id\":8802}}"
}
],
"isError": true
}
}6.3 タイムアウト戦略
| 区間 | タイムアウト |
|---|---|
| 顧客 AI → API Gateway | クライアント側設定(通常 30〜60 秒) |
| API Gateway → Lambda | 29 秒(API Gateway HTTP API 制限) |
| Lambda Data Fetcher → Aurora | 10 秒(読取系) |
| Lambda 全体実行時間 | 30 秒(Phase 1 読取系として十分) |
6.4 リトライ方針
- 読取系: 5xx エラーのみクライアント側で 1 回まで自動リトライ可(DynamoDB / Aurora の一時障害想定)
- Lambda 自動リトライ: API Gateway 経由は同期呼び出しのためデフォルトでは無し(クライアント主導でリトライ)
- Aurora 接続失敗: Lambda Data Fetcher 内で接続を再試行(最大 2 回、合計 5 秒以内)
7. レート制限
API Gateway HTTP API の標準機能で実装。
| 適用範囲 | 制限 | 理由 |
|---|---|---|
| API Gateway 全体 | 10,000 req/秒(バースト 5,000) | DoS 対策(AWS デフォルト値) |
| access_token 単位(Authorizer 経由) | 60 req/分(Phase 1) | 暫定値、運用フィードバックで調整 |
| client_id 単位 | 600 req/時 | クライアント丸ごとの暴走対策 |
8. 監査・モニタリング
8.1 ログ出力
- CloudWatch Logs: 全 Lambda 関数のログ(リクエスト・レスポンスのサマリー、エラー詳細)
- DynamoDB(監査ログ): 認可結果・tool 呼び出し・拒否・トークン発行を構造化記録
- 保持期間: CloudWatch Logs 30 日、DynamoDB は TTL 1 年
8.2 主要メトリクス
| メトリクス | 監視対象 | 通知閾値 |
|---|---|---|
| API Gateway 4xx 率 | 認証ミス検出 | > 5% / 5 分 |
| API Gateway 5xx 率 | サーバー異常 | > 1% / 5 分 |
| Lambda エラー率 | 各関数のエラー | > 1% / 5 分 |
| Lambda 平均実行時間 | パフォーマンス劣化検出 | p95 > 3 秒 / 5 分 |
| DynamoDB スロットリング | 想定外の負荷 | 発生時 |
通知先は既存の cloudwatch-to-slack Lambda を流用する想定。
9. 既存リソースとの干渉回避
| 既存リソース | MCP からの影響 | 対策 |
|---|---|---|
| Aurora 4 クラスター | 接続数の増加 | Lambda reserved concurrency = 10〜20 に設定、max_connections 90(db.t3.medium)の範囲内に抑える |
| 既存 Lambda 11 関数 | なし | 別関数として独立 |
| 既存 ALB 8 本 | なし | API Gateway を別新規構築 |
| Laravel アプリ(EC2) | なし | DB は読取のみ、Laravel 経由の API 呼び出しは Phase 1 では行わない |
既存 Amazon_EventBridge_Invoke_Lambda_* ロール | なし | MCP 用ロールを別に発行 |
10. 未確定事項(設計レビュー or 製造前確認で決定)
| # | 項目 | 状態 |
|---|---|---|
| 1 | 4 製品の mappy_users テーブル構造が完全一致か | ✅ GMAC で本番確認済(30 カラム、access_level 系含む)。GCOR/PIPIT/口コミONE も同一前提(Phase 2 横展開時に念のため抜き打ち確認) |
| 2 | OAuth ログイン時の product 選択方式 | 認証設計書で確定、ログイン画面 UI 検討必要 |
| 3 | レート制限の最終値 | Phase 1 リリース後の運用フィードバックで調整 |
| 4 | 監査ログを DynamoDB に何日保持するか | 1 年(暫定)、コンプライアンス要件があれば見直し |
| 5 | Lambda Authorizer のキャッシュ TTL | 5 分(暫定)、トークン失効反映の遅延と引き換え |
| 6 | API Gateway カスタムドメイン | mcp.h2t-products.com 等、未確定 |
| 7 | MCP プロトコル仕様変更への追随ポリシー | 公式 SDK の更新を半年に 1 度ペースで取り込む案 |