Skip to content

toolfoundation User Journey

Overview

This guide walks through the typical usage patterns for toolfoundation, from defining your first tool to converting between LLM provider formats.

1. Installation

go get github.com/jonwraymond/toolfoundation@latest

2. Define Your First Tool

import (
  "github.com/jonwraymond/toolfoundation/model"
  "github.com/modelcontextprotocol/go-sdk/mcp"
)

// Create a tool definition
tool := model.Tool{
  Namespace: "calculator",
  Tool: mcp.Tool{
    Name:        "add",
    Description: "Add two numbers together",
    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"},
    },
  },
  Tags: model.NormalizeTags([]string{"math", "arithmetic"}),
}

// Validate the tool
if err := tool.Validate(); err != nil {
  log.Fatalf("Invalid tool: %v", err)
}

// Get the canonical ID
fmt.Println(tool.ToolID()) // "calculator:add"

3. Assign a Backend

// Local handler backend
tool.Backend = model.NewLocalBackend("add_handler")

// Or MCP server backend
tool.Backend = model.NewMCPBackend("math-server")

4. Convert to OpenAI Format

import "github.com/jonwraymond/toolfoundation/adapter"

// Use the default registry with all built-in adapters
registry := adapter.DefaultRegistry()

// Convert MCP tool to OpenAI format
result, err := registry.Convert(&tool, "mcp", "openai")
if err != nil {
  log.Fatalf("Conversion failed: %v", err)
}

// Check for feature loss
for _, warning := range result.Warnings {
  log.Printf("Warning: %s", warning)
}

openaiTool := result.Tool.(*adapter.OpenAITool)
fmt.Printf("OpenAI function: %s\n", openaiTool.Function.Name)

5. Round-Trip Conversion

// Convert OpenAI → MCP
result2, err := registry.Convert(openaiTool, "openai", "mcp")
if err != nil {
  log.Fatal(err)
}

mcpTool := result2.Tool.(mcp.Tool)

Common Patterns

Batch Tool Registration

tools := []model.Tool{
  {Namespace: "math", Tool: mcp.Tool{Name: "add", ...}},
  {Namespace: "math", Tool: mcp.Tool{Name: "subtract", ...}},
  {Namespace: "math", Tool: mcp.Tool{Name: "multiply", ...}},
}

for _, t := range tools {
  if err := t.Validate(); err != nil {
    log.Printf("Skipping invalid tool %s: %v", t.ToolID(), err)
    continue
  }
  // Register with index...
}

Schema Validation

validator := model.NewDefaultValidator()

// Validate input against tool schema
input := map[string]any{"a": 5, "b": 10}
if err := validator.ValidateInput(&tool, input); err != nil {
  log.Fatalf("Invalid input: %v", err)
}

Version Compatibility

import "github.com/jonwraymond/toolfoundation/version"

current := version.MustParse("v1.2.0")
required := version.MustParse("v1.0.0")

if !current.Compatible(required) {
  log.Fatalf("version %s is not compatible with %s", current, required)
}

matrix := version.NewMatrix()
matrix.Add(version.Compatibility{
  Component:  "toolfoundation",
  MinVersion: required,
})

ok, msg := matrix.Check("toolfoundation", current)
if !ok {
  log.Fatal(msg)
}

Next Steps