Files
metamcp-patched/README.md
T
justin d5cd602d85
Build & push patched image / build (push) Failing after 1m13s
initial commit: wrapper Dockerfile + CI
The wrapper sed-patches the two host-wide OAuth 2.1 discovery route
registrations in MetaMCP's compiled backend bundle so spec-compliant
MCP clients do not force an interactive login flow on public endpoints.

See README for full rationale (RFC 9728, MCP Authorization spec
2026-03-26 revision) and the diagnostic evidence.

Guarded with grep pre/post-conditions so a future upstream release
that renames or restructures these routes fails the build loudly
rather than silently shipping an unpatched image.
2026-07-22 12:04:58 -04:00

3.6 KiB

metamcp-patched

A thin wrapper around ghcr.io/metatool-ai/metamcp that hides the host-wide OAuth 2.1 discovery endpoints so spec-compliant MCP clients don't force an interactive login on public endpoints.

The problem this fixes

MetaMCP unconditionally publishes RFC 9728 protected-resource metadata and RFC 8414 authorization-server metadata at:

  • /.well-known/oauth-protected-resource
  • /.well-known/oauth-authorization-server

Both documents describe the whole MetaMCP host as OAuth-protected — even if every configured endpoint is public. Per the MCP Authorization spec (2026-03-26 revision), a spec-compliant client — Claude.ai's remote-MCP integration, Claude Desktop, and the reference SDKs — probes these paths on connect. When it sees them, it kicks off the OAuth flow (with dynamic client registration and PKCE) before calling any tool. Users get an interactive login page even when trying to connect to an endpoint that doesn't require auth.

The route mounts live in a compiled bundle with no env-var gate — the line app.use(oauth_default) in apps/backend/dist/index.js pulls the metadata router in unconditionally. There is no admin toggle for it in the shipping build.

This repo produces a wrapper image that sed-patches the two discovery route registrations to bogus paths, so Express falls through to its default 404 for those requests. Nothing else in MetaMCP changes.

Endpoints that DO enforce auth still 401 correctly; they just can't be consumed via OAuth dynamic-discovery clients any more (consume them via a bearer token in the MCP client's config instead).

Using the pre-built image

# docker-compose.yml
services:
  metamcp:
    image: git.jpaul.io/justin/metamcp-patched:latest
    pull_policy: always
    # ... rest of your existing metamcp service config unchanged

Or build from source locally

services:
  metamcp:
    image: metamcp-patched:local
    pull_policy: never
    build:
      context: https://git.jpaul.io/justin/metamcp-patched.git
      # or a local clone / vendored path

Bump upstream at any time with:

docker compose build --pull metamcp && docker compose up -d metamcp

The Dockerfile has grep guards that fail the build loudly if a future upstream release renames or restructures the OAuth routes, so a bad bump never silently ships an unpatched image.

Verify it worked

UA="Mozilla/5.0 (X11; Linux x86_64) Firefox/120.0"

# want 404, was 200 pre-patch
curl -sSo /dev/null -w "%{http_code}\n" -H "User-Agent: $UA" \
    "https://<your-metamcp-host>/.well-known/oauth-protected-resource"
curl -sSo /dev/null -w "%{http_code}\n" -H "User-Agent: $UA" \
    "https://<your-metamcp-host>/.well-known/oauth-authorization-server"

# want 200 (unchanged) — proves you didn't collaterally break the endpoint
curl -sSo /dev/null -w "%{http_code}\n" -H "User-Agent: $UA" \
    -H "Accept: application/json, text/event-stream" \
    -X POST -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"diag","version":"1.0"}}}' \
    "https://<your-metamcp-host>/metamcp/<a-public-endpoint>/mcp"

Delete this repo the day upstream ships a toggle

The right fix belongs in MetaMCP itself — either an env var like DISABLE_OAUTH_DISCOVERY=true, or per-endpoint RFC 9728 metadata scoping so public endpoints don't advertise. Track upstream at https://github.com/metatool-ai/metamcp.

License

MIT for the wrapper contents (Dockerfile, workflow, docs). The base image and everything it contains remain under their upstream licenses.