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
- Check the wrapped cause with errors.Is/errors.As or by inspecting err.Error() suffix to see the real failure
- Verify the client is still connected; re-create the client via the manager (GetOrCreateClient) if it was disconnected by checkErrorAndDisconnectIfNeeded
- Confirm the tool name and arguments match what the server advertises (GetMCPToolsInfo)
- 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
- Reuse a manager-managed client so disconnects are detected and recreated automatically
- Validate tool names against GetMCPToolsInfo before invoking
- Handle the wrapped cause with errors.Is/As instead of string matching only
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
- failed to read resource: %w
- failed to list resources: %w
- failed to list tools: %w
- failed to list resources: %w
- failed to get MCP client: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2aeb5cdee5e93563.
Report an issue: GitHub.