Handling JSON-RPC Error Codes -32001 and -32601 in MCP list_tools

The McpClient class catches JSON-RPC error codes -32001 and -32601 to gracefully handle MCP servers that do not implement the tools/list method, returning an empty list instead of raising a fatal exception.

When integrating with the Model Context Protocol (MCP) using the junjiem/dify-plugin-tools-mcp_sse repository, handling diverse server capabilities is crucial for plugin stability. The list_tools method in utils/mcp_client.py specifically manages JSON-RPC error codes -32001 and -32601 to ensure compatibility with servers that may not support tool enumeration, allowing the Dify plugin to continue operating without interruption.

Understanding JSON-RPC Error Codes -32001 and -32601

The Model Context Protocol uses JSON-RPC 2.0 for communication between clients and servers. When the list_tools method calls the tools/list endpoint, two specific error codes indicate that the server does not support this functionality:

  • -32601: Method not found — The standard JSON-RPC 2.0 error indicating the requested method does not exist on the server.
  • -32001: Server error — unsupported method — A custom error code used by some MCP implementations to signal that the method is not implemented.

Both codes communicate the same practical reality: the MCP server does not expose a tools/list endpoint.

Implementation in McpClient.list_tools

In utils/mcp_client.py, the McpClient.list_tools method implements explicit error handling for these codes. When the method receives a JSON-RPC error response, it checks the error code before deciding whether to raise an exception or return an empty list.


# utils/mcp_client.py – list_tools method

def list_tools(self) -> list[dict]:
    request = {
        "jsonrpc": "2.0",
        "id": self._get_next_id(),
        "method": "tools/list",
        "params": {}
    }
    response = self.send_message(request)
    if "error" in response:
        error = response["error"]
        # -32001: Unsupported method

        # -32601: Method not found

        if error["code"] in {-32001, -32601}:
            return []                     # ← graceful fallback

        raise Exception(f"{self.name} - MCP Server tools/list error: {error}")
    tools = response.get("result", {}).get("tools", [])
    logger.info(f"{self.name} - MCP Server tools/list: {tools}")
    return tools

(Source: utils/mcp_client.py)

This implementation ensures that missing functionality is treated as "no tools available" rather than a critical failure.

Why Graceful Degradation Matters

Handling JSON-RPC error codes -32001 and -32601 specifically in list_tools provides three critical benefits for the Dify plugin:

Compatibility across server implementations. MCP servers vary in their capabilities. Some minimal or legacy implementations may not support the tools/list method. By catching these specific error codes, the client accommodates servers that predate or omit this functionality without requiring version detection logic.

Operational robustness. The plugin can continue executing even when connected to servers lacking tool enumeration. This prevents the entire Dify workflow from failing due to a single unsupported method, allowing other operations like resource listing or prompt retrieval to proceed normally.

Semantic clarity in error handling. Distinguishing between "method not supported" and genuine server errors (network failures, malformed JSON, authentication issues) allows the system to surface real problems while silently ignoring expected capability gaps. This prevents false positives in error monitoring and logging.

Practical Usage Example

When using the McpClients wrapper in your Dify plugin integration, the error handling operates transparently. The following example demonstrates how list_tools behaves safely against servers with varying capabilities:

from utils.mcp_client import McpClients

# Example servers configuration (JSON string or dict)

servers_cfg = {
    "mcpServers": {
        "demo": {
            "url": "https://demo.mcp.example.com",
            "transport": "sse"
        }
    }
}

# Initialise the client wrapper

clients = McpClients(servers_cfg)

# Fetch the list of tools; missing 'tools/list' on a server yields [] not an exception

tools = clients.fetch_tools()
print("Available tools:", tools)   # → [] if the server does not support tools/list

If the remote MCP server implements tools/list, the tools variable contains the full list of tool descriptors. If the server returns JSON-RPC error codes -32001 or -32601, the method returns an empty list without interrupting execution.

Summary

  • JSON-RPC error codes -32001 and -32601 indicate that an MCP server does not support the tools/list method, either through standard "method not found" semantics or custom "unsupported method" signaling.
  • The list_tools method in utils/mcp_client.py explicitly checks for these codes to distinguish between missing functionality and genuine server errors.
  • Graceful degradation allows the Dify plugin to return an empty tool list instead of raising exceptions, ensuring compatibility with minimal or legacy MCP servers while maintaining operational stability.

Frequently Asked Questions

What is the difference between JSON-RPC error code -32601 and -32001?

JSON-RPC error code -32601 is the standard "Method not found" error defined in the JSON-RPC 2.0 specification, indicating the requested method does not exist on the server. Error code -32001 is a custom server error used by some MCP implementations to specifically signal that the method is unsupported or not implemented. Both communicate the same practical outcome for list_tools: the server cannot enumerate available tools.

Why doesn't the client raise an exception when these error codes are returned?

The client treats these specific error codes as capability indicators rather than failures. Since MCP servers vary in functionality, the absence of a tools/list endpoint is considered a valid server state indicating the server has no tools to list or does not support tool enumeration. Raising an exception would break workflows for servers that simply lack this optional feature, whereas returning an empty list allows the plugin to continue operating.

Where is the error handling logic implemented in the codebase?

The error handling logic resides in the list_tools method of the McpClient class within utils/mcp_client.py (around lines 50-66). This method constructs the JSON-RPC request for tools/list, sends it to the remote server, and inspects the response for error codes -32001 and -32601 before deciding whether to return an empty list or raise an exception.

Can this pattern be applied to other MCP methods like resources or prompts?

Yes, the same graceful degradation pattern can and should be applied to other optional MCP methods such as resources/list or prompts/list. By checking for error codes -32001 and -32601 (or similar capability-related errors), clients can distinguish between "server does not support this feature" and "server encountered an error," allowing the application to adapt its behavior accordingly without failing.

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 →