fastmcp(fix[ids]): avoid duplicate IDs on same-slug headings#49
Merged
Conversation
why: A page heading whose slug matches a tool's bare compatibility alias makes the tool card claim the same physical ID the heading already owns; docutils reports a duplicate ID and the HTML fragment target is ambiguous (#48). what: - Add heading-collision scenario: "Delete buffer" heading + fastmcp-tool delete_buffer on one page - Add strict-xfail tests: no duplicate-ID diagnostic; bare anchor owned solely by the heading; toolref and tool-summary links target the canonical fastmcp-tool-<slug> fragment - Add stable assertions that the card classes/badges keep rendering
why: A tool card carrying both fastmcp-tool-<slug> and the bare <slug> in section["ids"] collides with any same-slug page heading, producing docutils duplicate-ID diagnostics and ambiguous HTML fragments (#48). The bare slug only needs to survive as a Sphinx label for historical {ref}/tool-role targets, not as a second physical anchor. what: - Tool card sections keep a single canonical physical ID - Bare-slug aliases register as std-domain labels pointing at the canonical ID; collision guard unchanged - register_tool_labels restores alias labels from the fastmcp_alias_labels node attribute on incremental rebuilds - fastmcp-tool-summary links target the canonical fragment - Remove strict-xfail markers from the reproduction tests; update the toolref href expectation to the canonical anchor
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #49 +/- ##
==========================================
+ Coverage 91.88% 91.90% +0.01%
==========================================
Files 233 233
Lines 18191 18223 +32
==========================================
+ Hits 16714 16747 +33
+ Misses 1477 1476 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Member
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
why: Users of published releases hit docutils duplicate-ID warnings
when a page heading's slug matched a tool's bare cross-reference
alias; the fix relocates the card anchor, which readers should learn
about at upgrade time.
what:
- Add Fixes entry under 0.0.1a27 (unreleased): tool cards expose a
single canonical fastmcp-tool-<slug> anchor; bare {ref} and
tool-role links keep resolving and target the canonical anchor
- Illustrate the heading-vs-card landing with an ASCII page-anatomy
diagram (ASCII only: IBM Plex Mono lacks rounded box-drawing
glyphs, so Unicode boxes drift via font fallback)
- Cite the PR
why: Issue #48's suggested coverage names both tool-role and bare {ref} resolution; the collision scenario only exercised :toolref:. Both read the same std.labels alias entry, but {ref} resolves through Sphinx's StandardDomain while :toolref: goes through the package's resolve_tool_refs transform, so each path deserves its own needle. what: - Add a bare :ref:`delete-buffer` link to the collision index - Split the canonical-anchor needle into a toolref case (<code> body) and a bare-ref case (<span> body), one match each
why: The bare slug never becomes a physical HTML id anymore; the FastMCPToolDirective docstring's "bare-slug alias" predates that and reads as if a second anchor were still involved. what: - Say "bare-slug label alias" in the :no-index: contract description
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.
Summary
Duplicate IDdiagnostics or an ambiguous HTML fragment (sphinx-autodoc-fastmcp: avoid duplicate IDs when tool alias matches page heading slug #48)fastmcp-tool-<slug>); the bare slug survives purely as a Sphinx label alias pointing at the canonical anchor{tool},{toolref},{toolicon*}, and bare{ref}targets keep working and now resolve to the canonical fragment;fastmcp-tool-summarytable links target it tooBefore/After
Before: the build emitted
CRITICAL: Duplicate ID: "delete-buffer". [docutils], the rendered page carried twodelete-bufferanchors, and tool links resolved to the ambiguous bare fragment.After: the heading owns
#delete-bufferexclusively; the card is reachable at#fastmcp-tool-delete-buffer; label-based references ({ref}, tool roles) resolve there.Design decisions
#<slug>no longer land on the card. Label-based references are unaffected; the bare fragment was ambiguous in exactly the colliding case this fixes.Test plan
test_heading_collision_emits_no_duplicate_id_diagnostic— same-slug heading + tool card builds without duplicate-ID diagnosticstest_heading_collision_anchor_counts— heading owns the sole bare anchor;{toolref}andfastmcp-tool-summarylinks target#fastmcp-tool-<slug>test_heading_collision_card_renders— card classes and badges render under the collisionuv run pytest,uv run ruff check .,uv run mypyjust build-docs— shipped docs build cleanly; tool-role links resolve to canonical anchors