Skip to main content

MCP Server Deployment

These notes cover deployment behavior that is specific to the MCP transport in apps/backend/src/mcp/. Runtime configuration values are managed outside the docs site; use Doppler and the environment-specific deployment manifests as the source of truth for secret and environment variable names.

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 \
--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 400 Unknown session ID.

  • 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.
  • Runtime configuration: verify the MCP JWT signing configuration and Redis connection configuration are present in the target environment before enabling V2. Do not keep environment variable inventories in docs; update Doppler and deployment manifests instead.
  • Redis instance: Use a Memorystore for Redis instance in the same VPC as Cloud Run. A Serverless VPC Access connector is required when Redis is VPC-internal.
  • --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 \
--vpc-connector projects/YOUR_PROJECT/locations/us-central1/connectors/YOUR_VPC_CONNECTOR \
--service-account YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com \
--allow-unauthenticated

Secret management

Secret names and values live in Doppler/GCP Secret Manager, not in this page. When deployment fails before the server starts, check the backend logs for MCP token-service startup errors first, then verify the Cloud Run service account can read the configured secrets.

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}