tooldiscovery¶
Discovery layer providing tool registry, search strategies, and progressive documentation for the ApertureStack tool framework.
Packages¶
| Package | Purpose |
|---|---|
discovery | Unified facade combining index, search, semantic, and tooldoc |
index | Global registry, tool lookup, and search interface |
search | BM25-based full-text search strategy |
semantic | Embedding-based semantic search (optional) |
tooldoc | Progressive documentation with detail levels |
registry | MCP server helper with local + backend execution |
Installation¶
go get github.com/jonwraymond/tooldiscovery@latest
Quick Start¶
Use the Discovery Facade (Recommended)¶
import (
"context"
"github.com/jonwraymond/tooldiscovery/discovery"
)
disc, _ := discovery.New(discovery.Options{})
// Register tools through the facade
_ = disc.RegisterTool(tool, backend)
// Search (hybrid-ready)
results, _ := disc.Search(context.Background(), "create issue", 5)
for _, r := range results {
fmt.Printf("[%s] %s\n", r.ScoreType, r.Summary.ID)
}
Build an MCP Server (registry)¶
import (
"context"
"github.com/jonwraymond/tooldiscovery/registry"
)
reg := registry.New(registry.Config{
ServerInfo: registry.ServerInfo{Name: "my-mcp", Version: "1.0.0"},
})
_ = reg.RegisterLocalFunc(
"echo",
"Echo input",
map[string]any{"type": "object"},
func(ctx context.Context, args map[string]any) (any, error) { return args, nil },
)
_ = reg.Start(context.Background())
defer reg.Stop()
Register and Search Tools¶
import (
"github.com/jonwraymond/tooldiscovery/index"
"github.com/jonwraymond/toolfoundation/model"
)
// Create an index
idx := index.NewInMemoryIndex()
// Register a tool
err := idx.RegisterTool(tool, backend)
if err != nil {
log.Fatal(err)
}
// Search for tools
summaries, err := idx.Search("create issue", 5)
for _, s := range summaries {
fmt.Printf("%s: %s\n", s.ID, s.Summary)
}
Enable BM25 Search¶
import (
"github.com/jonwraymond/tooldiscovery/index"
"github.com/jonwraymond/tooldiscovery/search"
)
// Create BM25 searcher
searcher, err := search.NewBM25Searcher(search.DefaultConfig())
if err != nil {
log.Fatal(err)
}
defer searcher.Close()
// Create index with BM25
idx := index.NewInMemoryIndex(index.WithSearchStrategy(searcher))
Search Strategy Guidance¶
- Lexical (default): simple substring matching; best for small registries.
- BM25 (
search): higher quality ranking for larger registries. - Semantic (
semantic): intent-based matching when embeddings are available. - Hybrid (
discovery): combines BM25 + semantic with weighted scoring.
Progressive Documentation¶
import "github.com/jonwraymond/tooldiscovery/tooldoc"
store := tooldoc.NewInMemoryStore(tooldoc.StoreOptions{Index: idx})
// Get summary only (token-cheap)
doc, _ := store.GetDoc(toolID, tooldoc.DetailSummary)
// Get full schema (on-demand)
doc, _ = store.GetDoc(toolID, tooldoc.DetailSchema)
Semantic Search (Optional)¶
import "github.com/jonwraymond/tooldiscovery/semantic"
// Provide an Embedder + VectorStore implementation
searcher := semantic.NewSemanticSearcher(embedder, vectorStore)
idx := index.NewInMemoryIndex(index.WithSearchStrategy(searcher))
Key Features¶
- Token-efficient: Summaries exclude schemas to reduce context usage
- Pluggable search: Swap between lexical, BM25, or semantic search
- Progressive disclosure: Request only the detail level needed
- Namespace support: List and filter tools by namespace