A thin MCP client for humans and agents — test the server you're building without touching a config file.
Change your Model Context Protocol server's code and test it
immediately — no editing mcp.json, no restarting your agent, no publishing to npm first.
run-mcp spawns the server, calls its tools, shows you its stderr when it crashes, and
restarts it on demand.
run-mcp provides three interfaces for interacting with MCP servers:
- Agent MCP Server (
run-mcp) — An MCP server that exposes tools (connect_to_mcp,call_mcp_primitive,reconnect_to_mcp) so AI agents can dynamically connect to and test local MCP projects without hardcoding them in configuration files. This is the default mode when you runnpx -y run-mcp. - Interactive REPL (
run-mcp -- node server.js) — A human-friendly CLI for developers to manually test and explore MCP servers using short, memorable commands (tools/call,status, etc.). - Headless CLI (
run-mcp call,run-mcp list-tools, etc.) — Single-shot subcommands that output clean JSON to stdout for CI/CD pipelines, shell scripts, andjqworkflows.
To protect the CLI and parent agents from large payloads, run-mcp automatically applies the following rules:
- Saving images to disk instead of passing multi-MB base64 strings through
- Enforcing timeouts so a hung tool call doesn't block forever
- Spilling huge text to disk: oversized responses are saved in full, and the truncated reply carries a result id — page through the rest with the
read_resulttool (or just open the file)
For humans, the REPL mode provides a quick way to test any MCP server without writing client code.
npm install
npm run buildTo install globally (makes run-mcp available system-wide):
npm install -g .# Start a REPL session with any MCP server
run-mcp -- node path/to/my-mcp-server.js
# Or use npx without installing globally
npx . -- node path/to/my-mcp-server.js
# Or start it without arguments to run the Agent Server mode!
run-mcpYou'll see an interactive prompt:
⟳ Connecting to target MCP server...
Command: node path/to/my-mcp-server.js
✓ Connected (PID: 12345)
5 tool(s) available. Type help for commands.
>
run-mcp [options] [target_command...]
| Option | Description |
|---|---|
-V, --version |
output the version number |
-o, --out-dir <path> |
Directory to save intercepted images and audio |
-t, --timeout <ms> |
Default tool call timeout in milliseconds (default: 300000) (Agent Mode only) |
--max-text <chars> |
Max text response length before truncation (default: 50000) (Agent Mode only) |
-m, --media-threshold <kb> |
Media size threshold in KB to save to disk (0 to always save, -1 to keep inline) |
--mcp |
Force start Agent Server mode even if run interactively without arguments |
-s, --script <file> |
Read commands from a file instead of stdin (REPL Mode only) |
--color <mode> |
Color output mode: always, never, auto (default: auto) |
--open-media |
Automatically open intercepted images and audio files using the host OS viewer |
--scan |
Scan the current workspace and parent directories for any JSON files containing mcpServers |
--transport <mode> |
Transport for http(s) targets: auto (default), http (Streamable HTTP), sse |
-w, --watch |
Watch the current directory for file changes and auto-reconnect (REPL Mode only) |
-h, --help |
display help for command |
Examples: $ run-mcp # Test harness (agent mode) $ run-mcp -- node my-server.js # Interactive testing (human REPL mode) $ run-mcp -s test.txt -- node my-server.js # Run a script in REPL mode $ run-mcp -- npx -y some-mcp-server # Test an npx server $ run-mcp --out-dir ./test-output # Agent mode with options $ run-mcp --out-dir ./screenshots -- node srv.js # REPL mode with options
When developing an MCP server, use --watch (or -w) to automatically reconnect whenever your source files change. This eliminates the manual reconnect step from your edit-test loop:
run-mcp -w -- node my-server.jsOn each file change, run-mcp will:
- Detect the changed files (debounced to 500ms to batch rapid saves)
- Disconnect from the current server process
- Reconnect to a fresh instance
- Show a diff of what primitives changed (tools added/removed/modified, resources, prompts)
Common directories like node_modules, .git, dist, and build are automatically ignored.
For CI/CD pipelines, shell scripts, or parsing via jq, run-mcp exposes a suite of headless subcommands that pipe clean JSON to stdout and isolate standard errors and progress updates to stderr.
To prevent argument parsing conflicts between run-mcp and the target server, you should separate the target command with a double-dash -- when the target command itself contains flags or options.
- Required when the target command has options/flags:
(Must use
run-mcp list-tools -- node my-server.js --verbose
--so--verboseis passed to your server, not parsed as an option forrun-mcp.) - Optional when the target command has no options/flags:
(Runs successfully without
run-mcp list-tools node my-server.js
--.)
Instead of escaping complex JSON strings on the command line, you can provide arguments using simple key-value shorthand notation:
key=value-> evaluated as a stringkey:=json_val-> parsed as a JSON primitive (boolean, number, array, object, null)
Example:
# Call a tool using shorthand arguments
run-mcp call greet name=Alice count:=5 -- node my-server.jsNormally, every headless command spawns a fresh process of the target server, which is slow and discards connection state. By passing --session <name>, run-mcp will spawn a persistent background daemon on the first call. Subsequent commands will dynamically attach to the same running session:
# Spawns a background session daemon & launches a browser
run-mcp call browser_launch headless:=true --session main -- node browser-server.js
# Navigates the browser on the active running session (no target command needed!)
run-mcp call browser_navigate url=https://google.com --session main
# Closes the session and stops the background target server
run-mcp close-session maincall [options] <tool> [json_args] [target_command...]list-tools [options] [target_command...]list-resources [options] [target_command...]list-prompts [options] [target_command...]read [options] <uri> [target_command...]describe [options] <tool> [target_command...]get-prompt [options] <name> [json_args] [target_command...]daemon <session_name> [target_command...]close-session <session_name>validate [options] [target_command...]
Use run-mcp <subcommand> --help for specific command options.
When an AI agent is actively developing an MCP server, it needs to test it. Standard MCP clients require updating a configuration file (mcp.json) and restarting the agent session entirely.
run-mcp solves this by giving the agent a suite of tools to dynamically spawn, inspect, and test local MCP servers on the fly.
How to use:
Add run-mcp to your agent's MCP configuration using npx:
{
"mcpServers": {
"run-mcp": {
"command": "npx",
"args": ["-y", "run-mcp"]
}
}
}Then use these tools from your agent:
| Tool | Description |
|---|---|
connect_to_mcp |
Spawn and connect (use include to get tools/resources/prompts) |
call_mcp_primitive |
Call a tool, read a resource, or get a prompt (auto-connects) |
list_mcp_primitives |
List tools, resources, and/or prompts |
get_server_notifications |
Inspect notifications the target emitted (list_changed, updates, logs) |
subscribe_to_resource |
Exercise a server's resource-subscription support |
reconnect_to_mcp |
Restart the target after a code edit and diff what changed |
read_result |
Page through an oversized result spilled to disk |
disconnect_from_mcp |
Tear down and reconnect after changes |
mcp_server_status |
Check connection status |
get_mcp_server_stderr |
View target server stderr output |
validate_mcp_server |
Validate an MCP server command and collect diagnostics |
list_available_mcp_servers |
List local MCP servers found in config files |
Once connected via run-mcp <command>, the following shorthand commands are available:
| Command | Description |
|---|---|
tools/list |
List all available tools |
tools/describe <name> |
Show a tool's input schema |
tools/call <name> [json] [opts] |
Call a tool (interactive if no json) |
tools/scaffold <name> |
Generate argument template for a tool |
resources/list |
List all available resources |
resources/read <uri> |
Read a resource by URI |
resources/templates |
List resource templates |
resources/subscribe <uri> |
Subscribe to resource changes |
resources/unsubscribe <uri> |
Unsubscribe from resource changes |
prompts/list |
List all available prompts |
prompts/get <name> [json_args] |
Get a prompt with arguments |
ping |
Verify connection, show round-trip time |
log-level <level> |
Set server logging verbosity |
| `history [count | clear]` |
| `notifications [count | clear]` |
roots/list |
Show configured client roots |
roots/add <uri> [name] |
Add a root directory |
roots/remove <uri> |
Remove a root directory |
!! / last |
Re-run the last command |
reconnect |
Disconnect and reconnect |
timing |
Show tool call performance stats |
status |
Show target server status |
# List available tools
> tools/list
# Inspect a tool's schema
> tools/describe screenshot
# Call a tool with arguments
> tools/call screenshot {"target": "#loginBtn"}
# Call with a custom timeout (5 seconds)
> tools/call long_running_tool {} --timeout 5000
# Arguments with spaces work fine
> tools/call send_message {"text": "hello world", "channel": "general"}Instead of prefixing every tool call with tools/call, you can invoke any target server tool directly by name, and provide arguments in shorthand key-value form:
# Direct inline tool execution with HTTPie shorthand parameters
> greet name=Bob count:=3If you invoke a tool without JSON arguments, run-mcp will guide you through an interactive scaffolding wizard:
> tools/call send_message
✔ text (string) Message text to send: Hello World!
✔ Select optional arguments to provide: channel
✔ channel (string) The Slack channel: general
✔ Execute? Yes
Calling send_message...run-mcp actively remembers your inputs across identical interactive calls, scaffolding defaults based on your last execution! Use tools/forget or --clear if you need a clean slate.
You can automate REPL commands by writing them to a file:
# commands.txt
tools/list
tools/call get_status {}
tools/call screenshot {"save_path": "/tmp/test.png"}run-mcp -s commands.txt -- node my-server.js- Lines starting with
#are treated as comments - Exits with code
0on success,1on first error
Some MCP features depend on what the client provides. run-mcp exposes these so
an agent can exercise them:
- Roots — pass
rootstoconnect_to_mcp(orreconnect_to_mcp) and your server'sroots/listcalls get a real answer.run-mcpadvertises the roots capability, so without this your server correctly sees an empty list. Roots persist across reconnects. - Log level — pass
log_levelto raise your server's logging verbosity. - Notifications —
get_server_notificationsshows what your server emitted (tools/list_changed,resources/updated, log messages). These travel outside the request/response flow, so a tool result will never reveal them. - Subscriptions —
subscribe_to_resource, then trigger a change and confirm withget_server_notifications(method='resources/updated').
Run with no target command (or --mcp), run-mcp is itself an MCP server that
exposes tools (connect_to_mcp, call_mcp_primitive, reconnect_to_mcp, …) so an
agent can dynamically spawn and test local MCP servers. Tool-call responses are
processed through the interceptor pipeline:
| Feature | Behavior |
|---|---|
| Image extraction | type: "image" responses with base64 data are saved to disk. Replaced with [Image saved to /path/to/img.png (24KB)] |
| Audio extraction | type: "audio" responses with base64 data are saved to disk. Replaced with [Audio saved to /path/to/audio.wav (12KB)] |
| Base64 detection | Text responses that are entirely base64-encoded (1000+ chars) are also saved as images |
| Timeouts | Tool calls are wrapped in a configurable timeout (default 5 minutes, use --timeout to change) |
| Truncation | Text exceeding the limit (default 50K chars, --max-text to change) is saved in full to disk; the reply keeps the head plus a result id, navigable via the read_result tool |
For the detailed system architecture diagram and source module directory map, please refer to AGENTS.md.
# Install dependencies
npm install
# Build (one-time)
npm run build
# Watch mode (rebuild on changes)
npm run dev
# Run directly
node dist/index.js -- <target_command...>MIT