MCP has no resilience layer of its own, so a single unresponsive upstream can stall an agent for as long as the client is willing to wait. Putting the retry and breaker policy in a proxy means it applies to servers you do not control and did not write. The per-tool config is where it earns its place — a search call and a file read rarely deserve the same timeout.
A transparent stdio proxy that sits between your agent and another MCP server. You launch the target server through it instead of directly, and every tool call inherits a timeout, a retry policy, a circuit breaker and structured logging.
- A hard timeout on every tool call, so a hung upstream API stops blocking the agent
- Retries with exponential backoff and jitter — deterministic errors such as invalid params or method not found are never retried
- A circuit breaker that trips after repeated failures and moves through Closed, Open and Half-Open rather than hammering a dead server
- One structured JSON line per call on stderr, carrying the server, the tool, `duration_ms`, status and attempt number
- Per-tool overrides in a YAML config: a slow tool gets a longer timeout, a flaky one gets more retries
- A programmatic entry point, `shield({...})`, for wiring the same proxy into your own code
Node.js 20 or newer and the npm package `@daino/mcp-shield`, version 1.1.0, installed globally or run through `npx`. Usage is `mcp-shield wrap -- <the server command>`; the defaults are a 30s timeout and 2 retries, overridable with `--timeout` and `--retries` or a `--config` file. In a client config, it replaces the server's own command line and keeps the target server's environment variables.
One command — npm install -g @daino/mcp-shield
