Skip to content

End-to-End Example

This example shows the full flow:

  1. Define a tool
  2. Register it + docs
  3. Discover and describe it
  4. 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.