Skip to content

feat(connect): one-click Claude Desktop via mcp-remote stdio bridge (MCP-2479)#682

Merged
Dumbris merged 3 commits into
mainfrom
fix/mcp-2479-claude-desktop-bridge
Jun 15, 2026
Merged

feat(connect): one-click Claude Desktop via mcp-remote stdio bridge (MCP-2479)#682
Dumbris merged 3 commits into
mainfrom
fix/mcp-2479-claude-desktop-bridge

Conversation

@Dumbris

@Dumbris Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

The Connect wizard marked Claude Desktop as unsupported even though mcpproxy is reachable from it through an npx -y mcp-remote <mcpURL> stdio bridge (already documented in docs/setup.md). This made a working, documented path look impossible and cost an adoption win.

This PR makes Claude Desktop a real one-click connect target.

Changes

  • internal/connect/clients.go — flip claude-desktop to Supported: true; add a stdio-bridge branch to buildServerEntry that writes command: "npx", args: ["-y", "mcp-remote", <mcpURL>]. New Note field on ClientDef carries the bridge caveat.
  • internal/connect/connect.go — add Note to ClientStatus (json:"note,omitempty") and propagate it in GetAllStatus. Connected-state detection already matches the canonical mcpproxy entry name, so bridge connections are tracked even without a URL field.
  • frontend/src/components/ConnectModal.vue + types/api.ts — render the bridge note under the client row; Claude Desktop now shows a real Connect button.
  • Docs / OASdocs/setup.md notes the one-click wizard path; connect POST/DELETE client-ID examples widened; make swagger regenerated.

TDD / Acceptance

  • buildServerEntry("claude-desktop", …) emits npx -y mcp-remote <mcpURL> and no URL field — TestBuildServerEntry_ClaudeDesktop_StdioBridge.
  • Connect("claude-desktop", …) writes the bridge entry (with API key in the URL when set) — TestConnect_ClaudeDesktop_WritesStdioBridge, TestConnect_ClaudeDesktop_BridgeIncludesAPIKey.
  • claude-desktop is Supported with a bridge note — TestClaudeDesktop_SupportedWithBridgeNote, updated TestGetAllStatus.
  • Bridge connection detected as connected — TestGetAllStatus_ClaudeDesktop_DetectsBridgeConnection.
  • ConnectModal renders a Connect button + bridge note — connect-modal.spec.ts.

Verification

  • go test ./internal/connect/... -race — ok
  • go build ./... — ok
  • golangci-lint v2.5.0 (CI config) on internal/connect/... — 0 issues
  • npx vitest run — 172 passed; vue-tsc --noEmit — clean
  • make swagger verify — passed (pre-push hook green)

Related MCP-2479

🚫 Do not merge — pre-merge gate is human-only (CI green + reviewers + QA first).

Claude Desktop was marked unsupported in the Connect wizard because it
only speaks stdio, even though mcpproxy can be reached from it via an
`npx -y mcp-remote <mcpURL>` bridge (already documented in docs/setup.md).

- Flip claude-desktop to Supported=true and add a stdio-bridge branch to
  buildServerEntry that writes `command: npx`, `args: [-y, mcp-remote, <mcpURL>]`.
- Add a Note field (ClientDef/ClientStatus) surfacing the bridge requirement;
  render it in ConnectModal so users know the path uses mcp-remote (needs Node.js).
- Connected-state detection already matches the canonical `mcpproxy` entry name,
  so bridge connections are tracked without a URL field.
- Docs: note the one-click wizard path in docs/setup.md; widen connect POST/DELETE
  client-ID examples.

Related MCP-2479
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 15, 2026

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 77a1b6a
Status: ✅  Deploy successful!
Preview URL: https://559adfcc.mcpproxy-docs.pages.dev
Branch Preview URL: https://fix-mcp-2479-claude-desktop.mcpproxy-docs.pages.dev

View logs

@codecov-commenter

codecov-commenter commented Jun 15, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 82.60870% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/connect/connect.go 78.94% 2 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

On Windows, ConfigPath ignores the homeDir override for claude-desktop
and vscode (it reads %APPDATA%), so the no-key and with-key Claude Desktop
bridge tests both wrote to the same real APPDATA\Claude path. The no-key
test ran first and created the entry; the with-key test then hit
`already_exists` (force=false) and never wrote the apikey, failing the
assertion on the windows-amd64 runner.

Pin %APPDATA% under the per-test temp dir in the test-service helpers,
mirroring the existing %LOCALAPPDATA% line, so every client's config path
is isolated per-test on Windows. No-op on macOS/Linux.

Related MCP-2479
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/mcp-2479-claude-desktop-bridge

Available Artifacts

  • archive-darwin-amd64 (28 MB)
  • archive-darwin-arm64 (25 MB)
  • archive-linux-amd64 (16 MB)
  • archive-linux-arm64 (14 MB)
  • archive-windows-amd64 (28 MB)
  • archive-windows-arm64 (25 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (21 MB)
  • installer-dmg-darwin-arm64 (19 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 27545308743 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@Dumbris

Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

codex review (gpt-5.5, in-checkout) → REQUEST_CHANGES. The generated bridge entry is valid (npx -y mcp-remote <url>) and other clients are unaffected, but two gaps defeat the one-click goal:

  1. Connect button hidden for fresh Claude Desktop installs. ConnectModal.vue only shows Connect when client.supported && client.exists, but a fresh Claude Desktop has no config file yet (exists===false) — the common case — even though backend Connect can create the file. Fix: for the bridge client, show Connect even when the config file doesn't exist yet (let Connect create it).
  2. Status detection only matches the mcpproxy key. connect.go reports the client disconnected unless the entry key is exactly mcpproxy, so a custom server_name bridge is written but shown disconnected. Fix: detect the bridge by inspecting the entry's args (mcp-remote + the mcpURL), not just the key name.

…e bridge

Addresses Codex REQUEST_CHANGES on PR #682 (MCP-2479):

Gap 1 — Connect button hidden on fresh installs. A fresh Claude Desktop has
no config file yet (exists=false), so the modal showed "Config not found"
instead of a Connect button even though Connect can create the file. Add a
`Bridge` flag to ClientDef/ClientStatus (true for claude-desktop) and relax
the frontend gate to `supported && (exists || bridge)` for the button and
the Connect-All set.

Gap 2 — Status detection only matched the `mcpproxy` key. A bridge written
under a custom server_name has no URL field and a non-default key, so it
showed disconnected. Detect the bridge by inspecting the entry args
(mcp-remote + mcpURL) via entryPointsToBridge, regardless of the key.

Tests: custom-name bridge detection, bridge flag on ClientDef/status, and a
fresh-install (exists=false) Connect-button render. go test ./internal/connect/...
green; full vitest + vue-tsc green.

Related MCP-2479
@Dumbris

Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

Addressed both REQUEST_CHANGES gaps (77a1b6a0)

Gap 1 — Connect button hidden on fresh installs. Added a Bridge flag to ClientDef/ClientStatus (true for claude-desktop, serialized as bridge). ConnectModal.vue now gates the button on supported && (exists || bridge) — both the per-row button (the Config not found branch is skipped for bridge clients) and the connectableClients set used by Connect All. A fresh install with no claude_desktop_config.json now shows Connect; backend Connect creates the file.

Gap 2 — Status detection only matched the mcpproxy key. Added entryPointsToBridge() in connect.go, called from findEntryJSON: a config entry is recognized as our bridge when its args contain both mcp-remote and our MCP URL (mcpURL/baseURL/baseURL?…), regardless of the entry key. A bridge written under a custom server_name is now reported connected with that name.

Tests added

  • TestGetAllStatus_ClaudeDesktop_DetectsBridgeUnderCustomName — custom-name bridge → connected, server_name preserved.
  • Bridge-flag assertions on ClientDef and GetAllStatus.
  • Vue: fresh-install (exists:false, bridge:true) renders Connect, no Config not found.

Verification

  • go test ./internal/connect/... -race — ok
  • go build ./... — ok; golangci-lint v2.5.0 (CI config) — 0 issues
  • npx vitest run — 173 passed; vue-tsc --noEmit — clean
  • make swagger — no diff (ClientStatus isn't a typed swagger schema)

Ready for re-review.

@mcpproxy-gatekeeper mcpproxy-gatekeeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

codex re-review ACCEPT (gpt-5.5, in-checkout): ConnectModal now shows Connect for bridge clients even when config file absent (connectableClients includes c.bridge); connect.go detects the bridge by args (mcp-remote + mcpURL) so custom server_name entries are recognized; generated entry valid; other clients unaffected. Both round-1 gaps closed.

@Dumbris Dumbris merged commit 3a34c8e into main Jun 15, 2026
40 checks passed
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.

2 participants