Skip to main content
Glama
MCP Recovery Lab

MCP Recovery Lab

by Dcastroro

MCP Recovery Lab

A tiny local MCP server that fails on purpose, so you can test how your agent recovers.

An agent's happy path is easy to demo. What happens when a tool returns an error? Does it retry a temporary failure, stop when a service is unavailable, and avoid inventing an answer?

MCP Recovery Lab provides a simulated, read-only order lookup over MCP stdio. It makes no network requests and uses no credentials or model provider. Each process starts with fresh state.

Try it

Requires Python 3.10+ and Git. Clone the repository and install it locally:

git clone https://github.com/Dcastroro/mcp-recovery-lab.git
cd mcp-recovery-lab
python -m pip install .
mcp-recovery-lab --scenario transient

The last command runs a stdio server, so it waits for an MCP client rather than displaying a UI. Add it to an MCP client that supports local stdio servers, using its own configuration format. For clients that accept the common mcpServers format:

{
  "mcpServers": {
    "recovery-lab": {
      "command": "mcp-recovery-lab",
      "args": ["--scenario", "transient"]
    }
  }
}

Ask your agent: “What's the status of order ORD-100? If the tool temporarily fails, try it once more.” The first valid lookup returns a tool error and the next returns shipped. Start a new server process to reset the scenario. You can also invoke the server with python -m mcp_recovery_lab.server --scenario transient if your client cannot find the console script.

To see a complete exchange without configuring an agent, install the optional official MCP Python client (python -m pip install "mcp>=2.3,<3") and run python examples/client.py. It discovers the tool, receives the simulated failure, and retries once.

Run a Pydantic AI agent without an API key

python -m pip install "pydantic-ai-slim[mcp]>=2.66,<3"
python examples/pydantic_agent.py

This example connects a real Pydantic AI Agent to the lab through MCP. A scripted FunctionModel calls the tool, sees the temporary error and retries once; assertions verify the two calls and final result. The model decisions are deliberately scripted: the example verifies the framework integration and recovery path, not how an LLM would behave. No model service is called. To verify every scenario with the official MCP Python client, run python examples/verify_scenarios.py.

Related MCP server: genpark-distributed-agent-chaos-latency-fuzzer-skill

Scenarios

Scenario

lookup_order behavior for ORD-100

What to observe

healthy

Returns the simulated shipped status.

Normal lookup.

transient

First valid lookup fails; subsequent lookups succeed.

Whether the client notices and retries.

rate-limit

First two valid lookups return a simulated limit error, then succeed.

Whether retries are bounded; the fixture does not impose a real delay.

stale

First lookup reports processing at revision 1; later lookups report shipped at revision 2.

How an agent handles conflicting observations and revision information.

unavailable

Every lookup fails.

Whether the agent reports uncertainty.

Unknown order IDs return a tool error and do not consume the transient failure. These are simulated outcomes, not a production service or a measure of model quality. The server does not judge an agent's answer, implement transport fault injection, or validate arbitrary MCP servers.

Run the checks

python -m unittest discover -s tests -v

The suite includes a real subprocess speaking newline-delimited JSON-RPC over stdio. No network or credentials are needed for the server or tests. MCP clients and models are separate software and may have their own costs or network access.

How it works

The server supports the MCP initialize, ping, tools/list, and tools/call methods needed for this example, plus notifications. It offers one tool, lookup_order. It intentionally implements a small subset of MCP: it is a teaching and testing fixture, not a general MCP framework. Only use simulated order identifiers with it.

Contributing

Small, reproducible examples and bug reports are welcome. Please include the client, Python version, scenario, and steps to reproduce. Do not include real prompts, private data, or credentials in issues or examples.

MIT license.

Available Tools

1 tool
lookup_orderC

Look up a simulated order. Use order ID ORD-100.

NameRequiredDescriptionDefault
order_idYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description carries the full behavioral burden. It never states that the operation is read-only, what happens for an unknown order ID (empty result vs. error), or whether any permissions apply; "simulated" is the only behavioral signal and it only characterizes the data, not the call's effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the purpose before the parameter hint; nothing is padded. The second sentence is slightly ambiguous ("Use order ID ORD-100" could be read as a fixed value rather than a format example), costing one point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool this is nearly adequate, but with no annotations and no output schema the description should say what a successful lookup returns and how a miss is reported. As written, an agent can form the call but cannot predict the result or failure mode.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% — the schema only declares order_id as a bare string — so the description must compensate. The example "ORD-100" usefully conveys the expected format/prefix, but it does not clarify case sensitivity or whether the ORD- prefix is mandatory, leaving interpretation to the agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Look up a simulated order" names a specific verb (look up) and resource (order) and flags that the data is simulated/mock, which tells an agent what to expect back. It stops short of 5 only because there is no scope detail (single order vs. list) beyond the singular noun and no sibling differentiation to provide.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, no prerequisites, and no alternatives (there are no siblings, but there is also no statement of what this tool is for versus other retrieval paths). The only actionable instruction is the ID format hint, which is parameter-level rather than usage-level.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.1.0
    • First observedlookup_order

TDQS

B3.1/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so an agent cannot misselect or confuse it with anything else. Its purpose (look up a simulated order by ID) is stated unambiguously.

Naming Consistency5/5

The single name 'lookup_order' follows a clear verb_noun snake_case convention. With one tool there is no deviation or mixing of styles to penalize.

Tool Count2/5

A single tool is too thin for a server framed as a 'Recovery Lab' with an order domain; any lookup, listing, or recovery workflow would need more operations. The surface is scoped to one hardcoded action, which is an extreme mismatch for the stated purpose.

Completeness2/5

The tool only retrieves a single simulated order (ORD-100), with no list, create, update, cancel, or recovery operations. Agents hitting any other order or needing to act on an order reach a dead end.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers