Skip to content

Add --command/--arg/--env flags to connect stdio servers without a config file #163

Open

Description

@jirispilka

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

  1. Argv form only. --command is the binary, --arg is repeatable. No shell string, no --shell, no --eval.
  2. No ${VAR} substitution in flag values. The shell already expands $VAR before mcpc sees it.
  3. --command cannot be combined with a URL server arg, --header, --profile, or --x402.
  4. If @session is omitted, derive it from the binary basename (e.g. dist/stdio.js → @stdio).
  5. 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?

Activity

  1. jancurn commented on Apr 15, 2026

    @jancurn
    Member

    @jirispilka thanks for the (good) suggestion, I'm now working on some changes of connect command, will address this right after to avoid merge conflicts

  2. jirispilka commented on Apr 15, 2026

    @jirispilka
    ContributorAuthor

    @jancurn cool, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions