agentic-community / agentic-community/mcp-gateway-registry

Per-server PRM: RFC 9728 path-aware URL returns 404 when registry_url has a path prefix (ROOT_PATH)

未关闭
#1,746 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Python
星标
911
派生
234
平均合并
1 天 11 小时
30 天内合并 PR
62

描述

## Summary

When the gateway runs under a path prefix (`ROOT_PATH=/registry`, `REGISTRY_URL=https://gw.example.com/registry`), the per-server PRM route does not resolve the RFC 9728 §3.1 path-aware URL that a client derives from the advertised `resource`.

- Advertised per-server resource (Entra, #990): `https://gw.example.com/registry/my-server/mcp`
- RFC 9728 §3.1 well-known URL for that resource (well-known segment inserted between host and path): `https://gw.example.com/.well-known/oauth-protected-resource/registry/my-server/mcp`
- URL the gateway advertises in `WWW-Authenticate` and serves: `https://gw.example.com/registry/.well-known/oauth-protected-resource/my-server/mcp`

Clients that follow `resource_metadata` from the 401 header work. Clients that derive the well-known URL from the resource (allowed by RFC 9728 §3.1 and done by at least one hosted coding agent we tested) hit the first URL and get `404 {"detail":"no per-server resource metadata"}`, because `_normalize_prm_server_path()` in `registry/api/wellknown_routes.py` only strips a trailing `/mcp` and turns `registry/my-server/mcp` into `/registry/my-server`, which is not a registered server. The client then falls back to legacy behaviour (on our side it tried `POST /registry/register`, refused with 405 by design, #995) and never reaches the IdP.

## Reproduce (inside the registry container, path-prefixed deployment)

```
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:7860/.well-known/oauth-protected-resource/my-server/mcp # 200
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:7860/.well-known/oauth-protected-resource/registry/my-server/mcp # 404
```

## Proposal

1. In `_normalize_prm_server_path()`, strip the path component of `settings.registry_url` when the incoming `server_path` starts with it (`registry/my-server/mcp` → `/my-server`). No change for deployments whose `registry_url` has no path. PR attached.
2. Docs: note in `docs/oauth-discovery-endpoints.md` that in path-prefixed deployments the root `/.well-known/` location must be routed to the registry by the operator's ingress as well (the bundled nginx already has `location ^~ /.well-known/`, but an external ingress that only forwards `/` will 404 the §3.1 form before it reaches nginx).
3. Optional follow-up: advertise the §3.1 form in `WWW-Authenticate` when `registry_url` has a path, so both derivations agree byte-for-byte with the served document.

## Acceptance criteria

- [ ] `GET /.well-known/oauth-protected-resource///mcp` returns the same document as `GET /.well-known/oauth-protected-resource//mcp` when `registry_url` carries ``.
- [ ] Behaviour unchanged when `registry_url` has no path.
- [ ] Unit test in `tests/unit/api/test_wellknown_routes.py`.

Related: #989, #990, #988 (path-aware discovery), #995.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。