VOOZH about

URL: https://deepwiki.com/WordPress/mcp-adapter/4.3-tools-handler

⇱ Tools Handler | WordPress/mcp-adapter | DeepWiki


Loading...
Menu

Tools Handler

This page documents the ToolsHandler class, which processes tools-related MCP requests. The handler implements three MCP methods: tools/list, tools/list/all, and tools/call. It manages tool discovery, execution, error handling, and schema transformation at runtime.

For information about creating tool abilities, see Creating Abilities. For how schemas are transformed during registration, see Schema Transformation. For other handler types, see Resources Handler and Prompts Handler.

Overview

The ToolsHandler class is responsible for processing all tool-related MCP protocol methods. It retrieves tools from the McpServer instance, executes tool callbacks through WordPress abilities, and formats responses according to the MCP specification.

Class Location: includes/Handlers/Tools/ToolsHandler.php20

Dependencies:

Key Responsibilities:

  • List available tools with sanitized data (no PHP callables)
  • Execute tool callbacks with permission checks
  • Handle two error response formats (JSON-RPC vs isError)
  • Unwrap/wrap arguments and results based on schema transformation metadata
  • Attach observability metadata to all responses

Sources: includes/Handlers/Tools/ToolsHandler.php17-37

Handler Methods

The ToolsHandler implements three public methods that correspond to MCP protocol methods:

Method Routing from RequestRouter

Handler Method to MCP Protocol Method Mapping:


Sources: includes/Handlers/Tools/ToolsHandler.php39-210

list_tools()

Method Signature: public function list_tools( int $request_id = 0 ): array

Returns all registered tools with sanitized data (PHP callables removed).

Implementation Flow:


Response Structure:


Key Implementation Details:

LineActionPurpose
47$this->mcp->get_tools()Retrieve all tools from ComponentRegistry
50-52Loop and sanitizeConvert McpTool objects to safe arrays
219-248sanitize_tool_data()Remove PHP callables that can't be JSON-encoded
244-245Exclude callbacksPrevent circular references during JSON encoding
56-59Add metadataInclude component_type and tools_count

Sources: includes/Handlers/Tools/ToolsHandler.php39-61 includes/Handlers/Tools/ToolsHandler.php219-248 tests/Unit/Handlers/ToolsHandlerTest.php20-31

list_all_tools()

Method Signature: public function list_all_tools( int $request_id = 0 ): array

Returns all tools with an additional available: true flag for each tool. This method is identical to list_tools() except for the availability flag.

Response Difference:


Implementation: includes/Handlers/Tools/ToolsHandler.php70-88

The available flag is always set to true since all returned tools are registered and callable. This method exists for future extensibility where tools might have conditional availability.

Sources: includes/Handlers/Tools/ToolsHandler.php63-88 tests/Unit/Handlers/ToolsHandlerTest.php43-52

call_tool()

Method Signature: public function call_tool( array $message, int $request_id = 0 ): array

Executes a tool by name with provided arguments. This is the main entry point for tool execution, which delegates to handle_tool_call() for the actual execution logic.

Method Responsibilities:

  1. Extract and validate parameters from the request message
  2. Call handle_tool_call() to execute the tool
  3. Distinguish between protocol errors and tool execution errors
  4. Convert tool execution errors to MCP isError format
  5. Format successful results into MCP response structure
  6. Handle top-level exceptions during tool execution

Implementation Structure:


Error Format Distinction Logic: includes/Handlers/Tools/ToolsHandler.php118-129

The handler checks failure_reason in the metadata to determine response format:

  • Protocol errors (tool doesn't exist, retrieval failed): Return as JSON-RPC error
  • Tool execution errors (permission denied, execution failed): Convert to isError: true format

Sources: includes/Handlers/Tools/ToolsHandler.php90-210

Tool Call Processing Flow

The handle_tool_call() method contains the core tool execution logic, including permission checks, argument unwrapping, ability execution, and result wrapping.

Detailed Execution Sequence:


Phase-by-Phase Breakdown:

PhaseLinesPurposePossible Outcomes
Tool Lookup263-281Find tool in registrySuccess, not_found error
Ability Retrieval289-310Get WP_Ability from toolSuccess, ability_retrieval_failed error
Schema Unwrapping312-325Unwrap arguments if neededArguments transformed or passed through
Permission Check328-369Verify access rightsAllowed, permission_denied, permission_check_failed
Execution372-400Call ability's executeSuccess, wp_error, execution_failed
Result Wrapping402-421Wrap result if neededResult transformed for MCP response

Sources: includes/Handlers/Tools/ToolsHandler.php250-446

Error Handling

The ToolsHandler implements a sophisticated error handling system that distinguishes between two types of errors, each with its own response format.

Two Error Response Formats

Format Decision Logic:


Protocol Errors (JSON-RPC Format)

Protocol errors occur when the tool itself cannot be found or accessed. These are returned as standard JSON-RPC errors.

Error Types:

failure_reasonCode LocationTrigger ConditionJSON-RPC Code
missing_parameter102-110No tool name provided-32602
not_found266-281Tool doesn't exist in registry-32601
ability_retrieval_failed291-310WP_Error when getting ability-32603

Example Response:


Sources: includes/Handlers/Tools/ToolsHandler.php102-110 includes/Handlers/Tools/ToolsHandler.php266-281 includes/Handlers/Tools/ToolsHandler.php291-310

Tool Execution Errors (isError Format)

Tool execution errors occur during permission checks or tool execution. Per MCP specification, these are returned with isError: true and the error message in the content array.

Error Types:

failure_reasonCode LocationTrigger Condition
permission_denied330-348Permission callback returns false or WP_Error
permission_check_failed350-368Exception thrown in permission callback
wp_error376-399Ability execution returns WP_Error
execution_failed423-444Exception thrown during execution

Example Response:


Error Message Format Compatibility:

The handler supports two error message formats from handle_tool_call():


Conversion Logic: includes/Handlers/Tools/ToolsHandler.php137-141

Sources: includes/Handlers/Tools/ToolsHandler.php116-158 includes/Handlers/Tools/ToolsHandler.php330-368 includes/Handlers/Tools/ToolsHandler.php376-444

Exception Handling

Two levels of exception handling protect against unexpected errors:

1. Inner Try-Catch (in handle_tool_call):

2. Outer Try-Catch (in call_tool):

Sources: includes/Handlers/Tools/ToolsHandler.php191-209 includes/Handlers/Tools/ToolsHandler.php350-368 includes/Handlers/Tools/ToolsHandler.php423-444

Schema Transformation at Runtime

While schemas are transformed during tool registration (see Schema Transformation), the ToolsHandler must handle the runtime unwrapping and wrapping of arguments and results based on transformation metadata.

Transformation Metadata Flags

When SchemaTransformer wraps a flattened schema into an object schema during registration, it sets metadata flags on the McpTool:

Input Schema Metadata:


Output Schema Metadata:


These flags are stored in the tool's metadata and retrieved via McpTool->get_metadata().

Sources: includes/Handlers/Tools/ToolsHandler.php313-314 includes/Handlers/Tools/ToolsHandler.php403

Argument Unwrapping

When: Before calling ability->check_permissions() and ability->execute() includes/Handlers/Tools/ToolsHandler.php312-325

Purpose: Convert MCP object format back to the flattened format expected by the ability

Unwrapping Logic:


Code Implementation: includes/Handlers/Tools/ToolsHandler.php312-319


Example:

Original SchemaMCP ReceivesAfter UnwrapAbility Receives
{type: 'string'}{input: "hello"}"hello""hello"
{type: 'integer'}{input: 42}4242
{type: 'object'}{id: 1, name: "test"}(no unwrap){id: 1, name: "test"}

Sources: includes/Handlers/Tools/ToolsHandler.php312-325 tests/Unit/Handlers/ToolsHandlerTest.php307-362

Result Wrapping

When: After successful ability->execute() includes/Handlers/Tools/ToolsHandler.php402-408

Purpose: Convert flattened result back to MCP object format for consistent response structure

Wrapping Logic:


Code Implementation: includes/Handlers/Tools/ToolsHandler.php402-413


Example:

Original SchemaAbility ReturnsAfter WrapMCP Sends
{type: 'string'}"hello"{result: "hello"}{structuredContent: {result: "hello"}}
{type: 'integer'}42{result: 42}{structuredContent: {result: 42}}
{type: 'object'}{id: 1}(no wrap, but ensure array){structuredContent: {id: 1}}
Any scalar"test"{result: "test"}{structuredContent: {result: "test"}}

Sources: includes/Handlers/Tools/ToolsHandler.php402-413 tests/Unit/Handlers/ToolsHandlerTest.php428-482

Special Case: Empty Input Schema

When an ability has no input schema, and the arguments are empty, the handler passes null instead of an empty array:

Code: includes/Handlers/Tools/ToolsHandler.php321-325


This ensures consistency with abilities that don't expect any input.

Sources: includes/Handlers/Tools/ToolsHandler.php321-325

Response Formatting

The call_tool() method formats successful tool executions into MCP-compliant response structures.

Successful Execution Response

Response Builder Flow:


Standard Response Structure:


Implementation: includes/Handlers/Tools/ToolsHandler.php160-190

Key steps:

  1. Extract _metadata from result before adding to response
  2. Remove _metadata from result so it doesn't appear in content
  3. Create dual representation: content (text) and structuredContent (object)
  4. Add _metadata at response top level

Sources: includes/Handlers/Tools/ToolsHandler.php160-190

Image Response Handling

Tools can return binary image data with special handling:

Image Result Format:


Image Response Format:


Implementation: includes/Handlers/Tools/ToolsHandler.php179-185

Image responses:

  • Do not include structuredContent (only content)
  • Base64-encode the binary data automatically
  • Use provided mimeType or default to image/png

Sources: includes/Handlers/Tools/ToolsHandler.php178-185

Scalar Result Wrapping

When an ability returns a non-array value (scalar), it is automatically wrapped to ensure structuredContent is always an object:

Wrapping Logic: includes/Handlers/Tools/ToolsHandler.php411-413


Examples:

Ability ReturnsstructuredContent
"hello"{"result": "hello"}
42{"result": 42}
true{"result": true}
["key" => "value"]{"key": "value"} (unchanged)

This wrapping happens after schema-based wrapping, ensuring all scalar values are properly contained in objects.

Sources: includes/Handlers/Tools/ToolsHandler.php411-413 tests/Unit/Handlers/ToolsHandlerTest.php428-482

Metadata and Observability

Tool operations include metadata for observability tracking, which is extracted by the RequestRouter before responses are returned to clients.

Metadata Structure

In Handler Response (before extraction):


After Router Extraction:

  • Metadata is used for observability event recording
  • Metadata is removed from client response
  • Clean response is sent to MCP client

Metadata Fields for Tools:

FieldTypePresent WhenDescription
component_typestringAlwaysAlways 'tool'
tool_namestringAlwaysMCP tool name
ability_namestringOn executionWordPress ability name
tools_countintegerOn listNumber of tools returned
failure_reasonstringOn errorError category
error_typestringOn exceptionException class name
error_codestringOn WP_ErrorWordPress error code

Sources: includes/Handlers/Tools/ToolsHandler.php56-59 includes/Handlers/Tools/ToolsHandler.php169-176 includes/Handlers/Tools/ToolsHandler.php276-280

Integration Points

With McpServer

ToolsHandler depends on McpServer to:

With RequestRouter

ToolsHandler methods are called by RequestRouter:

With McpTool

McpTool domain object provides:

Sources: includes/Handlers/Tools/ToolsHandler.php20-37