Skip to content

MCP サーバー アーキテクチャ全体像(v2)

概要

項目内容
ステータス🟡 設計中
親ドキュメント案件提案書
関連設計認証・テナンシ / ツール一覧 / インフラ・実装計画

本ドキュメントは、H2T プロダクト群 MCP サーバーの機能設計の全体像を定義する。コンポーネント構成・責務分担・リクエストフロー・4 プロダクト振り分け方式・トランスポート方式・エラーハンドリング方針をここで確定し、後続の設計書(認証 / ツール / インフラ)の前提とする。

1. システム全体構成

1.1 アーキテクチャ図

1.2 コンポーネント責務

コンポーネント主な責務配置
API Gateway HTTP APIMCP プロトコルの HTTP 受付、TLS 終端、Authorizer 起動、Dispatcher へのルーティング新規(AWS マネージド)
Lambda AuthorizerOAuth 2.1 access_token 検証、scope 確認、認証ユーザー解決(user_id + product の取り出し)新規 / VPC 外 Lambda
Lambda MCP Dispatchertool 呼び出しのルーティング、入力スキーマ検証、レスポンス整形、監査ログ書込、OAuth エンドポイント実装新規 / VPC 外 Lambda
Lambda Data FetcherAurora への SQL クエリ実行、4 プロダクト振り分けによる接続先 Aurora の切替新規 / VPC 内 Lambda
DynamoDBOAuth 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/gmacgmac-db-production-cluster-1 の接続情報
mcp/db/gcorgcor-db-production-cluster の接続情報
mcp/db/pipitkingmeo-db-production-cluster の接続情報
mcp/db/kuchikomi_onekuchikomi-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 /mcpPOSTMCP プロトコルのメインエンドポイント(tools/list、tools/call 等)
GET /oauth/authorizeGETOAuth 認可エンドポイント
POST /oauth/tokenPOSTアクセストークン発行・更新
POST /oauth/revokePOSTトークン失効
POST /oauth/registerPOST動的クライアント登録(RFC 7591)
GET /.well-known/oauth-authorization-serverGETOAuth メタデータ
GET /healthGETヘルスチェック

6. エラーハンドリング

6.1 エラー区分

区分HTTP ステータスJSON-RPC code動作
認証エラー(トークン無効・期限切れ)401-32001クライアントに再認証を促す
認可エラー(scope 不足、テナンシ違反)403-32004tool 結果を isError: true で返す
入力スキーマエラー400-32602詳細メッセージ付きで返却
tool 見つからない404-32601tools/list で確認を促す
Aurora 接続エラー502-32603リトライ可、監査ログに記録
タイムアウト(API Gateway 30 秒超過)504-32603クライアントに通知
レート制限超過429-32003retry_after ヘッダ付き

6.2 エラーレスポンス形式

MCP プロトコルの仕様に従い、JSON-RPC エラー or tool result の isError: true

json
{
  "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 → Lambda29 秒(API Gateway HTTP API 制限)
Lambda Data Fetcher → Aurora10 秒(読取系)
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 製造前確認で決定)

#項目状態
14 製品の mappy_users テーブル構造が完全一致かGMAC で本番確認済(30 カラム、access_level 系含む)。GCOR/PIPIT/口コミONE も同一前提(Phase 2 横展開時に念のため抜き打ち確認)
2OAuth ログイン時の product 選択方式認証設計書で確定、ログイン画面 UI 検討必要
3レート制限の最終値Phase 1 リリース後の運用フィードバックで調整
4監査ログを DynamoDB に何日保持するか1 年(暫定)、コンプライアンス要件があれば見直し
5Lambda Authorizer のキャッシュ TTL5 分(暫定)、トークン失効反映の遅延と引き換え
6API Gateway カスタムドメインmcp.h2t-products.com 等、未確定
7MCP プロトコル仕様変更への追随ポリシー公式 SDK の更新を半年に 1 度ペースで取り込む案

11. 関連ドキュメント