nginx reverse proxy that fronts a GCP-hosted MCP server, injecting a bearer token into every request
728
An nginx-based reverse proxy that fronts one of Google Cloud's hosted MCP
servers (see the supported products list)
and injects a bearer token into every request's Authorization header. Only
the exact root path / is proxied (query strings on it are preserved);
requests to any other path get a 404 - MCP is a single JSON-RPC endpoint,
so clients only ever need to call /.
Published on Docker Hub as
p0security/mcp-gcp
(linux/amd64 and linux/arm64).
Pull the published image:
docker pull p0security/mcp-gcp:latest
...or build it locally:
docker build -t p0security/mcp-gcp .
The image is configured entirely through environment variables:
| Variable | Description |
|---|---|
GCP_MCP_URL | Base URL of the target GCP MCP server, e.g. https://compute.googleapis.com/mcp (see supported products). Must be https on a *.googleapis.com host - the container refuses to start otherwise, and the upstream's TLS certificate is verified against the system trust store. |
GCP_BEARER_TOKEN | Bearer token injected into the Authorization header of every proxied request. This overrides any Authorization header sent by the client. |
docker run -d --name mcp-gcp-proxy -p 127.0.0.1:8080:8080 \
-e GCP_MCP_URL=https://compute.googleapis.com/mcp \
-e GCP_BEARER_TOKEN="$(cat path/to/token)" \
p0security/mcp-gcp
The proxy listens on port 8080 inside the container. Bind the published
port to a single interface (127.0.0.1 above) rather than all of them - the
proxy injects GCP_BEARER_TOKEN into every request it forwards, so anything
that can reach the port gets to use that token. Plain -p 8080:8080 binds to
0.0.0.0, exposing it to your whole network.
GCP_BEARER_TOKEN is typically a short-lived OAuth access token with the
right scope for the target API, e.g. for Compute Engine:
gcloud auth print-access-token --scopes=https://www.googleapis.com/auth/compute
Point the proxy at Compute Engine's MCP endpoint:
docker run -d --name mcp-gcp-compute -p 127.0.0.1:8080:8080 \
-e GCP_MCP_URL=https://compute.googleapis.com/mcp \
-e GCP_BEARER_TOKEN="$(gcloud auth print-access-token --scopes=https://www.googleapis.com/auth/compute)" \
p0security/mcp-gcp
The proxied server speaks MCP over streamable HTTP/JSON-RPC. First
initialize, then send an initialized notification, then call tools.
# 1. Initialize
curl -s -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "test-client", "version": "1.0.0" }
}
}'
# 2. Notify initialized
curl -s -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "method": "notifications/initialized"}'
# 3. List available tools
curl -s -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'
# 4. Call a tool, e.g. list Compute Engine instances in a zone
curl -s -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "list_instances",
"arguments": { "project": "my-gcp-project", "zone": "us-west1-a" }
}
}'
You do not need to set an Authorization header yourself — the proxy
injects Authorization: Bearer $GCP_BEARER_TOKEN on every request
regardless of what the client sends.
Note that tool names and required arguments vary by GCP product; use
tools/list to discover what a given GCP_MCP_URL exposes. Some tools
(e.g. Compute Engine's list_instances) require a specific zone rather
than supporting an aggregated, all-zones listing.
Content type
Image
Digest
sha256:c2c647ede…
Size
20 MB
Last updated
about 2 months ago
docker pull p0security/mcp-gcp