Skip to content

fix(registry): Docker MCP Catalog → docker run install (closes #483)#484

Merged
Dumbris merged 1 commit into
mainfrom
fix/483-docker-catalog-installcmd
May 20, 2026
Merged

fix(registry): Docker MCP Catalog → docker run install (closes #483)#484
Dumbris merged 1 commit into
mainfrom
fix/483-docker-catalog-installcmd

Conversation

@Dumbris

@Dumbris Dumbris commented May 20, 2026

Copy link
Copy Markdown
Member

Summary

Closes #483. Adding a server from the Docker MCP Catalog repository now produces a valid stdio config (docker run -i --rm mcp/<name>) instead of the synthetic docker://mcp/<name> URL that the frontend then mis-classified as an HTTP transport.

Two stacked bugs were both blocking the flow — fixing #1 alone surfaces #2.

Bug 1 — backend: parseDocker produced a fake URL

internal/registries/search.go left ServerEntry.URL empty in parseDocker and then constructServerURL filled the gap with docker://mcp/<name>. The frontend treats any non-empty server.url as an HTTP endpoint, so the MCP client tried POST docker://mcp/sqliteunsupported protocol scheme: docker (the exact error in #483).

Fix: parseDocker now emits InstallCmd: "docker run -i --rm mcp/<name>" (matching the OCI pattern that parseFleur was already using), and constructServerURL no longer fabricates URLs for protocolDocker. The URL field is reserved for HTTP/SSE endpoints.

Bug 2 — frontend: snake_case vs camelCase mismatch

The backend contract (contracts.RepositoryServer) serialises install_cmd and connect_url in snake_case, but frontend/src/{services/api.ts,types/api.ts,views/Repositories.vue} were reading server.installCmd / server.connectUrl (camelCase). Always undefined. Pre-fix, Docker entries fell through to server.url (the fake docker:// value), so this latent bug was hidden behind Bug 1.

Fix: read install_cmd / connect_url consistently, matching source_code_url etc. already used in the same file.

Regression tests

  • TestParseDocker asserts InstallCmd populated and URL empty.
  • TestConstructServerURL/docker_protocol_returns_empty asserts no synthetic URL.

Verification

End-to-end verified locally:

  1. curl /api/v1/registries/docker-mcp-catalog/servers?q=sqlite returns install_cmd: "docker run -i --rm mcp/sqlite", no url.
  2. Calling upstream_servers via MCP with that command/args registers the server cleanly as {protocol: stdio, command: docker, args: [run,-i,--rm,mcp/sqlite]}.
  3. Chrome flow on the Repositories page: pick Docker MCP Catalog → search "sqlite" → "Add to MCP" → server appears in Servers list as "sqlite — stdio • docker", auto-quarantined for review. No error banner.

Follow-up

A larger registry modernisation is being drafted under specs/051-registry-modernization/ — adopt the canonical registry.modelcontextprotocol.io v0 schema (packages[] / remotes[]), retire stale fallbacks (Smithery, Azure demo), and unify the parsed payload so the frontend doesn't have to guess transport from installCmd vs url. This PR is the narrow, ship-now half.

Refs: #483

…ocker:// URL)

Two stacked bugs were preventing 'Add server from Docker MCP Catalog'
from ever working:

1. internal/registries/search.go — parseDocker left ServerEntry.URL
   empty, then constructServerURL synthesised 'docker://mcp/<name>'.
   The frontend treated any non-empty URL as an HTTP transport and
   issued POST 'docker://mcp/sqlite' → 'unsupported protocol scheme:
   docker' (the user-visible error in #483).

   Fix: parseDocker now emits InstallCmd 'docker run -i --rm mcp/<name>'
   (matching the parseFleur pattern for OCI servers) and
   constructServerURL no longer fabricates URLs for protocolDocker.

2. frontend/src/services/api.ts + types/api.ts + views/Repositories.vue
   — the backend contract serialises install_cmd / connect_url in
   snake_case, but the Vue code read server.installCmd / server.connectUrl
   (camelCase), so the value was always undefined. With #483's URL
   gone, the second bug surfaced as 'Either url or command parameter
   is required'.

   Fix: read snake_case consistently (matches source_code_url etc.
   already used elsewhere in the same file).

Regression tests:
- TestParseDocker asserts InstallCmd populated, URL empty.
- TestConstructServerURL/docker_protocol_returns_empty asserts no
  synthetic URL.

End-to-end verified via curl (REST + MCP tool call) and Playwright-
style Chrome flow: a sqlite catalog entry now lands as
{protocol:stdio, command:docker, args:[run,-i,--rm,mcp/sqlite]},
auto-quarantined for review.

Refs: #483
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: d0819c4
Status: ✅  Deploy successful!
Preview URL: https://b0c395f1.mcpproxy-docs.pages.dev
Branch Preview URL: https://fix-483-docker-catalog-insta.mcpproxy-docs.pages.dev

View logs

@github-actions

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/483-docker-catalog-installcmd

Available Artifacts

  • archive-darwin-amd64 (26 MB)
  • archive-darwin-arm64 (23 MB)
  • archive-linux-amd64 (15 MB)
  • archive-linux-arm64 (13 MB)
  • archive-windows-amd64 (26 MB)
  • archive-windows-arm64 (23 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (20 MB)
  • installer-dmg-darwin-arm64 (18 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 26142774386 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@Dumbris Dumbris merged commit f772e49 into main May 20, 2026
24 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.

Error adding server from Docker repository

1 participant