|
| 1 | +package tools |
| 2 | + |
| 3 | +import "github.com/modelcontextprotocol/go-sdk/mcp" |
| 4 | + |
| 5 | +// boolPtr returns a pointer to a bool value. |
| 6 | +func boolPtr(b bool) *bool { |
| 7 | + return &b |
| 8 | +} |
| 9 | + |
| 10 | +// defaultAnnotations holds the default annotations for each built-in tool. |
| 11 | +// These follow the MCP specification: |
| 12 | +// - ReadOnlyHint (bool, default false): tool does not modify state |
| 13 | +// - DestructiveHint (*bool, default true): tool may destructively update |
| 14 | +// - IdempotentHint (bool, default false): repeated calls produce same result |
| 15 | +// - OpenWorldHint (*bool, default true): tool interacts with external entities |
| 16 | +var defaultAnnotations = map[ToolName]*mcp.ToolAnnotations{ |
| 17 | + // Read-only tools |
| 18 | + ToolSearch: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 19 | + ToolGetEntity: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 20 | + ToolGetSchema: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 21 | + ToolGetLineage: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 22 | + ToolGetColumnLineage: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 23 | + ToolGetQueries: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 24 | + ToolGetGlossaryTerm: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 25 | + ToolListTags: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 26 | + ToolListDomains: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 27 | + ToolListDataProducts: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 28 | + ToolGetDataProduct: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 29 | + ToolListConnections: {ReadOnlyHint: true, IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 30 | + |
| 31 | + // Write tools |
| 32 | + ToolUpdateDescription: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 33 | + ToolAddTag: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 34 | + ToolRemoveTag: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 35 | + ToolAddGlossaryTerm: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 36 | + ToolRemoveGlossaryTerm: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 37 | + ToolAddLink: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 38 | + ToolRemoveLink: {DestructiveHint: boolPtr(false), IdempotentHint: true, OpenWorldHint: boolPtr(false)}, |
| 39 | +} |
| 40 | + |
| 41 | +// DefaultAnnotations returns the default annotations for a tool. |
| 42 | +// Returns nil for unknown tool names. |
| 43 | +func DefaultAnnotations(name ToolName) *mcp.ToolAnnotations { |
| 44 | + return defaultAnnotations[name] |
| 45 | +} |
| 46 | + |
| 47 | +// getAnnotations resolves the annotations for a tool using the priority chain: |
| 48 | +// 1. Per-registration override (cfg.annotations) — highest priority |
| 49 | +// 2. Toolkit-level override (t.annotations) — medium priority |
| 50 | +// 3. Default annotations — lowest priority. |
| 51 | +func (t *Toolkit) getAnnotations(name ToolName, cfg *toolConfig) *mcp.ToolAnnotations { |
| 52 | + // Per-registration override (highest priority) |
| 53 | + if cfg != nil && cfg.annotations != nil { |
| 54 | + return cfg.annotations |
| 55 | + } |
| 56 | + |
| 57 | + // Toolkit-level override (medium priority) |
| 58 | + if ann, ok := t.annotations[name]; ok { |
| 59 | + return ann |
| 60 | + } |
| 61 | + |
| 62 | + // Default annotations (lowest priority) |
| 63 | + return defaultAnnotations[name] |
| 64 | +} |
0 commit comments