[BUG] `claude mcp add` passthrough arg parser breaks on bare -p flag in subcommand args

Status Fixed / completed
Reported on v2.1.216
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 21, 2026 · closed Aug 25, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

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.

View original on GitHub ↗

3 Comments

bcherny collaborator · 1 month ago

Thanks for the detailed report and the minimal isolation table — this reproduces exactly as described.

Verified on the latest release (2.1.233, Linux, clean config):

$ claude mcp add testA -s user -- docker run -i --rm -p 127.0.0.1:8085:8085 alpine
error: unknown option '-s'

Every row of your isolation table matches: -p 8085 fails the same way, while --publish 127.0.0.1:8085:8085, no--p, and -e FOO=bar-only variants all succeed.

We also bisected across published releases: this worked correctly up through 2.1.81 and first breaks in 2.1.83 (no 2.1.82 was published), so it's a confirmed regression from that release onward — predating the 2.1.216 you reported against and still present in 2.1.233. Your diagnosis matches what we observed: a bare -p token after -- collides with a top-level short flag during a rescan of the passthrough args, which then corrupts parsing of the earlier, valid options. Everything after -- should of course be treated as opaque.

Marking as a reproduced regression. Until a fix ships, the workaround you found — using the long form (--publish) in the passthrough command — is the best option.

🤖 Generated with Claude Code

bcherny collaborator · 1 month ago

This was fixed in Claude Code v2.1.239: the CLI's early scan for the print flag (-p/--print) now stops at the -- separator, so flags in the passthrough command (like docker's -p 127.0.0.1:8085:8085) are no longer misread as CLI options.

Verified on the current build:

$ claude mcp add testA -s user -- docker run -i --rm -p 127.0.0.1:8085:8085 alpine
Added stdio MCP server testA with command: docker run -i --rm -p 127.0.0.1:8085:8085 alpine to user config
$ claude mcp get testA
  Command: docker
  Args: run -i --rm -p 127.0.0.1:8085:8085 alpine

Please update to v2.1.239 or later (claude update). We also added regression tests covering this exact command so it stays fixed. Changelog: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md

github-actions[bot] · 15 hours ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.