package tools import ( "context" "strings" "github.com/modelcontextprotocol/go-sdk/mcp" "git.warky.dev/wdevs/amcs/internal/store" ) // ToolEntry describes a single registered MCP tool. type ToolEntry struct { Name string Description string Category string } // DescribeTool implements the describe_tools and annotate_tool MCP tools. type DescribeTool struct { store *store.DB catalog []ToolEntry } func NewDescribeTool(db *store.DB, catalog []ToolEntry) *DescribeTool { return &DescribeTool{store: db, catalog: catalog} } // describe_tools type DescribeToolsInput struct { Category string `json:"category,omitempty" jsonschema:"filter results to a single category (e.g. thoughts, projects, files, skills, chat, meta)"` } type AnnotatedToolEntry struct { Name string `json:"name"` Description string `json:"description"` Category string `json:"category"` Notes string `json:"notes,omitempty"` } type DescribeToolsOutput struct { Tools []AnnotatedToolEntry `json:"tools"` } func (t *DescribeTool) Describe(ctx context.Context, _ *mcp.CallToolRequest, in DescribeToolsInput) (*mcp.CallToolResult, DescribeToolsOutput, error) { annotations, err := t.store.GetToolAnnotations(ctx) if err != nil { return nil, DescribeToolsOutput{}, err } cat := strings.TrimSpace(strings.ToLower(in.Category)) entries := make([]AnnotatedToolEntry, 0, len(t.catalog)) for _, e := range t.catalog { if cat != "" && e.Category != cat { continue } entries = append(entries, AnnotatedToolEntry{ Name: e.Name, Description: e.Description, Category: e.Category, Notes: annotations[e.Name], }) } return nil, DescribeToolsOutput{Tools: entries}, nil } // annotate_tool type AnnotateToolInput struct { ToolName string `json:"tool_name" jsonschema:"the exact name of the tool to annotate"` Notes string `json:"notes" jsonschema:"your usage notes, reminders, or gotchas for this tool; pass empty string to clear"` } type AnnotateToolOutput struct { ToolName string `json:"tool_name"` } func (t *DescribeTool) Annotate(ctx context.Context, _ *mcp.CallToolRequest, in AnnotateToolInput) (*mcp.CallToolResult, AnnotateToolOutput, error) { if strings.TrimSpace(in.ToolName) == "" { return nil, AnnotateToolOutput{}, errRequiredField("tool_name") } if err := t.store.UpsertToolAnnotation(ctx, in.ToolName, in.Notes); err != nil { return nil, AnnotateToolOutput{}, err } return nil, AnnotateToolOutput{ToolName: in.ToolName}, nil }