mirror of
https://hk.gh-proxy.com/https://github.com/mcp-wp/ai-command.git
synced 2025-10-03 10:10:57 +08:00
Add mcp proxy command (#65)
This commit is contained in:
parent
87fc7b6189
commit
1f540698bb
4 changed files with 215 additions and 1 deletions
|
@ -14,4 +14,5 @@ if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
|
|||
|
||||
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 );
|
||||
|
|
|
@ -7,7 +7,6 @@ use McpWp\AiCommand\AI\AiClient;
|
|||
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;
|
||||
|
|
115
src/MCP/ProxySession.php
Normal file
115
src/MCP/ProxySession.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace McpWp\AiCommand\MCP;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Mcp\Client\ClientSession;
|
||||
use Mcp\Server\InitializationOptions;
|
||||
use Mcp\Server\ServerSession;
|
||||
use Mcp\Server\Transport\Transport;
|
||||
use Mcp\Shared\RequestResponder;
|
||||
use Mcp\Types\CallToolRequest;
|
||||
use Mcp\Types\CallToolResult;
|
||||
use Mcp\Types\ClientRequest;
|
||||
use Mcp\Types\CompleteRequest;
|
||||
use Mcp\Types\CompleteResult;
|
||||
use Mcp\Types\EmptyResult;
|
||||
use Mcp\Types\GetPromptRequest;
|
||||
use Mcp\Types\GetPromptResult;
|
||||
use Mcp\Types\InitializeRequest;
|
||||
use Mcp\Types\InitializeResult;
|
||||
use Mcp\Types\ListPromptsRequest;
|
||||
use Mcp\Types\ListPromptsResult;
|
||||
use Mcp\Types\ListResourcesRequest;
|
||||
use Mcp\Types\ListResourcesResult;
|
||||
use Mcp\Types\ListToolsRequest;
|
||||
use Mcp\Types\ListToolsResult;
|
||||
use Mcp\Types\PingRequest;
|
||||
use Mcp\Types\ReadResourceRequest;
|
||||
use Mcp\Types\ReadResourceResult;
|
||||
use Mcp\Types\SubscribeRequest;
|
||||
use Mcp\Types\UnsubscribeRequest;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
||||
/**
|
||||
* ProxySession to pass messages from STDIO to an HTTP MCP server.
|
||||
*/
|
||||
class ProxySession extends ServerSession {
|
||||
protected ?ClientSession $client_session;
|
||||
|
||||
public function __construct(
|
||||
protected readonly string $url,
|
||||
Transport $transport,
|
||||
InitializationOptions $init_options,
|
||||
?LoggerInterface $logger = null
|
||||
) {
|
||||
parent::__construct(
|
||||
$transport,
|
||||
$init_options,
|
||||
$logger
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming requests. If it's the initialize request, handle it specially.
|
||||
* Otherwise, ensure initialization is complete before handling other requests.
|
||||
*
|
||||
* @param ClientRequest $request The incoming client request.
|
||||
* @param callable $respond The responder callable.
|
||||
*/
|
||||
public function handleRequest( RequestResponder $responder ): void {
|
||||
$request = $responder->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 );
|
||||
}
|
||||
}
|
99
src/McpCommand.php
Normal file
99
src/McpCommand.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace McpWp\AiCommand;
|
||||
|
||||
use Exception;
|
||||
use Mcp\Server\Server;
|
||||
use Mcp\Server\Transport\StdioServerTransport;
|
||||
use McpWp\AiCommand\MCP\ProxySession;
|
||||
use McpWp\AiCommand\Utils\CliLogger;
|
||||
use McpWp\AiCommand\Utils\McpConfig;
|
||||
use WP_CLI;
|
||||
use WP_CLI_Command;
|
||||
|
||||
/**
|
||||
* MCP command.
|
||||
*
|
||||
* Manage MCP servers for use with WP-CLI and proxy requests to servers using the HTTP transport.
|
||||
*/
|
||||
class McpCommand extends WP_CLI_Command {
|
||||
/**
|
||||
* Proxy MCP requests to a given server.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <server>
|
||||
* : 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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue