Skip to content

feat(core): dynamic tool annotations for multi-mode tools on read-only sources - #3816

Open
anubhav756 wants to merge 1 commit into
anubhav-readonly-corefrom
anubhav-readonly-annotation
Open

feat(core): dynamic tool annotations for multi-mode tools on read-only sources#3816
anubhav756 wants to merge 1 commit into
anubhav-readonly-corefrom
anubhav-readonly-annotation

Conversation

@anubhav756

@anubhav756 anubhav756 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Enables multi-mode tools (e.g., SQL execution tools) to dynamically advertise readOnlyHint: true and destructiveHint: false in MCP tool manifests when bound to a read-only data source, and centralizes tool suppression logic across the server.

Context & Motivation

  • Tools like postgres-execute-sql and mysql-execute-sql are multi-mode (capable of both reads and writes) and default to readOnlyHint: false / destructiveHint: true. When connected to a readOnly: true database source (where session-level locks prevent modifications), these tools should dynamically report readOnlyHint: true and destructiveHint: false to MCP clients without requiring separate read-only tool implementations.
  • Refactored ShouldSuppress from a BaseTool method into a package-level function tools.ShouldSuppress(ctx, t, src) that operates on the Tool interface, allowing suppression to dynamically evaluate t.GetAnnotations(src) without requiring concrete tool method overrides.

Changes

  • Updated Tool.GetAnnotations(sources.Source) *ToolAnnotations to make annotations source-aware (matching the design pattern of GetParameters(sources.Source) and Manifest(sources.Source)).
  • Updated BaseTool.GetAnnotations(_ sources.Source) to return static annotations by default.
  • Added DynamicReadOnlyAnnotations(base *ToolAnnotations) *ToolAnnotations in internal/tools/tools.go to safely copy base annotations and set ReadOnlyHint: true / DestructiveHint: false while preserving other custom hints (e.g. idempotentHint, openWorldHint).
  • Updated postgres-execute-sql and mysql-execute-sql to implement GetAnnotations(src) using tools.DynamicReadOnlyAnnotations(t.BaseTool.GetAnnotations(src)) when src.IsReadOnly().
  • Removed redundant ShouldSuppress method overrides from concrete SQL tool structs.
  • Updated all 5 MCP schema version generators (v20241105, v20250326, v20250618, v20251125, v20260728) in internal/server/mcp/ to pass src into tool.GetAnnotations(src).
  • Added table-driven tests for tools.DynamicReadOnlyAnnotations in internal/tools/tools_test.go verifying nil handling, default flipping, custom hint preservation, and pointer immutability.
  • Updated internal/server/server_test.go and internal/tools/tools_test.go to test tools.ShouldSuppress with both write and destructive tools using tools.NewWriteAnnotations() and tools.NewDestructiveAnnotations().
  • Updated Looker unit test suites to pass tool.GetAnnotations(nil).

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@anubhav756 anubhav756 assigned Yuan325 and unassigned duwenxin99 Aug 13, 2026
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 8930b29 to 53be9fe Compare August 13, 2026 07:49
@anubhav756
anubhav756 requested review from a team as code owners August 13, 2026 07:49
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 53be9fe to 5fade7d Compare August 13, 2026 08:14
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 5fade7d to f36035b Compare August 13, 2026 08:33
@anubhav756
anubhav756 requested review from a team as code owners August 13, 2026 08:38
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch 3 times, most recently from ee8f29a to 9dc7d07 Compare August 13, 2026 10:24
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch 2 times, most recently from dd8d903 to 2b6758a Compare August 13, 2026 13:11
Comment thread internal/tools/tools.go Outdated
Comment thread internal/tools/tools.go
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 2b6758a to 43ada14 Compare August 13, 2026 15:49
@anubhav756
anubhav756 requested a review from Yuan325 August 13, 2026 15:49
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 43ada14 to d2f4003 Compare August 13, 2026 15:49
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from d2f4003 to a8b4325 Compare August 14, 2026 06:05
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from a8b4325 to 1f3900f Compare August 14, 2026 15:11
@anubhav756
anubhav756 force-pushed the anubhav-readonly-annotation branch from 1f3900f to aa93c11 Compare August 17, 2026 05:45
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.

3 participants