docs: cover the remaining Tier 1 audit items - #3325
Conversation
📚 Documentation preview
|
3b3ff7c to
88e497e
Compare
There was a problem hiding this comment.
All reported issues were addressed across 10 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| @@ -0,0 +1,25 @@ | |||
| from pathlib import Path | |||
There was a problem hiding this comment.
🟡 [quality] New docs examples/claims added without the chapter behavioral tests every existing tutorial has sweep:docs_src/(media/tutorial005|prompts/tutorial00[4-6]|lowlevel/tutorial007)\.py [also at: docs_src/media/tutorial005.py:1 - [quality] Five new docs_src tutorials (media/tutorial005, prompts/tutorial004-006, lowlevel/tutorial007) and the two new]
Extended reasoning...
Repo convention (tests/docs_src/test_media.py, test_prompts.py, test_lowlevel.py all open with "every claim the page makes, proved against the real SDK" and import/exercise every prior tutorial: media 001-004, prompts 001-003, lowlevel 001-006) is that each docs_src tutorial gets a behavioral test; the five new modules (docs_src/media/tutorial005.py, docs_src/prompts/tutorial004-006.py, docs_src/lowlevel/tutorial007.py) are only covered by the test_shape.py import-only floor, and likewise tests/docs_src/test_deprecated.py's header says each prose claim on docs/deprecated.md is executed, yet the two new sections' claims (legacy ping both directions with the printed '2025-11-25' output, roots list_changed end-to-end via on_roots_list_changed, the notification being 'silently dropped' on modern connections) have no test. Concrete cost: the rendered JSON/output blocks and behavioral assertions on these pages can silently drift from real SDK behavior — exactly the drift these chapter tests exist to prevent — and future refactors won't fail CI when they break the examples' runtime behavi
Verification: nit — Convention is real and violated. tests/docs_src/test_media.py:1, test_prompts.py:1 and test_lowlevel.py:1 all open with "every claim the page makes, proved against the real SDK", and their imports stop just short of the new files: test_media.py:9 from docs_src.media import tutorial001, tutorial002, tutorial003, tutorial004 (no 005), test_prompts.py:9 `from docs_src.prompts import tutoria
There was a problem hiding this comment.
Intentional for this PR: it is scoped to the narrative coverage the tier audit needs and adds no tests. The new docs_src modules are still import-checked by test_shape.py, type-checked by pyright and the fences ruff-linted by test_examples.py; behavioural chapter tests for them can follow separately if we want them.
88e497e to
4586b19
Compare
| from pathlib import Path | ||
|
|
||
| from mcp.server import MCPServer | ||
| from mcp.server.mcpserver import Message, UserMessage |
There was a problem hiding this comment.
🟡 [quality] nit: New prompt examples import Message/UserMessage from mcp.server.mcpserver, contradicting the same page's prose and every existing docs_src example sweep:from mcp\.server\.mcpserver import .*(UserMessage|Message)
Extended reasoning...
docs/servers/prompts.md line 88 (the bullet under tutorial002, unchanged by this PR) states "UserMessage and AssistantMessage come from mcp.server.mcpserver.prompts.base", and every pre-existing docs_src example imports them from that path (docs_src/prompts/tutorial002.py:2, docs_src/mrtr/tutorial004.py:2). The two new examples rendered on the very same page a few sections later import the same symbols from the top-level re-export instead (docs_src/prompts/tutorial004.py:4 from mcp.server.mcpserver import Message, UserMessage; docs_src/prompts/tutorial005.py:4). Concrete cost: the prompts page now contradicts itself about where these classes live — a reader who follows the earlier bullet and then copies tutorial004 sees two different canonical import paths for the same names on one page, and the docs_src corpus loses its single established spelling. Fix in one sweep: change the two new files to from mcp.server.mcpserver.prompts.base import ... (or, if the top-level spelling is now preferred, update the line-88 prose and the older examples in a follow-up).
Verification: nit — Factually accurate quality finding. docs_src/prompts/tutorial004.py:4 (from mcp.server.mcpserver import Message, UserMessage) and tutorial005.py:4 import from the top-level re-export, while the same rendered page states at docs/servers/prompts.md:88 that "UserMessage and AssistantMessage come from mcp.server.mcpserver.prompts.base", and all pre-existing examples import from that pa
Adds the narrative coverage and examples the SEP-1730 docs audit still flagged as missing on main: a tool returning an EmbeddedResource (media page), prompt messages carrying an embedded file and an image plus adding prompts at runtime with the list-changed notification (prompts page), ping and roots change notifications on a legacy session (deprecated-features page), and the JSON Schema 2020-12 dialect (low-level server page, with a pointer from tools). Docs and docs_src only. No-Verification-Needed: docs and docs_src examples only
4586b19 to
918cc78
Compare
There was a problem hiding this comment.
Beyond the inline finding, two other candidates were examined and ruled out this run: the new ping section's SEP-2575 attribution is correct (the repo's own interaction-requirements notes credit SEP-2575 with deleting ping from the schema), and tutorial007's unguarded args['isbn']/args['title'] access only misbehaves for clients that violate the tool's advertised oneOf schema — an accepted simplification in the low-level examples, which don't validate arguments server-side.
Extended reasoning...
This run produced one confirmed finding (posted inline) plus two newly investigated candidates that were ruled out; since neither ruled-out item was covered in the prior two reviews on earlier pushed versions, a brief informational note recording them is warranted. The SEP-2575 attribution in docs/deprecated.md was verified against tests/interaction/_requirements.py, which repeatedly attributes the ping removal to SEP-2575 ("ping deleted from the schema, no replacement"), so the misattribution concern does not hold. The tutorial007 KeyError candidate describes a crash only reachable when a client sends arguments violating the advertised schema — the low-level Server never validates input_schema by design, and the docs example's simplification matches the rest of the low-level tutorial series. The hunt exited on max_rounds and a confirmed finding exists, so approval is off the table; this note is informational only and does not restate the inline finding.
| ``` | ||
|
|
||
| * `mcp.add_prompt(Prompt.from_function(fn, name=..., description=...))` registers a function exactly as `@mcp.prompt()` would, and `mcp.remove_prompt(name)` is the reverse. `add_prompt` keeps an existing entry of the same name rather than overwrite it, so the tool removes any old one first to make saving a replace. `prompts/list` reflects the change immediately. | ||
| * `await ctx.notify_prompts_changed()` sends `notifications/prompts/list_changed` to every `2026-07-28` client listening on a `subscriptions/listen` stream (**[Subscriptions](../handlers/subscriptions.md)**). `await ctx.session.send_prompt_list_changed()` sends it to the calling client when that client is pre-2026 (**[Serving legacy clients](../run/legacy-clients.md)**). Call both; each does nothing when there is nobody to tell. |
There was a problem hiding this comment.
🟣 Pre-existing: new "Changing the list at runtime" section claims ctx.session.send_prompt_list_changed() notifies pre-2026 clients, but MCPServer advertises prompts.listChanged: false in every legacy handshake, so spec-compliant legacy clients ignore the notification the tutorial teaches
Extended reasoning...
docs/servers/prompts.md:183 (and the recap at line 195, backed by docs_src/prompts/tutorial006.py:27) states "await ctx.session.send_prompt_list_changed() sends it to the calling client when that client is pre-2026". The notification is indeed written to the legacy standalone stream, but the server never declared it would send it: every MCPServer path builds the InitializeResult capabilities via create_initialization_options() with a default NotificationOptions() (src/mcp/server/mcpserver/server.py:1024 and :1115, src/mcp/server/runner.py:431 for the streamable-HTTP manager path), and Server.get_capabilities then sets PromptsCapability(list_changed=False) for handshake-era versions (src/mcp/server/lowlevel/server.py:588-595) — notification_options is only honored for modern versions via the subscriptions/listen derivation. The MCP spec makes prompts.listChanged the opt-in that tells a client to expect and handle notifications/prompts/list_changed, so a spec-compliant pre-2026 host that checks the negotiated capability ignores the notification (or never wires up a
Verification: pre-existing — the capability mismatch is real but lives in src/ code this docs-only PR did not touch. New docs/servers/prompts.md:183 teaches "await ctx.session.send_prompt_list_changed() sends it to the calling client when that client is pre-2026" (tutorial006.py:27 calls it), yet every MCPServer legacy handshake advertises prompts.listChanged: false: src/mcp/server/mcpserver/server.py:1024
Adds the narrative coverage the SEP-1730 docs audit still flags as missing on
main, and nothing else. Each item goes on the page that already owns the feature, as a short section plus adocs_srcexample (or an inline snippet on the deprecated-features page, the one page that calls deprecated APIs). Follows #3320, which the prompt and media examples rely on.Motivation and Context
servers/media.md"Embedding a resource" +docs_src/media/tutorial005.pyservers/prompts.md"More than text / Embedding a file" +docs_src/prompts/tutorial004.pyservers/prompts.md"Attaching an image" +docs_src/prompts/tutorial005.pyservers/prompts.md"Changing the list at runtime" +docs_src/prompts/tutorial006.pydeprecated.md"pingon a legacy session" (inline snippet)deprecated.md"Roots change notifications" (inline snippet)advanced/low-level-server.md"The dialect is JSON Schema 2020-12" +docs_src/lowlevel/tutorial007.py, one-sentence pointer inservers/tools.mdHow Has This Been Tested?
Docs and
docs_srconly. The existingtests/docs_src/test_shape.pyimports and reference-checks the new example modules,tests/test_examples.pylints the inline snippets, pyright coversdocs_src/, andscripts/docs/build.shbuilds strictly with no issues. Each example was also run by hand against an in-memoryClientin both protocol modes.Breaking Changes
None.
Types of changes
Checklist
AI Disclaimer