PluginProbe
ZIP AI – AI Website Builder & AI Agent (Beta) / 0.0.8
ZIP AI – AI Website Builder & AI Agent (Beta) v0.0.8
0.0.10 0.0.9 trunk 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8
zip-ai / lib / mcp-adapter / includes / Cli / McpCommand.php

McpCommand.php in ZIP AI – AI Website Builder & AI Agent (Beta) 0.0.8, at lib/mcp-adapter/includes/Cli/McpCommand.php

188 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP-CLI Command for MCP STDIO Transport
4 *
5 * @package McpAdapter
6 */
7
8 declare( strict_types=1 );
9
10 namespace WP\MCP\Cli;
11
12 use WP\MCP\Core\McpAdapter;
13 use function WP_CLI\Utils\format_items;
14
15 /**
16 * Manage MCP servers via WP-CLI.
17 *
18 * Provides commands to serve MCP servers over STDIO transport for
19 * communication with MCP clients via subprocess.
20 */
21 class McpCommand extends \WP_CLI_Command { // phpcs:ignore
22
23 /**
24 * Serve an MCP server via STDIO transport.
25 *
26 * This command starts an MCP server that communicates via standard input/output
27 * using the JSON-RPC 2.0 protocol. It's designed to be launched as a subprocess
28 * by MCP clients.
29 *
30 * ## OPTIONS
31 *
32 * [--server=<server-id>]
33 * : The ID of the MCP server to serve. If not specified, uses the first available server.
34 *
35 * [--user=<id|login|email>]
36 * : Run as a specific WordPress user for permission checks.
37 * : Without this, runs as unauthenticated (limited capabilities).
38 *
39 * ## EXAMPLES
40 *
41 * # Serve the default MCP server as admin user
42 * wp mcp serve --user=admin
43 *
44 * # Serve a specific server as user with ID 1
45 * wp mcp serve --server=my-mcp-server --user=1
46 *
47 * # Serve without authentication (limited capabilities)
48 * wp mcp serve --server=public-server
49 *
50 * @when after_wp_load
51 * @synopsis [--server=<server-id>] [--user=<id|login|email>]
52 */
53 public function serve( array $args, array $assoc_args ): void {
54
55 // Get the MCP adapter instance
56 $adapter = McpAdapter::instance();
57
58 // Get all registered servers
59 $servers = $adapter->get_servers();
60
61 if ( empty( $servers ) ) {
62 \WP_CLI::error( 'No MCP servers are registered. Please register at least one server first.' );
63 }
64
65 // Determine which server to use
66 $server_id = $assoc_args['server'] ?? null;
67 $server = null;
68
69 if ( $server_id ) {
70 $server = $adapter->get_server( $server_id );
71 if ( ! $server ) {
72 \WP_CLI::error( sprintf( 'Server with ID "%s" not found.', $server_id ) );
73 }
74 } else {
75 // Use the first available server
76 $server = array_values( $servers )[0];
77 $server_id = $server->get_server_id();
78 \WP_CLI::line( sprintf( 'Using server: %s', $server_id ) );
79 }
80
81 // Set user context if specified
82 if ( isset( $assoc_args['user'] ) ) {
83 $user = $this->get_user( $assoc_args['user'] );
84 if ( ! $user ) {
85 \WP_CLI::error( sprintf( 'User "%s" not found.', $assoc_args['user'] ) );
86 }
87
88 wp_set_current_user( $user->ID );
89 \WP_CLI::debug( sprintf( 'Running as user: %s (ID: %d)', $user->user_login, $user->ID ) );
90 } else {
91 \WP_CLI::debug( 'Running without authentication. Some capabilities may be limited.' );
92 }
93
94 // Create and start STDIO server bridge
95 try {
96 \WP_CLI::debug( sprintf( 'Starting STDIO bridge for server: %s', $server_id ) );
97
98 // Create STDIO server bridge
99 $stdio_bridge = new StdioServerBridge( $server );
100
101 // Start serving (this blocks until terminated)
102 $stdio_bridge->serve();
103 } catch ( \RuntimeException $e ) {
104 \WP_CLI::error( $e->getMessage() );
105 } catch ( \Throwable $e ) {
106 \WP_CLI::error( 'Failed to start STDIO bridge: ' . $e->getMessage() );
107 }
108 }
109
110 /**
111 * Get a user by ID, login, or email.
112 *
113 * @param string $user User identifier (ID, login, or email).
114 *
115 * @return \WP_User|false User object or false if not found.
116 */
117 private function get_user( string $user ) {
118 // Try as ID first
119 if ( is_numeric( $user ) ) {
120 return get_user_by( 'id', (int) $user );
121 }
122
123 // Try as login
124 $user_obj = get_user_by( 'login', $user );
125 if ( $user_obj ) {
126 return $user_obj;
127 }
128
129 // Try as email
130 return get_user_by( 'email', $user );
131 }
132
133 /**
134 * List all registered MCP servers.
135 *
136 * ## OPTIONS
137 *
138 * [--format=<format>]
139 * : Render output in a particular format.
140 * ---
141 * default: table
142 * options:
143 * - table
144 * - csv
145 * - json
146 * - yaml
147 * ---
148 *
149 * ## EXAMPLES
150 *
151 * # List all MCP servers
152 * wp mcp list
153 *
154 * # List servers in JSON format
155 * wp mcp list --format=json
156 *
157 * @when after_wp_load
158 * @synopsis [--format=<format>]
159 */
160 public function list( array $args, array $assoc_args ): void {
161 $adapter = McpAdapter::instance();
162
163 $servers = $adapter->get_servers();
164
165 if ( empty( $servers ) ) {
166 \WP_CLI::line( 'No MCP servers registered.' );
167
168 return;
169 }
170
171 $items = array();
172 foreach ( $servers as $server ) {
173 $items[] = array(
174 'ID' => $server->get_server_id(),
175 'Name' => $server->get_server_name(),
176 'Version' => $server->get_server_version(),
177 'Tools' => count( $server->get_tools() ),
178 'Resources' => count( $server->get_resources() ),
179 'Prompts' => count( $server->get_prompts() ),
180 'Description' => $server->get_server_description(),
181 );
182 }
183
184 $format = $assoc_args['format'] ?? 'table';
185 format_items( $format, $items, array( 'ID', 'Name', 'Version', 'Tools', 'Resources', 'Prompts' ) );
186 }
187 }
188