Skip to content

[Bug]: stdio MCP server fails to start when its command/args path contains spaces or parentheses #174

Description

@julianmesa-gitkraken

What happened?

When an ACP host declares a stdio MCP server whose resolved command/args contain a path with a space or parentheses (e.g. a macOS app bundle named MyApp (staging).app), Auggie fails to start that MCP server with:

MCP error -32000: Connection closed
Command: node /Applications/MyApp (staging).app/.../server.js

Root cause (found by reading the shipped auggie bundle, v0.36.0): the code path that normalizes a stdio server config joins command and args into a single string and clears args:

let l = a.length > 0 ? `${e(s)} ${a.join(" ")}` : e(s);
// -> { command: l, args: [], useShellInterpolation: true }

The resulting { command, args: [], useShellInterpolation: true } is then spawned through a shell (/bin/sh -c "<command>"). If the joined string contains an unescaped space or (, the shell word-splits it, node receives only the first path segment as its entry point, fails with "Cannot find module", the child exits immediately, and the MCP client sees "Connection closed" instead of the real error.

This affects any stdio MCP server whose command or argument path contains a space or shell metacharacter — which is common on macOS, where app bundle names routinely contain spaces and parentheses (e.g. non-default release channels named MyApp (staging).app, MyApp (beta).app, etc.), and on Windows under C:\Program Files\....

What did you expect to happen?

A stdio MCP server whose command/args resolve to a path containing spaces or parentheses should start normally. Either:

  • don't collapse command + args into a single shell string (keep them as an argv array passed with shell: false), or
  • if a single string is required for some code path, shell-quote each token (command and every arg) before joining, so the shell can't re-split it.

Steps to reproduce

  1. Build a minimal ACP client that spawns auggie --acp and speaks the ACP protocol directly (initialize → session/new → session/prompt).
  2. In the session/new (or --mcp-config) MCP server list, add a stdio server whose command/args resolve to a path containing a space and a parenthesis, e.g.:
    { "name": "repro", "command": "node", "args": ["/tmp/dir (with parens)/server.js"] }
  3. Observe Auggie's stderr during MCP initialization:
    ⚠️ MCP server startup error: MCP error -32000: Connection closed
       Command: node /tmp/dir (with parens)/server.js
       ❌ repro (failed)
    
  4. For comparison, the same server.js at a path with no spaces starts fine.

We reproduced this end-to-end against the real @augmentcode/auggie@0.36.0 npm bundle (not just by reading the source) — the child process for the spaced/parenthesized path never starts (confirmed by having the target script log its own process.argv to a file on launch), while the unspaced path starts every time.

Auggie version

0.36.0

Request ID

N/A — reproduced with a minimal standalone ACP client script driving the auggie --acp bundle directly, not the interactive CLI, so no /request-id was generated. Happy to provide a request ID from an interactive repro if useful.

Environment details

Environment
  • OS: macOS (Apple Silicon)
  • Shell: zsh
  • Tool/CLI version: @augmentcode/auggie@0.36.0 (npm)
  • Host: a third-party ACP host (GitKraken Kepler) that shells out to auggie --acp; the host's own non-production build names its app bundle with a space and parentheses (e.g. Kepler (staging).app), which is what surfaces this on macOS.

Anything else we need to know?

We worked around this on our side with a local patch that shell-quotes each token before Auggie joins command/args, which resolves the symptom for us, but the underlying collapse-to-a-single-shell-string behavior seems like something worth fixing upstream so every ACP host (and every OS whose paths can contain spaces) doesn't need the same workaround.

Happy to share the exact reproduction harness/script privately if that's useful for triage.

Activity

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