Skip to content

MCP サーバー インフラ設計

項目内容
ステータス🟡 設計中
関連案件#13 Mappy MCP サーバー新設
親ドキュメントMCP サーバー 全体像
関連設計DB(監査ログ) / DB(OAuth)

1. 本ドキュメントの目的

MCP サーバーの AWS 上でのホスティング構成を確定する。

  • 既存 GMAC インフラ(VPC vpc-0b4c742f84f3b2d9d、リージョン ap-northeast-1)への統合
  • コンテナ運用(ECS Fargate)
  • 認証・OAuth 状態管理ストア
  • ネットワーク・セキュリティ
  • 監視・アラート
  • スタック両案(Python / TypeScript)に共通の構成

2. 既存インフラの活用方針

2.1 流用するもの

項目既存リソース流用方針
VPCvpc-0b4c742f84f3b2d9d (10.0.0.0/16)そのまま使用
プライベートサブネットsubnet-095de9e00c1894a0c(1a), subnet-0f38ab1dce252e375(1c)MCP ECS タスク配置先
パブリックサブネットsubnet-0ff23c0ce66750053(1a), subnet-0ebe6abb3572271e8(1c)MCP 専用 ALB 配置先
RDSh2t-db (MySQL 8.0)mappy DB に MCP テーブル追加
ECR新規リポジトリ h2t-mappy-mcp 追加既存命名規則に従う
S3既存バケット新規バケットは原則作らない
CloudWatch既存ロググループ構成に倣う新規ロググループ追加
Route 53既存 hosted zoneサブドメイン mcp.mappy.<existing-domain> を追加
AWS Account635388747933同一アカウント

2.2 新規追加するもの

項目理由
ALBMCP は独立ドメインで動かす(既存 ALB と分離)
ElastiCache(Redis)OAuth 認可コード・セッション・レート制限カウンタ
Secrets ManagerJWT 署名鍵・OAuth クライアントシークレット
ECS サービスh2t-mcp-server Fargate
セキュリティグループh2t-sg-mcp, h2t-sg-mcp-redis
ACM 証明書mcp.mappy.example.com(仮)
WAFDDoS / レート制限の補強(任意)

3. 全体構成図

4. コンテナ構成(ECS Fargate)

4.1 タスク定義

項目
タスク定義ファミリーh2t-mcp-server
起動タイプFargate
プラットフォームバージョンLATEST
CPU0.5 vCPU(Phase 1)/ 1 vCPU(Phase 2 以降)
メモリ1 GB(Phase 1)/ 2 GB(Phase 2 以降)
ネットワークモードawsvpc
タスクロールh2t-mcp-task-role
実行ロールh2t-mcp-execution-role
ログドライバーawslogs
ロググループ/ecs/h2t-mcp-server

4.2 コンテナ定義

項目
イメージ635388747933.dkr.ecr.ap-northeast-1.amazonaws.com/h2t-mappy-mcp:<tag>
ポート8000(コンテナ内)→ ALB から HTTP で転送
ヘルスチェックGET /health(30 秒間隔、5 秒タイムアウト、リトライ 3 回)
ストップタイムアウト30 秒(Streamable HTTP のグレースフルシャットダウン)
環境変数後述「環境変数・シークレット」

4.3 サービス定義

項目
サービス名h2t-mcp-server
クラスターh2t-cluster(既存)または新規 h2t-mcp-cluster
希望タスク数Phase 1: 2 / Phase 2: 4 / Phase 3: 6
最小タスク数2
最大タスク数10
デプロイタイプRolling Update(minimum healthy 50%、maximum 200%)
Auto ScalingTarget Tracking(CPU 70%、リクエスト数 100/分)
ロードバランサーh2t-mcp-alb ターゲットグループ h2t-mcp-tg
サービスディスカバリ任意

Streamable HTTP の sticky session

MCP の Streamable HTTP セッションは long-lived。ALB の sticky session 設定が必要(同一クライアントは同一タスクへ)。または Redis にセッション状態を集中して、stateless にする設計も可。 本設計では Redis 集中管理(stateless) を採用する。

5. ロードバランサー(ALB)

5.1 構成

項目
ALB 名h2t-mcp-alb
スキームinternet-facing
サブネットh2t-public-1a, h2t-public-1c
セキュリティグループh2t-sg-mcp-alb(新規)
アイドルタイムアウト600 秒(Streamable HTTP の長時間接続対応)
HTTP/2有効
WAF アタッチoptional(Phase 2 以降検討)

5.2 リスナー

ポートプロトコル動作
80HTTP301 リダイレクトで HTTPS へ
443HTTPSACM 証明書、ターゲットグループ h2t-mcp-tg へ転送

5.3 ターゲットグループ

項目
名前h2t-mcp-tg
プロトコルHTTP
ポート8000
ヘルスチェックパス/health
ヘルスチェック間隔30 秒
ヘルスチェック閾値成功 2 回、失敗 3 回
デレジストレーション遅延30 秒(接続終了待ち)
Sticky session無効(Redis 集中管理のため)

6. データストア

6.1 ElastiCache Redis(新規)

OAuth 認可コード・セッション・レート制限・idempotency キャッシュ用。

項目
エンジンRedis 7.x
ノードタイプcache.t4g.micro(Phase 1)/ cache.t4g.small(Phase 2 以降)
ノード数1(Phase 1、Multi-AZ なし)/ Cluster Mode(Phase 3 で検討)
サブネットh2t-private-1a, h2t-private-1c
セキュリティグループh2t-sg-mcp-redis
暗号化 (at-rest)有効
暗号化 (in-transit)有効(TLS)
認証Redis AUTH(Secrets Manager で管理)
バックアップ日次スナップショット、7 日保持
maintenance window火曜 04:00-05:00 JST

キー設計

プレフィックス用途TTL
oauth:code:<hash>認可コード60 秒
oauth:state:<hash>state パラメータ検証5 分
mcp:session:<id>Streamable HTTP セッション30 分(idle)
idempotency:<client_id>:<user_id>:<key>冪等性キャッシュ24 時間
confirm:<token>一括反映の確認トークン5 分
ratelimit:<scope>:<key>レート制限カウンタ1 分〜1 時間
jwt:revoke:<jti>アクセストークン失効リスト(Bloom Filter キャッシュ)JWT exp まで

6.2 RDS(既存)

mappy DB に MCP 用テーブル群を追加:

  • mappy_mcp_audit_logs
  • mappy_mcp_batches
  • mappy_mcp_rate_limit_logs
  • mappy_mcp_oauth_clients
  • mappy_mcp_oauth_consents
  • mappy_mcp_oauth_refresh_tokens
  • mappy_mcp_oauth_access_token_revocations

詳細は DB 監査ログ / DB OAuth を参照。

RDS 接続元の SG 更新

既存 h2t-sg-rds のインバウンドに 新規 h2t-sg-mcp からの 3306 アクセスを追加する。

7. ECR・コンテナイメージ

7.1 リポジトリ

名前URI
h2t-mappy-mcp635388747933.dkr.ecr.ap-northeast-1.amazonaws.com/h2t-mappy-mcp

7.2 イメージタグ規約

タグ用途
latest最新 main ブランチ
v1.0.0リリース版
staging-<sha>ステージング
dev-<sha>開発環境

7.3 イメージ構成

案A: Python (FastMCP)

dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY pyproject.toml uv.lock /app/
RUN pip install --no-cache-dir uv && \
    uv sync --frozen --no-dev

COPY src/ /app/src/

USER 1000
EXPOSE 8000

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

案B: TypeScript

dockerfile
FROM node:20-alpine AS build

WORKDIR /app
COPY package.json pnpm-lock.yaml /app/
RUN corepack enable && pnpm install --frozen-lockfile

COPY src/ /app/src/
COPY tsconfig.json /app/
RUN pnpm build

FROM node:20-alpine AS runtime
WORKDIR /app
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
COPY package.json /app/

USER 1000
EXPOSE 8000

CMD ["node", "dist/main.js"]

7.4 イメージサイズ目安

言語期待サイズ
Python (slim base)約 200 MB
Node.js (alpine base)約 150 MB

8. ネットワーク・セキュリティグループ

8.1 新規 SG

SG 名インバウンド用途
h2t-sg-mcp-alb80 / 443 from 0.0.0.0/0ALB
h2t-sg-mcp8000 from h2t-sg-mcp-albECS タスク
h2t-sg-mcp-redis6379 from h2t-sg-mcpRedis

8.2 既存 SG への追加

既存 SG追加インバウンド
h2t-sg-rds3306 from h2t-sg-mcp

8.3 アウトバウンド

全 SG で:

  • 443 to 0.0.0.0/0(GBP API・外部 API 用)
  • 53 to 0.0.0.0/0(DNS)
  • VPC エンドポイントを使う場合は不要

9. 環境変数・シークレット

9.1 環境変数(タスク定義に直接記述)

変数名
APP_ENVproduction / staging
LOG_LEVELINFO
MCP_BASE_URLhttps://mcp.mappy.example.com
OAUTH_ISSUER同上
OAUTH_AUDIENCEmappy-mcp
LARAVEL_API_BASE_URLhttps://api.mappy.example.com
REDIS_HOSTh2t-mcp-redis.cache.amazonaws.com
REDIS_PORT6379
RDS_HOST既存
RDS_DATABASEmappy

9.2 Secrets Manager(参照のみ)

Secret 名内容
h2t-mcp/jwt-signing-keysJWT 署名鍵(RS256 のプライベートキー、複数 kid)
h2t-mcp/redis-auth-tokenRedis AUTH トークン
h2t-mcp/rds-credentialsDB ユーザー名・パスワード
h2t-mcp/laravel-api-tokenLaravel API への内部認証トークン
h2t-mcp/oauth-client-secrets信頼クライアントの secret(registry)

タスクロールに以下の IAM ポリシーを付与:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["secretsmanager:GetSecretValue"],
      "Resource": [
        "arn:aws:secretsmanager:ap-northeast-1:635388747933:secret:h2t-mcp/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": [
        "arn:aws:logs:ap-northeast-1:635388747933:log-group:/ecs/h2t-mcp-server:*"
      ]
    }
  ]
}

10. Route 53 / ドメイン

項目
ドメインmcp.mappy.example.com(仮、確定はレビュー時)
ALB エイリアスh2t-mcp-alb-xxxxxxxx.ap-northeast-1.elb.amazonaws.com
レコード種別A (alias)
ヘルスチェック任意(CloudWatch でカバー可)

10.1 ドメイン候補

注意点
サブドメイン分離mcp.mappy.example.com推奨。CORS・Cookie 分離が容易
パス分離mappy.example.com/mcpNG。Streamable HTTP の長時間接続と既存 ALB 設定が干渉
別ドメインmappy-mcp.com新規ドメイン取得コスト・SEO 配慮不要なら可

11. CI/CD

11.1 既存方式に倣う

ステップ内容
コードリポジトリh2t/mappy-mcp(新規)または h2t/mappy 配下に subdirectory
ビルドパイプラインGitLab CI(既存 CI 流用)
ビルド対象Dockerfile から ECR h2t-mappy-mcp へ push
デプロイECS サービス更新(タスク定義の新リビジョン適用)
ロールバック前リビジョンへ revert

11.2 環境分け

環境ALBECS サービスRedisRDS
本番h2t-mcp-albh2t-mcp-serverh2t-mcp-redish2t-db
ステージングh2t-mcp-alb-stgh2t-mcp-server-stgh2t-mcp-redis-stgh2t-db-stg
開発(ローカル docker-compose)-(ローカル Redis)(ローカル MySQL)

12. 監視・アラート

12.1 CloudWatch Metrics

メトリクス閾値アクション
ECS CPU 利用率> 80% (5 分)Auto Scaling + 通知
ECS Memory 利用率> 80% (5 分)通知
ALB 5xx 率> 1% (5 分)CRITICAL 通知
ALB Target Health< 50% healthyCRITICAL 通知
ALB レスポンス時間p99 > 3 秒 (5 分)WARNING 通知
Redis CPU> 70% (5 分)スケールアップ検討
Redis メモリ> 80%スケールアップ
RDS 接続数> 80% max_connectionsWARNING

12.2 CloudWatch Logs

ロググループ保持期間
/ecs/h2t-mcp-server30 日
/ecs/h2t-mcp-server-access90 日
/ecs/h2t-mcp-server-audit1 年

12.3 ログのフィールド規約

JSON 形式で構造化、以下のフィールドを必ず含める:

json
{
  "timestamp": "2026-05-26T10:00:00Z",
  "level": "INFO",
  "service": "mcp-server",
  "request_id": "...",
  "user_id": 1435,
  "client_id": "...",
  "tool_name": "location.list",
  "elapsed_ms": 123,
  "message": "tool executed"
}

12.4 アラート通知

  • Slack #h2t-mcp-alerts チャンネル
  • CRITICAL は電話通知 + メール

13. バックアップ・DR

対象方法頻度
RDS データ自動バックアップ(既存)日次 7 日
Redis データスナップショット日次 7 日
ECS タスク定義バージョン管理(自動)自動
Secrets Managerバージョン保持自動

RTO(復旧目標時間): 1 時間以内 RPO(復旧目標時点): 直近 24 時間以内のデータ復旧

14. コスト試算(Phase 1)

リソース月額試算
ECS Fargate(2 タスク × 0.5 vCPU / 1 GB)約 30 USD
ALB約 25 USD
ElastiCache Redis(cache.t4g.micro)約 15 USD
ACM 証明書無料
Route 53約 1 USD
Secrets Manager(5 secret)約 2 USD
CloudWatch Logs(30 日 × 5 GB)約 5 USD
ECR ストレージ約 1 USD
データ転送約 5 USD
合計約 84 USD/月

Phase 2 以降:

  • ECS タスク増加(4 タスク × 1 vCPU / 2 GB) → 約 120 USD/月
  • Redis スケールアップ → 約 30 USD/月
  • 合計:約 180 USD/月

コスト最適化

  • Phase 1 では Fargate Spot を活用すれば 30〜50% 削減可
  • 既存 RDS に同居するため DB コストは追加なし
  • ステージング環境は Fargate Spot + ノード 1 で運用可

15. セキュリティチェックリスト

項目状態
ALB は HTTPS のみ(HTTP は 301 リダイレクト)
ECS タスクは private subnet 配置
Redis は in-transit + at-rest 暗号化
RDS は既存設定(暗号化済み)
Secrets Manager の参照は IAM で制限
WAF(Phase 2 以降検討)🔵
VPC エンドポイントで AWS API トラフィック内製化🔵(推奨)
GuardDuty 有効(既存)
AWS Config によるリソース変更追跡既存設定に従う
アクセスログを S3 へ集約🔵

16. デプロイ手順(Phase 1 初回)

  1. 基盤準備

    • 新規 SG 作成(h2t-sg-mcp-alb / h2t-sg-mcp / h2t-sg-mcp-redis
    • 既存 h2t-sg-rds にインバウンド追加
    • ElastiCache Redis インスタンス作成
    • Secrets Manager に JWT 鍵・各種シークレット保管
    • ECR リポジトリ h2t-mappy-mcp 作成
  2. DB マイグレーション

    • mappy_mcp_* テーブル作成(OAuth / 監査ログ の DDL)
    • 初期 OAuth クライアント登録(Claude Desktop / ChatGPT 等)
  3. ALB 構築

    • ACM 証明書発行(mcp.mappy.example.com
    • ALB / ターゲットグループ作成
    • Route 53 レコード追加
  4. ECS 構築

    • クラスター(既存流用 or 新規)
    • タスク定義(IAM ロール、環境変数、Secrets 参照)
    • サービス作成(ALB 連携、Auto Scaling)
  5. アプリ初回デプロイ

    • Dockerfile ビルド & ECR push
    • ECS サービス更新
  6. 動作確認

    • /health 応答確認
    • /.well-known/oauth-authorization-server 確認
    • Claude Desktop / ChatGPT からの接続テスト
  7. 監視・アラート設定

    • CloudWatch Alarm 作成
    • Slack 通知設定

17. 未確定事項(設計レビューで決定)

#項目候補
1MCP 用ドメイン名mcp.mappy.example.com(仮)
2ECS クラスター既存流用 / 新規
3WAF 導入時期Phase 1 / Phase 2
4Redis Multi-AZPhase 1 で対応 / Phase 2 以降
5Fargate Spot の活用範囲全本番 / ステージングのみ
6リポジトリ構成h2t/mappy-mcp 新設 / h2t/mappy 配下
7デプロイ承認フロー自動 / 手動承認
8VPC エンドポイント導入即時 / Phase 2

18. 関連ドキュメント