Tencent/WeKnora · error

failed to call tool: %w

Error message

failed to call tool: %w

What it means

CallTool wraps any failure from the underlying MCP client's CallTool RPC (including OAuth token acquisition failures handled by oauthCall) with "failed to call tool: %w". It first runs checkErrorAndDisconnectIfNeeded, which may mark the client disconnected if the error indicates a stale connection. The wrapped original error is preserved via %w, so errors.Is/As still work on the cause.

Source

Thrown at internal/mcp/client.go:490

// CallTool calls a tool on the MCP service
func (c *mcpGoClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*CallToolResult, error) {
	if !c.initialized {
		return nil, ErrNotConnected
	}

	req := mcp.CallToolRequest{
		Params: mcp.CallToolParams{
			Name:      name,
			Arguments: args,
		},
	}

	result, err := oauthCall(ctx, c, func() (*mcp.CallToolResult, error) {
		return c.client.CallTool(ctx, req)
	})
	if err != nil {
		c.checkErrorAndDisconnectIfNeeded(err)
		return nil, fmt.Errorf("failed to call tool: %w", err)
	}

	// Convert to our types
	content := make([]ContentItem, 0, len(result.Content))
	for _, item := range result.Content {
		if textContent, ok := mcp.AsTextContent(item); ok {
			content = append(content, ContentItem{
				Type: "text",
				Text: textContent.Text,
			})
		} else if imageContent, ok := mcp.AsImageContent(item); ok {
			content = append(content, ContentItem{
				Type:     "image",
				Data:     imageContent.Data,
				MimeType: imageContent.MIMEType,
			})
		}
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the wrapped cause with errors.Is/errors.As or by inspecting err.Error() suffix to see the real failure
  2. Verify the client is still connected; re-create the client via the manager (GetOrCreateClient) if it was disconnected by checkErrorAndDisconnectIfNeeded
  3. Confirm the tool name and arguments match what the server advertises (GetMCPToolsInfo)
  4. Check network connectivity and that the MCP service URL is correct

Example fix

// before
res, err := client.CallTool(ctx, req)
if err != nil { log.Fatal(err) }
// after
res, err := client.CallTool(ctx, req)
if err != nil {
    if errors.Is(err, ErrDisconnected) {
        client, err = manager.GetOrCreateClient(ctx, svc) // reconnect
    }
    return fmt.Errorf("failed to call tool: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if client == nil || !client.IsConnected() { client, err = manager.GetOrCreateClient(ctx, svc); if err != nil { return err } }

Type guard

func isToolCallFailure(err error) bool { return err != nil && strings.Contains(err.Error(), "failed to call tool:") }

Try / catch

result, err := client.CallTool(ctx, req)
if err != nil {
    var reauth *mcp.OAuthReauthorizationRequiredError
    if errors.As(err, &reauth) { /* re-auth */ }
    if isDisconnected(err) { client = reconnect(ctx, svc) }
    return fmt.Errorf("tool call failed: %w", err)
}

Prevention

When it happens

Trigger: Calling MCPClient.CallTool(ctx, req) when the remote MCP server is unreachable, returns a tool-execution error, the session was disconnected, or the OAuth flow inside oauthCall fails.

Common situations: Remote MCP server restarted or crashed (stale SSE connection); tool name typo'd so server rejects; network timeout mid-call; OAuth token refresh failed before the request was sent.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/2aeb5cdee5e93563. Report an issue: GitHub.