Skip to content

Annotate all 30 lens tools with ToolAnnotations - #5

Merged
tarungarg546 merged 1 commit into
mainfrom
add-readonly-tool-annotations
Sep 2, 2026
Merged

Annotate all 30 lens tools with ToolAnnotations#5
tarungarg546 merged 1 commit into
mainfrom
add-readonly-tool-annotations

Conversation

@tarungarg546

Copy link
Copy Markdown
Member

Problem

All 30 tools in lens_mcp/server.py were declared as a bare @mcp.tool(). The word annotations did not appear anywhere in the package, so the advertised tool schemas carried no behavioural hints. A client has to assume an unannotated tool can write, so every lens tool looked write-capable and every lens call stopped to ask permission.

Change

Two module-level ToolAnnotations constants next to the FastMCP instance, applied at each decorator:

readOnlyHint destructiveHint idempotentHint openWorldHint tools
READ_ONLY True False True True 27
WRITES_LOCAL_FILES False False True True 3

The three download_* tools (download_entity_logs, download_trace_logs, download_prompts) genuinely write .log/.txt files into the scratchpad dir, so they cannot claim readOnlyHint. They are non-destructive and idempotent — a repeat call overwrites the same per-SID paths. openWorldHint is True throughout because every tool hits the remote Lens API.

No tool bodies, signatures, or docstrings changed — the diff is the import, the two constants, and 30 decorator lines.

Verification

mcp.list_tools() returns 30 tools, all with annotations, and exactly the three download_* are non-read-only.

New tests/test_annotations.py (3 tests, same self-running style as test_stats.py) guards this:

  • every tool has annotations
  • the non-read-only set is exactly the three download_*
  • nothing claims destructive; everything is idempotent and open-world
$ uv run python tests/test_annotations.py
ok   test_every_tool_is_annotated
ok   test_nothing_is_destructive_and_everything_is_open_world
ok   test_only_the_download_tools_are_not_read_only

0 failure(s)

tests/test_stats.py still passes (0 failures).

🤖 Generated with Claude Code

Every tool was a bare @mcp.tool(), so the schema carried no annotations and
clients had to treat all 30 as potentially write-capable — a permission prompt
on every lens call.

27 query tools get readOnlyHint=True. The three download_* tools write files
into the scratchpad dir, so they stay readOnlyHint=False (non-destructive,
idempotent — a repeat call overwrites the same per-SID paths). openWorldHint is
True throughout since every tool hits the remote Lens API.

tests/test_annotations.py guards that all tools stay annotated and that only
the download_* three are non-read-only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tarungarg546
tarungarg546 merged commit 2377c81 into main Sep 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant