A minimal, production-ready MCP server implemented with FastAPI and deployable to Google Cloud Run. It exposes a single tool get_time
via the OpenAI Model Context Protocol (MCP) using JSON‑RPC 2.0 over HTTP.
tools/list
andtools/call
implemented exactly to spec- Returns content (text for humans) and structuredContent (JSON for machines)
- Proper JSON‑RPC error codes and input validation with
jsonschema
- CORS enabled (dev) + optional API key auth via
x-api-key
- Health check (
/healthz
) and simple request logging - Dockerfile and one‑command Cloud Run deploy
POST /
— JSON‑RPC 2.0 endpoint fortools/list
andtools/call
GET /healthz
— returns{ "ok": true }
Description: Returns the current UTC timestamp, optionally formatted.
Input schema:
{
"type": "object",
"properties": {
"format": {
"type": "string",
"description": "strftime format, e.g. %Y-%m-%dT%H:%M:%SZ"
}
},
"required": []
}
Output structuredContent:
{
"iso": "2025-01-01T00:00:00Z",
"formatted": "optional if format passed"
}
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn app:app --reload --port 8000
Test:
curl -s localhost:8000/ -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq
curl -s localhost:8000/ -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_time","arguments":{"format":"%Y-%m-%dT%H:%M:%SZ"}}}' | jq
If you set API_KEY=secret
, include a header: -H 'x-api-key: secret'
Option 1 — from source (simplest):
./deploy.sh
# Set PROJECT_ID, REGION, SERVICE (or export them)
Option 2 — via Cloud Build pipeline:
gcloud builds submit --project $PROJECT_ID --substitutions=_REGION=us-central1,_SERVICE=mcp-clock
- Add a new MCP Server to your agent
- Server URL: your Cloud Run URL (e.g.
https://mcp-clock-xxxx-uc.a.run.app
) - Label:
clock
- Allowed tools:
get_time
(or leave empty to allow all)
MIT