Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 586
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Prompts
0.00% covered (danger)
0.00%
0 / 586
0.00% covered (danger)
0.00%
0 / 7
3422
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 register_guided_product_creation_prompt
0.00% covered (danger)
0.00%
0 / 91
0.00% covered (danger)
0.00%
0 / 1
56
 register_prompt_description
0.00% covered (danger)
0.00%
0 / 112
0.00% covered (danger)
0.00%
0 / 1
156
 register_prompt_categories
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 1
72
 register_prompt_tags
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 1
72
 register_prompt_brands
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 1
72
 register_smart_product_prompt
0.00% covered (danger)
0.00%
0 / 114
0.00% covered (danger)
0.00%
0 / 1
182
1<?php
2/**
3 * This class manage the Abilities managed like Prompts
4 *
5 * @package BLU\Abilities
6 */
7
8namespace BLU\Abilities;
9
10use WP_Error;
11
12/**
13 * The class
14 */
15class Prompts {
16    /**
17     * Constructor - registers WooCommerce product abilities if WooCommerce is active.
18     */
19    public function __construct() {
20        if ( ! class_exists( 'WooCommerce' ) ) {
21            return;
22        }
23
24        $this->register_guided_product_creation_prompt();
25        $this->register_prompt_description();
26        $this->register_smart_product_prompt();
27        $this->register_prompt_categories();
28        $this->register_prompt_tags();
29        $this->register_prompt_brands();
30    }
31
32    /**
33     * Create a prompt to instruct AI all step required to add a new WooCommerce Product
34     *
35     * @return void
36     */
37    private function register_guided_product_creation_prompt() {
38        blu_register_ability(
39            'blu/guided-product-creation-prompt',
40            array(
41                'label'               => 'Guided Product Creation',
42                'description'         => 'Step-by-step wizard that guides the merchant through enriching and publishing a WooCommerce product. Calls blu tools directly for categories, tags, descriptions, and variations — no sub-prompts.',
43                'category'            => 'blu-mcp',
44                'input_schema'        => array(
45                    'type'       => 'object',
46                    'properties' => array(
47                        'product_name'  => array(
48                            'type'        => 'string',
49                            'description' => 'The name of the product to create.',
50                        ),
51                        'price'         => array(
52                            'type'        => 'string',
53                            'description' => 'Regular price (e.g. 29.99). If omitted, the assistant will suggest a market price.',
54                        ),
55                        'extra_details' => array(
56                            'type'        => 'string',
57                            'description' => 'Any additional product context the merchant already has (type, material, specs, etc.).',
58                        ),
59                    ),
60                    'required'   => array( 'product_name' ),
61                ),
62                'execute_callback'    => function ( $input ) {
63
64                    $product_name  = sanitize_text_field( $input['product_name'] );
65                    $price         = isset( $input['price'] ) && '' !== $input['price'] && is_numeric( $input['price'] ) ? (float) $input['price'] : null;
66                    $extra_details = sanitize_textarea_field( isset( $input['extra_details'] ) ? $input['extra_details'] : '' );
67
68                    $price_display = null !== $price
69                        ? wc_price( $price, array( 'in_span' => false ) )
70                        : '(not set — you will suggest one)';
71
72                    $product_name_safe = addslashes( $product_name );
73                    $price_safe        = addslashes( $price_display );
74                    $details_safe      = addslashes( $extra_details );
75                    $system_text       = include_once __DIR__ . '/../instructions/product-full-flow.php';
76                    $price_line        = null !== $price
77                        ? sprintf( 'price: **$%.2f**', $price )
78                        : 'price: **not set yet** — I\'ll suggest one';
79
80                    $intro_text = sprintf(
81                        "Let's add **%s** (%s) to your WooCommerce store!\n\n" .
82                        'How would you like to proceed?\n\n' .
83                        "**A)** Add the product now with only the details you provided.\n" .
84                        "**B)** Enrich the product first — I'll suggest categories, tags, " .
85                        "description, and/or variations.\n\n" .
86                        'Which option would you prefer?',
87                        esc_html( $product_name ),
88                        $price_line
89                    );
90
91                    return array(
92                        'messages' => array(
93                            array(
94                                'role'    => 'user',
95                                'content' => array(
96                                    'type'        => 'text',
97                                    'text'        => $system_text,
98                                    'annotations' => array(
99                                        'audience' => array( 'assistant' ),
100                                        'priority' => 1.0,
101                                    ),
102                                ),
103                            ),
104                            array(
105                                'role'    => 'assistant',
106                                'content' => array(
107                                    'type'        => 'text',
108                                    'text'        => $intro_text,
109                                    'annotations' => array(
110                                        'audience' => array( 'user' ),
111                                        'priority' => 0.9,
112                                    ),
113                                ),
114                            ),
115                        ),
116                    );
117                },
118                'permission_callback' => function () {
119                    return current_user_can( 'edit_posts' );
120                },
121                'meta'                => array(
122                    'annotations' => array(
123                        'audience'     => array( 'user', 'assistant' ),
124                        'priority'     => 1.0,
125                        'lastModified' => gmdate( 'c' ),
126                    ),
127                    'mcp'         => array(
128                        'public' => true,
129                        'type'   => 'prompt',
130                    ),
131                ),
132            )
133        );
134    }
135
136    /**
137     * Create a prompt to instruct the AI the steps to follow to generate/improve a new  long and short description
138     *
139     * @return void
140     */
141    private function register_prompt_description() {
142        blu_register_ability(
143            'blu/suggest-product-description',
144            array(
145                'label'               => 'Guided Product Description Generation',
146                'category'            => 'blu-mcp',
147                'description'         => 'Improves or generates the description and short description for a WooCommerce product. When a product ID is provided the existing content, categories and tags are used as context. Without an ID it generates descriptions from scratch using the product name.',
148                'input_schema'        => array(
149                    'type'       => 'object',
150                    'properties' => array(
151                        'product_id'   => array(
152                            'type'        => 'integer',
153                            'description' => 'Existing WooCommerce product ID. When provided the prompt loads the product and uses its data as context.',
154                            'minimum'     => 1,
155                        ),
156                        'product_name' => array(
157                            'type'        => 'string',
158                            'description' => 'Product name — required when product_id is not supplied.',
159                        ),
160                        'tone'         => array(
161                            'type'        => 'string',
162                            'description' => 'Writing tone for the generated descriptions.',
163                            'enum'        => array( 'formal', 'technical', 'empathetic', 'persuasive' ),
164                            'default'     => 'formal',
165                        ),
166                    ),
167                ),
168                'execute_callback'    => function ( $input ) {
169                    $product_id   = isset( $input['product_id'] ) ? (int) $input['product_id'] : null;
170                    $product_name = sanitize_text_field( isset( $input['product_name'] ) ? $input['product_name'] : '' );
171                    $tone         = isset( $input['tone'] ) ? $input['tone'] : '';
172                    $tone         = in_array(
173                        $tone,
174                        array(
175                            'formal',
176                            'technical',
177                            'empathetic',
178                            'persuasive',
179                        ),
180                        true
181                    )
182                        ? $input['tone']
183                        : 'formal';
184
185                    $has_id = null !== $product_id && $product_id > 0;
186                    $mode   = $has_id ? 'improve' : 'create';
187
188                    $product_id_safe   = $has_id ? (string) $product_id : '(none)';
189                    $product_name_safe = addslashes( $product_name );
190                    $tone_safe         = addslashes( $tone );
191                    $mode_safe         = $mode;
192                    $instruction       = include_once __DIR__ . '/../instructions/product-description-improvement.php';
193
194                    if ( $has_id ) {
195                        $intro_text = sprintf(
196                            "Let's improve the descriptions for product **#%d**.\n\n" .
197                            "I'll load the current content, categories, and tags — then use them as context to generate better copy.\n\n" .
198                            "**Tone:** %s%s\n\n" .
199                            'Loading product data now…',
200                            $product_id,
201                            ucfirst( $tone ),
202                            'formal' === $tone ? ' *(default)*' : ''
203                        );
204                    } else {
205                        $intro_text = sprintf(
206                            "Let's write descriptions for **%s**.\n\n" .
207                            "Since no product ID was provided, I'll generate fresh copy from scratch.\n\n" .
208                            "**Tone:** %s%s\n\n" .
209                            "Do you have any categories or tags you'd like me to factor in? " .
210                            '*(Reply with them or say \"none\" to skip.)*',
211                            ! empty( $product_name ) ? esc_html( $product_name ) : 'your product',
212                            ucfirst( $tone ),
213                            'formal' === $tone ? ' *(default)*' : ''
214                        );
215                    }
216
217                    return array(
218                        'messages' => array(
219                            array(
220                                'role'    => 'user',
221                                'content' => array(
222                                    'type'        => 'text',
223                                    'text'        => $instruction,
224                                    'annotations' => array(
225                                        'audience' => array( 'assistant' ),
226                                        'priority' => 1.0,
227                                    ),
228                                ),
229                            ),
230                            array(
231                                'role'    => 'assistant',
232                                'content' => array(
233                                    'type'        => 'text',
234                                    'text'        => $intro_text,
235                                    'annotations' => array(
236                                        'audience' => array( 'user' ),
237                                        'priority' => 0.9,
238                                    ),
239                                ),
240                            ),
241                        ),
242                    );
243                },
244                'permission_callback' => function () {
245                    return current_user_can( 'edit_posts' );
246                },
247                'meta'                => array(
248                    'annotations' => array(
249                        'audience'     => array( 'user', 'assistant' ),
250                        'priority'     => 1.0,
251                        'lastModified' => gmdate( 'c' ),
252                    ),
253                    'mcp'         => array(
254                        'public' => true,
255                        'type'   => 'prompt',
256                    ),
257                ),
258            )
259        );
260    }
261
262
263    /**
264     * Create a prompt to instruct the AI the step to follow to suggest the categories
265     *
266     * @return void
267     */
268    private function register_prompt_categories() {
269        blu_register_ability(
270            'blu/suggest-product-categories',
271            array(
272                'label'               => 'Suggest Product Categories',
273                'category'            => 'blu-mcp',
274                'description'         => 'Suggest WooCommerce and Google taxonomy categories using an existing product ID, or a product name when the product is not in the store yet.',
275                'input_schema'        => array(
276                    'type'       => 'object',
277                    'properties' => array(
278                        'product_id' => array(
279                            'type'        => 'integer',
280                            'description' => 'Existing WooCommerce product ID. When set, the assistant loads the product and uses its data to build category search patterns.',
281                            'minimum'     => 1,
282                        ),
283                        'name'       => array(
284                            'type'        => 'string',
285                            'description' => 'Product name — use when there is no product ID yet, or as a hint alongside troubleshooting.',
286                            'default'     => '',
287                        ),
288                    ),
289                ),
290                'execute_callback'    => function ( $input ) {
291                    $product_id   = isset( $input['product_id'] ) ? (int) $input['product_id'] : 0;
292                    $product_name = isset( $input['name'] ) ? sanitize_text_field( $input['name'] ) : '';
293
294                    $has_id = $product_id > 0;
295                    $mode   = $has_id ? 'existing' : 'planned';
296
297                    $product_id_safe   = $has_id ? (string) $product_id : '(none)';
298                    $product_name_safe = addslashes( $product_name );
299                    $mode_safe         = $mode;
300
301                    $instruction = include_once __DIR__ . '/../instructions/product-categories-suggester.php';
302
303                    if ( $has_id ) {
304                        $intro_text = sprintf(
305                            "Let's suggest categories for **product #%d**.\n\n" .
306                            "I'll load the product, then match your store categories with the Google Product Taxonomy.\n\n" .
307                            '%s',
308                            $product_id,
309                            ! empty( $product_name )
310                                ? sprintf( "*(You also provided the name \"%s\" — I'll treat it as extra context if it differs.)*\n\n", esc_html( $product_name ) )
311                                : ''
312                        ) . 'Loading product data now…';
313                    } else {
314                        $intro_text = sprintf(
315                            "Let's suggest categories for **%s**.\n\n" .
316                            'No product ID was given, so I will work from the name only (the product may not exist in WooCommerce yet).',
317                            ! empty( $product_name ) ? esc_html( $product_name ) : 'your product'
318                        );
319                    }
320
321                    return array(
322                        'messages' => array(
323                            array(
324                                'role'    => 'user',
325                                'content' => array(
326                                    'type'        => 'text',
327                                    'text'        => $instruction,
328                                    'annotations' => array(
329                                        'audience' => array( 'assistant' ),
330                                        'priority' => 0.9,
331                                    ),
332                                ),
333                            ),
334                            array(
335                                'role'    => 'assistant',
336                                'content' => array(
337                                    'type'        => 'text',
338                                    'text'        => $intro_text,
339                                    'annotations' => array(
340                                        'audience' => array( 'user' ),
341                                        'priority' => 0.9,
342                                    ),
343                                ),
344                            ),
345                        ),
346                    );
347                },
348                'permission_callback' => function () {
349                    return current_user_can( 'edit_posts' );
350                },
351                'meta'                => array(
352                    'annotations' => array(
353                        'readonly'   => true,
354                        'idempotent' => true,
355                    ),
356                    'mcp'         => array(
357                        'public' => true,
358                        'type'   => 'prompt',
359                    ),
360                ),
361            )
362        );
363    }
364
365    /**
366     * Create a prompt to instruct the AI the step to follow to suggest the tag
367     *
368     * @return void
369     */
370    private function register_prompt_tags() {
371        blu_register_ability(
372            'blu/suggest-product-tag',
373            array(
374                'label'               => 'Suggest Product Tags',
375                'category'            => 'blu-mcp',
376                'description'         => 'Suggest WooCommerce product tags using an existing product ID, or a product name when the product is not in the store yet (same workflow as guided product flow Step 3-B).',
377                'input_schema'        => array(
378                    'type'       => 'object',
379                    'properties' => array(
380                        'product_id' => array(
381                            'type'        => 'integer',
382                            'description' => 'Existing WooCommerce product ID. When set, the assistant loads the product and uses its data to build tag search patterns.',
383                            'minimum'     => 1,
384                        ),
385                        'name'       => array(
386                            'type'        => 'string',
387                            'description' => 'Product name — use when there is no product ID yet, or as extra context alongside an ID.',
388                            'default'     => '',
389                        ),
390                    ),
391                ),
392                'execute_callback'    => function ( $input ) {
393                    $product_id   = isset( $input['product_id'] ) ? (int) $input['product_id'] : 0;
394                    $product_name = isset( $input['name'] ) ? sanitize_text_field( $input['name'] ) : '';
395
396                    $has_id = $product_id > 0;
397                    $mode   = $has_id ? 'existing' : 'planned';
398
399                    $product_id_safe   = $has_id ? (string) $product_id : '(none)';
400                    $product_name_safe = addslashes( $product_name );
401                    $mode_safe         = $mode;
402
403                    $instruction = include_once __DIR__ . '/../instructions/product-tags-suggester.php';
404
405                    if ( $has_id ) {
406                        $intro_text = sprintf(
407                            "Let's suggest tags for **product #%d**.\n\n" .
408                            "I'll load the product, list matching store tags, and fill in SEO ideas if needed.\n\n" .
409                            '%s',
410                            $product_id,
411                            ! empty( $product_name )
412                                ? sprintf( "*(You also provided the name \"%s\" — I'll treat it as extra context if it differs.)*\n\n", esc_html( $product_name ) )
413                                : ''
414                        ) . 'Loading product data now…';
415                    } else {
416                        $intro_text = sprintf(
417                            "Let's suggest tags for **%s**.\n\n" .
418                            'No product ID was given, so I will work from the name only (the product may not exist in WooCommerce yet).',
419                            ! empty( $product_name ) ? esc_html( $product_name ) : 'your product'
420                        );
421                    }
422
423                    return array(
424                        'messages' => array(
425                            array(
426                                'role'    => 'user',
427                                'content' => array(
428                                    'type'        => 'text',
429                                    'text'        => $instruction,
430                                    'annotations' => array(
431                                        'audience' => array( 'assistant' ),
432                                        'priority' => 0.9,
433                                    ),
434                                ),
435                            ),
436                            array(
437                                'role'    => 'assistant',
438                                'content' => array(
439                                    'type'        => 'text',
440                                    'text'        => $intro_text,
441                                    'annotations' => array(
442                                        'audience' => array( 'user' ),
443                                        'priority' => 0.9,
444                                    ),
445                                ),
446                            ),
447                        ),
448                    );
449                },
450                'permission_callback' => function () {
451                    return current_user_can( 'edit_posts' );
452                },
453                'meta'                => array(
454                    'annotations' => array(
455                        'readonly'   => true,
456                        'idempotent' => true,
457                    ),
458                    'mcp'         => array(
459                        'public' => true,
460                        'type'   => 'prompt',
461                    ),
462                ),
463            )
464        );
465    }
466
467    /**
468     * Create a prompt to instruct the AI the step to follow to suggest the brand
469     *
470     * @return void
471     */
472    private function register_prompt_brands() {
473        blu_register_ability(
474            'blu/suggest-product-brand',
475            array(
476                'label'               => 'Suggest Product Brands',
477                'category'            => 'blu-mcp',
478                'description'         => 'Generate a list of product brands based on product details',
479                'input_schema'        => array(
480                    'type'       => 'object',
481                    'properties' => array(
482                        'product_id' => array(
483                            'type'        => 'integer',
484                            'description' => 'Existing WooCommerce product ID. When set, the assistant loads the product and uses its data to build tag search patterns.',
485                            'minimum'     => 1,
486                        ),
487                        'name'       => array(
488                            'type'        => 'string',
489                            'description' => 'Product name — use when there is no product ID yet, or as extra context alongside an ID.',
490                            'default'     => '',
491                        ),
492                    ),
493                ),
494                'execute_callback'    => function ( $input ) {
495                    $product_id   = isset( $input['product_id'] ) ? (int) $input['product_id'] : 0;
496                    $product_name = isset( $input['name'] ) ? sanitize_text_field( $input['name'] ) : '';
497
498                    $has_id = $product_id > 0;
499                    $mode   = $has_id ? 'existing' : 'planned';
500
501                    $product_id_safe   = $has_id ? (string) $product_id : '(none)';
502                    $product_name_safe = addslashes( $product_name );
503                    $mode_safe         = $mode;
504
505                    $instruction = include_once __DIR__ . '/../instructions/product-brands-suggester.php';
506
507                    if ( $has_id ) {
508                        $intro_text = sprintf(
509                            "Let's suggest brands for **product #%d**.\n\n" .
510                                            "I'll load the product, list matching store brands, and fill in SEO ideas if needed.\n\n" .
511                                            '%s',
512                            $product_id,
513                            ! empty( $product_name )
514                                                ? sprintf( "*(You also provided the name \"%s\" — I'll treat it as extra context if it differs.)*\n\n", esc_html( $product_name ) )
515                                                : ''
516                        ) . 'Loading product data now…';
517                    } else {
518                        $intro_text = sprintf(
519                            "Let's suggest brands for **%s**.\n\n" .
520                            'No product ID was given, so I will work from the name only (the product may not exist in WooCommerce yet).',
521                            ! empty( $product_name ) ? esc_html( $product_name ) : 'your product'
522                        );
523                    }
524
525                    return array(
526                        'messages' => array(
527                            array(
528                                'role'    => 'user',
529                                'content' => array(
530                                    'type'        => 'text',
531                                    'text'        => $instruction,
532                                    'annotations' => array(
533                                        'audience' => array( 'assistant' ),
534                                        'priority' => 0.9,
535                                    ),
536                                ),
537                            ),
538                            array(
539                                'role'    => 'assistant',
540                                'content' => array(
541                                    'type'        => 'text',
542                                    'text'        => $intro_text,
543                                    'annotations' => array(
544                                        'audience' => array( 'user' ),
545                                        'priority' => 0.9,
546                                    ),
547                                ),
548                            ),
549                        ),
550                    );
551                },
552                'permission_callback' => function () {
553                    return current_user_can( 'edit_posts' );
554                },
555                'meta'                => array(
556                    'annotations' => array(
557                        'readonly'   => true,
558                        'idempotent' => true,
559                    ),
560                    'mcp'         => array(
561                        'public' => true,
562                        'type'   => 'prompt',
563                    ),
564                ),
565            )
566        );
567    }
568
569    /**
570     * Register the prompt for the smart product details
571     *
572     * @return void
573     */
574    private function register_smart_product_prompt() {
575        blu_register_ability(
576            'blu/smart-product-details',
577            array(
578                'label'               => 'Merchant Content Intelligence Generator',
579                'category'            => 'blu-mcp',
580                'description'         => 'A compact all‑in‑one prompt for merchants that uses the product ID and basic product details to automatically generate all key listing content — required materials, size charts, care instructions, warranty info, and ingredient lists — ensuring every product page is complete and compliant.',
581                'input_schema'        => array(
582                    'type'       => 'object',
583                    'properties' => array(
584                        'id' => array(
585                            'type'        => 'integer',
586                            'description' => 'Product ID.',
587                        ),
588                    ),
589                    'required'   => array( 'id' ),
590                ),
591                'execute_callback'    => function ( $input ) {
592                    if ( ! isset( $input['id'] ) ) {
593                        return blu_standardize_rest_response(
594                            new WP_Error(
595                                400,
596                                'Miss required Product ID.',
597                            )
598                        );
599                    }
600                    $product_id = $input['id'];
601                    $product    = wc_get_product( $input['id'] );
602                    if ( ! $product ) {
603                        return blu_standardize_rest_response(
604                            new WP_Error(
605                                400,
606                                'Invalid Product ID.',
607                            )
608                        );
609                    }
610
611                    $sections    = isset( $input['sections'] ) ? $input['sections'] : array();
612                    $name        = $product->get_title();
613                    $description = $product->get_description();
614                    $categories  = wc_get_product_category_list( $product->get_id() );
615                    $tags        = wc_get_product_tag_list( $product->get_id() );
616                    $append_mode = empty( $description ) ? 'replace' : 'append';
617
618                    $append_label = 'replace' === $append_mode
619                        ? 'Replace existing description'
620                        : 'Append to existing description';
621
622                    $sections_list = ! empty( $sections )
623                        ? implode( ', ', $sections )
624                        : '(auto-detect based on product data)';
625
626                    $desc_preview = mb_strlen( $description ) > 120
627                        ? mb_substr( strip_tags( $description ), 0, 120 ) . '…'
628                        : ( strip_tags( $description ) ? strip_tags( $description ) : '(empty)' );
629
630                    // Safe versions for heredoc injection
631                    $name_safe        = addslashes( $name );
632                    $description_safe = addslashes( $description );
633                    $categories_safe  = addslashes( $categories ? $categories : '(none)' );
634                    $tags_safe        = addslashes( $tags ? $tags : '(none)' );
635
636                    $instruction = include_once __DIR__ . '/../instructions/smart-product-details.php';
637
638                    $sections_note = "I'll auto-detect which content sections apply based on the product data.";
639
640                    $intro_text = sprintf(
641                        "🔍 Generating supplementary content for **%s** (ID: #%d).\n\n" .
642                        "| Field       | Value |\n" .
643                        "|-------------|-------|\n" .
644                        "| Categories  | %s |\n" .
645                        "| Tags        | %s |\n" .
646                        "| Description | %s |\n\n" .
647                        "%s\n\n" .
648                        "**Save mode:** %s\n\n" .
649                        'Analysing product data now…',
650                        esc_html( $name ),
651                        $product_id,
652                        esc_html( $categories ? $categories : '(none)' ),
653                        esc_html( $tags ? $tags : '(none)' ),
654                        esc_html( $desc_preview ),
655                        $sections_note,
656                        $append_label
657                    );
658
659                    return array(
660                        'messages' => array(
661                            array(
662                                'role'    => 'user',
663                                'content' => array(
664                                    'type'        => 'text',
665                                    'text'        => $instruction,
666                                    'annotations' => array(
667                                        'audience' => array( 'assistant' ),
668                                        'priority' => 1.0,
669                                    ),
670                                ),
671                            ),
672                            array(
673                                'role'    => 'assistant',
674                                'content' => array(
675                                    'type'        => 'text',
676                                    'text'        => $intro_text,
677                                    'annotations' => array(
678                                        'audience' => array( 'user' ),
679                                        'priority' => 0.9,
680                                    ),
681                                ),
682                            ),
683                        ),
684                    );
685                },
686                'permission_callback' => function () {
687                    return current_user_can( 'edit_posts' );
688                },
689                'meta'                => array(
690                    'annotations' => array(
691                        'readonly'   => true,
692                        'idempotent' => true,
693                    ),
694                    'mcp'         => array(
695                        'public' => true,
696                        'type'   => 'prompt',
697                    ),
698                ),
699            )
700        );
701    }
702}