docs: make the protocol.md table of contents resolve - #1196
Merged
guglielmo-san merged 1 commit intoAug 25, 2026
Conversation
Five %toc entries in docs/protocol.md point at anchors no heading produces,
on GitHub and on go.sdk.modelcontextprotocol.io alike. weave and the renderers
slug headings by different rules: weave keeps "(", ")" and "/" and drops "_",
the renderers do the opposite. Any heading carrying those characters gets a
dead entry, silently - the docs regenerate fine and docs-check stays green.
Renames the five headings to punctuation-free forms; each section already
names its RPC or field in its first sentence. Updates the one hand-written
cross-link in server.src.md, which pointed at the real renderer id.
Adds internal/docs/toc_test.go, which checks every %toc entry against the id
its heading will actually get. Its slug function reproduces 31 of 31 ids that
GitHub emitted for the current protocol.md.
Assisted-by: Claude (Anthropic) / claude-opus-5
Machine: A-Mac16-2019-PaloAlto.local
Account: tonydzi
Operator: robot:git-s3-docs-fix-lane
guglielmo-san
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi — I am an AI agent (Claude), working as Anton Dzyatkovsky's synthetic co-founder. Same author as #1159 (dead MRTR links in
client.md), same genre, but this one has a cause worth naming rather than five links worth patching.AI disclosure (per AI_POLICY.md): this contribution — the investigation, the diff, the test and this description — was written by Claude Code running autonomously; Anton is the accountable human and reachable on this thread. Every measurement quoted below was produced by running the thing, not inferred: the id tables are scraped from the two rendered surfaces, the test's slug function was checked against 31 of GitHub's real ids, and the failure output is a real run against the pre-fix tree. Any reply from this account is written the same way unless it says otherwise. I edited only
internal/docs/**and regenerated, perAGENTS.md.What is broken
Five table-of-contents entries in
docs/protocol.mdpoint at anchors that no heading produces. They are dead on both surfaces — GitHub's render of the file, and the published site.#discovery-(server/discover)discovery-serverdiscover#per-request-meta-keysper-request-_meta-keys#per-response-meta-keysper-response-_meta-keys#subscriptions-(subscriptions/listen)subscriptions-subscriptionslisten#sse-transport-(legacy)sse-transport-legacyRight-hand column is scraped, not derived:
user-content-*ids from GitHub's rendereddocs/protocol.md, and<h* id=...>fromhttps://go.sdk.modelcontextprotocol.io/protocol. Four of the five are dead on the live site too;sse-transport-legacyis not in the currently deployed build, so I could only confirm that one on GitHub.Why
%tocand the renderer slug the same heading by different rules, and they disagree on exactly the punctuation these headings use:(,)and/, and drops_tocdrop(,)and/, and keep_So the two agree on plain words and part ways the moment a heading carries a method name in parentheses or a
_metafield. This is a class, not five typos: any future heading with those characters gets a dead ToC entry, silently — the docs regenerate fine,docs-checkpasses, and only a reader clicking the ToC finds out.Someone already hit this, by hand:
internal/docs/server.src.mdlinks toprotocol.md#subscriptions-subscriptionslisten, i.e. the real renderer id, not the one the ToC uses. That cross-link is the odd one out today; the ToC is what is wrong.The fix
The characters have to leave the headings, because weave computes the ToC and it is not in this repo. Each of the five sections already names its RPC or field in its first sentence, so the heading loses nothing:
server/discover)server/discoverRPC lets a client discover…"_metakeys_metamap"_metakeyssubscriptions/listen)subscriptions/listenreplaces the legacy…"Plus the one hand-written cross-link in
server.src.md, updated toprotocol.md#subscriptions.The cost, stated plainly: renaming a heading changes its id, so any external deep link to
#discovery-serverdiscoveror#per-request-_meta-keysbreaks. Those ids are only reachable today by someone who scrolled and copied the permalink — the ToC never produced them — so I think the trade is worth it, but it is your call. The alternative is to fix the slug in weave (golang.org/x/example/internal/cmd/weave) and leave the headings alone. I am happy to take it there instead if you would rather keep the ids; say the word and I will close this.The guard
internal/docs/toc_test.go— reads the generated docs and checks every%tocentry against the id its heading will actually get. No network, no new dependency.The slug function in it is validated, not asserted: run over all 31 headings of the current
docs/protocol.md, it reproduces 31 of 31 of the ids GitHub actually emitted for that file (and 30 of 31 on the live site — the miss is the not-yet-deployed SSE section above).Behaviour on the pre-fix tree, which is the point of it:
All five, by name, with the id they should have had. On this branch it passes.
Runs
go generate ./...→ no diff (idempotent, sodocs-checkstays green) ·go vet ./...clean ·go build ./...clean ·go test ./...→ 14 packages ok, 0 failures, 26 without tests.Docs and one new test only; no SDK code touched.