Skip to content

fix(cli): stdio mcp-remote bridge for Claude Desktop onboarding#96

Draft
d-mo wants to merge 1 commit into
mainfrom
fix/claude-desktop-mcp-bridge
Draft

fix(cli): stdio mcp-remote bridge for Claude Desktop onboarding#96
d-mo wants to merge 1 commit into
mainfrom
fix/claude-desktop-mcp-bridge

Conversation

@d-mo

@d-mo d-mo commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Problem

Onboarding wrote a remote-shaped MCP entry ({url, transport, headers}) into claude_desktop_config.json. Claude Desktop's config file only supports stdio servers (command/args/env) — remote servers are added via Settings → Connectors — and the invalid entry can wedge the app's whole MCP subsystem. This bricked an external tester's Claude Desktop (older build, Intel Mac) until they logged out/in.

Fix (Claude Desktop only; other agents' shapes untouched)

  • Bridge entry: BuildManagedServer now writes the mcp-remote stdio bridge:
    {
      "command": "npx",
      "args": ["-y", "mcp-remote", "<url>", "--header", "Authorization:${AUTH_HEADER}"],
      "env": {"AUTH_HEADER": "Bearer <token>"}
    }
    The header is split into a space-free arg + env block, per the mcp-remote README workaround for Claude Desktop mangling spaces in args.
  • Preflight: when npx/node is not resolvable, no Preloop entry is written at all (there is no valid fallback shape). The enrollment marks the MCP-config step skipped and tells the user their options: install Node.js and re-run, or add Preloop as a custom connector in Settings → Connectors using the MCP URL (the endpoint supports the MCP OAuth flow). The existing prune still removes any broken remote-shaped entry left by an earlier onboard, so re-running the CLI repairs bricked configs.
  • Validation: ValidateManagedConfig validates the bridge shape for Claude Desktop and rejects the legacy remote shape.
  • Honest output: onboarding no longer claims MCP-firewall governance when the step was skipped; skip reason is persisted in the enrollment validation result (mcp_config_skipped).

Testing

  • 5 new tests: bridge shape + round-trip validation, JSON-reloaded validation, legacy-shape rejection, preflight write and skip paths (via new resolveClaudeDesktopBridgeRuntime test seam).
  • go build ./... && go test ./... green (350 tests in internal/cmd), gofmt -l clean.

Note

Low Risk
Well-structured fix following existing patterns; only affects Claude Desktop onboarding path.

Overview
Replaces the invalid remote-shaped MCP entry in Claude Desktop config with an mcp-remote stdio bridge. Adds preflight checks for Node.js availability, updates validation, and provides clear fallback guidance.

Written by Preloop PR Reviewer for commit fix/claude-desktop-mcp-bridge. Updates automatically on new commits.

Claude Desktop's claude_desktop_config.json only supports stdio MCP
servers (command/args/env); remote servers are added through the app's
Settings -> Connectors UI. Onboarding previously wrote a remote-shaped
entry ({url, transport, headers}) into the file, which Claude Desktop
cannot parse and which can wedge the app's entire MCP subsystem
(observed bricking an external tester's install on an older build).

Changes:
- BuildManagedServer now emits an mcp-remote stdio bridge for Claude
  Desktop: command "npx", args ["-y", "mcp-remote", <url>, "--header",
  "Authorization:${AUTH_HEADER}"] with env {AUTH_HEADER: "Bearer
  <token>"}. The header is split into a space-free arg plus an env
  block per the mcp-remote README workaround for Claude Desktop's
  arg-space mangling.
- Preflight: onboarding writes no Preloop entry at all when npx/node
  is not resolvable (there is no valid fallback shape). The plan marks
  the MCP-config step skipped, records it in the enrollment validation
  result, and tells the user their options: install Node.js and re-run,
  or add Preloop as a custom connector via Settings -> Connectors using
  the MCP URL (the endpoint supports the MCP OAuth flow). The existing
  preloop-entry prune still removes any broken remote-shaped entry left
  by an earlier onboard.
- ValidateManagedConfig validates the bridge shape for Claude Desktop
  (npx + mcp-remote + endpoint URL in args, --header auth via env or
  literal) and rejects the legacy remote shape.
- Onboarding output no longer claims MCP-firewall governance when the
  MCP-config step was skipped.

New seam resolveClaudeDesktopBridgeRuntime (package-level var, in the
style of resolveNpmExecutable) lets tests stub runtime resolution.
Adds 5 tests covering the bridge shape, JSON round-trip validation,
legacy-shape rejection, and both preflight outcomes.

@preloop-staging preloop-staging Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Preloop approves this PR.

A few minor observations below, but the code is ready to merge.

See the summary comment for details.

@preloop-staging

Copy link
Copy Markdown
Contributor

🔍 Preloop Code Review

Last Updated: 2026-07-20
Reviewing Commit: fix/claude-desktop-mcp-bridge
Review Status: ✅ Approved


📝 Summary

Well-structured fix for the Claude Desktop MCP onboarding issue. The PR correctly replaces the invalid remote-shaped entry with an mcp-remote stdio bridge, adds preflight checks for Node.js availability, updates validation to match the new shape, and provides clear user guidance when the bridge can't be written. Follows existing code patterns consistently.

✅ What Looks Good

  • Clean per-case handling for Claude Desktop without touching other agents' config shapes
  • Preflight check prevents writing invalid MCP entries when dependencies are missing
  • Validation explicitly rejects the legacy remote shape that caused the original bug
  • Good test coverage: bridge shape, JSON round-trip, legacy rejection, npx-present and npx-missing plan paths
  • Honest output — skip reason persisted in validation result and surfaced to user
  • Test seam pattern (resolveClaudeDesktopBridgeRuntime) consistent with existing resolveNpmExecutable

⚠️ Issues Found

🟢 Low Priority

Minor improvements, optional

  • Quality: stringArgsFromConfigValue silently drops non-string elements from []interface{} slices at agents.go:3290 — consider logging or erroring on unexpected types to avoid silently masking data corruption during JSON round-trips
  • Testing: TestClaudeDesktopPlanWritesBridgeWhenNpxPresent verifies only the command field; extending it to also check args and env shape would match the thoroughness of TestManagedServerSchemaClaudeDesktop

📄 Documentation Impact

  • CHANGELOG: Add entry for Claude Desktop mcp-remote bridge fix (user-visible behavior change for Claude Desktop onboarding)
  • README/onboarding docs: Document that Claude Desktop onboarding requires Node.js (or the Settings → Connectors fallback)

Progress: 0 of 2 issues addressed

This summary updates automatically on each review. Inline comments provide detailed feedback on specific lines.

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