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-affinityflag 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_PROJECTandYOUR_SAwith your GCP project ID and service account email. The--session-affinityflag is critical for MCP session routing — without it, subsequent JSON-RPC requests may land on a different instance and receive400 Unknown session ID.
- No additional infrastructure needed beyond the existing PostgreSQL instance (for
mcp_api_keytable).
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-affinityis still required for reliable MCP traffic routing. Redis persistence keeps principal mutations (for exampleset_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
- OAuth discovery endpoints are reachable
GET /.well-known/oauth-authorization-serverGET /.well-known/oauth-protected-resource
- Token exchange works
POST /mcp/tokenreturnsaccessTokenandexpiresIn
- MCP initialize works and returns session header
POST /mcpwith{ "method": "initialize" }- response includes
mcp-session-id
- Authenticated session close works
DELETE /mcpwith bothAuthorizationandmcp-session-id- returns successful close
- Redis principal key appears for OAuth session
- key pattern:
mcp:session:{sessionId}
- key pattern: