chore: sync from fn-registry agent
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
)
|
||||
|
||||
type usesArgs struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func usesTool() mcp.Tool {
|
||||
return mcp.NewTool("fn_uses",
|
||||
mcp.WithDescription("Return the dependency edges for a function or type: which functions/types it uses (forward) and which functions consume it (reverse). Reverse lookup uses LIKE on uses_functions/uses_types JSON, so it's O(N) over the table — fast on registry.db (~1k rows)."),
|
||||
mcp.WithString("id",
|
||||
mcp.Required(),
|
||||
mcp.Description("Registry ID."),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handleUses(ctx context.Context, _ mcp.CallToolRequest, args usesArgs) (*mcp.CallToolResult, error) {
|
||||
if args.ID == "" {
|
||||
return mcp.NewToolResultError("id is required"), nil
|
||||
}
|
||||
|
||||
out := map[string]any{"id": args.ID}
|
||||
if f, err := d.db.GetFunction(args.ID); err == nil {
|
||||
out["entity"] = "function"
|
||||
out["uses_functions"] = f.UsesFunctions
|
||||
out["uses_types"] = f.UsesTypes
|
||||
} else if t, err := d.db.GetType(args.ID); err == nil {
|
||||
out["entity"] = "type"
|
||||
out["uses_types"] = t.UsesTypes
|
||||
} else {
|
||||
return mcp.NewToolResultError("id not found: " + args.ID), nil
|
||||
}
|
||||
|
||||
conn := d.db.Conn()
|
||||
pattern := "%\"" + args.ID + "\"%"
|
||||
rows, err := conn.Query(`SELECT id FROM functions WHERE uses_functions LIKE ? OR uses_types LIKE ? ORDER BY id`, pattern, pattern)
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError("reverse lookup: " + err.Error()), nil
|
||||
}
|
||||
defer rows.Close()
|
||||
var consumers []string
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return mcp.NewToolResultError("scan reverse: " + err.Error()), nil
|
||||
}
|
||||
consumers = append(consumers, id)
|
||||
}
|
||||
out["consumed_by"] = consumers
|
||||
|
||||
// Apps that declare the id in uses_functions (the apps table also stores the JSON list).
|
||||
rows, err = conn.Query(`SELECT id FROM apps WHERE uses_functions LIKE ? ORDER BY id`, pattern)
|
||||
if err == nil {
|
||||
defer rows.Close()
|
||||
var apps []string
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err == nil {
|
||||
apps = append(apps, id)
|
||||
}
|
||||
}
|
||||
out["consumed_by_apps"] = apps
|
||||
}
|
||||
|
||||
b, _ := json.MarshalIndent(out, "", " ")
|
||||
return mcp.NewToolResultText(string(b)), nil
|
||||
}
|
||||
Reference in New Issue
Block a user