diff options
Diffstat (limited to 'internal/llm/agent/mcp-tools.go')
| -rw-r--r-- | internal/llm/agent/mcp-tools.go | 198 |
1 files changed, 0 insertions, 198 deletions
diff --git a/internal/llm/agent/mcp-tools.go b/internal/llm/agent/mcp-tools.go deleted file mode 100644 index 601fdf705..000000000 --- a/internal/llm/agent/mcp-tools.go +++ /dev/null @@ -1,198 +0,0 @@ -package agent - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/sst/opencode/internal/config" - "github.com/sst/opencode/internal/llm/tools" - "github.com/sst/opencode/internal/permission" - "github.com/sst/opencode/internal/version" - "log/slog" - - "github.com/mark3labs/mcp-go/client" - "github.com/mark3labs/mcp-go/mcp" -) - -type mcpTool struct { - mcpName string - tool mcp.Tool - mcpConfig config.MCPServer - permissions permission.Service -} - -type MCPClient interface { - Initialize( - ctx context.Context, - request mcp.InitializeRequest, - ) (*mcp.InitializeResult, error) - ListTools(ctx context.Context, request mcp.ListToolsRequest) (*mcp.ListToolsResult, error) - CallTool(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) - Close() error -} - -func (b *mcpTool) Info() tools.ToolInfo { - return tools.ToolInfo{ - Name: fmt.Sprintf("%s_%s", b.mcpName, b.tool.Name), - Description: b.tool.Description, - Parameters: b.tool.InputSchema.Properties, - Required: b.tool.InputSchema.Required, - } -} - -func runTool(ctx context.Context, c MCPClient, toolName string, input string) (tools.ToolResponse, error) { - defer c.Close() - initRequest := mcp.InitializeRequest{} - initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION - initRequest.Params.ClientInfo = mcp.Implementation{ - Name: "OpenCode", - Version: version.Version, - } - - _, err := c.Initialize(ctx, initRequest) - if err != nil { - return tools.NewTextErrorResponse(err.Error()), nil - } - - toolRequest := mcp.CallToolRequest{} - toolRequest.Params.Name = toolName - var args map[string]any - if err = json.Unmarshal([]byte(input), &args); err != nil { - return tools.NewTextErrorResponse(fmt.Sprintf("error parsing parameters: %s", err)), nil - } - toolRequest.Params.Arguments = args - result, err := c.CallTool(ctx, toolRequest) - if err != nil { - return tools.NewTextErrorResponse(err.Error()), nil - } - - output := "" - for _, v := range result.Content { - if v, ok := v.(mcp.TextContent); ok { - output = v.Text - } else { - output = fmt.Sprintf("%v", v) - } - } - - return tools.NewTextResponse(output), nil -} - -func (b *mcpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolResponse, error) { - sessionID, messageID := tools.GetContextValues(ctx) - if sessionID == "" || messageID == "" { - return tools.ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file") - } - permissionDescription := fmt.Sprintf("execute %s with the following parameters: %s", b.Info().Name, params.Input) - p := b.permissions.Request( - ctx, - permission.CreatePermissionRequest{ - SessionID: sessionID, - Path: config.WorkingDirectory(), - ToolName: b.Info().Name, - Action: "execute", - Description: permissionDescription, - Params: params.Input, - }, - ) - if !p { - return tools.NewTextErrorResponse("permission denied"), nil - } - - switch b.mcpConfig.Type { - case config.MCPStdio: - c, err := client.NewStdioMCPClient( - b.mcpConfig.Command, - b.mcpConfig.Env, - b.mcpConfig.Args..., - ) - if err != nil { - return tools.NewTextErrorResponse(err.Error()), nil - } - return runTool(ctx, c, b.tool.Name, params.Input) - case config.MCPSse: - c, err := client.NewSSEMCPClient( - b.mcpConfig.URL, - client.WithHeaders(b.mcpConfig.Headers), - ) - if err != nil { - return tools.NewTextErrorResponse(err.Error()), nil - } - return runTool(ctx, c, b.tool.Name, params.Input) - } - - return tools.NewTextErrorResponse("invalid mcp type"), nil -} - -func NewMcpTool(name string, tool mcp.Tool, permissions permission.Service, mcpConfig config.MCPServer) tools.BaseTool { - return &mcpTool{ - mcpName: name, - tool: tool, - mcpConfig: mcpConfig, - permissions: permissions, - } -} - -var mcpTools []tools.BaseTool - -func getTools(ctx context.Context, name string, m config.MCPServer, permissions permission.Service, c MCPClient) []tools.BaseTool { - var stdioTools []tools.BaseTool - initRequest := mcp.InitializeRequest{} - initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION - initRequest.Params.ClientInfo = mcp.Implementation{ - Name: "OpenCode", - Version: version.Version, - } - - _, err := c.Initialize(ctx, initRequest) - if err != nil { - slog.Error("error initializing mcp client", "error", err) - return stdioTools - } - toolsRequest := mcp.ListToolsRequest{} - tools, err := c.ListTools(ctx, toolsRequest) - if err != nil { - slog.Error("error listing tools", "error", err) - return stdioTools - } - for _, t := range tools.Tools { - stdioTools = append(stdioTools, NewMcpTool(name, t, permissions, m)) - } - defer c.Close() - return stdioTools -} - -func GetMcpTools(ctx context.Context, permissions permission.Service) []tools.BaseTool { - if len(mcpTools) > 0 { - return mcpTools - } - for name, m := range config.Get().MCPServers { - switch m.Type { - case config.MCPStdio: - c, err := client.NewStdioMCPClient( - m.Command, - m.Env, - m.Args..., - ) - if err != nil { - slog.Error("error creating mcp client", "error", err) - continue - } - - mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c)...) - case config.MCPSse: - c, err := client.NewSSEMCPClient( - m.URL, - client.WithHeaders(m.Headers), - ) - if err != nil { - slog.Error("error creating mcp client", "error", err) - continue - } - mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c)...) - } - } - - return mcpTools -} |
