Skip to content

feat: resolve virtual servers by name in RFC 9728 well-known and MCP endpoints#4237

Open
smorand wants to merge 1 commit intoIBM:mainfrom
smorand:fix/well-known-name-resolution
Open

feat: resolve virtual servers by name in RFC 9728 well-known and MCP endpoints#4237
smorand wants to merge 1 commit intoIBM:mainfrom
smorand:fix/well-known-name-resolution

Conversation

@smorand
Copy link
Copy Markdown

@smorand smorand commented Apr 16, 2026

Summary

  • The RFC 9728 /.well-known/oauth-protected-resource endpoint only accepted UUID server identifiers, requiring clients to use opaque hex strings like b1a1acaa408744919481e10fca4ce9f2 in URLs
  • This adds server name resolution as a fallback, enabling human-readable URLs like /servers/gdrive/mcp while keeping full UUID backward compatibility
  • The resource URL in the well-known response always uses the canonical UUID, ensuring stable resource identifiers per RFC 9728

Changes

  • mcpgateway/routers/well_known.py: accept server name (validated against SERVER_NAME_PATTERN) in addition to UUID, resolve to canonical UUID via DB lookup
  • mcpgateway/services/server_service.py: add resolve_server_id() method that tries PK lookup first, then falls back to name lookup
  • mcpgateway/transports/streamablehttp_transport.py: use resolve_server_id() in _validate_server_id and _check_server_oauth_enforcement for consistent name support across MCP transport layer
  • tests/unit/mcpgateway/routers/test_well_known_rfc9728.py: update test expectations to reflect name resolution behavior

Security

Server name input is validated against a strict alphanumeric pattern (^[a-zA-Z0-9][a-zA-Z0-9_-]{0,253}[a-zA-Z0-9]$) to prevent path traversal and injection. Path traversal attempts like /../admin are rejected before any DB lookup.

Test plan

  • UUID-based well-known still works (backward compatible)
  • Name-based well-known resolves and returns canonical UUID in resource URL
  • MCP endpoint /servers/{name}/mcp returns correct 401 + WWW-Authenticate
  • Path traversal attempts rejected (404)
  • Nonexistent server names return 404
  • Existing unit tests pass (21 well-known + 121 server service tests)
  • Tested on live deployment

…endpoints

The well-known OAuth Protected Resource endpoint (RFC 9728) only accepted
UUID server identifiers, forcing clients to use opaque hex strings in URLs.
This adds server name resolution as a fallback while keeping full UUID
backward compatibility.

Changes:
- well_known.py: accept server name in addition to UUID, resolve to
  canonical UUID for the resource URL (RFC 9728 stability)
- server_service.py: add resolve_server_id() that tries PK lookup first,
  then falls back to name lookup
- streamablehttp_transport.py: use resolve_server_id() in _validate_server_id
  and _check_server_oauth_enforcement for consistent name support
- Update tests to reflect name resolution behavior

Security: server name input is validated against a strict alphanumeric
pattern (SERVER_NAME_PATTERN) to prevent path traversal and injection.

Signed-off-by: Sébastien MORAND <sebastien.morand@ibm.com>
@smorand smorand force-pushed the fix/well-known-name-resolution branch from f0beca5 to 702aaec Compare April 16, 2026 12:23
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.

1 participant