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.
- 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.
- Stdio servers: redirect ALL diagnostics to stderr. Audit your codebase for
print(, library defaults, debugger output, tqdm bars. Stdout is the wire. - 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.
- OAuth scopes are tight. Each scope you ask for is a future security incident if breached. Default to the smallest set that works.
- Annotate your tools honestly. destructiveHint, openWorldHint, idempotentHint matter to hosts; lying gets you delisted.
- Append-only audit log for write tools. Distinct from observability logs. Redacted at the boundary.
- Idempotency keys on every external write. Stripe-style keys keyed to (conversation/session/proposal). Network blips are not "rare in production."
- Compatibility matrix in the README. Three revisions × top three clients × both transports. Mark untested cells.
- 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.
- 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.