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

100 lines
3.6 KiB
Markdown

# metamcp-patched
A thin wrapper around [`ghcr.io/metatool-ai/metamcp`](https://github.com/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
```yaml
# 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
```yaml
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:
```bash
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
```bash
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.