Skip to content

fix(fix-pin): preserve canonical raw command/args instead of dropping arguments#48

Merged
Conalh merged 1 commit into
mainfrom
pr2-fix-pin-raw-command
May 29, 2026
Merged

fix(fix-pin): preserve canonical raw command/args instead of dropping arguments#48
Conalh merged 1 commit into
mainfrom
pr2-fix-pin-raw-command

Conversation

@Conalh
Copy link
Copy Markdown
Owner

@Conalh Conalh commented May 29, 2026

Problem

planPinFixes built the target edit from:

canonicalCommand: canonicalServer.command.split(' ')[0],
canonicalArgs: canonicalServer.args,

But McpServer.command is the joined display string (command + args + url), and args is only populated when the parser saw a separate args array. So when a canonical config authors the launch as a single inline string:

"command": "npx -y @modelcontextprotocol/server-github@1.2.3"

command.split(' ')[0] copied only "npx" and args was undefined — the fix silently dropped the package argument and rewrote the target down to a broken npx. A "helpful" fix that quietly lobotomizes the config.

Fix

  • Add McpServer.rawCommand — the verbatim command value as authored, before args/url were joined for the display string. Populated in the MCP parser.
  • planPinFixes now copies rawCommand + the verbatim args array, faithfully reproducing the canonical raw shape (inline command string vs. bare command + separate args). Url-only servers (nothing launchable to copy) are skipped.
  • alignCommandAndArgs now validates all edits before mutating (atomic per call — a partially-applicable fix can no longer half-rewrite a file), and refuses with a clear message when the canonical folds args into the command string but the target keeps a separate args array. Applying that would yield a duplicated, corrupt launch (npx -y pkg@1.2.3 -y pkg@2.0.0), so we skip and tell the user to align manually.

Tests

  • fix-pin-inline-command: canonical inline command string is preserved in full (package + flags intact), no stray args introduced, mismatch resolved on re-audit.
  • fix-pin-shape-mismatch: skipped with Applied 0 edit(s), skipped 1 and the target file left byte-for-byte untouched.
  • Existing Shape-A (separate args) fix-pin test still passes.

All 120 tests pass; dist/ rebuilt and committed.

🤖 Generated with Claude Code

… arguments

planPinFixes built the target edit from canonicalServer.command.split(' ')[0],
but `command` is the joined *display* string (command + args + url). When the
canonical config authored the launch as a single inline command string
("npx -y @modelcontextprotocol/server-github@1.2.3") with no separate `args`
array, the split copied only "npx" and silently dropped the package argument —
rewriting the target down to a broken launch line.

- Add McpServer.rawCommand: the verbatim `command` value as authored, before
  args/url were joined for display. Set it in the MCP parser.
- planPinFixes now copies rawCommand + the verbatim args array, faithfully
  reproducing the canonical raw shape. Skip planning for url-only servers that
  have nothing launchable to copy.
- alignCommandAndArgs validates all edits before mutating (atomic per call, so
  a partially-applicable fix can't half-rewrite a file) and refuses with a
  clear message when the canonical folds args into the command string but the
  target keeps a separate args array — applying that would yield a duplicated,
  corrupt launch line.

Tests: inline-command canonical keeps its full command; shape-mismatch is
skipped with the file left byte-for-byte untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Conalh Conalh merged commit 190be29 into main May 29, 2026
5 checks passed
@Conalh Conalh deleted the pr2-fix-pin-raw-command branch May 29, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant