* Implement DescribeTool for listing available MCP tools with annotations. * Add UpsertToolAnnotation and GetToolAnnotations methods for managing tool notes. * Create tool_annotations table for storing tool usage notes.
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
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
|
|
}
|