package tools import ( "context" "code.nochebuena.dev/einherjar/mcp/internal/index" "github.com/modelcontextprotocol/go-sdk/mcp" ) type searchSymbolsInput struct { Query string `json:"query" jsonschema:"text to match against symbol name, doc comment, sub-package, or module"` Limit int `json:"limit,omitempty" jsonschema:"max results (default 25)"` Module string `json:"module,omitempty" jsonschema:"restrict to one module by name"` Kind string `json:"kind,omitempty" jsonschema:"restrict to one kind: type, interface, func, method, const, var"` } type searchSymbolsOutput struct { Results []index.Symbol `json:"results"` Total int `json:"total"` } func registerSearchSymbols(s *mcp.Server, idx *index.Index) { mcp.AddTool(s, &mcp.Tool{ Name: "search_symbols", Description: "Search Einherjar's exported symbols (types, interfaces, funcs, methods, consts, vars) by name or doc text. Optionally filter by module or kind. Use when you need to find where a type or function lives.", }, func(ctx context.Context, req *mcp.CallToolRequest, args searchSymbolsInput) (*mcp.CallToolResult, searchSymbolsOutput, error) { all := idx.SearchSymbols(args.Query, args.Limit*4+25) filtered := all[:0] for _, sym := range all { if args.Module != "" && sym.Module != args.Module { continue } if args.Kind != "" && sym.Kind != args.Kind { continue } filtered = append(filtered, sym) } limit := args.Limit if limit <= 0 { limit = 25 } if len(filtered) > limit { filtered = filtered[:limit] } out := searchSymbolsOutput{Results: filtered, Total: len(filtered)} return jsonText(out), out, nil }) }