feat: add MCP tool annotations (readOnly/destructive hints)#123
feat: add MCP tool annotations (readOnly/destructive hints)#123yunanwg wants to merge 6 commits into
Conversation
🦋 Changeset detectedLatest commit: 81391a4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughA new annotation constants module ( Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds automatic MCP tool annotations based on tool-name verb prefixes so MCP clients can better distinguish read vs write vs destructive operations without changing every tool registration call site.
Changes:
- Import MCP SDK types needed to annotate tools (
RegisteredTool,ToolAnnotations). - Add
toolAnnotations(name)helper that derivesreadOnlyHint/destructiveHint/openWorldHintfrom tool-name prefixes. - Wrap
server.toolto automatically stamp annotations onto every registered tool.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
baruchiro
left a comment
There was a problem hiding this comment.
I'm from mobile and it is hard to review it well, so expect another review, hopefully this weekend.
Replace the verb-prefix wrapper that derived annotations from tool names with explicit annotations at each server.tool(...) call site, via three shared constants (READ_ONLY / WRITE / DESTRUCTIVE). This keeps every tool's hint visible at its registration and lets exceptions be set per tool, addressing review feedback to annotate tools manually. bulk_edit_* stay destructive because each exposes a permanent 'delete' method in its description; update_* are non-destructive edits. Add src/tools/annotations.test.ts, which builds the server and asserts every registered tool declares annotations, so a new tool can't ship without one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/tools/annotations.test.ts`:
- Around line 30-34: The assertion for openWorldHint in the test only validates
the type is boolean but does not enforce the required value. Modify the
assert.equal call to check that annotations.openWorldHint is explicitly equal to
false instead of just checking typeof, ensuring the closed-system contract is
properly validated.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6f31aece-d0de-4294-b067-cb256bb41cb6
📒 Files selected for processing (10)
.changeset/mcp-tool-annotations.mdsrc/server.tssrc/tools/annotations.test.tssrc/tools/correspondents.tssrc/tools/customFields.tssrc/tools/documentTypes.tssrc/tools/documents.tssrc/tools/mail.tssrc/tools/tags.tssrc/tools/utils/annotations.ts
✅ Files skipped from review due to trivial changes (2)
- src/tools/utils/annotations.ts
- src/server.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- .changeset/mcp-tool-annotations.md
Per the repo's comment policy (CLAUDE.md): remove the per-constant JSDoc in annotations.ts and the header comment in annotations.test.ts — the constant names + field values and the test name + assertion messages already say what they said. Keep only the openWorldHint "why" note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
baruchiro
left a comment
There was a problem hiding this comment.
I see the annotations are still WIP?
https://modelcontextprotocol.io/community/interest-groups/tool-annotations
What
Stamps MCP tool
annotations(readOnlyHint/destructiveHint/openWorldHint) onto every registered tool, derived from the tool-name verb prefix:list_/get_/search_/download_→readOnlyHint: truedelete_/bulk_edit_→destructiveHint: trueopenWorldHint: false(Paperless-ngx is a closed system)It is implemented as a one-time wrap of
server.toolincreateMcpServer(using the publicRegisteredTool.update()), so no change is needed at anyserver.tool(...)call site and new tools are covered automatically. It only fills in annotations a tool has not already set, so explicit per-tool annotations would still win.Why
MCP tool annotations are the hints clients use to present and guard tools — flagging or confirming destructive operations. The server already encodes this intent in prose (
⚠️ DESTRUCTIVE: ...); this exposes it as the structured field clients actually read. Without it a client cannot tellget_documentfromdelete_document.Notes
No change to tool behavior — only
tools/listgainsannotations. The verb prefixes follow the existing tool naming convention. If you would prefer explicit per-tool annotations instead of the wrapper, happy to expand it.Summary by CodeRabbit
Release Notes