Minimal remote MCP server packaged for Docker, with Basic Auth and/or API Key auth, plus 3 Python tools:
generate_poem(topic="life", line_count=4)calculate_age(birthdate, as_of=None)random_life_advice()
- MCP Streamable HTTP endpoint at
/mcp - Auth on MCP routes (Basic Auth and/or API Key)
- Unauthenticated health check at
/health - One-command deployment via Docker Compose
For production hosting, security, connectivity, and operations requirements, see docs/server-requirements.md.
For production, apply this minimum security baseline:
- Put MCP behind an API gateway/WAF with a stable domain (no ngrok).
- Enforce TLS 1.2+ and redirect HTTP to HTTPS.
- Use strong auth (OIDC/JWT or mTLS preferred); keep API key only if required.
- If API keys are used, issue per-client keys and rotate via secret manager.
- Keep the MCP service private; expose only gateway/ingress.
- Apply network controls (
NetworkPolicy, security groups, egress allowlist). - Store secrets in a managed store (not in repo, not in plain YAML).
- Enforce request limits (rate, size, timeout, concurrency).
- Log/audit tool calls with identity and latency, but never log secrets/PII.
- Use scanned/signed images, progressive rollouts, and tested rollback runbooks.
- Create your environment file:
cp .env.example .env- Edit
.envand set secure credentials:
MCP_BASIC_AUTH_USERNAME=admin
MCP_BASIC_AUTH_PASSWORD=change-me
MCP_API_KEY_LOCATION=header
MCP_API_KEY_PARAMETER_NAME=x-api-key
MCP_API_KEY_VALUE=replace-with-strong-api-keyAt least one auth method must be configured:
- Basic Auth (
MCP_BASIC_AUTH_USERNAME+MCP_BASIC_AUTH_PASSWORD) - API Key (
MCP_API_KEY_VALUE)
- Build and run:
docker compose up --build -d- Verify health:
curl http://localhost:8000/healthExpected response:
{"status":"ok"}- URL:
http://localhost:8000/mcp - Auth: Basic Auth and/or API Key (from
.env)
Example request without auth (should return 401):
curl -i http://localhost:8000/mcpExample MCP request with Basic Auth:
curl -i -u "$MCP_BASIC_AUTH_USERNAME:$MCP_BASIC_AUTH_PASSWORD" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
http://localhost:8000/mcpExample MCP request with API Key header:
curl -i \
-H "${MCP_API_KEY_PARAMETER_NAME}: ${MCP_API_KEY_VALUE}" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
http://localhost:8000/mcpIf you use MCP Inspector, configure:
- Transport: Streamable HTTP
- URL:
http://localhost:8000/mcp - Headers:
Authorization: Basic <base64(username:password)>(Basic Auth), or${MCP_API_KEY_PARAMETER_NAME}: ${MCP_API_KEY_VALUE}(API Key)
Generate the header value:
printf '%s' "$MCP_BASIC_AUTH_USERNAME:$MCP_BASIC_AUTH_PASSWORD" | base64python -m pytest -qYou can deploy this MCP server to Kubernetes using the manifests in k8s/.
- Build and push your image:
docker build -t ghcr.io/<your-org>/random-mcp-server:<tag> .
docker push ghcr.io/<your-org>/random-mcp-server:<tag>- Update image in
k8s/deployment.yaml:
image: ghcr.io/<your-org>/random-mcp-server:<tag>- Create your secrets (recommended via secret manager/CI, not committed files):
kubectl create secret generic random-mcp-secrets \
--from-literal=MCP_BASIC_AUTH_USERNAME=<username> \
--from-literal=MCP_BASIC_AUTH_PASSWORD=<password> \
--from-literal=MCP_API_KEY_LOCATION=header \
--from-literal=MCP_API_KEY_PARAMETER_NAME=x-api-key \
--from-literal=MCP_API_KEY_VALUE=<strong-api-key>- Deploy:
kubectl apply -k k8s- Optional ingress:
kubectl apply -f k8s/ingress.example.yamlUse your ingress domain + /mcp as the MCP URL.
If your clients run in the same Kubernetes cluster, do not use ngrok/ingress. Use the internal service DNS directly:
http://random-mcp.<namespace>.svc.cluster.local:8093/mcp
Example (API key auth):
curl -sS \
-H "x-api-key: <your-api-key>" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
http://random-mcp.<namespace>.svc.cluster.local:8093/mcpYou can also run the included client pod example:
kubectl apply -f k8s/in-cluster-client.example.yaml
kubectl logs random-mcp-client-test
kubectl delete pod random-mcp-client-testFor SAM Cloud MCP integration, use:
- Protocol:
Streamable HTTP - URL: your public tunnel/domain +
/mcp - Authentication Type:
API Key - API Key Location:
Header - API Key Parameter Name: value from
MCP_API_KEY_PARAMETER_NAME - API Key Value: value from
MCP_API_KEY_VALUE
If using ngrok free tunnels and your client is blocked by ngrok warning pages, add:
ngrok-skip-browser-warning: 1
- TLS is intentionally out of scope in this container. For production, place this service behind HTTPS termination (reverse proxy / ingress).
/healthis intentionally open for orchestration and uptime checks..envis ignored by git; keep real credentials there and never commit them.