McpTransportBase.php•5.63 kB
<?php //phpcs:ignore
declare(strict_types=1);
namespace Automattic\WordpressMcp\Core;
use WP_Error;
use Automattic\WordpressMcp\RequestMethodHandlers\InitializeHandler;
use Automattic\WordpressMcp\RequestMethodHandlers\ToolsHandler;
use Automattic\WordpressMcp\RequestMethodHandlers\ResourcesHandler;
use Automattic\WordpressMcp\RequestMethodHandlers\PromptsHandler;
use Automattic\WordpressMcp\RequestMethodHandlers\SystemHandler;
/**
* Abstract base class for MCP transport protocols
*
* Contains shared logic between different transport protocols (STDIO/Streamable)
*/
abstract class McpTransportBase {
/**
* The WordPress MCP instance.
*
* @var WpMcp
*/
protected WpMcp $mcp;
/**
* The initialize handler.
*
* @var InitializeHandler
*/
protected InitializeHandler $initialize_handler;
/**
* The tools handler.
*
* @var ToolsHandler
*/
protected ToolsHandler $tools_handler;
/**
* The resources handler.
*
* @var ResourcesHandler
*/
protected ResourcesHandler $resources_handler;
/**
* The prompts handler.
*
* @var PromptsHandler
*/
protected PromptsHandler $prompts_handler;
/**
* The system handler.
*
* @var SystemHandler
*/
protected SystemHandler $system_handler;
/**
* Initialize the shared handlers
*
* @param WpMcp $mcp The WordPress MCP instance.
*/
public function __construct( WpMcp $mcp ) {
$this->mcp = $mcp;
// Initialize handlers.
$this->initialize_handler = new InitializeHandler();
$this->tools_handler = new ToolsHandler( $mcp );
$this->resources_handler = new ResourcesHandler( $mcp );
$this->prompts_handler = new PromptsHandler( $mcp );
$this->system_handler = new SystemHandler();
}
/**
* Check if MCP is enabled in settings
*
* @return bool
*/
protected function is_mcp_enabled(): bool {
$options = get_option( 'wordpress_mcp_settings', array() );
return isset( $options['enabled'] ) && $options['enabled'];
}
/**
* Route a request to the appropriate handler
*
* @param string $method The MCP method name.
* @param array $params The request parameters.
* @param int $request_id The request ID (for JSON-RPC).
* @return array
*/
protected function route_request( string $method, array $params, int $request_id = 0 ): array {
try {
$result = match ( $method ) {
'initialize' => $this->initialize_handler->handle(),
'init' => $this->initialize_handler->handle(),
'ping' => $this->system_handler->ping(),
'tools/list' => $this->tools_handler->list_tools(),
'tools/list/all' => $this->tools_handler->list_all_tools(),
'tools/call' => $this->tools_handler->call_tool( $params ),
'resources/list' => $this->add_cursor_compatibility( $this->resources_handler->list_resources() ),
'resources/templates/list' => $this->add_cursor_compatibility( $this->resources_handler->list_resource_templates() ),
'resources/read' => $this->resources_handler->read_resource( $params ),
'resources/subscribe' => $this->resources_handler->subscribe_resource( $params ),
'resources/unsubscribe' => $this->resources_handler->unsubscribe_resource( $params ),
'prompts/list' => $this->prompts_handler->list_prompts(),
'prompts/get' => $this->handle_prompt_get( $params ),
'logging/setLevel' => $this->system_handler->set_logging_level( $params ),
'completion/complete' => $this->system_handler->complete(),
'roots/list' => $this->system_handler->list_roots(),
default => $this->create_method_not_found_error( $method, $request_id ),
};
return $result;
} catch ( \Throwable $exception ) {
return $this->handle_exception( $exception, $request_id );
}
}
/**
* Add nextCursor for backward compatibility with existing API
*
* @param array $result The result array.
* @return array
*/
private function add_cursor_compatibility( array $result ): array {
if ( ! isset( $result['nextCursor'] ) ) {
$result['nextCursor'] = '';
}
return $result;
}
/**
* Handle prompt get requests with special result structure
*
* @param array $params Request parameters.
* @return array
*/
private function handle_prompt_get( array $params ): array {
$result = $this->prompts_handler->get_prompt( $params );
// Handle the nested result structure from the handler.
if ( isset( $result['result'] ) ) {
return $result['result'];
}
return $result;
}
/**
* Create a method not found error
*
* @param string $method The method that was not found.
* @param int $request_id The request ID.
* @return array
*/
abstract protected function create_method_not_found_error( string $method, int $request_id ): array;
/**
* Handle exceptions that occur during request processing
*
* @param \Throwable $exception The exception.
* @param int $request_id The request ID.
* @return array
*/
abstract protected function handle_exception( \Throwable $exception, int $request_id ): array;
/**
* Format a successful response
*
* @param array $result The result data.
* @param int $request_id The request ID.
* @return mixed
*/
abstract protected function format_success_response( array $result, int $request_id = 0 ): mixed;
/**
* Format an error response
*
* @param array $error The error data.
* @param int $request_id The request ID.
* @return mixed
*/
abstract protected function format_error_response( array $error, int $request_id = 0 ): mixed;
/**
* Check if the user has permission to access the MCP API
*
* @return bool|WP_Error
*/
abstract public function check_permission(): WP_Error|bool;
}