registry¶
High-level helpers for building MCP servers with tool discovery, registration, local execution, and MCP backend aggregation. The registry composes:
toolfoundation/model(tool schema + validation)tooldiscovery/index(registry + lookup)tooldiscovery/search(BM25 search)
Goals¶
- Provide a fast path to a working MCP server.
- Keep tool discovery and tool execution in a single, minimal API.
- Support local tools and federated MCP backends.
Package Overview¶
registry/
├── registry.go # Core Registry type and lifecycle
├── handler.go # Local tool handler and registration helpers
├── backend.go # MCP backend connections
├── mcp.go # MCP JSON-RPC request/response handling
├── server.go # ServeStdio, ServeHTTP, ServeSSE
└── errors.go # Sentinel errors + MCP error codes
Core Types¶
// Config configures a Registry.
type Config struct {
SearchConfig *search.BM25Config
ServerInfo ServerInfo
BackendSelector index.BackendSelector
}
// ServerInfo describes this MCP server for initialize response.
type ServerInfo struct {
Name string
Version string
}
// Registry is a high-level MCP tool registry.
type Registry struct { /* ... */ }
Local Tools¶
reg := registry.New(registry.Config{
ServerInfo: registry.ServerInfo{
Name: "my-mcp",
Version: "1.0.0",
},
})
reg.RegisterLocalFunc(
"echo",
"Echoes back input",
map[string]any{
"type": "object",
"properties": map[string]any{
"message": map[string]any{"type": "string"},
},
"required": []string{"message"},
},
func(ctx context.Context, args map[string]any) (any, error) {
return map[string]any{"echo": args["message"]}, nil
},
registry.WithNamespace("utility"),
registry.WithTags("echo", "debug"),
)
MCP Backends¶
Backends allow the registry to aggregate tools from other MCP servers.
err := reg.RegisterMCP(registry.BackendConfig{
Name: "remote-tools",
URL: "https://example.com/mcp",
Headers: map[string]string{
"Authorization": "Bearer ...",
},
})
BackendConfig¶
type BackendConfig struct {
Name string
URL string
Headers map[string]string
MaxRetries int
RetryInterval time.Duration
Transport mcp.Transport // optional override
}
URLsupportshttp(s)://(streamable HTTP),sse://(legacy SSE), andstdio://(stdio transport bound to the current process).Headersare injected into HTTP requests.Transportis useful for tests or custom transports (e.g. in-memory).
Execution¶
result, err := reg.Execute(ctx, "utility:echo", map[string]any{"message": "hi"})
Execution routing:
- Tool lookup in
index - Backend selection via
BackendSelector - Local handler or MCP backend call
Result Mapping¶
When calling an MCP backend:
StructuredContentis returned when available- single
TextContentreturns a string - otherwise, the full
[]mcp.Contentis returned
MCP Protocol Handling¶
The registry handles MCP JSON-RPC methods:
initializetools/listtools/call
These are exposed via ServeStdio, ServeHTTP, or ServeSSE.
Transports¶
// Stdio
_ = registry.ServeStdio(ctx, reg)
// HTTP (streamable)
http.Handle("/mcp", registry.ServeHTTP(reg))
// SSE (legacy)
http.Handle("/mcp-sse", registry.ServeSSE(reg))
Lifecycle¶
if err := reg.Start(ctx); err != nil {
log.Fatal(err)
}
defer reg.Stop()
Startconnects registered MCP backends and registers their toolsStopcloses backend sessions
Errors¶
Registry returns sentinel errors from errors.go:
ErrNotStartedErrAlreadyStartedErrToolNotFoundErrBackendNotFoundErrHandlerNotFoundErrExecutionFailedErrInvalidRequest
Diagram¶
flowchart LR
Local["Local handlers"] --> Registry
MCP["MCP backends"] --> Registry
Registry --> Index
Index --> Search
Registry -->|ServeStdio / ServeHTTP / ServeSSE| Transports