C.W.K.
Stream
Lesson 05 of 05 · published

Production Shipping Checklist

~24 min · production, checklist, launch

Level 0Curious Reader
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Shipping an MCP server to humans you do not personally know is a different category of work than running it for yourself. The checklist below is the shortest list that has saved real production incidents I have seen. Skipping any single item has, at some point, been someone's bad week.

  1. Pin the protocol revision and document it. README + manifest + initialize-time assertion. When the spec moves, you upgrade explicitly; you do not silently track latest.
  2. Stdio servers: redirect ALL diagnostics to stderr. Audit your codebase for print(, library defaults, debugger output, tqdm bars. Stdout is the wire.
  3. HTTP servers: bind to 127.0.0.1 if local, validate Origin/Host always, run behind TLS. The local-server traps from Track 7 are not optional.
  4. OAuth scopes are tight. Each scope you ask for is a future security incident if breached. Default to the smallest set that works.
  5. Annotate your tools honestly. destructiveHint, openWorldHint, idempotentHint matter to hosts; lying gets you delisted.
  6. Append-only audit log for write tools. Distinct from observability logs. Redacted at the boundary.
  7. Idempotency keys on every external write. Stripe-style keys keyed to (conversation/session/proposal). Network blips are not "rare in production."
  8. Compatibility matrix in the README. Three revisions × top three clients × both transports. Mark untested cells.
  9. Smoke test in CI on every commit. Boot server, list tools, call one tool, shutdown. Anything more elaborate is bonus; this minimum catches 90% of regressions.
  10. Public changelog with deprecation notes. Same vocabulary as the spec — "deprecated as of 1.5.0, removed in 1.7.0" with parallel availability.

Read the list twice. The list does not get longer; servers that follow it tend to live for years. Servers that skip items end up in war stories like the ones in this quest.

Code

Smoke-test pytest fixture·python
import pytest, asyncio
from mcp.client.stdio import StdioServerParameters, stdio_client
from mcp.client.session import ClientSession

@pytest.mark.asyncio
async def test_smoke():
    params = StdioServerParameters(command="uvx", args=["my-mcp-server"])
    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as s:
            init = await s.initialize()
            assert init.protocolVersion in {"2025-06-18","2025-11-25"}
            tools = await s.list_tools()
            assert any(t.name == "get_stock_price" for t in tools.tools)
            res = await s.call_tool("get_stock_price", {"symbol": "AAPL"})
            assert "AAPL" in res.content[0].text

External links

Exercise

Take a server you have written and check off the ten items above. Each unchecked item is your remaining shipping work. Mark a release date only when the list is clean.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.