What Happens When an MCP Server Returns an Error During Tool Execution

When an MCP server returns an error during tool execution, the Dify MCP plugin detects the error in the call_tool method, raises a Python exception containing the server name and raw error payload, and re-wraps it in execute_tool before propagating the failure to the Dify runtime.

The junjiem/dify-plugin-agent-mcp_sse repository implements a Model Context Protocol (MCP) client that enables Dify agents to invoke tools hosted on remote MCP servers. Understanding what happens when an MCP server returns an error during tool execution is critical for building resilient agent workflows and debugging integration failures.

Error Detection in the MCP Client Layer

When a Dify agent invokes an MCP tool, the request flows through the McpClient class defined in utils/mcp_client.py. The call_tool method constructs a JSON‑RPC tools/call request and transmits it via the configured transport (SSE or streamable HTTP).

The call_tool Method Implementation

Inside call_tool, the client awaits the server response and inspects the payload for an error field. If present, the method immediately raises a Python exception that includes the server name and the complete error object.


# utils/mcp_client.py (lines 71-84)

response = self.send_message(data)
if "error" in response:                       # Line 82

    error = response["error"]
    raise Exception(f"{self.name} - MCP Server tools/call error: {error}")

This early detection ensures that protocol‑level errors—such as method not found (-32601) or custom MCP application errors—are captured before any result processing occurs.

Error Propagation to the Dify Runtime

The McpClients class (plural) orchestrates multiple server connections and provides the execute_tool entry point that Dify agents actually invoke. This method wraps the lower‑level call_tool logic and standardizes exception handling across all configured servers.

Exception Handling in execute_tool

When execute_tool delegates to call_tool, it wraps the invocation in a try‑except block. Any exception—whether from network failures, JSON‑RPC errors, or the explicit error raise in call_tool—is caught and re‑wrapped with a descriptive prefix.


# utils/mcp_client.py (lines 12-74)

try:
    if action_type == ActionType.TOOL:
        tool_contents = client.call_tool(tool_name, tool_args)   # Line 26-28

except Exception as e:
    raise Exception(f"Error executing tool: {str(e)}")             # Line 73-74

This two‑layer wrapping preserves the original error details while providing context about which tool execution failed, making debugging easier for Dify developers.

Impact on Dify Workflow Execution

Once the re‑wrapped exception bubbles up to the Dify orchestration layer, the platform treats it as a hard tool failure. Dify surfaces the error message to the end user—typically displaying “Tool execution failed: …”—and may trigger configured fallback behaviors such as retry loops, alternative tool selection, or graceful degradation based on the agent’s error‑handling policy.

Practical Example: Handling MCP Server Errors in Python

The following example demonstrates how to invoke an MCP tool through the plugin and catch the specific error chain described above.

from utils.mcp_client import McpClients

# Initialize client with server configuration

clients = McpClients(
    servers_config={
        "my_server": {
            "url": "https://example.com/mcp",
            "transport": "sse"
        }
    }
)

try:
    # Attempt to execute a tool that may fail on the server

    result = clients.execute_tool("risky_operation", {"param": "value"})
    print("Success:", result)
except Exception as exc:
    # Output: Error executing tool: my_server - MCP Server tools/call error: {...}

    print("Captured error:", exc)

When the remote MCP server returns a JSON‑RPC error object—such as {"code": -32601, "message": "Method not found"}—the exception message will contain the full error payload, allowing precise diagnosis of whether the failure is due to a missing tool, invalid parameters, or server‑side logic errors.

Summary

When an MCP server returns an error during tool execution, the Dify MCP plugin handles it through a strict two‑phase process:

  • Immediate detection in McpClient.call_tool (utils/mcp_client.py), which inspects JSON‑RPC responses and raises an exception containing the server name and raw error payload.
  • Standardized propagation in McpClients.execute_tool, which catches all lower‑level exceptions, wraps them with execution context, and propagates the failure to the Dify runtime.
  • No partial results are returned; the entire tool invocation is treated as a hard failure that Dify surfaces to users and handles according to agent‑level retry or fallback policies.

Frequently Asked Questions

Does the Dify MCP plugin automatically retry failed tool calls?

No, the plugin itself does not implement automatic retry logic. When McpClient.call_tool detects a server error or when McpClients.execute_tool catches an exception, it immediately raises a wrapped exception. Any retry behavior must be configured at the Dify agent or workflow level, where the orchestration layer can catch the failure and decide whether to retry, switch tools, or degrade gracefully.

What specific error information is included in the exception message?

The exception message includes the server name (e.g., my_server), the MCP method that failed (tools/call), and the complete JSON‑RPC error object returned by the server. For example: my_server - MCP Server tools/call error: {'code': -32601, 'message': 'Method not found'}. This structure allows developers to distinguish between protocol errors (like invalid method names) and application‑specific errors defined by the MCP server.

Can partial tool results be returned when an MCP server error occurs?

No. The error handling logic in utils/mcp_client.py treats any presence of an error field in the JSON‑RPC response as a complete failure. The call_tool method raises an exception immediately upon detecting the error, preventing any partial content from being processed or returned to the Dify agent. This all‑or‑nothing approach ensures data consistency but requires that MCP servers return valid results only when execution is fully successful.

How can I customize error handling for specific MCP servers?

Currently, the plugin uses a uniform error handling strategy across all configured servers through the McpClients class. To implement server‑specific logic (such as custom retry policies or error translation), you would need to extend the McpClient class in utils/mcp_client.py and override the call_tool method, or wrap the execute_tool call in your Dify agent code with custom exception handling that inspects the server name embedded in the error message.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →