Files
picoclaw/pkg/tools/mcp.go
T

86 lines
2.1 KiB
Go

package tools
import (
"context"
"errors"
"fmt"
"github.com/sipeed/picoclaw/pkg/mcp"
)
type MCPTool struct {
manager *mcp.Manager
name string
description string
parameters map[string]any
}
func NewMCPTool(manager *mcp.Manager, tool mcp.RegisteredTool) *MCPTool {
description := tool.Description
if description == "" {
description = fmt.Sprintf("MCP tool %s from server %s", tool.ToolName, tool.ServerName)
}
return &MCPTool{
manager: manager,
name: tool.QualifiedName,
description: description,
parameters: tool.Parameters,
}
}
func (t *MCPTool) Name() string {
return t.name
}
func (t *MCPTool) Description() string {
return t.description
}
func (t *MCPTool) Parameters() map[string]interface{} {
return t.parameters
}
func (t *MCPTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
if t.manager == nil {
return ErrorResult("MCP manager is not configured")
}
result, err := t.manager.CallTool(ctx, t.name, args)
if err != nil {
return ErrorResult(fmt.Sprintf("MCP tool %s failed: %v", t.name, err)).WithError(err)
}
if result.IsError {
err := errors.New(result.Content)
return ErrorResult(result.Content).WithError(err)
}
return SilentResult(result.Content)
}
// RegisterMCPTools discovers tools from MCP servers and registers them into the registry.
func RegisterMCPTools(ctx context.Context, registry *ToolRegistry, manager *mcp.Manager) (int, error) {
if registry == nil || manager == nil {
return 0, nil
}
discoveredTools, err := manager.DiscoverTools(ctx)
if err != nil {
return 0, err
}
return RegisterKnownMCPTools(registry, manager, discoveredTools), nil
}
// RegisterKnownMCPTools registers already-discovered MCP tools.
// This avoids repeated discovery work when multiple registries share one manager.
func RegisterKnownMCPTools(registry *ToolRegistry, manager *mcp.Manager, discoveredTools []mcp.RegisteredTool) int {
if registry == nil || manager == nil || len(discoveredTools) == 0 {
return 0
}
for _, tool := range discoveredTools {
registry.Register(NewMCPTool(manager, tool))
}
return len(discoveredTools)
}