[BUG] `claude mcp add` passthrough arg parser breaks on bare -p flag in subcommand args
Description
claude mcp add <name> -s <scope> -- <command> [args...] fails to parse when the passthrough command args (after --) contain a bare short flag -p (as in docker run ... -p 127.0.0.1:8085:8085). The CLI's own top-level option parser appears to rescan the args after -- and misfires on an unrelated top-level flag, rather than treating everything after -- as opaque passthrough.
This breaks the documented Docker-based local setup for MCP servers that need a published port (e.g. GitHub's official MCP server local/OAuth setup, per https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-claude.md).
Environment
- Claude Code CLI version: 2.1.216
- OS: macOS (Darwin 25.5.0)
Steps to reproduce
# Fails: "error: unknown option '-s'"
claude mcp add testA -s user -- docker run -i --rm -p 127.0.0.1:8085:8085 alpine
# Fails the same way even with a simple non-colon value:
claude mcp add testC -s user -- docker run -i --rm -p 8085 alpine
Expected behavior
Everything after -- should be treated as opaque args for the subprocess command and never re-parsed as top-level CLI options — this is the standard meaning of -- in POSIX-style CLIs (and is what commander.js does by default).
Actual behavior
error: unknown option '-s'
The reported "unknown option" is whichever top-level option was passed before -- (-s, -e, or --scope, depending on order) — i.e. the presence of -p later in the passthrough args corrupts parsing of earlier, valid top-level options.
Workaround
Replacing the short flag with its long form in the passthrough command avoids the bug entirely, since it's specifically the bare -p token that trips the parser:
# Works:
claude mcp add testB -s user -- docker run -i --rm --publish 127.0.0.1:8085:8085 alpine
Minimal isolation
| Command tail (after --rm) | Result |
|---|---|
| -p 127.0.0.1:8085:8085 alpine | ❌ unknown option '-s' |
| -p 8085 alpine | ❌ unknown option '-s' |
| --publish 127.0.0.1:8085:8085 alpine | ✅ works |
| (no -p/-e at all) | ✅ works |
| single -e FOO=bar (no -p) | ✅ works |
Adding -p anywhere in the passthrough args reproduces the failure regardless of whether -e is also present.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗