End-to-End Example¶
This example shows the full flow:
- Define a tool
- Register it + docs
- Discover and describe it
- Execute it
It is intentionally small but exercises the core layers.
package main
import (
"context"
"fmt"
"github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/jonwraymond/toolfoundation/model"
"github.com/jonwraymond/tooldiscovery/index"
"github.com/jonwraymond/tooldiscovery/tooldoc"
"github.com/jonwraymond/toolexec/exec"
)
func main() {
ctx := context.Background()
// 1) Define a tool
tool := model.Tool{
Tool: mcp.Tool{
Name: "add",
Description: "Add two numbers",
InputSchema: map[string]any{
"type": "object",
"properties": map[string]any{
"a": map[string]any{"type": "number"},
"b": map[string]any{"type": "number"},
},
"required": []string{"a", "b"},
},
},
Namespace: "math",
Tags: []string{"math", "add"},
}
// 2) Create registry + docs
idx := index.NewInMemoryIndex()
docs := tooldoc.NewInMemoryStore(tooldoc.StoreOptions{Index: idx})
// 3) Register tool + docs
_ = idx.RegisterTool(tool, model.ToolBackend{Kind: model.BackendKindLocal, Local: &model.LocalBackend{Name: "math-add"}})
_ = docs.RegisterDoc(tool.ToolID(), tooldoc.DocEntry{Summary: "Adds two numbers"})
// 4) Create executor with local handler
executor, _ := exec.New(exec.Options{
Index: idx,
Docs: docs,
LocalHandlers: map[string]exec.Handler{
"math-add": func(_ context.Context, args map[string]any) (any, error) {
return args["a"].(float64) + args["b"].(float64), nil
},
},
})
// 5) Discover
summaries, _ := idx.Search("add", 3)
fmt.Println("summaries", summaries)
// 6) Describe
doc, _ := docs.DescribeTool(tool.ToolID(), tooldoc.DetailSchema)
fmt.Println("doc", doc.Summary)
// 7) Execute
result, _ := executor.RunTool(ctx, tool.ToolID(), map[string]any{"a": 2.0, "b": 3.0})
fmt.Println("result", result.Value)
}
Notes: - In real use, the registry often sits behind metatools-mcp or metatools-a2a. - For server wiring, see metatools-mcp/examples and metatools-a2a docs.