Writing
MCP Is an Unstable Contract Until You Test Your Client
published: 2026-10-03 · status: canonical · expanded from the original post
Most engineers I talk to assume MCP is a clean interface standard. Servers expose tools; clients consume them. The mental model is a pipe: bytes go in one end, the model receives them unchanged at the other. The reality is messier. Codex and Claude Code don't just pass server output to the model. They reshape it first. That reshaping happens before the model ever sees the tool definitions and instructions you worked hard to write.
Let me put that in plain English. The instructions and metadata your MCP server sends are not necessarily what the AI actually sees. Client-side processing can strip annotations, reorder definitions, or alter search behavior before the model ever touches them. For example, a server might group a set of tools together or attach hints about when to use them. The client can decide to drop those hints, merge the tools into a flat list, or translate the server's structured format into something slightly different. None of that violates the MCP spec. But it changes what the model has to work with.
This is not a minor implementation detail. If you're building enterprise AI workflows on top of MCP, you're not testing against the spec; you're testing against a moving client implementation. The spec says what a server may send and what a client may do with it, but the spec leaves room for clients to make their own choices. Outflank's deep dive covers concrete gaps around parallel execution and approval modes, and it's worth reading carefully: https://www.outflank.nl/blog/2026/09/30/mcp-design/?utm_source=tldrit. The key takeaway is that the server's view of a tool and the model's view of that same tool can diverge.
A tool definition that looks safe server-side might arrive at the model without its safety guardrails.
Here's one example that shows why this matters. A server might mark a tool as needing approval or flag it as read-only, but if the client doesn't carry that annotation through, the model's decision context changes. The friction you expected is gone. Maybe the model now thinks it can call a destructive operation without asking, because the approval flag was stripped. Or maybe a read-only tool gets presented in a way that makes it look safe to ignore. That's not a theoretical edge case; it's a gap in how controls are enforced. The server author assumed the client would pass those guardrails along. The client author assumed the server would not rely on them. Both read the same spec and reached different conclusions.
This has practical consequences for how teams should validate MCP integrations. If you're responsible for an enterprise deployment, you can't rely on a server's self-declared conformance or on a clean pass against the MCP spec. You need to inspect what actually arrives at the model in each client you support. That means capturing the tool definitions and metadata after client processing, comparing them with what you intended, and checking that approval modes, read-only flags, and search behavior survive the trip. If they don't, you've found a real defect, even if both sides are technically following the spec.
My prediction is that as MCP adoption grows in enterprises, client-specific compliance tests will become part of CI, not manual debugging. Just as we test APIs against real clients rather than against a written contract, MCP servers will need integration tests that run against the actual Codex or Claude Code client processing stack. Until your own integration suite proves otherwise, treat MCP as an unstable contract.
Originally covered at outflank.nl ↗