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 }