2026-05-29 18:12:45 +00:00
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" ,
2026-06-10 10:38:30 -06:00
Description : "Search Einherjar's exported symbols (types, interfaces, funcs, methods, consts, vars) by name or doc text. Structs also match on a field name, field type, or struct tag (e.g. an env-var key); interfaces also match on a required method. Optionally filter by module or kind. Use when you need to find where a type, function, field, or tag lives." ,
2026-05-29 18:12:45 +00:00
}, 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
})
}