Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mcp-down-wrapper

A transparent wrapper for MCP server commands. When the wrapped server fails to start — bad binary, missing dependency, crash during boot, whatever — Claude sees a server that loaded successfully with zero tools, instead of a "failed to load" warning.

The problem

Claude's MCP client shows a hard failure warning any time a configured server process exits or errors before completing its handshake. That's the right default, but it means a single flaky/optional MCP server (e.g. one that depends on a local service like ArangoDB being up) throws a scary warning every time that dependency isn't running — even if you don't care about that server's tools right now.

mcp-down-wrapper sits between Claude and the real server command. If the real command starts fine, the wrapper is invisible — it proxies stdio byte-for-byte. If the real command fails before producing any output, the wrapper answers the MCP handshake itself and reports an empty tool list, so Claude treats it as a normal, healthy, toolless server.

How it works

The wrapper is invoked as:

mcp-down-wrapper <command> [args...]

<command> [args...] is exactly what used to be your server's own command/args — the wrapper spawns it verbatim, inheriting env from its own process (which Claude already populated from your MCP config).

  • Child starts and talks normally: stdin/stdout are proxied directly between Claude and the child process. The wrapper does not parse or alter any protocol messages in this path — it's a transparent pipe.
  • Child fails to spawn (e.g. ENOENT) or exits before writing a single byte to stdout: the wrapper switches into a minimal built-in MCP responder. It replays whatever Claude had already sent (so the initialize request isn't lost) and answers:
    • initialize → normal handshake response, no tools capability advertised
    • tools/list{ "tools": [] }
    • ping{}
    • anything else → JSON-RPC "method not found" (-32601)
  • Child crashes after already producing real output: this is treated as a genuine runtime crash, not a failed start, and the wrapper just exits with the child's exit code. Masking only applies to startup failures.

The child's stderr is always inherited straight through, so real crash logs and error messages are still visible for debugging — only the protocol-level "did the server fail to load" signal is smoothed over.

Usage

Wrap any existing MCP server config by moving its command/args inside a mcp-down-wrapper invocation. env stays exactly as it was.

Before:

{
  "command": "npx",
  "args": ["arango-server"],
  "env": {
    "ARANGO_URL": "http://localhost:8529",
    "ARANGO_USERNAME": "root",
    "ARANGO_PASSWORD": "root"
  }
}

After (published to npm):

{
  "command": "npx",
  "args": ["mcp-down-wrapper", "npx", "arango-server"],
  "env": {
    "ARANGO_URL": "http://localhost:8529",
    "ARANGO_USERNAME": "root",
    "ARANGO_PASSWORD": "root"
  }
}

Note that args is a real array — "mcp-down-wrapper" and "npx" are separate elements, not one string. The wrapper is intentionally generic: the first argument is whatever command needs to run (npx, uvx, node, python, ...), and everything after it is that command's own arguments.

Running it locally (not published)

Two options, since this package isn't on the npm registry:

Option A — point npx at the project folder directly:

{
  "command": "npx",
  "args": [
    "/absolute/path/to/mcp-down-wrapper",
    "npx",
    "arango-server"
  ],
  "env": {
    "ARANGO_URL": "http://localhost:8529",
    "ARANGO_USERNAME": "root",
    "ARANGO_PASSWORD": "root"
  }
}

npm 7+ resolves a local folder path directly to its bin, so this works without installing or publishing anything.

Option B — call node on the built file directly (most deterministic):

{
  "command": "node",
  "args": [
    "/absolute/path/to/mcp-down-wrapper/dist/index.js",
    "npx",
    "arango-server"
  ],
  "env": {
    "ARANGO_URL": "http://localhost:8529",
    "ARANGO_USERNAME": "root",
    "ARANGO_PASSWORD": "root"
  }
}

Option C — npm link for a plain npx mcp-down-wrapper ... invocation:

cd /absolute/path/to/mcp-down-wrapper
npm link

This registers mcp-down-wrapper globally, so you can use the exact same config shape as the "published to npm" example above, with no path or version to keep track of.

How to build

Prerequisites: Node.js 20+ and npm.

git clone <this-repo>
cd mcp-down-wrapper
npm install    # installs devDependencies and builds via the `prepare` script
npm run build  # compiles src/index.ts -> dist/index.js

dist/ is a build artifact and is gitignored — rebuild it after pulling changes or editing src/index.ts. There's no test suite, so validate a build by pointing one of the local usage options at your freshly built dist/index.js.

Development

There's no test suite; the behavior was verified manually against three scenarios: a well-behaved child (pure passthrough), a nonexistent command (ENOENT), and a child that exits immediately without writing to stdout (both fall back to the empty-tools response).

Limitations

  • Only startup failures are masked. A server that starts fine and crashes later behaves normally (wrapper exits with the child's code) — Claude already knows about its tools by that point, so there's nothing sensible to hide.
  • The fallback responder does not advertise resources or prompts capabilities, but still answers resources/list/prompts/list with empty arrays defensively in case a client calls them anyway.
  • No shell is used to spawn the child (child_process.spawn without shell: true), so shell syntax in args won't be interpreted — pass a real command and argv, same as you would in the original unwrapped config.

About

A transparent wrapper for MCP server commands. When the wrapped server fails to start — bad binary, missing dependency, crash during boot, whatever — Claude sees a server that loaded successfully with zero tools, instead of a "failed to load" warning.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages