Skip to content

Bug: MCP Server Mode (mcp serve) Outputs Non-JSON Text to Stdout, Breaking Protocol Communication #440

Open
@jroth55

Description

@jroth55

Description:

When running repomix in MCP server mode (repomix mcp serve), the process outputs various non-JSON text elements (startup banner, interactive prompts, spinners, logs) to standard output (stdout). This contaminates the JSON-RPC communication channel expected by the Model Context Protocol, causing MCP clients like Claude Desktop to fail parsing the output, resulting in timeouts and disconnections.

Environment:

  • OS: macOS (Latest version)
  • Node.js Version: (Latest version)
  • Repomix Version: (Latest version)
  • Installation Method: npx (also observed similar behavior potentially with homebrew global install)
  • MCP Client: Claude Desktop (Latest version)
  • Other MCP Servers: mcp-file-operations-server (running concurrently, but issue appears specific to Repomix output)

Steps to Reproduce:

  1. Configure Claude Desktop's MCP settings file (claude_desktop_config.json or similar) to run the Repomix MCP server using npx:
    {
      "mcpServers": {
        "file-operations-server": {
          "command": "node",
          "args": [
            "/path/to/mcp-file-operations-server/build/index.js"
          ]
        },
        "repomix": {
          "command": "npx",
          "args": [
            // "-y", // Note: Including -y caused an "unknown option" error from repomix itself
            "repomix",
            "mcp",
            "serve"
            // "--quiet" // Adding --quiet here did not resolve the issue
          ]
        }
      }
    }
  2. Start Claude Desktop, ensuring it launches the configured MCP servers.
  3. Attempt to use a Repomix tool via Claude, for example, by asking it to analyze a local project directory (this should trigger the pack_codebase tool).
  4. Observe the MCP server logs provided by Claude Desktop (usually accessible via Developer Tools or a log file).

Expected Behavior:

The repomix mcp serve process should strictly adhere to the Model Context Protocol's communication standard:

  • Only valid JSON-RPC 2.0 messages should be printed to stdout.
  • No startup banners, interactive prompts (like the migration check), spinners, ANSI escape codes, or general log messages should be output to stdout. Output intended for debugging or user visibility during normal CLI operation should be suppressed or redirected to stderr when in MCP mode.
  • The MCP client (Claude Desktop) should maintain a stable connection and successfully parse responses from the repomix server process.

Actual Behavior:

The repomix process outputs non-JSON text to stdout, causing the MCP client's JSON parser to fail. This leads to request timeouts and the server connection being dropped by the client.

Log snippets demonstrating the invalid output on stdout:

  • Startup Banner:

    [error] [repomix] Unexpected token '�', "📦 Repomix v0.3.0" is not valid JSON
    
  • Migration Check Prompt (from @clack/prompts via src/cli/actions/migrationAction.ts):

    [error] [repomix] Unexpected token '◆', "◆  Found R"... is not valid JSON
    [error] [repomix] Unexpected token '│', "│  ● Yes / ○ No" is not valid JSON
    [error] [repomix] Unexpected token '│', "│  No" is not valid JSON
    [error] [repomix] Unexpected token 'M', "Migration cancelled." is not valid JSON
    
  • Spinner/ANSI Codes (from log-update via src/cli/cliSpinner.ts):

    [error] [repomix] Unexpected token ' ', " [?25l│" is not valid JSON
    [error] [repomix] Unexpected token ' ', " [999D [4A"... is not valid JSON
    
  • Standard Logger Output (from src/shared/logger.ts):

    [error] [repomix] Unexpected token 'N', "No custom "... is not valid JSON
    [error] [repomix] Unexpected token 'N', "Need help?" is not valid JSON
    [error] [repomix] Unexpected token '•', "• Join our"... is not valid JSON
    
  • Error Handling Output:

    [error] [repomix] Unexpected token '✖', "✖ Error du"... is not valid JSON
    
  • (Separate Issue Observed): When using args: ["-y", "repomix", "mcp", "serve"], the process immediately crashes with error: unknown option '-y', indicating -y is incorrectly passed to repomix instead of being consumed by npx. Removing -y allows the server to start but reveals the stdout pollution issue.

Analysis:

The core issue is that the MCP server mode does not adequately suppress or redirect output generated by various components:

  1. The initial version banner.
  2. The interactive migration check prompt (this should likely be completely disabled in MCP mode).
  3. Spinners and progress indicators using libraries like log-update.
  4. Regular log messages (info, notes, potentially even errors formatted for CLI).

While the MCP tool handlers (e.g., src/mcp/tools/packCodebaseTool.ts) attempt to mitigate this by passing quiet: true when invoking the underlying runCli function, this seems insufficient to silence all output sources, especially interactive elements and potentially the initial banner.

Suggested Fix:

  1. Ensure the mcp serve command path completely bypasses or silences the startup banner.
  2. Prevent the interactive migration check (src/cli/actions/migrationAction.ts) from running or rendering its UI when in MCP mode.
  3. Ensure that all instances of spinners (cliSpinner.ts) or other stdout-manipulating libraries (like log-update) are effectively disabled when quiet: true is active or specifically when running in MCP mode. Redirecting progress updates to stderr might be an alternative if progress reporting is desired for debugging.
  4. Verify that the logger respects the quiet flag consistently across all log levels (or that logging in MCP mode is redirected to stderr).

Thank you for considering this issue! Repomix MCP integration is a very useful feature.


Image

mcp-server-repomix.log

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions