docs: add best practices for server and client implementors#36
docs: add best practices for server and client implementors#36tadasant wants to merge 10 commits into
Conversation
Adds docs/best-practices.md covering guidance for hosting Server Cards and for discovering/installing servers from an AI Catalog in-session.
3307923 to
472f446
Compare
Matches the shape of the client implementor section: an intro paragraph followed by ### subsections, rather than a flat bullet list.
Opens with why in-session discovery is worth building, states a default-on recommendation for user-entered URLs, and marks broader triggers (tool results, egress) as opt-in for now. Regroups the subsections into trigger points, install, and security, and adds flow diagrams for the recommended flow and the trigger spectrum.
- Remove the URL-scheme / install-link guidance as nonstandard - Add a minimal prompt mockup showing the endorsement chain - Require explicit approval for every install; offer session-scoped vs persistent accept instead of a blanket always-allow - Soften the catalog-culling advice to an invitation to experiment - Expand the enterprise path into a pre-filled request-to-IT flow
Each client mechanism now leads with the general shape any client can implement; Goose specifics follow in parentheses as one concrete instance. Drops the verbatim goose:// deep-link template.
- description is required, not optional; remove the auth field from the IT-request mock (no such field exists; issue #13 is v2) - Goose is AAIF-hosted, not Block's; drop the 404 sandbox link; hooks live in a plugin's hooks/hooks.json per the Open Plugins spec - Genericize the GitHub mockups to example.com / mcp-host-saas.com - Replace 'endorsement' with 'listing', and note the trust manifest is the spec's actual mechanism where present - Add probe bounds: no IP literals, loopback, link-local or private ranges; re-check after DNS; no ambient credentials; bound redirects - De-dup on the server endpoint rather than self-asserted name, and move the check after the card fetch - Note catalog nesting, depth cap and cycle tracking; note inline entries - Lowercase the invented MUST NOT; cut 'at someone else's development cost'
…ives The specification identifies a catalog by media type rather than path, and its discovery procedure checks a Link header and an HTML <link> element ahead of the well-known URI. Recommend .well-known as the primary location for both sides, and tell servers to advertise and clients to honor the other two. Cite ai-catalog.io/spec throughout.
Keeps the guidance to the one mechanism the extension implements today, worded so additional modes can be added without a rewrite.
Keeps the client flow to the flat catalog the extension resolves today, worded so entry handling can gain cases.
SamMorrowDrums
left a comment
There was a problem hiding this comment.
Pretty happy with this, will be great to get other eyes on it but I made a few comments.
| If your server is **not remote**, there is nothing to serve a card for — Server Cards exist to | ||
| advertise remote transport endpoints only. Locally-installable server metadata lives in the | ||
| [MCP Registry](https://github.com/modelcontextprotocol/registry)'s `server.json` schema instead | ||
| (see [Relationship to the MCP Registry](../README.md#relationship-to-the-mcp-registry)). |
There was a problem hiding this comment.
Probably we want to gloss over it, but technically the AI Catalog is including static assets like STDIO MCP runtimes right?
I certainly remember being at a meeting where they discussed that.
| **Serve it at `/.well-known/ai-catalog.json`.** That is the one location a client can try | ||
| against a bare domain, with nothing fetched from you first — which is exactly what in-session | ||
| discovery depends on. (The specification allows a catalog to live elsewhere, and defines other | ||
| ways to point at one; support for those is tracked in | ||
| [#43](https://github.com/modelcontextprotocol/experimental-ext-server-card/issues/43).) |
There was a problem hiding this comment.
As you recently highlighted the well known mechanism is not the sole mechanism, and the <link rel="_ai_catalog \> was added since this was written.
| Every MCP server your client can reach is capability you did not have to build. A user who | ||
| connects one gets more done without leaving you, and comes back for it — servers make a client | ||
| more useful and stickier. The hard part is that connecting a server is a chore the user has to | ||
| go and do somewhere else, out of band, before it can help them — so most users never do it, and | ||
| the capability sits unclaimed. |
There was a problem hiding this comment.
| Every MCP server your client can reach is capability you did not have to build. A user who | |
| connects one gets more done without leaving you, and comes back for it — servers make a client | |
| more useful and stickier. The hard part is that connecting a server is a chore the user has to | |
| go and do somewhere else, out of band, before it can help them — so most users never do it, and | |
| the capability sits unclaimed. | |
| Every MCP server your client can discover organically helps the user to stay in the flow while giving them the capabilities they need. The hard part is that connecting a server is a often a chore where the user has to leave their flow to configure it out of band, before it can help them — so most users never do it. |
| you — for example the domain hosting your REST API or the other resources a team becomes aware | ||
| of _before_ they learn you also expose MCP. | ||
|
|
||
| Review the guidance below for Client Implementors to determine the appropriate domain for your service. For example, for GitHub, it would be common for the user of a coding agent to paste a URL like `https://github.com/modelcontextprotocol/experimental-ext-server-card/pull/36` into a session. So `github.com/.well-known/ai-catalog.json` is an excellent place to put your AI catalog - not `api.githubcopilot.com/.well-known/ai-catalog.json`, where GitHub's MCP server [happens to live](https://github.com/github/github-mcp-server). |
There was a problem hiding this comment.
Nit: there are a mix of long lines, and consciously truncated lines. I believe the standard should probably be enforced by automation, but at very least we should ensure the internal consistency of this document. if text has a fixed column width.
| - **No new UX to design.** You already ask users to approve consequential actions like tool calls. This is one | ||
| more approval, in a flow they already know. | ||
| - **No new trust to establish.** You only ever offer servers published by a domain the user | ||
| themselves just put in front of you. You are not recommending anyone — the domain the user |
There was a problem hiding this comment.
| themselves just put in front of you. You are not recommending anyone — the domain the user | |
| themselves just put in front of you. You are not recommending anything — the domain the user |
Adds
docs/best-practices.mdand links it from the README. Docs-only; no schema or code changes.The doc speaks for itself — read it here. This description covers only what it does not say about itself.
Why
The repo documents the mechanics of Server Cards but never says when to serve one, or what a client should do with one it finds. This fills that gap as advisory guidance layered on the normative material in the README,
discovery.md, and the AI Catalog spec.Positions worth reviewing explicitly
These are judgment calls, not obvious consequences of the spec. Argue with them here:
Relationship to other work
docs/discovery.mdonmainstill specifies the MCP Catalog at/.well-known/mcp/catalog.json; this doc tells implementors to publish and probe/.well-known/ai-catalog.json. Until Use AI Catalog for Server Card discovery #42 ("Use AI Catalog for Server Card discovery",Closes #26) lands, the two docs indocs/disagree on the single most load-bearing URL. There is no textual conflict — this PR touches onlydocs/best-practices.mdandREADME.md, and the anchors it uses survive Use AI Catalog for Server Card discovery #42 — but merging this first would ship an internally inconsistentdocs/directory.discovery.mdif Discovery: recommend ETag + conditional requests (If-None-Match/304) as a SHOULD for card/catalog endpoints #33 lands.Verification
npm run check,npm run validate,npm run format:checkpassmain; picks up the terminology change from docs: drop references to the MCP initialization handshake (SEP-2575) #37schema.ts/schema.json; remaining Goose citations re-verified against live docs (dead sandbox link dropped, AAIF attribution corrected)well-known/mcpreferences introduced (grep-clean)docs/andREADME.md