Skip to content

docs(auth): clarify that resource_server_url must include the transport path#2662

Open
adityasingh2400 wants to merge 2 commits into
modelcontextprotocol:mainfrom
adityasingh2400:fix-1264-resource-server-url-docs
Open

docs(auth): clarify that resource_server_url must include the transport path#2662
adityasingh2400 wants to merge 2 commits into
modelcontextprotocol:mainfrom
adityasingh2400:fix-1264-resource-server-url-docs

Conversation

@adityasingh2400
Copy link
Copy Markdown

Issue #1264 keeps surfacing because RFC 9728 §3.3 requires strict equality between the client's resource identifier and the resource value advertised in protected resource metadata, but the public surface of AuthSettings.resource_server_url does not say this. PR #1407 established the contract that resource_server_url must be the full endpoint URL including the transport path, and the simple-auth example was updated, but the matching examples/snippets/servers/oauth_server.py snippet (which is rendered into README.v2.md by scripts/update_readme_snippets.py) still passes http://localhost:3001 with no path, the AuthSettings.resource_server_url description still says only "URL of the MCP server", and simple-auth/server.py hardcodes /mcp even when the user passes --transport=sse.

This change updates the AuthSettings.resource_server_url field description to spell out the contract, including the requirement that the URL include the transport path and the reference to RFC 9728 §3.3. The oauth_server.py snippet is changed to http://localhost:3001/mcp with a comment explaining why, and README.v2.md is regenerated so the embedded snippet matches. In simple-auth/server.py, the override that built server_url picks /sse or /mcp based on the --transport flag so the SSE path no longer produces an RFC 9728 mismatch.

Per the closing comment on #2189, the maintainer asked for a docs and example fix here rather than auto-appending streamable_http_path, because streamable_http_path is an internal Starlette route and not always the public URL (for example when the app is mounted at /api with streamable_http_path="/", or behind a reverse proxy). Verified with uv run --frozen ruff check, uv run --frozen pyright, uv run --frozen pytest tests/server/auth/ tests/server/mcpserver/ (388 passed), and uv run --frozen python scripts/update_readme_snippets.py --check.

Refs #1264

…rt path

The `resource_server_url` setting must equal the full public URL of the MCP
endpoint, including the transport path, so that the value advertised in
RFC 9728 Protected Resource Metadata matches the URL the client used to
reach the server. RFC 9728 §3.3 requires strict equality.

Update the `AuthSettings.resource_server_url` docstring to spell this out,
fix the `examples/snippets/servers/oauth_server.py` snippet so it ends in
`/mcp`, and select `/mcp` or `/sse` in the `simple-auth` example based on
the chosen transport instead of hardcoding `/mcp` regardless of the
`--transport=sse` flag.

Refs modelcontextprotocol#1264
The README code snippet at L1024-1028 is run through ruff via pytest_examples.
On Windows the ruff subprocess pipe defaults to cp1252 and fails to decode the
\xc2\xa7 byte sequence, breaking the 10 Windows CI jobs with 'stream did not
contain valid UTF-8'. Linux and macOS pipes default to UTF-8 so they passed.

Replace \xc2\xa7 with the word 'section' across the four files I introduced it
in. Pre-existing \xc2\xa7 references elsewhere in the tree are unaffected.
@adityasingh2400
Copy link
Copy Markdown
Author

Pushed d54b216 to fix the 10 Windows CI failures.

Root cause was the § section symbol I put in the README code snippet at line 1027. tests/test_examples.py::test_docs_examples pipes the snippet through ruff via stdin, and on Windows the pipe defaults to cp1252 so ruff fails to decode the two-byte UTF-8 sequence with stream did not contain valid UTF-8. Linux and macOS pipes default to UTF-8 so all 17 non-Windows jobs passed.

Replaced § with the word "section" across the four files I introduced it in (README.v2.md, src/mcp/server/auth/settings.py, and the two example servers). Pre-existing § references in tests, routes.py, auth.py, and oauth2.py are untouched since they are not run through pytest_examples.

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