run-mcp 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -38
- package/dist/index.js +64 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -60,14 +60,28 @@ You'll see an interactive prompt:
|
|
|
60
60
|
|
|
61
61
|
run-mcp [options] [target_command...]
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
--
|
|
68
|
-
--
|
|
69
|
-
-
|
|
70
|
-
|
|
63
|
+
<!-- OPTIONS_START -->
|
|
64
|
+
| Option | Description |
|
|
65
|
+
| :--- | :--- |
|
|
66
|
+
| `-V, --version` | output the version number |
|
|
67
|
+
| `-o, --out-dir <path>` | Directory to save intercepted images and audio |
|
|
68
|
+
| `-t, --timeout <ms>` | Default tool call timeout in milliseconds (default: 300000) (Agent Mode only) |
|
|
69
|
+
| `--max-text <chars>` | Max text response length before truncation (default: 50000) (Agent Mode only) |
|
|
70
|
+
| `-m, --media-threshold <kb>` | Media size threshold in KB to save to disk (0 to always save, -1 to keep inline) |
|
|
71
|
+
| `--mcp` | Force start Agent Server mode even if run interactively without arguments |
|
|
72
|
+
| `-s, --script <file>` | Read commands from a file instead of stdin (REPL Mode only) |
|
|
73
|
+
| `--color <mode>` | Color output mode: always, never, auto (default: auto) |
|
|
74
|
+
| `--open-media` | Automatically open intercepted images and audio files using the host OS viewer |
|
|
75
|
+
| `--sandbox <mode>` | Sandbox execution mode: auto, docker, native, audit, none (default: "none") |
|
|
76
|
+
| `--scan` | Scan the current workspace and parent directories for any JSON files containing mcpServers |
|
|
77
|
+
| `--allow-read <paths...>` | Paths to allow reading under the sandbox |
|
|
78
|
+
| `--allow-write <paths...>` | Paths to allow writing under the sandbox |
|
|
79
|
+
| `--allow-net <domains...>` | Network domains to allow connecting to under the sandbox |
|
|
80
|
+
| `--deny-read <paths...>` | Paths to deny reading under the sandbox |
|
|
81
|
+
| `--deny-write <paths...>` | Paths to deny writing under the sandbox |
|
|
82
|
+
| `--deny-net <domains...>` | Network domains to deny connecting to under the sandbox |
|
|
83
|
+
| `-h, --help` | display help for command |
|
|
84
|
+
<!-- OPTIONS_END -->
|
|
71
85
|
|
|
72
86
|
Examples:
|
|
73
87
|
$ run-mcp # Test harness (agent mode)
|
|
@@ -81,12 +95,20 @@ Examples:
|
|
|
81
95
|
|
|
82
96
|
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.
|
|
83
97
|
|
|
84
|
-
### ⚠️
|
|
98
|
+
### ⚠️ Double-Dash `--` Separator
|
|
85
99
|
|
|
86
|
-
To prevent argument parsing conflicts between `run-mcp` and the target server,
|
|
100
|
+
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.
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
* **Required when the target command has options/flags:**
|
|
103
|
+
```bash
|
|
104
|
+
run-mcp list-tools -- node my-server.js --verbose
|
|
105
|
+
```
|
|
106
|
+
*(Must use `--` so `--verbose` is passed to your server, not parsed as an option for `run-mcp`.)*
|
|
107
|
+
* **Optional when the target command has no options/flags:**
|
|
108
|
+
```bash
|
|
109
|
+
run-mcp list-tools node my-server.js
|
|
110
|
+
```
|
|
111
|
+
*(Runs successfully without `--`.)*
|
|
90
112
|
|
|
91
113
|
### ⚡ HTTPie-Style Shorthand Arguments
|
|
92
114
|
|
|
@@ -119,14 +141,17 @@ run-mcp close-session main
|
|
|
119
141
|
|
|
120
142
|
### Available Headless Subcommands
|
|
121
143
|
|
|
122
|
-
|
|
123
|
-
- `
|
|
124
|
-
- `list-
|
|
125
|
-
- `list-
|
|
126
|
-
- `
|
|
127
|
-
- `
|
|
128
|
-
- `
|
|
144
|
+
<!-- SUBCOMMANDS_START -->
|
|
145
|
+
- `call [options] <tool> [json_args] [target_command...]`
|
|
146
|
+
- `list-tools [options] [target_command...]`
|
|
147
|
+
- `list-resources [options] [target_command...]`
|
|
148
|
+
- `list-prompts [options] [target_command...]`
|
|
149
|
+
- `read [options] <uri> [target_command...]`
|
|
150
|
+
- `describe [options] <tool> [target_command...]`
|
|
151
|
+
- `get-prompt [options] <name> [json_args] [target_command...]`
|
|
152
|
+
- `daemon [options] <session_name> [target_command...]`
|
|
129
153
|
- `close-session <session_name>`
|
|
154
|
+
<!-- SUBCOMMANDS_END -->
|
|
130
155
|
|
|
131
156
|
Use `run-mcp <subcommand> --help` for specific command options.
|
|
132
157
|
|
|
@@ -154,30 +179,49 @@ Add `run-mcp` to your agent's MCP configuration using `npx`:
|
|
|
154
179
|
|
|
155
180
|
Then use these tools from your agent:
|
|
156
181
|
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
182
|
+
<!-- AGENT_TOOLS_START -->
|
|
183
|
+
| Tool | Description |
|
|
184
|
+
| :--- | :--- |
|
|
185
|
+
| `connect_to_mcp` | Spawn and connect (use include to get tools/resources/prompts) |
|
|
186
|
+
| `call_mcp_primitive` | Call a tool, read a resource, or get a prompt (auto-connects) |
|
|
187
|
+
| `list_mcp_primitives` | List tools, resources, and/or prompts |
|
|
188
|
+
| `disconnect_from_mcp` | Tear down and reconnect after changes |
|
|
189
|
+
| `mcp_server_status` | Check connection status |
|
|
190
|
+
| `get_mcp_server_stderr` | View target server stderr output |
|
|
191
|
+
| `validate_mcp_server` | Validate an MCP server command and collect diagnostics |
|
|
192
|
+
| `search_all_local_mcp_servers` | Scan and search all local MCP servers for a query |
|
|
193
|
+
<!-- AGENT_TOOLS_END -->
|
|
166
194
|
|
|
167
195
|
## REPL Mode Commands
|
|
168
196
|
|
|
169
197
|
Once connected via `run-mcp <command>`, the following shorthand commands are available:
|
|
170
198
|
|
|
171
|
-
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
| `tools/list`
|
|
175
|
-
| `tools/describe <name>`
|
|
176
|
-
| `tools/call <name> [json] [
|
|
177
|
-
| `tools/
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
199
|
+
<!-- REPL_COMMANDS_START -->
|
|
200
|
+
| Command | Description |
|
|
201
|
+
| :--- | :--- |
|
|
202
|
+
| `tools/list` | List all available tools |
|
|
203
|
+
| `tools/describe <name>` | Show a tool's input schema |
|
|
204
|
+
| `tools/call <name> [json] [opts]` | Call a tool (interactive if no json) |
|
|
205
|
+
| `tools/scaffold <name>` | Generate argument template for a tool |
|
|
206
|
+
| `resources/list` | List all available resources |
|
|
207
|
+
| `resources/read <uri>` | Read a resource by URI |
|
|
208
|
+
| `resources/templates` | List resource templates |
|
|
209
|
+
| `resources/subscribe <uri>` | Subscribe to resource changes |
|
|
210
|
+
| `resources/unsubscribe <uri>` | Unsubscribe from resource changes |
|
|
211
|
+
| `prompts/list` | List all available prompts |
|
|
212
|
+
| `prompts/get <name> [json_args]` | Get a prompt with arguments |
|
|
213
|
+
| `ping` | Verify connection, show round-trip time |
|
|
214
|
+
| `log-level <level>` | Set server logging verbosity |
|
|
215
|
+
| `history [count|clear]` | Show request/response history |
|
|
216
|
+
| `notifications [count|clear]` | Show server notifications |
|
|
217
|
+
| `roots/list` | Show configured client roots |
|
|
218
|
+
| `roots/add <uri> [name]` | Add a root directory |
|
|
219
|
+
| `roots/remove <uri>` | Remove a root directory |
|
|
220
|
+
| `!! / last` | Re-run the last command |
|
|
221
|
+
| `reconnect` | Disconnect and reconnect |
|
|
222
|
+
| `timing` | Show tool call performance stats |
|
|
223
|
+
| `status` | Show target server status |
|
|
224
|
+
<!-- REPL_COMMANDS_END -->
|
|
181
225
|
|
|
182
226
|
### Examples
|
|
183
227
|
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { spawn } from "child_process";
|
|
|
11
11
|
|
|
12
12
|
// src/config-scanner.ts
|
|
13
13
|
import { existsSync } from "fs";
|
|
14
|
-
import { readFile } from "fs/promises";
|
|
14
|
+
import { readFile, readdir } from "fs/promises";
|
|
15
15
|
import { homedir } from "os";
|
|
16
16
|
import path from "path";
|
|
17
17
|
import process2 from "process";
|
|
@@ -57,10 +57,14 @@ function getConfigPaths() {
|
|
|
57
57
|
{ source: "Gemini CLI (Project)", file: path.join(cwd, ".gemini", "settings.json") },
|
|
58
58
|
{ source: "Claude Code (Global)", file: path.join(home, ".claude.json") },
|
|
59
59
|
{ source: "Claude Code (Project)", file: path.join(cwd, ".mcp.json") },
|
|
60
|
-
{ source: "Antigravity", file: path.join(home, ".gemini", "antigravity", "mcp_config.json") }
|
|
60
|
+
{ source: "Antigravity", file: path.join(home, ".gemini", "antigravity", "mcp_config.json") },
|
|
61
|
+
{
|
|
62
|
+
source: "Gemini App (Global)",
|
|
63
|
+
file: path.join(home, ".gemini", "config", "mcp_config.json")
|
|
64
|
+
}
|
|
61
65
|
];
|
|
62
66
|
}
|
|
63
|
-
async function discoverServers() {
|
|
67
|
+
async function discoverServers(options) {
|
|
64
68
|
const servers = [];
|
|
65
69
|
const paths = getConfigPaths();
|
|
66
70
|
for (const { source, file } of paths) {
|
|
@@ -86,10 +90,52 @@ async function discoverServers() {
|
|
|
86
90
|
} catch {
|
|
87
91
|
}
|
|
88
92
|
}
|
|
93
|
+
if (options?.scan) {
|
|
94
|
+
try {
|
|
95
|
+
let currentDir = process2.cwd();
|
|
96
|
+
const visited = /* @__PURE__ */ new Set();
|
|
97
|
+
while (currentDir && !visited.has(currentDir)) {
|
|
98
|
+
visited.add(currentDir);
|
|
99
|
+
if (existsSync(currentDir)) {
|
|
100
|
+
const files = await readdir(currentDir, { withFileTypes: true });
|
|
101
|
+
for (const file of files) {
|
|
102
|
+
if (file.isFile() && file.name.endsWith(".json")) {
|
|
103
|
+
if (file.name === "package-lock.json" || file.name === "package.json" || file.name === "tsconfig.json") {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const filePath = path.join(currentDir, file.name);
|
|
107
|
+
try {
|
|
108
|
+
const content = await readFile(filePath, "utf8");
|
|
109
|
+
if (content.includes("mcpServers")) {
|
|
110
|
+
const json = JSON.parse(content);
|
|
111
|
+
if (json.mcpServers && typeof json.mcpServers === "object") {
|
|
112
|
+
for (const [name, config] of Object.entries(json.mcpServers)) {
|
|
113
|
+
if (config && typeof config === "object" && config.command) {
|
|
114
|
+
servers.push({
|
|
115
|
+
name,
|
|
116
|
+
config,
|
|
117
|
+
source: `Local Workspace (${file.name})`
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const parent = path.dirname(currentDir);
|
|
129
|
+
if (parent === currentDir) break;
|
|
130
|
+
currentDir = parent;
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
89
135
|
return servers;
|
|
90
136
|
}
|
|
91
|
-
async function pickDiscoveredServer() {
|
|
92
|
-
const servers = await discoverServers();
|
|
137
|
+
async function pickDiscoveredServer(options) {
|
|
138
|
+
const servers = await discoverServers(options);
|
|
93
139
|
if (servers.length === 0) {
|
|
94
140
|
return null;
|
|
95
141
|
}
|
|
@@ -99,7 +145,7 @@ async function pickDiscoveredServer() {
|
|
|
99
145
|
if (!uniqueServers.has(key)) {
|
|
100
146
|
uniqueServers.set(key, s);
|
|
101
147
|
} else {
|
|
102
|
-
if (s.source.includes("Project")) {
|
|
148
|
+
if (s.source.includes("Project") || s.source.includes("Local Workspace")) {
|
|
103
149
|
uniqueServers.set(key, s);
|
|
104
150
|
}
|
|
105
151
|
}
|
|
@@ -1430,7 +1476,7 @@ var TargetManager = class _TargetManager extends EventEmitter {
|
|
|
1430
1476
|
this.transport = stdioTransport;
|
|
1431
1477
|
}
|
|
1432
1478
|
this.client = new Client(
|
|
1433
|
-
{ name: "run-mcp", version: "1.7.
|
|
1479
|
+
{ name: "run-mcp", version: "1.7.1" },
|
|
1434
1480
|
{
|
|
1435
1481
|
capabilities: {
|
|
1436
1482
|
roots: { listChanged: true },
|
|
@@ -4425,7 +4471,7 @@ async function startServer(opts) {
|
|
|
4425
4471
|
mediaThresholdKb: opts.mediaThresholdKb
|
|
4426
4472
|
});
|
|
4427
4473
|
const mcpServer = new McpServer(
|
|
4428
|
-
{ name: "run-mcp", version: "1.7.
|
|
4474
|
+
{ name: "run-mcp", version: "1.7.1" },
|
|
4429
4475
|
{
|
|
4430
4476
|
capabilities: {
|
|
4431
4477
|
tools: {},
|
|
@@ -5020,7 +5066,7 @@ Available: ${available}`
|
|
|
5020
5066
|
},
|
|
5021
5067
|
async () => {
|
|
5022
5068
|
try {
|
|
5023
|
-
const servers = await discoverServers();
|
|
5069
|
+
const servers = await discoverServers({ scan: opts.scan });
|
|
5024
5070
|
if (servers.length === 0) {
|
|
5025
5071
|
return {
|
|
5026
5072
|
content: [
|
|
@@ -5454,7 +5500,7 @@ ${stderrLines.join("\n") || "(none)"}`
|
|
|
5454
5500
|
const searchTypes = type ?? ["tools"];
|
|
5455
5501
|
const lowerQuery = query.toLowerCase();
|
|
5456
5502
|
try {
|
|
5457
|
-
const servers = await discoverServers();
|
|
5503
|
+
const servers = await discoverServers({ scan: opts.scan });
|
|
5458
5504
|
if (servers.length === 0) {
|
|
5459
5505
|
return {
|
|
5460
5506
|
content: [{ type: "text", text: "No local MCP servers found to search." }]
|
|
@@ -5975,7 +6021,7 @@ program.command("close-session").argument("<session_name>", "Session name").desc
|
|
|
5975
6021
|
}
|
|
5976
6022
|
}
|
|
5977
6023
|
});
|
|
5978
|
-
program.name("run-mcp").description("A smart interactive REPL and live test harness for MCP servers").version("1.7.
|
|
6024
|
+
program.name("run-mcp").description("A smart interactive REPL and live test harness for MCP servers").version("1.7.1").passThroughOptions().allowUnknownOption().argument(
|
|
5979
6025
|
"[target_command...]",
|
|
5980
6026
|
"Command to spawn the target MCP server (starts REPL if provided, Agent server otherwise)"
|
|
5981
6027
|
).option("-o, --out-dir <path>", "Directory to save intercepted images and audio").option(
|
|
@@ -5990,7 +6036,10 @@ program.name("run-mcp").description("A smart interactive REPL and live test harn
|
|
|
5990
6036
|
).option("--mcp", "Force start Agent Server mode even if run interactively without arguments").option("-s, --script <file>", "Read commands from a file instead of stdin (REPL Mode only)").option("--color <mode>", "Color output mode: always, never, auto (default: auto)").option(
|
|
5991
6037
|
"--open-media",
|
|
5992
6038
|
"Automatically open intercepted images and audio files using the host OS viewer"
|
|
5993
|
-
).option("--sandbox <mode>", "Sandbox execution mode: auto, docker, native, audit, none", "none").
|
|
6039
|
+
).option("--sandbox <mode>", "Sandbox execution mode: auto, docker, native, audit, none", "none").option(
|
|
6040
|
+
"--scan",
|
|
6041
|
+
"Scan the current workspace and parent directories for any JSON files containing mcpServers"
|
|
6042
|
+
).addHelpText(
|
|
5994
6043
|
"after",
|
|
5995
6044
|
`
|
|
5996
6045
|
Examples:
|
|
@@ -6085,10 +6134,11 @@ Shortcuts: tl td tc ts rl rr rt rs ru pl pg (see help for details)`
|
|
|
6085
6134
|
allowNet: opts.allowNet,
|
|
6086
6135
|
denyRead: opts.denyRead,
|
|
6087
6136
|
denyWrite: opts.denyWrite,
|
|
6088
|
-
denyNet: opts.denyNet
|
|
6137
|
+
denyNet: opts.denyNet,
|
|
6138
|
+
scan: opts.scan
|
|
6089
6139
|
});
|
|
6090
6140
|
} else {
|
|
6091
|
-
const selected = await pickDiscoveredServer();
|
|
6141
|
+
const selected = await pickDiscoveredServer({ scan: opts.scan });
|
|
6092
6142
|
if (!selected) {
|
|
6093
6143
|
console.log("Run 'run-mcp --help' to see manual usage instructions.");
|
|
6094
6144
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run-mcp",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "A smart proxy and interactive REPL for Model Context Protocol (MCP) servers",
|
|
5
5
|
"homepage": "https://github.com/funkyfunc/run-mcp#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"run-mcp": "dist/index.js"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
|
-
"build": "tsup",
|
|
32
|
+
"build": "tsup && node scripts/update-readme-help.js",
|
|
33
33
|
"build:fixtures": "tsup tests/fixtures/mock-server.ts tests/fixtures/vulnerable-stdio-server.ts --format esm --target node18 --out-dir tests/fixtures/dist",
|
|
34
34
|
"dev": "tsup --watch",
|
|
35
35
|
"start": "node dist/index.js",
|