Skip to content

[smoke-detector] 🔍 Smoke Test Investigation - Smoke Claude: Invalid MCP Configuration Argument #2267

Description

@github-actions

🔍 Smoke Test Investigation - Run #18769543228

Summary

The Smoke Claude workflow failed immediately when Claude Code CLI attempted to parse the --mcp-config argument. The CLI received inline JSON but interpreted it as a file path, causing it to exit with "MCP config file not found" error before any agent execution could begin.

Failure Details

  • Run: #18769543228
  • Commit: 24bb96c
  • Branch: copilot/update-engines-cli-arguments
  • Trigger: workflow_dispatch
  • Duration: 1.8 minutes
  • Failed Job: agent (21s duration)

Root Cause Analysis

Primary Error

Error: Invalid MCP configuration:
MCP config file not found: /home/runner/work/gh-aw/gh-aw/{mcpServers:{github:{command:docker,args:[run,-i,--rm,-e,GITHUB_PERSONAL_ACCESS_TOKEN,-e,GITHUB_READ_ONLY=1,-e,GITHUB_TOOLSETS=default,ghcr.io/github/github-mcp-server:v0.19.1],env:{GITHUB_PERSONAL_ACCESS_TOKEN:ghs***}},safe_outputs:{...}}}

The error shows Claude Code CLI attempted to use the entire JSON string as a file path at pkg/workflow/claude_engine.go:238:17 (cli.js:3744).

Investigation Findings

The Problem: CLI Argument Interpretation Mismatch

The commit 24bb96c made changes to JSON compaction:

  • Modified validateAndCompactJSON to remove backslash escaping from ${VAR} patterns
  • Intent: Correct for single-quoted CLI arguments (no shell expansion needed)
  • Effect on Claude: Claude Code's --mcp-config expects a file path, not inline JSON
Component Expected Format Actual Format Status
Claude Code --mcp-config File path to JSON config Inline JSON string ❌ Mismatch
Copilot --additional-mcp-config Raw JSON string Raw JSON string ✅ Works

CLI Command That Failed

claude --print \
  --mcp-config "{"mcpServers":{"github":{...},"safe_outputs":{...}}}" \
  --allowed-tools "..." \
  --debug --verbose \
  --permission-mode bypassPermissions \
  "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"

Claude Code tried to open /home/runner/work/gh-aw/gh-aw/{mcpServers:{...}} as a file, which obviously doesn't exist.

Failed Jobs and Errors

Job Sequence

  1. activation - succeeded (9s)
  2. agent - failed (21s) - Claude Code CLI couldn't parse MCP config argument
  3. create_issue - failed (5s) - Dependent on agent job
  4. ⏭️ missing_tool - skipped
  5. ⏭️ detection - skipped

Error Details

Location: /tmp/gh-aw/agent-stdio.log:5-8

Error: Invalid MCP configuration:
MCP config file not found: /home/runner/work/gh-aw/gh-aw/{mcpServers:...}
MCP config file not found: /home/runner/work/gh-aw/gh-aw/{mcpServers:...}  
MCP config file not found: /home/runner/work/gh-aw/gh-aw/{mcpServers:...}

Context: Claude Code CLI validates the --mcp-config argument during initialization and expects it to be a file path, not raw JSON content.

Commit Analysis

Commit: 24bb96c
Author: copilot-swe-agent[bot]
Message: "Fix JSON escaping issue for environment variables"

Files Changed (12 lines total):

  • pkg/workflow/engine_shared_helpers.go (+8 lines)
  • pkg/workflow/mcp-config.go (+4 lines)

Changes in validateAndCompactJSON (engine_shared_helpers.go:387-411):

// Look ahead - if next char is $, skip the backslash (for env var refs)
if i+1 < len(jsonStr) && jsonStr[i+1] == '$' && inString {
    // Skip the backslash - we're in a single-quoted context so no escaping needed
    continue
}

Intent: The change was correct for Copilot (which uses --additional-mcp-config and accepts raw JSON), but broke Claude Code which interprets --mcp-config as a file path parameter.

Comparison with Similar Issues

This is similar to issue #2262 (Copilot Base64 vs JSON), but with a different root cause:

Issue Engine Problem Root Cause
#2262 Copilot Expected JSON, got base64 Workflow not recompiled after code changes
This Issue Claude Expected file path, got JSON Different CLI argument semantics between engines

Recommended Actions

Critical Priority

  • Switch Claude to file-based MCP config

    # Instead of:
    claude --mcp-config "$MCP_JSON" ...
    
    # Use:
    echo "$MCP_JSON" > /tmp/mcp-config.json
    claude --mcp-config /tmp/mcp-config.json ...

    Rationale: Match Claude Code's expected behavior

  • Verify Claude Code CLI --mcp-config documentation

    • Confirm it only accepts file paths
    • Check if there's an alternative flag for inline JSON
    • Rationale: Ensure we're using the correct CLI interface

High Priority

  • Review BuildMCPConfigJSON usage across engines

    grep -r "BuildMCPConfigJSON" pkg/workflow/
    • Identify which engines use inline JSON vs file paths
    • Document engine-specific requirements
    • Rationale: Prevent similar issues with other engines
  • Add engine-specific integration tests

    • Test Claude with file-based MCP config
    • Test Copilot with inline JSON MCP config
    • Rationale: Catch CLI argument incompatibilities early

Medium Priority

  • Document MCP config approach for each engine

    - Claude: File path via --mcp-config
    - Copilot: Inline JSON via --additional-mcp-config  
    - Codex: TOML config file
    - GenAIScript: File path via --mcp-config
  • Consider unified approach

    • Evaluate using file-based config for ALL engines
    • Would eliminate escaping/quoting issues
    • Rationale: Simplify and standardize

Prevention Strategies

  1. Engine-Specific CLI Tests: Add tests that invoke actual CLI tools with MCP config

    func TestClaudeMCPConfig(t *testing.T) {
        // Write config to file
        // Invoke claude CLI with --mcp-config /path/to/file
        // Verify it starts without errors
    }
  2. Documentation: Create engine comparison matrix documenting CLI differences

  3. Code Review Checklist: Add item: "Does this affect MCP config for any engine?"

  4. Smoke Tests in PR CI: Run smoke tests automatically when engine code changes

Technical Details

Expected Behavior (After Fix)

# Write MCP config to file
cat > /tmp/mcp-config.json << 'EOF'
{
  "mcpServers": {
    "github": { ... },
    "safe_outputs": { ... }
  }
}
EOF

# Pass file path to Claude
claude --mcp-config /tmp/mcp-config.json ...

Actual Behavior (Current)

# Attempt to pass inline JSON
claude --mcp-config '{"mcpServers":{...}}' ...

# Claude interprets entire string as file path
# Error: MCP config file not found: /home/runner/work/gh-aw/gh-aw/{mcpServers:...}

Engine MCP Config Comparison

Engine CLI Flag Accepts Format
Claude Code --mcp-config File path JSON file
Copilot --additional-mcp-config Inline JSON JSON string
Codex Config file File path TOML file
GenAIScript --mcp-config File path JSON file

Related Information

Pattern Storage

Investigation saved to: /tmp/gh-aw/cache-memory/investigations/2025-10-24-18769543228.json
Pattern ID: CLAUDE_INVALID_MCP_CONFIG_ARG


Investigation Metadata:

  • Investigator: Smoke Detector
  • Investigation Run: #18769573968
  • Pattern ID: CLAUDE_INVALID_MCP_CONFIG_ARG
  • Severity: Critical
  • Is Flaky: No
  • Related Patterns: COPILOT_BASE64_MCP_CONFIG

Labels: smoke-test, investigation, claude, configuration, mcp, critical

AI generated by Smoke Detector - Smoke Test Failure Investigator

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions