44
55use WP_CLI ;
66use WP_CLI_Command ;
7+ use WP_Community_Events ;
8+ use WP_Error ;
79
810/**
911 *
@@ -44,6 +46,46 @@ class AiCommand extends WP_CLI_Command {
4446 */
4547 public function __invoke ( $ args , $ assoc_args ) {
4648 $ server = new MCP \Server ();
49+ $ client = new MCP \Client ($ server );
50+
51+ $ this ->register_tools ($ server , $ client );
52+
53+ $ this ->register_resources ($ server );
54+
55+ $ result = $ client ->call_ai_service_with_prompt ( $ args [0 ] );
56+
57+ WP_CLI ::success ( $ result );
58+ }
59+
60+ // Register tools for AI processing
61+ private function register_tools ($ server , $ client ) {
62+ $ server ->register_tool (
63+ [
64+ 'name ' => 'list_tools ' ,
65+ 'description ' => 'Lists all available tools with their descriptions. ' ,
66+ 'inputSchema ' => [
67+ 'type ' => 'object ' , // Object type for input
68+ 'properties ' => [
69+ 'placeholder ' => [
70+ 'type ' => 'integer ' ,
71+ 'description ' => '' ,
72+ ]
73+ ],
74+ 'required ' => [], // No required fields
75+ ],
76+ 'callable ' => function () use ($ server ) {
77+ // Get all capabilities
78+ $ capabilities = $ server ->get_capabilities ();
79+
80+ // Prepare a list of tools with their descriptions
81+ $ tool_list = 'Return this to the user as a bullet list with each tool name and description on a new line. \n\n ' ;
82+ $ tool_list .= print_r ($ capabilities ['methods ' ], true );
83+
84+ // Return the formatted string of tools with descriptions
85+ return $ tool_list ;
86+ },
87+ ]
88+ );
4789
4890 $ map_rest_to_mcp = new MapRESTtoMCP (
4991 require __DIR__ . '/../settings/rest-routes.php '
@@ -89,12 +131,6 @@ public function __invoke( $args, $assoc_args ) {
89131 ]
90132 );
91133
92- $ client = new MCP \Client ( $ server );
93- $ result = $ client ->call_ai_service_with_prompt ( $ args [0 ] );
94-
95- WP_CLI ::success ( $ result );
96- return ;
97-
98134 $ server ->register_tool (
99135 [
100136 'name ' => 'calculate_total ' ,
@@ -122,6 +158,37 @@ public function __invoke( $args, $assoc_args ) {
122158 ]
123159 );
124160
161+
162+
163+ // Register tool to retrieve last N posts in JSON format.
164+ $ server ->register_tool ([
165+ 'name ' => 'list_posts ' ,
166+ 'description ' => 'Retrieves the last N posts. ' ,
167+ 'inputSchema ' => [
168+ 'type ' => 'object ' ,
169+ 'properties ' => [
170+ 'count ' => [
171+ 'type ' => 'integer ' ,
172+ 'description ' => 'The number of posts to retrieve. ' ,
173+ ],
174+ ],
175+ 'required ' => ['count ' ],
176+ ],
177+ 'callable ' => function ($ params ) {
178+ $ query = new \WP_Query ([
179+ 'posts_per_page ' => $ params ['count ' ],
180+ 'post_status ' => 'publish ' ,
181+ ]);
182+ $ posts = [];
183+ while ($ query ->have_posts ()) {
184+ $ query ->the_post ();
185+ $ posts [] = ['title ' => get_the_title (), 'content ' => get_the_content ()];
186+ }
187+ wp_reset_postdata ();
188+ return $ posts ;
189+ },
190+ ]);
191+
125192 $ server ->register_tool (
126193 [
127194 'name ' => 'greet ' ,
@@ -142,29 +209,6 @@ public function __invoke( $args, $assoc_args ) {
142209 ]
143210 );
144211
145- // Register resources:
146- $ server ->register_resource (
147- [
148- 'name ' => 'users ' ,
149- 'uri ' => 'data://users ' ,
150- 'description ' => 'List of users ' ,
151- 'mimeType ' => 'application/json ' ,
152- 'dataKey ' => 'users ' , // This tells getResourceData() to look in the $data array
153- ]
154- );
155-
156- $ server ->register_resource (
157- [
158- 'name ' => 'product_catalog ' ,
159- 'uri ' => 'file://./products.json ' ,
160- 'description ' => 'Product catalog ' ,
161- 'mimeType ' => 'application/json ' ,
162- 'filePath ' => './products.json ' , // This tells getResourceData() to read from a file
163- ]
164- );
165-
166- $ client = new MCP \Client ( $ server );
167-
168212 $ server ->register_tool (
169213 [
170214 'name ' => 'generate_image ' ,
@@ -185,9 +229,114 @@ public function __invoke( $args, $assoc_args ) {
185229 ]
186230 );
187231
188- $ result = $ client ->call_ai_service_with_prompt ( $ args [0 ] );
232+ $ server ->register_tool (
233+ [
234+ 'name ' => 'fetch_wp_community_events ' ,
235+ 'description ' => 'Fetches upcoming WordPress community events near a specified city or the user \'s current location. If no events are found in the exact location, nearby events within a specific radius will be considered. ' ,
236+ 'inputSchema ' => [
237+ 'type ' => 'object ' ,
238+ 'properties ' => [
239+ 'location ' => [
240+ 'type ' => 'string ' ,
241+ 'description ' => 'City name or "near me" for auto-detected location. If no events are found in the exact location, the tool will also consider nearby events within a specified radius (default: 100 km). ' ,
242+ ],
243+ ],
244+ 'required ' => [ 'location ' ], // We only require the location
245+ ],
246+ 'callable ' => function ( $ params ) {
247+ // Default user ID is 0
248+ $ user_id = 0 ;
189249
190- WP_CLI ::success ( $ result );
250+ // Get the location from the parameters (already supplied in the prompt)
251+ $ location_input = strtolower ( trim ( $ params ['location ' ] ) );
252+
253+ // Manually include the WP_Community_Events class if it's not loaded
254+ if ( ! class_exists ( 'WP_Community_Events ' ) ) {
255+ require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php ' ;
256+ }
257+
258+ // Determine location for the WP_Community_Events class
259+ $ location = null ;
260+ if ( $ location_input !== 'near me ' ) {
261+ // Provide city name (WP will resolve coordinates)
262+ $ location = [
263+ 'description ' => $ location_input ,
264+ ];
265+ }
266+
267+ // Instantiate WP_Community_Events with user ID (0) and optional location
268+ $ events_instance = new WP_Community_Events ( $ user_id , $ location );
269+
270+ // Get events from WP_Community_Events
271+ $ events = $ events_instance ->get_events ($ location_input );
272+
273+ // Check for WP_Error
274+ if ( is_wp_error ( $ events ) ) {
275+ return [ 'error ' => $ events ->get_error_message () ];
276+ }
277+
278+ // If no events found
279+ if ( empty ( $ events ['events ' ] ) ) {
280+ return [ 'message ' => 'No events found near ' . ( $ location_input === 'near me ' ? 'your location ' : $ location_input ) ];
281+ }
282+
283+ // Format and return the events correctly
284+ $ formatted_events = array_map ( function ( $ event ) {
285+ // Log event details to ensure properties are accessible
286+ error_log ( 'Event details: ' . print_r ( $ event , true ) );
287+
288+ // Initialize a formatted event string
289+ $ formatted_event = '' ;
191290
291+ // Format event title
292+ if ( isset ( $ event ['title ' ] ) ) {
293+ $ formatted_event .= $ event ['title ' ] . "\n" ;
294+ }
295+
296+ // Format the date nicely
297+ $ formatted_event .= ' - Date: ' . ( isset ( $ event ['date ' ] ) ? date ( 'F j, Y g:i A ' , strtotime ( $ event ['date ' ] ) ) : 'No date available ' ) . "\n" ;
298+
299+ // Format the location
300+ if ( isset ( $ event ['location ' ]['location ' ] ) ) {
301+ $ formatted_event .= ' - Location: ' . $ event ['location ' ]['location ' ] . "\n" ;
302+ }
303+
304+ // Format the event URL
305+ $ formatted_event .= isset ( $ event ['url ' ] ) ? ' - URL: ' . $ event ['url ' ] . "\n" : '' ;
306+
307+ return $ formatted_event ;
308+ }, $ events ['events ' ] );
309+
310+ // Combine the formatted events into a single string
311+ $ formatted_events_output = implode ("\n" , $ formatted_events );
312+
313+ // Return the formatted events string
314+ return [
315+ 'message ' => "OK. I found " . count ($ formatted_events ) . " WordPress events near " . ( $ location_input === 'near me ' ? 'your location ' : $ location_input ) . ": \n\n" . $ formatted_events_output
316+ ];
317+ },
318+ ]
319+ );
320+ }
321+
322+ // Register resources for AI access
323+ private function register_resources ($ server ) {
324+ // Register Users resource
325+ $ server ->register_resource ([
326+ 'name ' => 'users ' ,
327+ 'uri ' => 'data://users ' ,
328+ 'description ' => 'List of users ' ,
329+ 'mimeType ' => 'application/json ' ,
330+ 'dataKey ' => 'users ' , // Data will be fetched from 'users'
331+ ]);
332+
333+ // Register Product Catalog resource
334+ $ server ->register_resource ([
335+ 'name ' => 'product_catalog ' ,
336+ 'uri ' => 'file://./products.json ' ,
337+ 'description ' => 'Product catalog ' ,
338+ 'mimeType ' => 'application/json ' ,
339+ 'filePath ' => './products.json ' , // Data will be fetched from products.json
340+ ]);
192341 }
193342}
0 commit comments