diff --git a/ai-command.php b/ai-command.php index 4a2c6d9..d959925 100644 --- a/ai-command.php +++ b/ai-command.php @@ -14,4 +14,5 @@ WP_CLI::add_command( 'ai', AiCommand::class ); WP_CLI::add_command( 'mcp prompt', AiCommand::class ); +WP_CLI::add_command( 'mcp', McpCommand::class ); WP_CLI::add_command( 'mcp server', McpServerCommand::class ); diff --git a/src/AiCommand.php b/src/AiCommand.php index dc38b8e..58c3ee4 100644 --- a/src/AiCommand.php +++ b/src/AiCommand.php @@ -7,7 +7,6 @@ use McpWp\AiCommand\MCP\Client; use McpWp\AiCommand\Utils\CliLogger; use McpWp\AiCommand\Utils\McpConfig; -use McpWp\MCP\Server; use McpWp\MCP\Servers\WordPress\WordPress; use WP_CLI; use WP_CLI\Utils; diff --git a/src/MCP/ProxySession.php b/src/MCP/ProxySession.php new file mode 100644 index 0000000..a78b390 --- /dev/null +++ b/src/MCP/ProxySession.php @@ -0,0 +1,115 @@ +getRequest(); + $actual_request = $request->getRequest(); + $method = $actual_request->method; + + $this->logger->info( 'Proxying request: ' . json_encode( $actual_request ) ); + + $result = null; + + if ( ! isset( $this->client_session ) ) { + $client = new Client( $this->logger ); + $this->client_session = $client->connect( + $this->url + ); + } + + switch ( get_class( $actual_request ) ) { + case InitializeRequest::class: + $result = $this->client_session->sendRequest( $actual_request, InitializeResult::class ); + break; + case SubscribeRequest::class: + case UnsubscribeRequest::class: + case PingRequest::class: + $result = $this->client_session->sendRequest( $actual_request, EmptyResult::class ); + break; + case ListResourcesRequest::class: + $result = $this->client_session->sendRequest( $actual_request, ListResourcesResult::class ); + break; + case ListToolsRequest::class: + $result = $this->client_session->sendRequest( $actual_request, ListToolsResult::class ); + break; + case CallToolRequest::class: + $result = $this->client_session->sendRequest( $actual_request, CallToolResult::class ); + break; + case ReadResourceRequest::class: + $result = $this->client_session->sendRequest( $actual_request, ReadResourceResult::class ); + break; + case ListPromptsRequest::class: + $result = $this->client_session->sendRequest( $actual_request, ListPromptsResult::class ); + break; + case GetPromptRequest::class: + $result = $this->client_session->sendRequest( $actual_request, GetPromptResult::class ); + break; + case CompleteRequest::class: + $result = $this->client_session->sendRequest( $actual_request, CompleteResult::class ); + break; + } + + if ( null === $result ) { + throw new InvalidArgumentException( "Unhandled proxied request for method: $method / " . get_class( $actual_request ) ); + } + + $responder->sendResponse( $result ); + } +} diff --git a/src/McpCommand.php b/src/McpCommand.php new file mode 100644 index 0000000..a98083e --- /dev/null +++ b/src/McpCommand.php @@ -0,0 +1,99 @@ + + * : Name of an existing server to proxy requests to. + * + * ## EXAMPLES + * + * # Add server from URL. + * $ wp mcp server add "mywpserver" "https://example.com/wp-json/mcp/v1/mcp" + * Success: Server added. + * + * # Proxy requests to server + * $ wp mcp proxy "mywpserver" + * + * @when before_wp_load + * + * @param string[] $args Indexed array of positional arguments. + */ + public function proxy( $args ): void { + $server = $this->get_config()->get_server( $args[0] ); + + if ( null === $server ) { + WP_CLI::error( 'Server does not exist.' ); + return; + } + + $url = $server['server']; + + if ( ! str_starts_with( $url, 'http://' ) && ! str_starts_with( $url, 'https://' ) ) { + WP_CLI::error( 'Server is not using HTTP transport.' ); + return; + } + + $logger = new CliLogger(); + + $server = new Server( $args[0], $logger ); + + try { + $transport = StdioServerTransport::create(); + + $proxy_session = new ProxySession( + $url, + $transport, + $server->createInitializationOptions(), + $logger + ); + + $server->setSession( $proxy_session ); + + $proxy_session->registerHandlers( $server->getHandlers() ); + $proxy_session->registerNotificationHandlers( $server->getNotificationHandlers() ); + + $proxy_session->start(); + + $logger->info( 'Server started' ); + + } catch ( Exception $e ) { + $logger->error( 'Proxy error: ' . $e->getMessage() ); + } finally { + if ( isset( $proxy_session ) ) { + $proxy_session->stop(); + } + if ( isset( $transport ) ) { + $transport->stop(); + } + } + } + + /** + * Returns an McpConfig instance. + * + * @return McpConfig Config instance. + */ + protected function get_config(): McpConfig { + return new McpConfig(); + } +}