Problem
mcpc is useful for developing MCP servers. The loop is: change code, rebuild, mcpc @stdio restart, run tools-list or tools-call, check the result. Faster and more scriptable than going through a full client like Claude Desktop or Cursor.
Right now this loop needs a config file:
mcpc connect ./.mcp.json:stdio @stdio
Fine for one stable setup. During feature work you often want to change what gets spawned:
- different tool sets to test
- two variants in parallel without maintaining two config entries
Every variant means editing a JSON file. In sandboxed or agent-supervised setups, writing a file often triggers an approval.
The transport already accepts {command, args, env} directly (createTransportFromConfig in src/core/transports.ts:141). There's just no CLI path to it without a file.
Proposal
Add flags to mcpc connect:
mcpc connect --command <binary> [--arg <value>...] [--env KEY=VAL...] @session
Example:
mcpc connect --command node --arg dist/stdio.js --env APIFY_TOKEN=xxx @stdio
mcpc @stdio tools-list
Rules
- Argv form only.
--command is the binary, --arg is repeatable. No shell string, no --shell, no --eval.
- No
${VAR} substitution in flag values. The shell already expands $VAR before mcpc sees it.
--command cannot be combined with a URL server arg, --header, --profile, or --x402.
- If
@session is omitted, derive it from the binary basename (e.g. dist/stdio.js → @stdio).
- Print
Launching: <command> <args...> on stderr at connect time. Already logged at debug in transports.ts:49 — promote to info for inline invocations.
Session reuse
For the --command path only: compare the new ServerConfig to the stored SessionData.server.
- Same name, same
{command, args, env}, bridge live → reuse.
- Same name, different config → stop the old bridge, spawn a new one.
Today's lookup is name-only (sessions.ts:253-282). This is a small semantic change, scoped to inline connects. HTTP and config-file paths are unchanged.
Security
mcpc already spawns arbitrary processes from config files. This feature is a CLI shortcut to the same ServerConfig shape. No new attack surface.
- Shell injection: not possible. Argv form, no shell string.
${VAR} env exfil: not possible. Config file substitutes ${VAR} (config.ts:147); flag values don't.
- Social engineering ("run this mcpc command"): same risk as today. The user trusts the command they type.
Peer tools accept inline command+args for the same reason:
npx @modelcontextprotocol/inspector node dist/stdio.js
claude mcp add <name> -- node dist/stdio.js
- Cursor, Windsurf CLIs
Complexity
Two files.
| Change |
File |
~LOC |
Add --command/--arg/--env options, mutual-exclusivity checks |
src/cli/index.ts (connect command) |
~20 |
Build ServerConfig from flags, skip parseServerArg |
src/cli/index.ts action handler |
~15 |
| Config-diff check on session reuse (scoped) |
src/cli/commands/sessions.ts |
~15 |
| Session-name auto-gen from binary basename |
src/cli/commands/sessions.ts |
~5 |
| Help text, README examples |
src/cli/index.ts, README.md |
~30 |
| Tests |
test/ |
~100 |
No changes to transports, bridge, session storage schema, reconnection, or auth.
Out of scope
- Applying the config-diff check to HTTP or config-file paths. Defensible as a separate PR, but behavior change for existing users.
- Stdin-config (
echo '{...}' | mcpc connect -). Same use case, worse ergonomics.
- Any shell-string variant of
--command.
Open questions
- Should the spawn echo be always on, or suppressible with
--quiet?
- If
--command derives @stdio and an existing @stdio was created from a different path, fall back to a numeric suffix or error out?
Problem
mcpcis useful for developing MCP servers. The loop is: change code, rebuild,mcpc @stdio restart, runtools-listortools-call, check the result. Faster and more scriptable than going through a full client like Claude Desktop or Cursor.Right now this loop needs a config file:
Fine for one stable setup. During feature work you often want to change what gets spawned:
Every variant means editing a JSON file. In sandboxed or agent-supervised setups, writing a file often triggers an approval.
The transport already accepts
{command, args, env}directly (createTransportFromConfiginsrc/core/transports.ts:141). There's just no CLI path to it without a file.Proposal
Add flags to
mcpc connect:Example:
Rules
--commandis the binary,--argis repeatable. No shell string, no--shell, no--eval.${VAR}substitution in flag values. The shell already expands$VARbefore mcpc sees it.--commandcannot be combined with a URL server arg,--header,--profile, or--x402.@sessionis omitted, derive it from the binary basename (e.g.dist/stdio.js→@stdio).Launching: <command> <args...>on stderr at connect time. Already logged atdebugintransports.ts:49— promote toinfofor inline invocations.Session reuse
For the
--commandpath only: compare the newServerConfigto the storedSessionData.server.{command, args, env}, bridge live → reuse.Today's lookup is name-only (
sessions.ts:253-282). This is a small semantic change, scoped to inline connects. HTTP and config-file paths are unchanged.Security
mcpc already spawns arbitrary processes from config files. This feature is a CLI shortcut to the same
ServerConfigshape. No new attack surface.${VAR}env exfil: not possible. Config file substitutes${VAR}(config.ts:147); flag values don't.Peer tools accept inline command+args for the same reason:
npx @modelcontextprotocol/inspector node dist/stdio.jsclaude mcp add <name> -- node dist/stdio.jsComplexity
Two files.
--command/--arg/--envoptions, mutual-exclusivity checkssrc/cli/index.ts(connect command)ServerConfigfrom flags, skipparseServerArgsrc/cli/index.tsaction handlersrc/cli/commands/sessions.tssrc/cli/commands/sessions.tssrc/cli/index.ts,README.mdtest/No changes to transports, bridge, session storage schema, reconnection, or auth.
Out of scope
echo '{...}' | mcpc connect -). Same use case, worse ergonomics.--command.Open questions
--quiet?--commandderives@stdioand an existing@stdiowas created from a different path, fall back to a numeric suffix or error out?