mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat: add MCP integration with context7 compatibility
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/mcp"
|
||||
)
|
||||
|
||||
func TestRegisterKnownMCPTools_RegistersAllTools(t *testing.T) {
|
||||
registry := NewToolRegistry()
|
||||
manager := &mcp.Manager{}
|
||||
discovered := []mcp.RegisteredTool{
|
||||
{
|
||||
QualifiedName: "mcp_context7__resolve_library_id",
|
||||
ServerName: "context7",
|
||||
ToolName: "resolve-library-id",
|
||||
Description: "Resolve library ID",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
{
|
||||
QualifiedName: "mcp_context7__query_docs",
|
||||
ServerName: "context7",
|
||||
ToolName: "query-docs",
|
||||
Description: "Query docs",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
count := RegisterKnownMCPTools(registry, manager, discovered)
|
||||
if count != 2 {
|
||||
t.Fatalf("RegisterKnownMCPTools count = %d, want 2", count)
|
||||
}
|
||||
|
||||
if _, ok := registry.Get("mcp_context7__resolve_library_id"); !ok {
|
||||
t.Fatalf("expected mcp_context7__resolve_library_id to be registered")
|
||||
}
|
||||
if _, ok := registry.Get("mcp_context7__query_docs"); !ok {
|
||||
t.Fatalf("expected mcp_context7__query_docs to be registered")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user