Skip to content

feat(fetch): add tool annotations to server-fetch - #3650

Closed
jasonsuhari wants to merge 1 commit into
modelcontextprotocol:mainfrom
jasonsuhari:feat/fetch-tool-annotations
Closed

feat(fetch): add tool annotations to server-fetch#3650
jasonsuhari wants to merge 1 commit into
modelcontextprotocol:mainfrom
jasonsuhari:feat/fetch-tool-annotations

Conversation

@jasonsuhari

Copy link
Copy Markdown

Closes #3572

Summary

Adds MCP tool annotations to the fetch tool, which currently has zero annotations despite the spec supporting them and server-filesystem already annotating all 14 of its tools.

Tool readOnlyHint destructiveHint idempotentHint openWorldHint
fetch true false true true

Rationale per annotation:

  • readOnlyHint: true — the tool performs an HTTP GET and returns content; it does not modify any data locally or on the target server
  • destructiveHint: false — no side effects
  • idempotentHint: true — fetching the same URL twice produces the same result (modulo server-side changes)
  • openWorldHint: true — the tool makes outbound HTTP requests to arbitrary URLs; this is the most safety-relevant annotation as it signals to clients that the tool can reach any internet host

No behaviour changes — annotations are hints only.

Changes

  • server.py: import ToolAnnotations, extract tool definition into _make_fetch_tool() helper, add the four annotations
  • tests/test_server.py: add TestListTools.test_fetch_tool_annotations asserting all four annotation values via _make_fetch_tool()

Test plan

  • All 21 existing tests pass (uv run pytest tests/ -v)
  • New annotation test passes

Adds MCP tool annotations to the fetch tool as requested in #3572.
The fetch tool now declares readOnlyHint, destructiveHint, idempotentHint,
and openWorldHint, matching the annotation coverage already present on
server-filesystem.

Also extracts the tool definition into _make_fetch_tool() to make it
independently testable without spinning up the full stdio server, and
adds a test asserting all four annotation values.
@jasonsuhari

Copy link
Copy Markdown
Author

friendly ping, happy to address any feedback

@cliffhall cliffhall added enhancement New feature or request server-fetch Reference implementation for the Fetch MCP server - src/fetch labels Apr 20, 2026
@cliffhall

Copy link
Copy Markdown
Member

@claude review

@claude

claude Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cliffhall's task in 1m 17s —— View job


PR Review: feat(fetch): add tool annotations to server-fetch

  • Gather context and read changed files
  • Review server.py changes
  • Review tests/test_server.py changes
  • Check alignment with existing patterns (e.g., filesystem server)
  • Post final review

The intent here is correct and the implementation is clean. One spec-alignment issue worth addressing, plus a couple of minor notes.

The spec issue: redundant hints when readOnlyHint=true

This is the main concern. The MCP spec states that idempotentHint and destructiveHint are only meaningful when readOnlyHint is false. The filesystem server README captures this explicitly:

idempotentHint and destructiveHint are meaningful only when readOnlyHint is false, as defined by the MCP spec.

Looking at how the filesystem server annotates its 9 read-only tools — read_text_file, list_directory, get_file_info, etc. — they all set only readOnlyHint: true and omit idempotentHint/destructiveHint entirely (shown as in the table). This PR sets all four, which is inconsistent with that pattern.

The annotations in server.py:189-194 should be simplified to:

annotations=ToolAnnotations(
    readOnlyHint=True,
    openWorldHint=True,
),

destructiveHint=False and idempotentHint=True are implied/irrelevant once readOnlyHint=True and add noise that could confuse spec-aware clients. Fix this →


Minor notes

_make_fetch_tool() helper (server.py:182): Reasonable refactor for testability. The leading underscore correctly signals it's not public API. No issues here.

Test class placement (test_server.py:17-29): TestListTools.test_fetch_tool_annotations calls _make_fetch_tool() directly rather than going through the MCP list_tools handler. This is fine as a unit test, but if idempotentHint/destructiveHint are removed from the annotations per the suggestion above, the test assertions should be updated accordingly (removing those two assert lines).

openWorldHint=True is the most safety-relevant annotation here and is the right call — it correctly signals that this tool makes outbound requests to arbitrary hosts. Good choice.


Summary

The PR is a welcome addition — openWorldHint=True in particular is an important safety signal for clients. The core change is straightforward; just needs the two redundant hints removed to align with the MCP spec and the existing pattern established by the filesystem server. Once that's addressed, this is ready to merge.

@LuuOW LuuOW left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technical audit: Verified MCP server implementation for consistency with current SDK patterns.

@jasonsuhari jasonsuhari closed this by deleting the head repository Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request server-fetch Reference implementation for the Fetch MCP server - src/fetch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add tool annotations to server-fetch (1 tool, 0 annotated)

3 participants