Production-survival MCP server template — for servers that don't die in production.
A Python MCP server template built around the patterns that distinguish 9% healthy from 52% dead MCP servers in production (April 2026 community scan, 2,181 endpoints).
Most MCP server templates ship the spec primitives. This one ships the production-survival foundation:
- Streamable HTTP transport — mandatory for remote deployment per 2026 spec, not stdio
- Bearer token authentication —
StaticTokenVerifierfor preview, migration path toJWTVerifierdocumented - OpenTelemetry observability — OTLP exporter wired in
lifespan, MCP semantic conventions - Pinned dependencies +
uv.lock— reproducible across dev, staging, production - JSON-RPC healthcheck — Docker
HEALTHCHECKruns an authenticatedtools/listJSON-RPC call validating bearer auth + Streamable HTTP transport + tool registration in one shot. Catches misconfig and protocol failure, not just process crash. (Upstream API connectivity validation is a future direction — see ROADMAP.md.)
If git clone && docker compose up && curl doesn't work on a fresh machine, this template has failed its primary contract.
git clone https://github.com/alexisgarcia-dev/claude-mcp-server-template.git
cd claude-mcp-server-template
docker compose up -dThe server is reachable at http://localhost:8000/mcp with Streamable HTTP transport. Bearer auth: demo-readonly (read access) or demo-readwrite (write).
List available tools using the FastMCP Python client:
from fastmcp import Client
import asyncio
async def main():
async with Client(
"http://127.0.0.1:8000/mcp",
headers={"Authorization": "Bearer demo-readonly"},
) as client:
tools = await client.list_tools()
for t in tools:
print(f" {t.name}: {t.description}")
asyncio.run(main())OpenTelemetry traces visible at http://localhost:16686 (Jaeger UI).
Manual HTTP protocol note — MCP Streamable HTTP transport requires a 2-step handshake (initialize → capture Mcp-Session-Id response header → tools/list with that session ID). The fastmcp Client SDK handles this transparently. For raw curl / PowerShell usage, see docs/manual-http-handshake.md.
| Primitive | Count | Notes |
|---|---|---|
| Tools | 4 | get_recipe, search_recipes, update_pantry, generate_meal_plan (async with progress) |
| Resources | 1 | recipe_resource (MIME-typed) |
| Prompts | 1 | weekly_planner (role-restricted per MCP 1.27) |
The demo wraps a fake SaaS (PantryAPI, included as pantry_mock_api.py) so you can see end-to-end wiring without external accounts.
⚠ DO NOT deploy with default
demo-readonly/demo-readwritetokens. They are committed to source for preview/dev parity (CI smoke tests, Claude Desktop demos). Production deployments require OAuth 2.1 + PKCE — see ROADMAP.md Future directions.
v0.1.0 ships StaticTokenVerifier with two demo tokens:
from fastmcp.server.auth.providers.jwt import StaticTokenVerifier
verifier = StaticTokenVerifier(
tokens={
"demo-readonly": {"client_id": "ro", "scopes": ["read:pantry"]},
"demo-readwrite": {"client_id": "rw", "scopes": ["read:pantry", "write:pantry"]},
},
required_scopes=["read:pantry"],
)This is preview/dev authentication. For internet-exposed production deployments, wait for v0.2.0 or use behind a gateway.
v0.2.0 will ship full OAuth 2.1 + PKCE with reference integrations for Auth0, WorkOS, and Azure Entra ID. Migration is a one-line change (StaticTokenVerifier → JWTVerifier(jwks_uri=..., issuer=..., audience=...)).
See ROADMAP.md for the full versioning plan.
Replace PantryAPI with your own:
- Update
src/config.pywith your API base URL, auth, timeouts - Replace tool implementations in
src/tools/with calls to your API - Update healthcheck in
src/server.py/readyendpoint to ping your upstream
The retry logic (tenacity AsyncRetrying), secret masking (SecretStr), and OTel masking hooks are configured once in src/pantry_client.py and reused.
Demo the server end-to-end against any MCP client (Claude Desktop, Cursor, Windsurf) without standing up the real backend. When PANTRY_API__DRY_RUN=true, every outbound HTTP request is short-circuited at the PantryClient chokepoint, returns a generic mock dict, and emits the would-be request as an OpenTelemetry event — sensitive headers (Authorization, Cookie, X-Api-Key, ...) are redacted by default. GDPR-safe, OTel-native, opt-in.
export PANTRY_API__DRY_RUN=true
uv run server
# Then trigger any Tool from your MCP client and inspect the captured
# payload in Jaeger (http://localhost:16686) under the "pantry.dry_run" span.See docs/dry-run.md for the full reference (vertical use cases for POD / RAG / scrapers, configuration table, telemetry contract, security model).
- Python 3.14
uvfor dependency managementmcp1.27 official SDKfastmcp3.2 frameworkpytest,ruff,mypyfor the test/lint/type pipeline- Docker compose with Jaeger for local observability
Exact pins in pyproject.toml and uv.lock.
uv run pytest -q48 tests passing (last run J14, 2026-05-08).
See ROADMAP.md for v0.2 → v0.5 trajectory.
v1.0.0 is the stable reference release. See ROADMAP.md for community-driven future directions.
This release is v1.0.0 — a stable reference for the current MCP spec (2025-11-25) and FastMCP 3.2.x line. It is frozen-by-design: maintenance is community-driven from this point forward (see ROADMAP.md).
What "frozen-by-design" means here:
- The five production-survival pillars and the demo PantryAPI integration are validated end-to-end against pinned versions (Python 3.11+ /
mcp1.27.0 /fastmcp3.2.4 / Jaeger 1.62.0). - A future
v1.1.xline is contemplated only if the MCP specification evolves with breaking changes or FastMCP ships a 4.x line with non-trivial migration. See ROADMAP.md for the conditions. - Bug fixes and security patches against
v1.0.xwill be accepted as community PRs and shipped asv1.0.1,v1.0.2, etc., on a best-effort basis.
What this is NOT:
- A commitment to track every FastMCP release indefinitely.
- A claim that this template is the right starting point for multi-tenant gateway deployments — see the "Out of scope by design" section of ROADMAP.md for honest scope limits.
MIT — see LICENSE.
Issues with the label roadmap carry weight. Real production feedback over speculative features.
