package main import ( "context" "encoding/json" "github.com/mark3labs/mcp-go/mcp" "fn-registry/registry" ) type proposalArgs struct { ID string `json:"id,omitempty"` Kind string `json:"kind,omitempty"` Status string `json:"status,omitempty"` Limit int `json:"limit,omitempty"` } func proposalTool() mcp.Tool { return mcp.NewTool("fn_proposal", mcp.WithDescription("Read proposals from registry.db. With `id`, returns that proposal in full (including evidence). Without `id`, lists proposals filtered by `kind`/`status`, ordered by created_at DESC. Replaces `sqlite3 registry.db \"SELECT ... FROM proposals\"` inline queries."), mcp.WithString("id", mcp.Description("Proposal ID. If set, ignores kind/status filters and returns single record."), ), mcp.WithString("kind", mcp.Description("Filter by kind: new_function, new_type, improve_function, improve_type, new_pipeline."), mcp.Enum("new_function", "new_type", "improve_function", "improve_type", "new_pipeline"), ), mcp.WithString("status", mcp.Description("Filter by status: pending, approved, rejected, implemented."), mcp.Enum("pending", "approved", "rejected", "implemented"), ), mcp.WithNumber("limit", mcp.Description("Max rows returned (default 100)."), mcp.Min(1), mcp.Max(1000), ), ) } func (d *deps) handleProposal(ctx context.Context, _ mcp.CallToolRequest, args proposalArgs) (*mcp.CallToolResult, error) { if args.ID != "" { p, err := d.db.GetProposal(args.ID) if err != nil { return mcp.NewToolResultError("proposal not found: " + args.ID), nil } b, _ := json.MarshalIndent(p, "", " ") return mcp.NewToolResultText(string(b)), nil } limit := args.Limit if limit <= 0 { limit = 100 } ps, err := d.db.ListProposals(registry.ProposalKind(args.Kind), registry.ProposalStatus(args.Status)) if err != nil { return mcp.NewToolResultError("list proposals: " + err.Error()), nil } if len(ps) > limit { ps = ps[:limit] } out := map[string]any{ "count": len(ps), "limit": limit, "kind": args.Kind, "status": args.Status, "proposals": ps, } b, _ := json.MarshalIndent(out, "", " ") return mcp.NewToolResultText(string(b)), nil }