mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
86 lines
2.1 KiB
Go
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)
|
|
}
|