docs: stop presenting the in-memory client as the way to connect - #3443
Conversation
📚 Documentation preview
|
Client(server_object) connects in-process, which is a testing technique, but much of the documentation led with it: the client page's first example, the transports page's first section, several "what Client accepts" lists, and a number of feature pages whose snippets connect that way so they can run as-is. This reframes all of that around URL and stdio as the normal ways to connect. The client page now starts a small server over HTTP and connects to it by URL, then says once that the remaining snippets build their server inline the way a test would. The transports page leads with Streamable HTTP and stdio and moves the in-memory section down, scoped to tests and embedding. Enumerations put the server object last, "in tests". Feature pages whose snippets connect in-process get one sentence saying so instead of a rewrite, and fences that define a server are no longer titled client.py. The progress page, the prior_discover example and the low-level Try-it now use real connections, since their point depends on one. A few stale statements found along the way are corrected (the callbacks page's "first argument is a transport object", the testing page's "In-process by default" heading, the Client docstring example).
52230cc to
af72034
Compare
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
No new blocking issues. Nothing in this review needs a push before merging.
1 further finding on code this push did not change was outside the scope of this re-review and not posted.
One verified lower-impact observation (a convention, logging or cleanup point) was not posted.
The previous commit left most feature pages' snippets connecting to the server object in-process and explained that away with a sentence per page. That was a disclaimer, not a fix. This replaces it: each affected page now shows its server once as server.py with the command that serves it, and every client snippet is its own client.py that connects to http://localhost:8000/mcp. Where a client has logic worth testing (the pagination loop, the caching demo) it is a function the tests drive in-process against the server module, the pattern the subscriptions page already used. Pages: the client page (one Bookshop server, six clients), protocol versions (four clients against that same server), extensions and MCP Apps (server/client pairs), pagination and caching (uvicorn-served low-level servers, the caching handler prints each real fetch), serving legacy clients (both eras from one client program over HTTP), and the inline fragments on the troubleshooting page. The framing sentences are gone.
There was a problem hiding this comment.
All reported issues were addressed across 44 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
No-Verification-Needed: doc-only wording change in docs/troubleshooting.md
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
The reader's first Client in the docs was still an inline Client(mcp) against the imported server object. Serve server.py over HTTP and connect by URL from a docs_src client file instead, like the rest of the docs now do, and move the in-memory mention into the pointer to Testing.
The entry linked down to a section whose first server.py is the ctx.elicit variant, which produces a different error. Include the resolver-based Bistro directly so the entry has its own server.
Client(server_object)connects in-process. That is how the SDK's own tests run and it is a fine test harness, but a lot of the documentation led with it: the client page's first example, the first section of the transports page, most "whatClientaccepts" lists, and most feature pages' client snippets. A reader came away thinking that importing the server object is how you write a client, with a URL as the variation.This makes the docs show clients the way people write them: a
server.pyyou serve, and aclient.pythat connects tohttp://localhost:8000/mcp(or aStdioServerParameters). In-memory stays where it belongs: the Testing page, "in tests" asides, and the transports page's "In memory" section.Motivation and Context
Follows #3315 (README) and #3321 (
Client(StdioServerParameters)), which came out of #3313. With those in, a real connection is one line either way, so the docs no longer need the in-memory form to keep examples short.What changed:
server.pywith the command that serves it (uv run mcp run server.py --transport streamable-http, oruvicorn server:app --port 8000for a low-levelServer), and each client snippet is its ownclient.pyconnecting by URL. That covers the client page (one Bookshopserver.py, six clients), protocol versions (four clients against that same server), progress, extensions and MCP Apps (server/client pairs), pagination and caching (uvicorn-served low-level servers; the caching handler prints each real fetch so "four calls, three fetches" is visible across the process boundary), serving legacy clients (both eras from one client program), the low-levelServerTry-it, and the inline fragments on the troubleshooting page. Where a client has logic worth testing (the pagination loop, the caching demo) it is a function thattests/docs_srcdrives in-process against the server module, the pattern the subscriptions page already used.docs/client/transports.mdleads with Streamable HTTP and stdio and moves "In memory" below them, scoped to tests and embedding. Enumerations that listed the server object first now put it last with "in tests" (whats-new.md,session-groups.md,multi-round-trip.md,callbacks.md,asgi.md,authorization.md,oauth-clients.md, four story READMEs). TheClientdocstring example is a URL client.callbacks.md"the first argument toClient(...)is a transport object",testing.md's "In-process by default" heading (now "Era-neutral by default") and intro,first-steps.md's description of whatClientis.Deliberately untouched:
docs/migration.md, the translations underi18n/(they regenerate; several now includedocs_srcfiles whose role changed and will show as outdated until then), and theexamples/stories/README.mdstatus table.How Has This Been Tested?
tests/docs_srcretargeted rather than reduced: each page's claims are asserted in-process against its server module, and the factored client functions (list_all_tools,list_all_resources, the caching demo) are driven the same way../scripts/testpasses at 100% coverage,scripts/docs/build.sh(strict) passes.server.pywith its stated command and ran eachclient.pyagainst it (the client page's seven, protocol-versions' four, pagination, caching, legacy-clients, apps, four extensions pairs, progress, low-level). All exit cleanly and the pages' output blocks are the observed output; the caching server logs exactly three fetches for the client's four calls, and the legacy-clients client reserves in both eras over HTTP.Breaking Changes
None. Documentation and examples only; the one
src/change is theClientdocstring example.Types of changes
Checklist
Additional context
Two commits: the first reorders and reframes, the second replaces the in-process example code (an earlier draft of this PR had added a sentence per page explaining the in-process snippets instead of changing them; that is gone). New
docs_srcfiles:client/tutorial001_client.py,apps/tutorial001_client.py,extensions/tutorial00{3,4,6,7}_client.py,legacy_clients/tutorial001_client.py.AI Disclaimer