Saltar al contenido principal

MCP Server — Cloud Run Deployment Notes

V1 (API Key, In-Memory Sessions)

  • Sessions are stored in process memory; each Cloud Run instance holds its own session map.
  • Session affinity is required: deploy with --session-affinity flag so all requests for a given session reach the same instance.
gcloud run deploy flowpos-backend \
--image gcr.io/YOUR_PROJECT/flowpos-backend:latest \
--region us-central1 \
--platform managed \
--session-affinity \
--min-instances 1 \
--max-instances 10 \
--memory 512Mi \
--cpu 1 \
--port 4000 \
--set-env-vars NODE_ENV=production \
--set-secrets MCP_TOKEN_SECRET=MCP_TOKEN_SECRET:latest \
--service-account YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com \
--allow-unauthenticated

Replace YOUR_PROJECT and YOUR_SA with your GCP project ID and service account email. The --session-affinity flag is critical for MCP session routing — without it, subsequent JSON-RPC requests may land on a different instance and receive a 404 Session not found error.

  • No additional infrastructure needed beyond the existing PostgreSQL instance (for mcp_api_key table).

V2 (OAuth Tokens, Redis-Backed Sessions)

  • Sessions created via Firebase token exchange persist the session principal in Redis with TTL = token expiry.
  • Required environment variables:
VariableDescriptionExample
MCP_TOKEN_SECRETJWT signing secret (min 32 chars)Set in GCP Secret Manager
MCP_TOKEN_TTL_SECONDSToken lifetime in seconds86400 (24h default)
REDIS_HOSTRedis hostname10.x.x.x (VPC-internal)
REDIS_PORTRedis port6379
REDIS_PASSWORDRedis password (if auth enabled)Set in GCP Secret Manager
  • Redis instance: Use a Memorystore for Redis instance in the same VPC as Cloud Run. Serverless VPC Access connector required.
  • --session-affinity is still required for reliable MCP traffic routing. Redis persistence keeps principal mutations (for example set_active_business) in sync, but the active streamable HTTP transport remains in-memory per instance.
gcloud run deploy flowpos-backend \
--image gcr.io/YOUR_PROJECT/flowpos-backend:latest \
--region us-central1 \
--platform managed \
--session-affinity \
--min-instances 1 \
--max-instances 10 \
--memory 512Mi \
--cpu 1 \
--port 4000 \
--set-env-vars NODE_ENV=production,MCP_TOKEN_TTL_SECONDS=86400,REDIS_HOST=10.x.x.x,REDIS_PORT=6379 \
--set-secrets MCP_TOKEN_SECRET=MCP_TOKEN_SECRET:latest,REDIS_PASSWORD=REDIS_PASSWORD:latest \
--vpc-connector projects/YOUR_PROJECT/locations/us-central1/connectors/YOUR_VPC_CONNECTOR \
--service-account YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com \
--allow-unauthenticated

GCP Secret Manager Setup

# Create MCP token secret
echo -n "$(openssl rand -hex 32)" | \
gcloud secrets create MCP_TOKEN_SECRET --data-file=-

# Grant Cloud Run service account access
gcloud secrets add-iam-policy-binding MCP_TOKEN_SECRET \
--member="serviceAccount:YOUR_SA@PROJECT.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"

Health Check

The MCP server does not expose a dedicated health endpoint. Use the standard /health endpoint of the backend application to confirm the container is healthy before routing MCP traffic.

Deployment verification checklist

  1. OAuth discovery endpoints are reachable
    • GET /.well-known/oauth-authorization-server
    • GET /.well-known/oauth-protected-resource
  2. Token exchange works
    • POST /mcp/token returns accessToken and expiresIn
  3. MCP initialize works and returns session header
    • POST /mcp with { "method": "initialize" }
    • response includes mcp-session-id
  4. Authenticated session close works
    • DELETE /mcp with both Authorization and mcp-session-id
    • returns successful close
  5. Redis principal key appears for OAuth session
    • key pattern: mcp:session:{sessionId}