Files
Cyrene_v2/internal/capability/mcp/tool.go
T

64 lines
1.7 KiB
Go

package mcp
import (
"context"
"strings"
)
// mcpTool adapts an MCP tool to the pkg/plugins/sdk Tool interface so it can be
// registered and invoked like any built-in tool. It is immutable and safe for
// concurrent use.
type mcpTool struct {
client *Client
info ToolInfo
}
// Name returns the MCP tool identifier.
func (t *mcpTool) Name() string {
return t.info.Name
}
// Description returns the MCP tool description.
func (t *mcpTool) Description() string {
return t.info.Description
}
// Parameters returns the MCP tool input schema, defaulting to an empty object
// schema when the server omits one.
func (t *mcpTool) Parameters() (map[string]any, error) {
if t.info.InputSchema == nil {
return map[string]any{"type": "object", "properties": map[string]any{}}, nil
}
return t.info.InputSchema, nil
}
// Execute invokes the MCP tool and returns its concatenated text content.
func (t *mcpTool) Execute(ctx context.Context, args any) (any, error) {
res, err := t.client.CallTool(ctx, t.info.Name, args)
if err != nil {
return nil, err
}
return contentText(res.Content), nil
}
// contentText concatenates the text blocks of a tool result into a single
// string, ignoring non-text blocks.
func contentText(content []ContentBlock) string {
var b strings.Builder
for _, blk := range content {
if blk.Type == "" || blk.Type == "text" {
b.WriteString(blk.Text)
}
}
return b.String()
}
// toContentBlocks converts wire content blocks to the public content block type.
func toContentBlocks(wire []contentBlock) []ContentBlock {
out := make([]ContentBlock, 0, len(wire))
for _, c := range wire {
out = append(out, ContentBlock{Type: c.Type, Text: c.Text})
}
return out
}