PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.1.2
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.1.2
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
cartflows / abilities / class-cartflows-ability-config.php

class-cartflows-ability-config.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.1.2, at abilities/class-cartflows-ability-config.php

3,522 lines 124.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Ability Config.
4 *
5 * Defines all ability registrations: labels, descriptions, schemas, permissions, and meta.
6 *
7 * @package CartFlows
8 */
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class Cartflows_Ability_Config
17 *
18 * Static registry of all CartFlows ability definitions.
19 */
20 class Cartflows_Ability_Config {
21
22 /**
23 * Cached ability definitions.
24 *
25 * @var array|false
26 */
27 public static $abilities = false;
28
29 /**
30 * Get all ability configurations.
31 *
32 * @return array
33 */
34 public static function get_abilities() {
35
36 if ( false !== self::$abilities ) {
37 return self::$abilities;
38 }
39
40 $cf = new Cartflows_Ability_Runtime();
41
42 $abilities = array(
43
44 // ============================================================
45 // Flows — CRUD / Read
46 // ============================================================
47
48 // List all funnels with pagination, status, and search filters.
49 CARTFLOWS_ABILITY_API_NAMESPACE . 'list-flows' => array(
50 'label' => __( 'List funnels', 'cartflows' ),
51 'description' => __( 'Returns a paginated list of CartFlows funnels. Supports filtering by status (publish, draft, trash) and keyword search. Excludes the store checkout flow. Use to browse or discover funnels before taking action on them.', 'cartflows' ),
52 'category' => 'cartflows',
53 'permission_callback' => function () use ( $cf ) {
54 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
55 },
56 'input_schema' => array(
57 'type' => 'object',
58 'properties' => array(
59 'status' => array(
60 'type' => 'string',
61 'enum' => array( 'publish', 'draft', 'trash', 'any' ),
62 'default' => 'publish',
63 'description' => __( 'Filter funnels by post status.', 'cartflows' ),
64 ),
65 'search' => array(
66 'type' => 'string',
67 'default' => '',
68 'description' => __( 'Keyword to search in funnel titles.', 'cartflows' ),
69 ),
70 'paged' => array(
71 'type' => 'integer',
72 'default' => 1,
73 'description' => __( 'Page number (1-based).', 'cartflows' ),
74 ),
75 'per_page' => array(
76 'type' => 'integer',
77 'default' => 10,
78 'description' => __( 'Funnels per page (max 100).', 'cartflows' ),
79 ),
80 ),
81 ),
82 'output_schema' => array(
83 'type' => 'object',
84 'properties' => array(
85 'flows' => array(
86 'type' => 'array',
87 'description' => __( 'The funnels.', 'cartflows' ),
88 'items' => array(
89 'type' => 'object',
90 'properties' => array(
91 'id' => array(
92 'type' => 'integer',
93 'description' => __( 'Funnel ID.', 'cartflows' ),
94 ),
95 'title' => array(
96 'type' => 'string',
97 'description' => __( 'Funnel title.', 'cartflows' ),
98 ),
99 'status' => array(
100 'type' => 'string',
101 'description' => __( 'Post status.', 'cartflows' ),
102 ),
103 'date_created' => array(
104 'type' => 'string',
105 'description' => __( 'Date created.', 'cartflows' ),
106 ),
107 'date_modified' => array(
108 'type' => 'string',
109 'description' => __( 'Date last modified.', 'cartflows' ),
110 ),
111 'url_view' => array(
112 'type' => 'string',
113 'format' => 'uri',
114 'description' => __( 'Frontend URL.', 'cartflows' ),
115 ),
116 'url_edit' => array(
117 'type' => 'string',
118 'format' => 'uri',
119 'description' => __( 'Admin edit URL.', 'cartflows' ),
120 ),
121 'flow_test_mode' => array(
122 'type' => 'boolean',
123 'description' => __( 'Whether in test/sandbox mode.', 'cartflows' ),
124 ),
125 ),
126 ),
127 ),
128 'total' => array(
129 'type' => 'integer',
130 'description' => __( 'Total matching funnels.', 'cartflows' ),
131 ),
132 'total_pages' => array(
133 'type' => 'integer',
134 'description' => __( 'Total pages.', 'cartflows' ),
135 ),
136 'page' => array(
137 'type' => 'integer',
138 'description' => __( 'Current page.', 'cartflows' ),
139 ),
140 ),
141 ),
142 'execute_callback' => function ( $input ) use ( $cf ) {
143 return $cf->list_flows( $input );
144 },
145 'meta' => array(
146 'uri' => 'cartflows://flows',
147 'annotations' => array(
148 'priority' => 1.0,
149 'readOnlyHint' => true,
150 'destructiveHint' => false,
151 'idempotentHint' => true,
152 'openWorldHint' => false,
153 ),
154 'show_in_rest' => true,
155 'mcp' => array(
156 'public' => true,
157 'type' => 'resource',
158 ),
159 ),
160 ),
161
162 // Get a single funnel by ID with full step list and settings.
163 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-flow' => array(
164 'label' => __( 'Get funnel', 'cartflows' ),
165 'description' => __( 'Returns full data for a single CartFlows funnel by ID, including its ordered steps, settings, and admin/frontend URLs. Use before editing, cloning, or inspecting a funnel.', 'cartflows' ),
166 'category' => 'cartflows',
167 'permission_callback' => function () use ( $cf ) {
168 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
169 },
170 'input_schema' => array(
171 'type' => 'object',
172 'required' => array( 'id' ),
173 'properties' => array(
174 'id' => array(
175 'type' => 'integer',
176 'description' => __( 'The funnel ID.', 'cartflows' ),
177 ),
178 ),
179 ),
180 'output_schema' => array(
181 'type' => 'object',
182 'properties' => array(
183 'id' => array(
184 'type' => 'integer',
185 'description' => __( 'Funnel ID.', 'cartflows' ),
186 ),
187 'title' => array(
188 'type' => 'string',
189 'description' => __( 'Funnel title.', 'cartflows' ),
190 ),
191 'slug' => array(
192 'type' => 'string',
193 'description' => __( 'URL slug.', 'cartflows' ),
194 ),
195 'status' => array(
196 'type' => 'string',
197 'description' => __( 'Post status.', 'cartflows' ),
198 ),
199 'url_view' => array(
200 'type' => 'string',
201 'format' => 'uri',
202 'description' => __( 'Frontend permalink.', 'cartflows' ),
203 ),
204 'url_edit' => array(
205 'type' => 'string',
206 'format' => 'uri',
207 'description' => __( 'Admin edit URL.', 'cartflows' ),
208 ),
209 'steps' => array(
210 'type' => 'array',
211 'description' => __( 'Ordered steps in this funnel.', 'cartflows' ),
212 'items' => array(
213 'type' => 'object',
214 'properties' => array(
215 'id' => array(
216 'type' => 'integer',
217 'description' => __( 'Step ID.', 'cartflows' ),
218 ),
219 'title' => array(
220 'type' => 'string',
221 'description' => __( 'Step title.', 'cartflows' ),
222 ),
223 'type' => array(
224 'type' => 'string',
225 'description' => __( 'Step type: checkout, thankyou, optin, or landing.', 'cartflows' ),
226 ),
227 'status' => array(
228 'type' => 'string',
229 'description' => __( 'Step post status (publish, draft, trash).', 'cartflows' ),
230 ),
231 'is_disabled' => array(
232 'type' => 'boolean',
233 'description' => __( 'Whether the step is disabled.', 'cartflows' ),
234 ),
235 'url' => array(
236 'type' => 'string',
237 'format' => 'uri',
238 'description' => __( 'Step frontend URL.', 'cartflows' ),
239 ),
240 ),
241 ),
242 ),
243 'settings_data' => array(
244 'type' => 'object',
245 'description' => __( 'Funnel settings panel data.', 'cartflows' ),
246 ),
247 ),
248 ),
249 'execute_callback' => function ( $input ) use ( $cf ) {
250 return $cf->get_flow( $input );
251 },
252 'meta' => array(
253 'uri' => 'cartflows://flows/{id}',
254 'annotations' => array(
255 'priority' => 1.0,
256 'readOnlyHint' => true,
257 'destructiveHint' => false,
258 'idempotentHint' => true,
259 'openWorldHint' => false,
260 ),
261 'show_in_rest' => true,
262 'mcp' => array(
263 'public' => true,
264 'type' => 'resource',
265 ),
266 ),
267 ),
268
269 // ============================================================
270 // Steps — CRUD / Read
271 // ============================================================
272
273 // Get a single step by ID.
274 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-step' => array(
275 'label' => __( 'Get step', 'cartflows' ),
276 'description' => __( 'Returns full data for a single CartFlows step by ID, including its type (checkout, thankyou, optin, landing), settings, and page-builder edit link. Use to inspect a step before editing or cloning it.', 'cartflows' ),
277 'category' => 'cartflows',
278 'permission_callback' => function () use ( $cf ) {
279 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
280 },
281 'input_schema' => array(
282 'type' => 'object',
283 'required' => array( 'id' ),
284 'properties' => array(
285 'id' => array(
286 'type' => 'integer',
287 'description' => __( 'The step ID.', 'cartflows' ),
288 ),
289 ),
290 ),
291 'output_schema' => array(
292 'type' => 'object',
293 'properties' => array(
294 'id' => array(
295 'type' => 'integer',
296 'description' => __( 'Step ID.', 'cartflows' ),
297 ),
298 'title' => array(
299 'type' => 'string',
300 'description' => __( 'Step title.', 'cartflows' ),
301 ),
302 'type' => array(
303 'type' => 'string',
304 'description' => __( 'Step type: checkout, thankyou, optin, or landing.', 'cartflows' ),
305 ),
306 'flow_id' => array(
307 'type' => 'integer',
308 'description' => __( 'Parent funnel ID.', 'cartflows' ),
309 ),
310 'flow_title' => array(
311 'type' => 'string',
312 'description' => __( 'Parent funnel title.', 'cartflows' ),
313 ),
314 'url_view' => array(
315 'type' => 'string',
316 'format' => 'uri',
317 'description' => __( 'Frontend URL.', 'cartflows' ),
318 ),
319 'url_edit' => array(
320 'type' => 'string',
321 'format' => 'uri',
322 'description' => __( 'WP admin edit link.', 'cartflows' ),
323 ),
324 'url_page_builder' => array(
325 'type' => 'string',
326 'format' => 'uri',
327 'description' => __( 'Page builder direct edit link.', 'cartflows' ),
328 ),
329 'settings_data' => array(
330 'type' => 'object',
331 'description' => __( 'Step settings.', 'cartflows' ),
332 ),
333 ),
334 ),
335 'execute_callback' => function ( $input ) use ( $cf ) {
336 return $cf->get_step( $input );
337 },
338 'meta' => array(
339 'uri' => 'cartflows://steps/{id}',
340 'annotations' => array(
341 'priority' => 1.0,
342 'readOnlyHint' => true,
343 'destructiveHint' => false,
344 'idempotentHint' => true,
345 'openWorldHint' => false,
346 ),
347 'show_in_rest' => true,
348 'mcp' => array(
349 'public' => true,
350 'type' => 'resource',
351 ),
352 ),
353 ),
354
355 // ============================================================
356 // Analytics / Stats
357 // ============================================================
358
359 // Get funnel analytics.
360 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-flow-stats' => array(
361 'label' => __( 'Get funnel analytics', 'cartflows' ),
362 'description' => __( 'Returns revenue and order analytics for CartFlows funnels within a date range. Optionally filter by a specific funnel ID. Returns totals, per-date breakdowns, and the 4 most recent orders. Requires WooCommerce.', 'cartflows' ),
363 'category' => 'cartflows',
364 'permission_callback' => function () use ( $cf ) {
365 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
366 },
367 'input_schema' => array(
368 'type' => 'object',
369 'properties' => array(
370 'date_from' => array(
371 'type' => 'string',
372 'format' => 'date',
373 'default' => '',
374 'description' => __( 'Start date in YYYY-MM-DD format. Defaults to 30 days ago if empty.', 'cartflows' ),
375 ),
376 'date_to' => array(
377 'type' => 'string',
378 'format' => 'date',
379 'default' => '',
380 'description' => __( 'End date in YYYY-MM-DD format. Defaults to today if empty.', 'cartflows' ),
381 ),
382 'flow_id' => array(
383 'type' => 'integer',
384 'default' => 0,
385 'description' => __( 'Filter by funnel ID. Set to 0 for all funnels.', 'cartflows' ),
386 ),
387 ),
388 ),
389 'output_schema' => array(
390 'type' => 'object',
391 'properties' => array(
392 'flow_stats' => array(
393 'type' => 'object',
394 'description' => __( 'Aggregated earnings and order counts for the date range.', 'cartflows' ),
395 ),
396 'recent_orders' => array(
397 'type' => 'array',
398 'description' => __( 'The 4 most recent CartFlows orders.', 'cartflows' ),
399 'items' => array(
400 'type' => 'object',
401 'properties' => array(
402 'order_id' => array(
403 'type' => 'integer',
404 'description' => __( 'WooCommerce order ID.', 'cartflows' ),
405 ),
406 'customer_name' => array(
407 'type' => 'string',
408 'description' => __( 'Customer full name.', 'cartflows' ),
409 ),
410 'customer_email' => array(
411 'type' => 'string',
412 'format' => 'email',
413 'description' => __( 'Customer email.', 'cartflows' ),
414 ),
415 'order_total' => array(
416 'type' => 'string',
417 'description' => __( 'Formatted order total with currency symbol.', 'cartflows' ),
418 ),
419 'order_status' => array(
420 'type' => 'string',
421 'description' => __( 'Order status.', 'cartflows' ),
422 ),
423 'order_date' => array(
424 'type' => 'string',
425 'description' => __( 'Order date (YYYY-MM-DD).', 'cartflows' ),
426 ),
427 ),
428 ),
429 ),
430 ),
431 ),
432 'execute_callback' => function ( $input ) use ( $cf ) {
433 return $cf->get_flow_stats( $input );
434 },
435 'meta' => array(
436 'uri' => 'cartflows://analytics/flow-stats',
437 'annotations' => array(
438 'priority' => 1.0,
439 'readOnlyHint' => true,
440 'destructiveHint' => false,
441 'idempotentHint' => true,
442 'openWorldHint' => false,
443 ),
444 'show_in_rest' => true,
445 'mcp' => array(
446 'public' => true,
447 'type' => 'resource',
448 ),
449 ),
450 ),
451
452 // ============================================================
453 // Flows — Lifecycle
454 // ============================================================
455
456 // Publish a funnel.
457 CARTFLOWS_ABILITY_API_NAMESPACE . 'publish-flow' => array(
458 'label' => __( 'Publish funnel', 'cartflows' ),
459 'description' => __( 'Sets a CartFlows funnel to published (active) status, making it and all its steps visible to visitors. Use to activate a funnel that is ready to go live.', 'cartflows' ),
460 'category' => 'cartflows',
461 'permission_callback' => function () use ( $cf ) {
462 return (
463 get_option( 'cartflows_abilities_api_edit', true ) &&
464 $cf->permission_callback( 'cartflows_manage_flows_steps' )
465 );
466 },
467 'input_schema' => array(
468 'type' => 'object',
469 'required' => array( 'id' ),
470 'properties' => array(
471 'id' => array(
472 'type' => 'integer',
473 'description' => __( 'The funnel ID to publish.', 'cartflows' ),
474 ),
475 ),
476 ),
477 'output_schema' => array(
478 'type' => 'object',
479 'properties' => array(
480 'id' => array(
481 'type' => 'integer',
482 'description' => __( 'Funnel ID.', 'cartflows' ),
483 ),
484 'status' => array(
485 'type' => 'string',
486 'description' => __( 'New status (publish).', 'cartflows' ),
487 ),
488 'message' => array(
489 'type' => 'string',
490 'description' => __( 'Result message.', 'cartflows' ),
491 ),
492 ),
493 ),
494 'execute_callback' => function ( $input ) use ( $cf ) {
495 return $cf->publish_flow( $input );
496 },
497 'meta' => array(
498 'annotations' => array(
499 'priority' => 2.0,
500 'readOnlyHint' => false,
501 'destructiveHint' => false,
502 'idempotentHint' => true,
503 'openWorldHint' => false,
504 ),
505 'show_in_rest' => true,
506 'mcp' => array(
507 'public' => true,
508 'type' => 'tool',
509 ),
510 ),
511 ),
512
513 // Unpublish (draft) a funnel.
514 CARTFLOWS_ABILITY_API_NAMESPACE . 'unpublish-flow' => array(
515 'label' => __( 'Unpublish funnel', 'cartflows' ),
516 'description' => __( 'Sets a CartFlows funnel to draft (inactive) status, hiding it and all its steps from visitors. Use to temporarily disable a funnel without deleting it.', 'cartflows' ),
517 'category' => 'cartflows',
518 'permission_callback' => function () use ( $cf ) {
519 return (
520 get_option( 'cartflows_abilities_api_edit', true ) &&
521 $cf->permission_callback( 'cartflows_manage_flows_steps' )
522 );
523 },
524 'input_schema' => array(
525 'type' => 'object',
526 'required' => array( 'id' ),
527 'properties' => array(
528 'id' => array(
529 'type' => 'integer',
530 'description' => __( 'The funnel ID to unpublish.', 'cartflows' ),
531 ),
532 ),
533 ),
534 'output_schema' => array(
535 'type' => 'object',
536 'properties' => array(
537 'id' => array(
538 'type' => 'integer',
539 'description' => __( 'Funnel ID.', 'cartflows' ),
540 ),
541 'status' => array(
542 'type' => 'string',
543 'description' => __( 'New status (draft).', 'cartflows' ),
544 ),
545 'message' => array(
546 'type' => 'string',
547 'description' => __( 'Result message.', 'cartflows' ),
548 ),
549 ),
550 ),
551 'execute_callback' => function ( $input ) use ( $cf ) {
552 return $cf->unpublish_flow( $input );
553 },
554 'meta' => array(
555 'annotations' => array(
556 'priority' => 2.0,
557 'readOnlyHint' => false,
558 'destructiveHint' => false,
559 'idempotentHint' => true,
560 'openWorldHint' => false,
561 ),
562 'show_in_rest' => true,
563 'mcp' => array(
564 'public' => true,
565 'type' => 'tool',
566 ),
567 ),
568 ),
569
570 // Clone a funnel.
571 CARTFLOWS_ABILITY_API_NAMESPACE . 'clone-flow' => array(
572 'label' => __( 'Clone funnel', 'cartflows' ),
573 'description' => __( 'Creates a full duplicate of a CartFlows funnel, including all its steps and their settings. The new funnel is titled "[Original Title] Clone". Use to create a variation or template-based copy of an existing funnel.', 'cartflows' ),
574 'category' => 'cartflows',
575 'permission_callback' => function () use ( $cf ) {
576 return (
577 get_option( 'cartflows_abilities_api_edit', true ) &&
578 $cf->permission_callback( 'cartflows_manage_flows_steps' )
579 );
580 },
581 'input_schema' => array(
582 'type' => 'object',
583 'required' => array( 'id' ),
584 'properties' => array(
585 'id' => array(
586 'type' => 'integer',
587 'description' => __( 'The funnel ID to clone.', 'cartflows' ),
588 ),
589 ),
590 ),
591 'output_schema' => array(
592 'type' => 'object',
593 'properties' => array(
594 'id' => array(
595 'type' => 'integer',
596 'description' => __( 'New funnel ID.', 'cartflows' ),
597 ),
598 'source_id' => array(
599 'type' => 'integer',
600 'description' => __( 'Original funnel ID.', 'cartflows' ),
601 ),
602 'title' => array(
603 'type' => 'string',
604 'description' => __( 'New funnel title.', 'cartflows' ),
605 ),
606 'url_edit' => array(
607 'type' => 'string',
608 'format' => 'uri',
609 'description' => __( 'Admin edit URL for new funnel.', 'cartflows' ),
610 ),
611 'steps_count' => array(
612 'type' => 'integer',
613 'description' => __( 'Number of steps cloned.', 'cartflows' ),
614 ),
615 'message' => array(
616 'type' => 'string',
617 'description' => __( 'Result message.', 'cartflows' ),
618 ),
619 ),
620 ),
621 'execute_callback' => function ( $input ) use ( $cf ) {
622 return $cf->clone_flow( $input );
623 },
624 'meta' => array(
625 'annotations' => array(
626 'priority' => 2.0,
627 'readOnlyHint' => false,
628 'destructiveHint' => false,
629 'idempotentHint' => false,
630 'openWorldHint' => false,
631 ),
632 'show_in_rest' => true,
633 'mcp' => array(
634 'public' => true,
635 'type' => 'tool',
636 ),
637 ),
638 ),
639
640 // Trash a funnel.
641 CARTFLOWS_ABILITY_API_NAMESPACE . 'trash-flow' => array(
642 'label' => __( 'Trash funnel', 'cartflows' ),
643 'description' => __( 'Moves a CartFlows funnel and all its steps to the WordPress trash. The funnel can be restored using restore-flow. Prefer this over permanent deletion.', 'cartflows' ),
644 'category' => 'cartflows',
645 'permission_callback' => function () use ( $cf ) {
646 return (
647 get_option( 'cartflows_abilities_api_edit', true ) &&
648 $cf->permission_callback( 'cartflows_manage_flows_steps' )
649 );
650 },
651 'input_schema' => array(
652 'type' => 'object',
653 'required' => array( 'id' ),
654 'properties' => array(
655 'id' => array(
656 'type' => 'integer',
657 'description' => __( 'The funnel ID to trash.', 'cartflows' ),
658 ),
659 ),
660 ),
661 'output_schema' => array(
662 'type' => 'object',
663 'properties' => array(
664 'id' => array(
665 'type' => 'integer',
666 'description' => __( 'Funnel ID.', 'cartflows' ),
667 ),
668 'status' => array(
669 'type' => 'string',
670 'description' => __( 'New status (trash).', 'cartflows' ),
671 ),
672 'message' => array(
673 'type' => 'string',
674 'description' => __( 'Result message.', 'cartflows' ),
675 ),
676 ),
677 ),
678 'execute_callback' => function ( $input ) use ( $cf ) {
679 return $cf->trash_flow( $input );
680 },
681 'meta' => array(
682 'annotations' => array(
683 'priority' => 2.0,
684 'readOnlyHint' => false,
685 'destructiveHint' => true,
686 'idempotentHint' => true,
687 'openWorldHint' => false,
688 ),
689 'instructions' => 'Always confirm with the user before executing this ability. This moves the funnel and all its steps to trash.',
690 'show_in_rest' => true,
691 'mcp' => array(
692 'public' => true,
693 'type' => 'tool',
694 ),
695 ),
696 ),
697
698 // Restore a funnel from trash.
699 CARTFLOWS_ABILITY_API_NAMESPACE . 'restore-flow' => array(
700 'label' => __( 'Restore funnel from trash', 'cartflows' ),
701 'description' => __( 'Restores a trashed CartFlows funnel and all its steps back to their previous published/draft status. Use to undo a trash-flow operation.', 'cartflows' ),
702 'category' => 'cartflows',
703 'permission_callback' => function () use ( $cf ) {
704 return (
705 get_option( 'cartflows_abilities_api_edit', true ) &&
706 $cf->permission_callback( 'cartflows_manage_flows_steps' )
707 );
708 },
709 'input_schema' => array(
710 'type' => 'object',
711 'required' => array( 'id' ),
712 'properties' => array(
713 'id' => array(
714 'type' => 'integer',
715 'description' => __( 'The funnel ID to restore from trash.', 'cartflows' ),
716 ),
717 ),
718 ),
719 'output_schema' => array(
720 'type' => 'object',
721 'properties' => array(
722 'id' => array(
723 'type' => 'integer',
724 'description' => __( 'Funnel ID.', 'cartflows' ),
725 ),
726 'status' => array(
727 'type' => 'string',
728 'description' => __( 'Restored status.', 'cartflows' ),
729 ),
730 'message' => array(
731 'type' => 'string',
732 'description' => __( 'Result message.', 'cartflows' ),
733 ),
734 ),
735 ),
736 'execute_callback' => function ( $input ) use ( $cf ) {
737 return $cf->restore_flow( $input );
738 },
739 'meta' => array(
740 'annotations' => array(
741 'priority' => 2.0,
742 'readOnlyHint' => false,
743 'destructiveHint' => false,
744 'idempotentHint' => true,
745 'openWorldHint' => false,
746 ),
747 'show_in_rest' => true,
748 'mcp' => array(
749 'public' => true,
750 'type' => 'tool',
751 ),
752 ),
753 ),
754
755 // ============================================================
756 // Flows — CRUD / Update
757 // ============================================================
758
759 // Update a funnel's title and/or slug.
760 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-flow' => array(
761 'label' => __( 'Update funnel', 'cartflows' ),
762 'description' => __( 'Updates a CartFlows funnel\'s title and optionally its URL slug. Use to rename a funnel or change its permalink.', 'cartflows' ),
763 'category' => 'cartflows',
764 'permission_callback' => function () use ( $cf ) {
765 return (
766 get_option( 'cartflows_abilities_api_edit', true ) &&
767 $cf->permission_callback( 'cartflows_manage_flows_steps' )
768 );
769 },
770 'input_schema' => array(
771 'type' => 'object',
772 'required' => array( 'id', 'title' ),
773 'properties' => array(
774 'id' => array(
775 'type' => 'integer',
776 'description' => __( 'The funnel ID to update.', 'cartflows' ),
777 ),
778 'title' => array(
779 'type' => 'string',
780 'description' => __( 'New funnel title.', 'cartflows' ),
781 ),
782 'slug' => array(
783 'type' => 'string',
784 'default' => '',
785 'description' => __( 'New URL slug (optional). Leave empty to keep current slug.', 'cartflows' ),
786 ),
787 ),
788 ),
789 'output_schema' => array(
790 'type' => 'object',
791 'properties' => array(
792 'id' => array(
793 'type' => 'integer',
794 'description' => __( 'Funnel ID.', 'cartflows' ),
795 ),
796 'title' => array(
797 'type' => 'string',
798 'description' => __( 'Updated title.', 'cartflows' ),
799 ),
800 'slug' => array(
801 'type' => 'string',
802 'description' => __( 'Updated slug.', 'cartflows' ),
803 ),
804 'url_edit' => array(
805 'type' => 'string',
806 'format' => 'uri',
807 'description' => __( 'Admin edit URL.', 'cartflows' ),
808 ),
809 'message' => array(
810 'type' => 'string',
811 'description' => __( 'Result message.', 'cartflows' ),
812 ),
813 ),
814 ),
815 'execute_callback' => function ( $input ) use ( $cf ) {
816 return $cf->update_flow( $input );
817 },
818 'meta' => array(
819 'annotations' => array(
820 'priority' => 2.0,
821 'readOnlyHint' => false,
822 'destructiveHint' => false,
823 'idempotentHint' => true,
824 'openWorldHint' => false,
825 ),
826 'show_in_rest' => true,
827 'mcp' => array(
828 'public' => true,
829 'type' => 'tool',
830 ),
831 ),
832 ),
833
834 // ============================================================
835 // Flows — Relationships
836 // ============================================================
837
838 // Reorder steps in a funnel.
839 CARTFLOWS_ABILITY_API_NAMESPACE . 'reorder-flow-steps' => array(
840 'label' => __( 'Reorder funnel steps', 'cartflows' ),
841 'description' => __( 'Changes the display order of steps within a CartFlows funnel. Provide the complete ordered array of step IDs. Call get-flow first to retrieve the current step IDs.', 'cartflows' ),
842 'category' => 'cartflows',
843 'permission_callback' => function () use ( $cf ) {
844 return (
845 get_option( 'cartflows_abilities_api_edit', true ) &&
846 $cf->permission_callback( 'cartflows_manage_flows_steps' )
847 );
848 },
849 'input_schema' => array(
850 'type' => 'object',
851 'required' => array( 'flow_id', 'step_ids' ),
852 'properties' => array(
853 'flow_id' => array(
854 'type' => 'integer',
855 'description' => __( 'The funnel ID.', 'cartflows' ),
856 ),
857 'step_ids' => array(
858 'type' => 'array',
859 'description' => __( 'Full ordered array of step IDs in the desired order.', 'cartflows' ),
860 'items' => array(
861 'type' => 'integer',
862 ),
863 ),
864 ),
865 ),
866 'output_schema' => array(
867 'type' => 'object',
868 'properties' => array(
869 'flow_id' => array(
870 'type' => 'integer',
871 'description' => __( 'Funnel ID.', 'cartflows' ),
872 ),
873 'steps' => array(
874 'type' => 'array',
875 'description' => __( 'Steps in updated order.', 'cartflows' ),
876 'items' => array(
877 'type' => 'object',
878 'properties' => array(
879 'id' => array(
880 'type' => 'integer',
881 'description' => __( 'Step ID.', 'cartflows' ),
882 ),
883 'title' => array(
884 'type' => 'string',
885 'description' => __( 'Step title.', 'cartflows' ),
886 ),
887 'type' => array(
888 'type' => 'string',
889 'description' => __( 'Step type.', 'cartflows' ),
890 ),
891 ),
892 ),
893 ),
894 'message' => array(
895 'type' => 'string',
896 'description' => __( 'Result message.', 'cartflows' ),
897 ),
898 ),
899 ),
900 'execute_callback' => function ( $input ) use ( $cf ) {
901 return $cf->reorder_flow_steps( $input );
902 },
903 'meta' => array(
904 'annotations' => array(
905 'priority' => 2.0,
906 'readOnlyHint' => false,
907 'destructiveHint' => false,
908 'idempotentHint' => true,
909 'openWorldHint' => false,
910 ),
911 'show_in_rest' => true,
912 'mcp' => array(
913 'public' => true,
914 'type' => 'tool',
915 ),
916 ),
917 ),
918
919 // ============================================================
920 // Flows — Output / Embedding
921 // ============================================================
922
923 // Export one or more funnels as JSON.
924 CARTFLOWS_ABILITY_API_NAMESPACE . 'export-flow' => array(
925 'label' => __( 'Export funnel data', 'cartflows' ),
926 'description' => __( 'Exports one or more CartFlows funnels as structured JSON data, including all steps and their settings. Use for backup, migration between sites, or auditing funnel configuration.', 'cartflows' ),
927 'category' => 'cartflows',
928 'permission_callback' => function () use ( $cf ) {
929 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
930 },
931 'input_schema' => array(
932 'type' => 'object',
933 'required' => array( 'flow_ids' ),
934 'properties' => array(
935 'flow_ids' => array(
936 'type' => 'array',
937 'description' => __( 'Array of funnel IDs to export. At least one required.', 'cartflows' ),
938 'items' => array(
939 'type' => 'integer',
940 ),
941 ),
942 ),
943 ),
944 'output_schema' => array(
945 'type' => 'object',
946 'properties' => array(
947 'flows' => array(
948 'type' => 'array',
949 'description' => __( 'Array of funnel export objects (one per funnel ID).', 'cartflows' ),
950 'items' => array(
951 'type' => 'object',
952 'description' => __( 'Full funnel export data including all steps and settings.', 'cartflows' ),
953 ),
954 ),
955 'export_count' => array(
956 'type' => 'integer',
957 'description' => __( 'Number of funnels exported.', 'cartflows' ),
958 ),
959 'message' => array(
960 'type' => 'string',
961 'description' => __( 'Result message.', 'cartflows' ),
962 ),
963 ),
964 ),
965 'execute_callback' => function ( $input ) use ( $cf ) {
966 return $cf->export_flow( $input );
967 },
968 'meta' => array(
969 'annotations' => array(
970 'priority' => 1.0,
971 'readOnlyHint' => true,
972 'destructiveHint' => false,
973 'idempotentHint' => true,
974 'openWorldHint' => false,
975 ),
976 'show_in_rest' => true,
977 'mcp' => array(
978 'public' => true,
979 'type' => 'tool',
980 ),
981 ),
982 ),
983
984 // ============================================================
985 // Steps — Lifecycle
986 // ============================================================
987
988 // Clone a step.
989 CARTFLOWS_ABILITY_API_NAMESPACE . 'clone-step' => array(
990 'label' => __( 'Clone step', 'cartflows' ),
991 'description' => __( 'Creates a duplicate of a CartFlows step within the same funnel, copying all content and settings. The new step is titled "[Original Title] Clone". Use to create a variation of an existing step for A/B testing or reuse.', 'cartflows' ),
992 'category' => 'cartflows',
993 'permission_callback' => function () use ( $cf ) {
994 return (
995 get_option( 'cartflows_abilities_api_edit', true ) &&
996 $cf->permission_callback( 'cartflows_manage_flows_steps' )
997 );
998 },
999 'input_schema' => array(
1000 'type' => 'object',
1001 'required' => array( 'flow_id', 'step_id' ),
1002 'properties' => array(
1003 'flow_id' => array(
1004 'type' => 'integer',
1005 'description' => __( 'The parent funnel ID.', 'cartflows' ),
1006 ),
1007 'step_id' => array(
1008 'type' => 'integer',
1009 'description' => __( 'The step ID to clone.', 'cartflows' ),
1010 ),
1011 ),
1012 ),
1013 'output_schema' => array(
1014 'type' => 'object',
1015 'properties' => array(
1016 'id' => array(
1017 'type' => 'integer',
1018 'description' => __( 'New step ID.', 'cartflows' ),
1019 ),
1020 'source_id' => array(
1021 'type' => 'integer',
1022 'description' => __( 'Original step ID.', 'cartflows' ),
1023 ),
1024 'flow_id' => array(
1025 'type' => 'integer',
1026 'description' => __( 'Parent funnel ID.', 'cartflows' ),
1027 ),
1028 'title' => array(
1029 'type' => 'string',
1030 'description' => __( 'New step title.', 'cartflows' ),
1031 ),
1032 'type' => array(
1033 'type' => 'string',
1034 'description' => __( 'Step type.', 'cartflows' ),
1035 ),
1036 'message' => array(
1037 'type' => 'string',
1038 'description' => __( 'Result message.', 'cartflows' ),
1039 ),
1040 ),
1041 ),
1042 'execute_callback' => function ( $input ) use ( $cf ) {
1043 return $cf->clone_step( $input );
1044 },
1045 'meta' => array(
1046 'annotations' => array(
1047 'priority' => 2.0,
1048 'readOnlyHint' => false,
1049 'destructiveHint' => false,
1050 'idempotentHint' => false,
1051 'openWorldHint' => false,
1052 ),
1053 'show_in_rest' => true,
1054 'mcp' => array(
1055 'public' => true,
1056 'type' => 'tool',
1057 ),
1058 ),
1059 ),
1060
1061 // ============================================================
1062 // Steps — CRUD / Update
1063 // ============================================================
1064
1065 // Rename a step.
1066 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-step-title' => array(
1067 'label' => __( 'Update step title', 'cartflows' ),
1068 'description' => __( 'Renames a CartFlows step. Use when setting up a new funnel or correcting step names.', 'cartflows' ),
1069 'category' => 'cartflows',
1070 'permission_callback' => function () use ( $cf ) {
1071 return (
1072 get_option( 'cartflows_abilities_api_edit', true ) &&
1073 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1074 );
1075 },
1076 'input_schema' => array(
1077 'type' => 'object',
1078 'required' => array( 'step_id', 'title' ),
1079 'properties' => array(
1080 'step_id' => array(
1081 'type' => 'integer',
1082 'description' => __( 'The step ID to rename.', 'cartflows' ),
1083 ),
1084 'title' => array(
1085 'type' => 'string',
1086 'description' => __( 'New step title.', 'cartflows' ),
1087 ),
1088 ),
1089 ),
1090 'output_schema' => array(
1091 'type' => 'object',
1092 'properties' => array(
1093 'id' => array(
1094 'type' => 'integer',
1095 'description' => __( 'Step ID.', 'cartflows' ),
1096 ),
1097 'title' => array(
1098 'type' => 'string',
1099 'description' => __( 'Updated title.', 'cartflows' ),
1100 ),
1101 'message' => array(
1102 'type' => 'string',
1103 'description' => __( 'Result message.', 'cartflows' ),
1104 ),
1105 ),
1106 ),
1107 'execute_callback' => function ( $input ) use ( $cf ) {
1108 return $cf->update_step_title( $input );
1109 },
1110 'meta' => array(
1111 'annotations' => array(
1112 'priority' => 2.0,
1113 'readOnlyHint' => false,
1114 'destructiveHint' => false,
1115 'idempotentHint' => true,
1116 'openWorldHint' => false,
1117 ),
1118 'show_in_rest' => true,
1119 'mcp' => array(
1120 'public' => true,
1121 'type' => 'tool',
1122 ),
1123 ),
1124 ),
1125
1126 // ============================================================
1127 // Admin / Settings — Read
1128 // ============================================================
1129
1130 // Get general settings (page builder, checkout, flags).
1131 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-general-settings' => array(
1132 'label' => __( 'Get general settings', 'cartflows' ),
1133 'description' => __( 'Returns CartFlows general settings: default page builder, global checkout page, and display/override flags such as override_global_checkout and disallow_indexing. Use to inspect the current CartFlows configuration before making changes.', 'cartflows' ),
1134 'category' => 'cartflows',
1135 'permission_callback' => function () use ( $cf ) {
1136 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1137 },
1138 'input_schema' => array(
1139 'type' => 'object',
1140 'properties' => array(),
1141 ),
1142 'output_schema' => array(
1143 'type' => 'object',
1144 'properties' => array(
1145 'default_page_builder' => array(
1146 'type' => 'string',
1147 'description' => __( 'Active page builder slug (e.g. elementor, gutenberg, divi).', 'cartflows' ),
1148 ),
1149 'global_checkout' => array(
1150 'type' => 'string',
1151 'description' => __( 'Global checkout flow ID or empty string if not set.', 'cartflows' ),
1152 ),
1153 'override_global_checkout' => array(
1154 'type' => 'string',
1155 'description' => __( 'enable or disable.', 'cartflows' ),
1156 ),
1157 'override_store_order_pay' => array(
1158 'type' => 'string',
1159 'description' => __( 'enable or disable.', 'cartflows' ),
1160 ),
1161 'disallow_indexing' => array(
1162 'type' => 'string',
1163 'description' => __( 'enable or disable.', 'cartflows' ),
1164 ),
1165 ),
1166 ),
1167 'execute_callback' => function ( $input ) use ( $cf ) {
1168 return $cf->get_general_settings( $input );
1169 },
1170 'meta' => array(
1171 'uri' => 'cartflows://settings/general',
1172 'annotations' => array(
1173 'priority' => 1.0,
1174 'readOnlyHint' => true,
1175 'destructiveHint' => false,
1176 'idempotentHint' => true,
1177 'openWorldHint' => false,
1178 ),
1179 'show_in_rest' => true,
1180 'mcp' => array(
1181 'public' => true,
1182 'type' => 'resource',
1183 ),
1184 ),
1185 ),
1186
1187 // Get the store checkout flow identity and status.
1188 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-store-checkout' => array(
1189 'label' => __( 'Get store checkout flow', 'cartflows' ),
1190 'description' => __( 'Returns the ID and details of the CartFlows flow configured as the global store checkout. Returns is_configured: false if no store checkout is set. Use to identify which funnel handles the WooCommerce checkout replacement.', 'cartflows' ),
1191 'category' => 'cartflows',
1192 'permission_callback' => function () use ( $cf ) {
1193 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1194 },
1195 'input_schema' => array(
1196 'type' => 'object',
1197 'properties' => array(),
1198 ),
1199 'output_schema' => array(
1200 'type' => 'object',
1201 'properties' => array(
1202 'flow_id' => array(
1203 'type' => 'integer',
1204 'description' => __( 'The store checkout flow ID, or 0 if not set.', 'cartflows' ),
1205 ),
1206 'flow_title' => array(
1207 'type' => 'string',
1208 'description' => __( 'The store checkout flow title.', 'cartflows' ),
1209 ),
1210 'url_edit' => array(
1211 'type' => 'string',
1212 'format' => 'uri',
1213 'description' => __( 'Admin edit URL for the store checkout flow.', 'cartflows' ),
1214 ),
1215 'is_configured' => array(
1216 'type' => 'boolean',
1217 'description' => __( 'Whether a store checkout flow is configured.', 'cartflows' ),
1218 ),
1219 ),
1220 ),
1221 'execute_callback' => function ( $input ) use ( $cf ) {
1222 return $cf->get_store_checkout( $input );
1223 },
1224 'meta' => array(
1225 'uri' => 'cartflows://settings/store-checkout',
1226 'annotations' => array(
1227 'priority' => 1.0,
1228 'readOnlyHint' => true,
1229 'destructiveHint' => false,
1230 'idempotentHint' => true,
1231 'openWorldHint' => false,
1232 ),
1233 'show_in_rest' => true,
1234 'mcp' => array(
1235 'public' => true,
1236 'type' => 'resource',
1237 ),
1238 ),
1239 ),
1240
1241 // Get permalink (URL slug) settings.
1242 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-permalink-settings' => array(
1243 'label' => __( 'Get permalink settings', 'cartflows' ),
1244 'description' => __( 'Returns the CartFlows URL slug configuration for flows and steps: the step base slug, the flow base slug, and the permalink structure option. Use before updating permalink settings or auditing URL structure.', 'cartflows' ),
1245 'category' => 'cartflows',
1246 'permission_callback' => function () use ( $cf ) {
1247 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1248 },
1249 'input_schema' => array(
1250 'type' => 'object',
1251 'properties' => array(),
1252 ),
1253 'output_schema' => array(
1254 'type' => 'object',
1255 'properties' => array(
1256 'permalink' => array(
1257 'type' => 'string',
1258 'description' => __( 'Step URL base slug.', 'cartflows' ),
1259 ),
1260 'permalink_flow_base' => array(
1261 'type' => 'string',
1262 'description' => __( 'Flow URL base slug.', 'cartflows' ),
1263 ),
1264 'permalink_structure' => array(
1265 'type' => 'string',
1266 'description' => __( 'Permalink structure option (empty for default).', 'cartflows' ),
1267 ),
1268 ),
1269 ),
1270 'execute_callback' => function ( $input ) use ( $cf ) {
1271 return $cf->get_permalink_settings( $input );
1272 },
1273 'meta' => array(
1274 'uri' => 'cartflows://settings/permalink',
1275 'annotations' => array(
1276 'priority' => 1.0,
1277 'readOnlyHint' => true,
1278 'destructiveHint' => false,
1279 'idempotentHint' => true,
1280 'openWorldHint' => false,
1281 ),
1282 'show_in_rest' => true,
1283 'mcp' => array(
1284 'public' => true,
1285 'type' => 'resource',
1286 ),
1287 ),
1288 ),
1289
1290 // Get pixel / analytics integration settings.
1291 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-integration-settings' => array(
1292 'label' => __( 'Get integration settings', 'cartflows' ),
1293 'description' => __( 'Returns the active pixel and analytics integration configurations for CartFlows: Facebook, Google Analytics, Google Ads, TikTok, Pinterest, and Snapchat. Each group contains the pixel/tracking ID and event toggle settings. Use the integration parameter to fetch a single group or omit it (default: all) to fetch everything at once.', 'cartflows' ),
1294 'category' => 'cartflows',
1295 'permission_callback' => function () use ( $cf ) {
1296 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1297 },
1298 'input_schema' => array(
1299 'type' => 'object',
1300 'properties' => array(
1301 'integration' => array(
1302 'type' => 'string',
1303 'enum' => array( 'facebook', 'google_analytics', 'google_ads', 'tiktok', 'pinterest', 'snapchat', 'all' ),
1304 'default' => 'all',
1305 'description' => __( 'Which integration group to return. Defaults to all.', 'cartflows' ),
1306 ),
1307 ),
1308 ),
1309 'output_schema' => array(
1310 'type' => 'object',
1311 'properties' => array(
1312 'facebook' => array(
1313 'type' => 'object',
1314 'description' => __( 'Facebook Pixel settings.', 'cartflows' ),
1315 ),
1316 'google_analytics' => array(
1317 'type' => 'object',
1318 'description' => __( 'Google Analytics (GA4) settings.', 'cartflows' ),
1319 ),
1320 'google_ads' => array(
1321 'type' => 'object',
1322 'description' => __( 'Google Ads conversion settings.', 'cartflows' ),
1323 ),
1324 'tiktok' => array(
1325 'type' => 'object',
1326 'description' => __( 'TikTok Pixel settings.', 'cartflows' ),
1327 ),
1328 'pinterest' => array(
1329 'type' => 'object',
1330 'description' => __( 'Pinterest Tag settings.', 'cartflows' ),
1331 ),
1332 'snapchat' => array(
1333 'type' => 'object',
1334 'description' => __( 'Snapchat Pixel settings.', 'cartflows' ),
1335 ),
1336 ),
1337 ),
1338 'execute_callback' => function ( $input ) use ( $cf ) {
1339 return $cf->get_integration_settings( $input );
1340 },
1341 'meta' => array(
1342 'uri' => 'cartflows://settings/integrations',
1343 'annotations' => array(
1344 'priority' => 1.0,
1345 'readOnlyHint' => true,
1346 'destructiveHint' => false,
1347 'idempotentHint' => true,
1348 'openWorldHint' => false,
1349 ),
1350 'show_in_rest' => true,
1351 'mcp' => array(
1352 'public' => true,
1353 'type' => 'resource',
1354 ),
1355 ),
1356 ),
1357
1358 // ============================================================
1359 // Admin / Settings — Write
1360 // ============================================================
1361
1362 // Update general settings (page builder, checkout, flags).
1363 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-general-settings' => array(
1364 'label' => __( 'Update general settings', 'cartflows' ),
1365 'description' => __( 'Updates CartFlows general settings: default page builder, global checkout page, override_global_checkout flag, and disallow_indexing flag. Only fields that are provided are updated; omitted fields retain their current values. Use get-general-settings first to inspect current values.', 'cartflows' ),
1366 'category' => 'cartflows',
1367 'permission_callback' => function () use ( $cf ) {
1368 return (
1369 get_option( 'cartflows_abilities_api_write', true ) &&
1370 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1371 );
1372 },
1373 'input_schema' => array(
1374 'type' => 'object',
1375 'properties' => array(
1376 'default_page_builder' => array(
1377 'type' => 'string',
1378 'enum' => array( 'elementor', 'gutenberg', 'divi', 'beaver-builder', 'bricks-builder' ),
1379 'description' => __( 'The page builder to set as default.', 'cartflows' ),
1380 ),
1381 'global_checkout' => array(
1382 'type' => 'string',
1383 'description' => __( 'Post ID of the global checkout flow, or empty string to unset.', 'cartflows' ),
1384 ),
1385 'override_global_checkout' => array(
1386 'type' => 'string',
1387 'enum' => array( 'enable', 'disable' ),
1388 'description' => __( 'Whether to override the WooCommerce checkout with the CartFlows global checkout.', 'cartflows' ),
1389 ),
1390 'disallow_indexing' => array(
1391 'type' => 'string',
1392 'enum' => array( 'enable', 'disable' ),
1393 'description' => __( 'Whether to block search engine indexing of CartFlows steps.', 'cartflows' ),
1394 ),
1395 ),
1396 ),
1397 'output_schema' => array(
1398 'type' => 'object',
1399 'properties' => array(
1400 'message' => array(
1401 'type' => 'string',
1402 'description' => __( 'Result message.', 'cartflows' ),
1403 ),
1404 'settings' => array(
1405 'type' => 'object',
1406 'description' => __( 'Updated settings values (full merged state).', 'cartflows' ),
1407 ),
1408 ),
1409 ),
1410 'execute_callback' => function ( $input ) use ( $cf ) {
1411 return $cf->update_general_settings( $input );
1412 },
1413 'meta' => array(
1414 'annotations' => array(
1415 'priority' => 2.0,
1416 'readOnlyHint' => false,
1417 'destructiveHint' => false,
1418 'idempotentHint' => true,
1419 'openWorldHint' => false,
1420 ),
1421 'show_in_rest' => true,
1422 'mcp' => array(
1423 'public' => true,
1424 'type' => 'tool',
1425 ),
1426 ),
1427 ),
1428
1429 // Update permalink (URL slug) settings.
1430 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-permalink-settings' => array(
1431 'label' => __( 'Update permalink settings', 'cartflows' ),
1432 'description' => __( 'Updates CartFlows URL slug settings for flows and steps. Forces a permalink flush after saving so changes take effect immediately. Use get-permalink-settings first to inspect current values before updating.', 'cartflows' ),
1433 'category' => 'cartflows',
1434 'permission_callback' => function () use ( $cf ) {
1435 return (
1436 get_option( 'cartflows_abilities_api_write', true ) &&
1437 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1438 );
1439 },
1440 'input_schema' => array(
1441 'type' => 'object',
1442 'properties' => array(
1443 'permalink' => array(
1444 'type' => 'string',
1445 'description' => __( 'Step URL base slug.', 'cartflows' ),
1446 ),
1447 'permalink_flow_base' => array(
1448 'type' => 'string',
1449 'description' => __( 'Flow URL base slug.', 'cartflows' ),
1450 ),
1451 'permalink_structure' => array(
1452 'type' => 'string',
1453 'description' => __( 'Permalink structure option (empty string for default).', 'cartflows' ),
1454 ),
1455 ),
1456 ),
1457 'output_schema' => array(
1458 'type' => 'object',
1459 'properties' => array(
1460 'message' => array(
1461 'type' => 'string',
1462 'description' => __( 'Result message.', 'cartflows' ),
1463 ),
1464 'permalink' => array(
1465 'type' => 'string',
1466 'description' => __( 'Saved step URL base slug.', 'cartflows' ),
1467 ),
1468 'permalink_flow_base' => array(
1469 'type' => 'string',
1470 'description' => __( 'Saved flow URL base slug.', 'cartflows' ),
1471 ),
1472 ),
1473 ),
1474 'execute_callback' => function ( $input ) use ( $cf ) {
1475 return $cf->update_permalink_settings( $input );
1476 },
1477 'meta' => array(
1478 'annotations' => array(
1479 'priority' => 2.0,
1480 'readOnlyHint' => false,
1481 'destructiveHint' => false,
1482 'idempotentHint' => true,
1483 'openWorldHint' => false,
1484 ),
1485 'show_in_rest' => true,
1486 'mcp' => array(
1487 'public' => true,
1488 'type' => 'tool',
1489 ),
1490 ),
1491 ),
1492
1493 // ============================================================
1494 // Checkout — Configuration / Read
1495 // ============================================================
1496
1497 // Get checkout step settings.
1498 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-checkout-settings' => array(
1499 'label' => __( 'Get checkout step settings', 'cartflows' ),
1500 'description' => __( 'Returns the full configuration of a checkout step: layout, products assigned, form field toggles, place order button settings, and design options. Requires WooCommerce. Use to inspect or audit a checkout step before making changes.', 'cartflows' ),
1501 'category' => 'cartflows',
1502 'permission_callback' => function () use ( $cf ) {
1503 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1504 },
1505 'input_schema' => array(
1506 'type' => 'object',
1507 'required' => array( 'step_id' ),
1508 'properties' => array(
1509 'step_id' => array(
1510 'type' => 'integer',
1511 'description' => __( 'The checkout step ID.', 'cartflows' ),
1512 ),
1513 ),
1514 ),
1515 'output_schema' => array(
1516 'type' => 'object',
1517 'properties' => array(
1518 'step_id' => array(
1519 'type' => 'integer',
1520 'description' => __( 'Step ID.', 'cartflows' ),
1521 ),
1522 'layout' => array(
1523 'type' => 'string',
1524 'description' => __( 'Checkout skin/layout.', 'cartflows' ),
1525 ),
1526 'primary_color' => array(
1527 'type' => 'string',
1528 'description' => __( 'Primary color hex.', 'cartflows' ),
1529 ),
1530 'font_family' => array(
1531 'type' => 'string',
1532 'description' => __( 'Base font family.', 'cartflows' ),
1533 ),
1534 'products' => array(
1535 'type' => 'array',
1536 'description' => __( 'Assigned products.', 'cartflows' ),
1537 'items' => array( 'type' => 'object' ),
1538 ),
1539 'form_settings' => array(
1540 'type' => 'object',
1541 'description' => __( 'Form-level toggles (coupon, shipping, additional fields).', 'cartflows' ),
1542 ),
1543 'button_settings' => array(
1544 'type' => 'object',
1545 'description' => __( 'Place order button configuration.', 'cartflows' ),
1546 ),
1547 'advanced_settings' => array(
1548 'type' => 'object',
1549 'description' => __( 'Product images, cart editing toggles.', 'cartflows' ),
1550 ),
1551 ),
1552 ),
1553 'execute_callback' => function ( $input ) use ( $cf ) {
1554 return $cf->get_checkout_settings( $input );
1555 },
1556 'meta' => array(
1557 'uri' => 'cartflows://steps/checkout/{id}/settings',
1558 'annotations' => array(
1559 'priority' => 1.0,
1560 'readOnlyHint' => true,
1561 'destructiveHint' => false,
1562 'idempotentHint' => true,
1563 'openWorldHint' => false,
1564 ),
1565 'show_in_rest' => true,
1566 'mcp' => array(
1567 'public' => true,
1568 'type' => 'resource',
1569 ),
1570 ),
1571 ),
1572
1573 // Get checkout products.
1574 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-checkout-products' => array(
1575 'label' => __( 'Get checkout products', 'cartflows' ),
1576 'description' => __( 'Returns the list of WooCommerce products assigned to a checkout step, including product ID, name, quantity, discount type/value, and thumbnail URL. Requires WooCommerce. Use to inspect what products will be added to cart when a customer visits this checkout.', 'cartflows' ),
1577 'category' => 'cartflows',
1578 'permission_callback' => function () use ( $cf ) {
1579 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1580 },
1581 'input_schema' => array(
1582 'type' => 'object',
1583 'required' => array( 'step_id' ),
1584 'properties' => array(
1585 'step_id' => array(
1586 'type' => 'integer',
1587 'description' => __( 'The checkout step ID.', 'cartflows' ),
1588 ),
1589 ),
1590 ),
1591 'output_schema' => array(
1592 'type' => 'object',
1593 'properties' => array(
1594 'step_id' => array(
1595 'type' => 'integer',
1596 'description' => __( 'Step ID.', 'cartflows' ),
1597 ),
1598 'products' => array(
1599 'type' => 'array',
1600 'description' => __( 'Assigned products.', 'cartflows' ),
1601 'items' => array(
1602 'type' => 'object',
1603 'properties' => array(
1604 'product_id' => array(
1605 'type' => 'integer',
1606 'description' => __( 'WooCommerce product ID.', 'cartflows' ),
1607 ),
1608 'name' => array(
1609 'type' => 'string',
1610 'description' => __( 'Product name.', 'cartflows' ),
1611 ),
1612 'quantity' => array(
1613 'type' => 'integer',
1614 'description' => __( 'Quantity.', 'cartflows' ),
1615 ),
1616 'discount_type' => array(
1617 'type' => 'string',
1618 'description' => __( 'Discount type (e.g. discount_percent, discount_price).', 'cartflows' ),
1619 ),
1620 'discount_value' => array(
1621 'type' => 'string',
1622 'description' => __( 'Discount amount.', 'cartflows' ),
1623 ),
1624 'add_to_cart' => array(
1625 'type' => 'string',
1626 'description' => __( 'Whether added to cart (yes/no).', 'cartflows' ),
1627 ),
1628 'img_url' => array(
1629 'type' => 'string',
1630 'description' => __( 'Product thumbnail URL.', 'cartflows' ),
1631 ),
1632 'regular_price' => array(
1633 'type' => 'string',
1634 'description' => __( 'Regular price.', 'cartflows' ),
1635 ),
1636 ),
1637 ),
1638 ),
1639 ),
1640 ),
1641 'execute_callback' => function ( $input ) use ( $cf ) {
1642 return $cf->get_checkout_products( $input );
1643 },
1644 'meta' => array(
1645 'uri' => 'cartflows://steps/checkout/{id}/products',
1646 'annotations' => array(
1647 'priority' => 1.0,
1648 'readOnlyHint' => true,
1649 'destructiveHint' => false,
1650 'idempotentHint' => true,
1651 'openWorldHint' => false,
1652 ),
1653 'show_in_rest' => true,
1654 'mcp' => array(
1655 'public' => true,
1656 'type' => 'resource',
1657 ),
1658 ),
1659 ),
1660
1661 // Get checkout form fields.
1662 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-checkout-fields' => array(
1663 'label' => __( 'Get checkout form fields', 'cartflows' ),
1664 'description' => __( 'Returns the billing and shipping field configuration for a checkout step, including field order, labels, enabled/required/optimized states, and widths. Also returns form-level toggles (coupon, additional fields, shipping). Requires WooCommerce. Use to inspect field layout before making changes.', 'cartflows' ),
1665 'category' => 'cartflows',
1666 'permission_callback' => function () use ( $cf ) {
1667 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
1668 },
1669 'input_schema' => array(
1670 'type' => 'object',
1671 'required' => array( 'step_id' ),
1672 'properties' => array(
1673 'step_id' => array(
1674 'type' => 'integer',
1675 'description' => __( 'The checkout step ID.', 'cartflows' ),
1676 ),
1677 'field_type' => array(
1678 'type' => 'string',
1679 'enum' => array( 'billing', 'shipping', 'all' ),
1680 'default' => 'all',
1681 'description' => __( 'Which field group to return. Defaults to all.', 'cartflows' ),
1682 ),
1683 ),
1684 ),
1685 'output_schema' => array(
1686 'type' => 'object',
1687 'properties' => array(
1688 'step_id' => array(
1689 'type' => 'integer',
1690 'description' => __( 'Step ID.', 'cartflows' ),
1691 ),
1692 'billing_fields' => array(
1693 'type' => 'object',
1694 'description' => __( 'Billing field configuration keyed by field name.', 'cartflows' ),
1695 ),
1696 'shipping_fields' => array(
1697 'type' => 'object',
1698 'description' => __( 'Shipping field configuration keyed by field name.', 'cartflows' ),
1699 ),
1700 'form_settings' => array(
1701 'type' => 'object',
1702 'description' => __( 'Form-level toggles.', 'cartflows' ),
1703 ),
1704 ),
1705 ),
1706 'execute_callback' => function ( $input ) use ( $cf ) {
1707 return $cf->get_checkout_fields( $input );
1708 },
1709 'meta' => array(
1710 'uri' => 'cartflows://steps/checkout/{id}/fields',
1711 'annotations' => array(
1712 'priority' => 1.0,
1713 'readOnlyHint' => true,
1714 'destructiveHint' => false,
1715 'idempotentHint' => true,
1716 'openWorldHint' => false,
1717 ),
1718 'show_in_rest' => true,
1719 'mcp' => array(
1720 'public' => true,
1721 'type' => 'resource',
1722 ),
1723 ),
1724 ),
1725
1726 // ============================================================
1727 // Checkout — Configuration / Write
1728 // ============================================================
1729
1730 // Update checkout products.
1731 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-checkout-products' => array(
1732 'label' => __( 'Update checkout products', 'cartflows' ),
1733 'description' => __( 'Sets or replaces the products assigned to a checkout step. Each product entry specifies a WooCommerce product ID, quantity, and optional discount. Requires WooCommerce. Use to configure which products are pre-loaded into the cart when a customer visits the checkout.', 'cartflows' ),
1734 'category' => 'cartflows',
1735 'permission_callback' => function () use ( $cf ) {
1736 return (
1737 get_option( 'cartflows_abilities_api_write', true ) &&
1738 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1739 );
1740 },
1741 'input_schema' => array(
1742 'type' => 'object',
1743 'required' => array( 'step_id', 'products' ),
1744 'properties' => array(
1745 'step_id' => array(
1746 'type' => 'integer',
1747 'description' => __( 'The checkout step ID.', 'cartflows' ),
1748 ),
1749 'products' => array(
1750 'type' => 'array',
1751 'description' => __( 'Array of product configurations.', 'cartflows' ),
1752 'items' => array(
1753 'type' => 'object',
1754 'properties' => array(
1755 'product' => array(
1756 'type' => 'integer',
1757 'description' => __( 'WooCommerce product ID.', 'cartflows' ),
1758 ),
1759 'quantity' => array(
1760 'type' => 'integer',
1761 'description' => __( 'Quantity. Defaults to 1.', 'cartflows' ),
1762 ),
1763 'discount_type' => array(
1764 'type' => 'string',
1765 'enum' => array( '', 'discount_percent', 'discount_price', 'coupon' ),
1766 'default' => '',
1767 'description' => __( 'Type of discount to apply.', 'cartflows' ),
1768 ),
1769 'discount_value' => array(
1770 'type' => 'string',
1771 'default' => '',
1772 'description' => __( 'Discount amount.', 'cartflows' ),
1773 ),
1774 'add_to_cart' => array(
1775 'type' => 'string',
1776 'enum' => array( 'yes', 'no' ),
1777 'default' => 'yes',
1778 'description' => __( 'Whether to add this product to cart.', 'cartflows' ),
1779 ),
1780 ),
1781 ),
1782 ),
1783 ),
1784 ),
1785 'output_schema' => array(
1786 'type' => 'object',
1787 'properties' => array(
1788 'step_id' => array(
1789 'type' => 'integer',
1790 'description' => __( 'Step ID.', 'cartflows' ),
1791 ),
1792 'products' => array(
1793 'type' => 'array',
1794 'description' => __( 'Saved product list.', 'cartflows' ),
1795 ),
1796 'message' => array(
1797 'type' => 'string',
1798 'description' => __( 'Result message.', 'cartflows' ),
1799 ),
1800 ),
1801 ),
1802 'execute_callback' => function ( $input ) use ( $cf ) {
1803 return $cf->update_checkout_products( $input );
1804 },
1805 'meta' => array(
1806 'annotations' => array(
1807 'priority' => 2.0,
1808 'readOnlyHint' => false,
1809 'destructiveHint' => false,
1810 'idempotentHint' => true,
1811 'openWorldHint' => false,
1812 ),
1813 'show_in_rest' => true,
1814 'mcp' => array(
1815 'public' => true,
1816 'type' => 'tool',
1817 ),
1818 ),
1819 ),
1820
1821 // Update checkout layout.
1822 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-checkout-layout' => array(
1823 'label' => __( 'Update checkout layout', 'cartflows' ),
1824 'description' => __( 'Changes the checkout skin/layout for a step. Available Free layouts: modern-checkout, modern-one-column, one-column, two-column. Pro-only layouts (two-step, multistep-checkout) are not available through this ability. Requires WooCommerce.', 'cartflows' ),
1825 'category' => 'cartflows',
1826 'permission_callback' => function () use ( $cf ) {
1827 return (
1828 get_option( 'cartflows_abilities_api_write', true ) &&
1829 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1830 );
1831 },
1832 'input_schema' => array(
1833 'type' => 'object',
1834 'required' => array( 'step_id', 'layout' ),
1835 'properties' => array(
1836 'step_id' => array(
1837 'type' => 'integer',
1838 'description' => __( 'The checkout step ID.', 'cartflows' ),
1839 ),
1840 'layout' => array(
1841 'type' => 'string',
1842 'enum' => array( 'modern-checkout', 'modern-one-column', 'one-column', 'two-column' ),
1843 'description' => __( 'Checkout skin to apply.', 'cartflows' ),
1844 ),
1845 ),
1846 ),
1847 'output_schema' => array(
1848 'type' => 'object',
1849 'properties' => array(
1850 'step_id' => array(
1851 'type' => 'integer',
1852 'description' => __( 'Step ID.', 'cartflows' ),
1853 ),
1854 'layout' => array(
1855 'type' => 'string',
1856 'description' => __( 'Applied layout.', 'cartflows' ),
1857 ),
1858 'message' => array(
1859 'type' => 'string',
1860 'description' => __( 'Result message.', 'cartflows' ),
1861 ),
1862 ),
1863 ),
1864 'execute_callback' => function ( $input ) use ( $cf ) {
1865 return $cf->update_checkout_layout( $input );
1866 },
1867 'meta' => array(
1868 'annotations' => array(
1869 'priority' => 2.0,
1870 'readOnlyHint' => false,
1871 'destructiveHint' => false,
1872 'idempotentHint' => true,
1873 'openWorldHint' => false,
1874 ),
1875 'show_in_rest' => true,
1876 'mcp' => array(
1877 'public' => true,
1878 'type' => 'tool',
1879 ),
1880 ),
1881 ),
1882
1883 // Update place order button.
1884 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-checkout-place-order-button' => array(
1885 'label' => __( 'Update place order button', 'cartflows' ),
1886 'description' => __( 'Configures the checkout Place Order button: text, lock icon toggle, and price display toggle. Only provided fields are updated; omitted fields retain their current values. Requires WooCommerce.', 'cartflows' ),
1887 'category' => 'cartflows',
1888 'permission_callback' => function () use ( $cf ) {
1889 return (
1890 get_option( 'cartflows_abilities_api_write', true ) &&
1891 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1892 );
1893 },
1894 'input_schema' => array(
1895 'type' => 'object',
1896 'required' => array( 'step_id' ),
1897 'properties' => array(
1898 'step_id' => array(
1899 'type' => 'integer',
1900 'description' => __( 'The checkout step ID.', 'cartflows' ),
1901 ),
1902 'button_text' => array(
1903 'type' => 'string',
1904 'description' => __( 'Place order button text.', 'cartflows' ),
1905 ),
1906 'show_lock_icon' => array(
1907 'type' => 'string',
1908 'enum' => array( 'yes', 'no' ),
1909 'description' => __( 'Show lock icon on button.', 'cartflows' ),
1910 ),
1911 'show_price' => array(
1912 'type' => 'string',
1913 'enum' => array( 'yes', 'no' ),
1914 'description' => __( 'Show cart total on button.', 'cartflows' ),
1915 ),
1916 ),
1917 ),
1918 'output_schema' => array(
1919 'type' => 'object',
1920 'properties' => array(
1921 'step_id' => array(
1922 'type' => 'integer',
1923 'description' => __( 'Step ID.', 'cartflows' ),
1924 ),
1925 'button_text' => array(
1926 'type' => 'string',
1927 'description' => __( 'Button text.', 'cartflows' ),
1928 ),
1929 'show_lock_icon' => array(
1930 'type' => 'string',
1931 'description' => __( 'Lock icon toggle.', 'cartflows' ),
1932 ),
1933 'show_price' => array(
1934 'type' => 'string',
1935 'description' => __( 'Price display toggle.', 'cartflows' ),
1936 ),
1937 'message' => array(
1938 'type' => 'string',
1939 'description' => __( 'Result message.', 'cartflows' ),
1940 ),
1941 ),
1942 ),
1943 'execute_callback' => function ( $input ) use ( $cf ) {
1944 return $cf->update_checkout_place_order_button( $input );
1945 },
1946 'meta' => array(
1947 'annotations' => array(
1948 'priority' => 2.0,
1949 'readOnlyHint' => false,
1950 'destructiveHint' => false,
1951 'idempotentHint' => true,
1952 'openWorldHint' => false,
1953 ),
1954 'show_in_rest' => true,
1955 'mcp' => array(
1956 'public' => true,
1957 'type' => 'tool',
1958 ),
1959 ),
1960 ),
1961
1962 // Update checkout form settings.
1963 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-checkout-form-settings' => array(
1964 'label' => __( 'Update checkout form settings', 'cartflows' ),
1965 'description' => __( 'Toggles form-level settings on a checkout step: coupon field, collapsible coupon, additional fields, collapsible order note, ship-to-different-address, Google address autocomplete, product images in order review, and cart editing. Only provided fields are updated. Requires WooCommerce.', 'cartflows' ),
1966 'category' => 'cartflows',
1967 'permission_callback' => function () use ( $cf ) {
1968 return (
1969 get_option( 'cartflows_abilities_api_write', true ) &&
1970 $cf->permission_callback( 'cartflows_manage_flows_steps' )
1971 );
1972 },
1973 'input_schema' => array(
1974 'type' => 'object',
1975 'required' => array( 'step_id' ),
1976 'properties' => array(
1977 'step_id' => array(
1978 'type' => 'integer',
1979 'description' => __( 'The checkout step ID.', 'cartflows' ),
1980 ),
1981 'show_coupon_field' => array(
1982 'type' => 'string',
1983 'enum' => array( 'yes', 'no' ),
1984 'description' => __( 'Show coupon field.', 'cartflows' ),
1985 ),
1986 'optimize_coupon_field' => array(
1987 'type' => 'string',
1988 'enum' => array( 'yes', 'no' ),
1989 'description' => __( 'Make coupon field collapsible.', 'cartflows' ),
1990 ),
1991 'show_additional_fields' => array(
1992 'type' => 'string',
1993 'enum' => array( 'yes', 'no' ),
1994 'description' => __( 'Show additional (order notes) field.', 'cartflows' ),
1995 ),
1996 'optimize_order_note' => array(
1997 'type' => 'string',
1998 'enum' => array( 'yes', 'no' ),
1999 'description' => __( 'Make order note field collapsible.', 'cartflows' ),
2000 ),
2001 'ship_to_different_address' => array(
2002 'type' => 'string',
2003 'enum' => array( 'yes', 'no' ),
2004 'description' => __( 'Enable ship to different address.', 'cartflows' ),
2005 ),
2006 'google_autoaddress' => array(
2007 'type' => 'string',
2008 'enum' => array( 'yes', 'no' ),
2009 'description' => __( 'Enable Google address autocomplete.', 'cartflows' ),
2010 ),
2011 'show_product_images' => array(
2012 'type' => 'string',
2013 'enum' => array( 'yes', 'no' ),
2014 'description' => __( 'Show product images in order review.', 'cartflows' ),
2015 ),
2016 'enable_cart_editing' => array(
2017 'type' => 'string',
2018 'enum' => array( 'yes', 'no' ),
2019 'description' => __( 'Allow removing products from checkout.', 'cartflows' ),
2020 ),
2021 ),
2022 ),
2023 'output_schema' => array(
2024 'type' => 'object',
2025 'properties' => array(
2026 'step_id' => array(
2027 'type' => 'integer',
2028 'description' => __( 'Step ID.', 'cartflows' ),
2029 ),
2030 'settings' => array(
2031 'type' => 'object',
2032 'description' => __( 'Updated form settings.', 'cartflows' ),
2033 ),
2034 'message' => array(
2035 'type' => 'string',
2036 'description' => __( 'Result message.', 'cartflows' ),
2037 ),
2038 ),
2039 ),
2040 'execute_callback' => function ( $input ) use ( $cf ) {
2041 return $cf->update_checkout_form_settings( $input );
2042 },
2043 'meta' => array(
2044 'annotations' => array(
2045 'priority' => 2.0,
2046 'readOnlyHint' => false,
2047 'destructiveHint' => false,
2048 'idempotentHint' => true,
2049 'openWorldHint' => false,
2050 ),
2051 'show_in_rest' => true,
2052 'mcp' => array(
2053 'public' => true,
2054 'type' => 'tool',
2055 ),
2056 ),
2057 ),
2058
2059 // ============================================================
2060 // Thank You — Configuration / Read
2061 // ============================================================
2062
2063 // Get thank you step settings.
2064 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-thankyou-settings' => array(
2065 'label' => __( 'Get thank you step settings', 'cartflows' ),
2066 'description' => __( 'Returns the full configuration of a thank you step: layout skin, section visibility toggles (order overview, order details, billing, shipping), custom thank you text, redirect settings, and design options. Requires WooCommerce. Use to inspect or audit a thank you step before making changes.', 'cartflows' ),
2067 'category' => 'cartflows',
2068 'permission_callback' => function () use ( $cf ) {
2069 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2070 },
2071 'input_schema' => array(
2072 'type' => 'object',
2073 'required' => array( 'step_id' ),
2074 'properties' => array(
2075 'step_id' => array(
2076 'type' => 'integer',
2077 'description' => __( 'The thank you step ID.', 'cartflows' ),
2078 ),
2079 ),
2080 ),
2081 'output_schema' => array(
2082 'type' => 'object',
2083 'properties' => array(
2084 'step_id' => array(
2085 'type' => 'integer',
2086 'description' => __( 'Step ID.', 'cartflows' ),
2087 ),
2088 'layout' => array(
2089 'type' => 'string',
2090 'description' => __( 'Thank you skin (legacy-tq-layout or modern-tq-layout).', 'cartflows' ),
2091 ),
2092 'sections' => array(
2093 'type' => 'object',
2094 'description' => __( 'Section visibility toggles (show_overview, show_details, show_billing, show_shipping).', 'cartflows' ),
2095 ),
2096 'custom_text' => array(
2097 'type' => 'string',
2098 'description' => __( 'Custom thank you page message text.', 'cartflows' ),
2099 ),
2100 'redirect' => array(
2101 'type' => 'object',
2102 'description' => __( 'Redirect settings (enabled, redirect_url).', 'cartflows' ),
2103 ),
2104 'design' => array(
2105 'type' => 'object',
2106 'description' => __( 'Design settings (colors, fonts, container width).', 'cartflows' ),
2107 ),
2108 ),
2109 ),
2110 'execute_callback' => function ( $input ) use ( $cf ) {
2111 return $cf->get_thankyou_settings( $input );
2112 },
2113 'meta' => array(
2114 'uri' => 'cartflows://steps/thankyou/{id}/settings',
2115 'annotations' => array(
2116 'priority' => 1.0,
2117 'readOnlyHint' => true,
2118 'destructiveHint' => false,
2119 'idempotentHint' => true,
2120 'openWorldHint' => false,
2121 ),
2122 'show_in_rest' => true,
2123 'mcp' => array(
2124 'public' => true,
2125 'type' => 'resource',
2126 ),
2127 ),
2128 ),
2129
2130 // ============================================================
2131 // Thank You — Configuration / Write
2132 // ============================================================
2133
2134 // Update thank you layout.
2135 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-thankyou-layout' => array(
2136 'label' => __( 'Update thank you layout', 'cartflows' ),
2137 'description' => __( 'Changes the thank you page skin/layout for a step. Available layouts: legacy-tq-layout (classic table-based) or modern-tq-layout (styled modern design). Requires WooCommerce.', 'cartflows' ),
2138 'category' => 'cartflows',
2139 'permission_callback' => function () use ( $cf ) {
2140 return (
2141 get_option( 'cartflows_abilities_api_write', true ) &&
2142 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2143 );
2144 },
2145 'input_schema' => array(
2146 'type' => 'object',
2147 'required' => array( 'step_id', 'layout' ),
2148 'properties' => array(
2149 'step_id' => array(
2150 'type' => 'integer',
2151 'description' => __( 'The thank you step ID.', 'cartflows' ),
2152 ),
2153 'layout' => array(
2154 'type' => 'string',
2155 'enum' => array( 'legacy-tq-layout', 'modern-tq-layout' ),
2156 'description' => __( 'Thank you skin to apply.', 'cartflows' ),
2157 ),
2158 ),
2159 ),
2160 'output_schema' => array(
2161 'type' => 'object',
2162 'properties' => array(
2163 'step_id' => array(
2164 'type' => 'integer',
2165 'description' => __( 'Step ID.', 'cartflows' ),
2166 ),
2167 'layout' => array(
2168 'type' => 'string',
2169 'description' => __( 'Applied layout.', 'cartflows' ),
2170 ),
2171 'message' => array(
2172 'type' => 'string',
2173 'description' => __( 'Result message.', 'cartflows' ),
2174 ),
2175 ),
2176 ),
2177 'execute_callback' => function ( $input ) use ( $cf ) {
2178 return $cf->update_thankyou_layout( $input );
2179 },
2180 'meta' => array(
2181 'annotations' => array(
2182 'priority' => 2.0,
2183 'readOnlyHint' => false,
2184 'destructiveHint' => false,
2185 'idempotentHint' => true,
2186 'openWorldHint' => false,
2187 ),
2188 'show_in_rest' => true,
2189 'mcp' => array(
2190 'public' => true,
2191 'type' => 'tool',
2192 ),
2193 ),
2194 ),
2195
2196 // Update thank you section visibility.
2197 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-thankyou-sections' => array(
2198 'label' => __( 'Update thank you sections', 'cartflows' ),
2199 'description' => __( 'Toggles visibility of order sections on a thank you step: order overview, order details, billing details, and shipping details. Only provided fields are updated; omitted fields retain their current values. Requires WooCommerce.', 'cartflows' ),
2200 'category' => 'cartflows',
2201 'permission_callback' => function () use ( $cf ) {
2202 return (
2203 get_option( 'cartflows_abilities_api_write', true ) &&
2204 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2205 );
2206 },
2207 'input_schema' => array(
2208 'type' => 'object',
2209 'required' => array( 'step_id' ),
2210 'properties' => array(
2211 'step_id' => array(
2212 'type' => 'integer',
2213 'description' => __( 'The thank you step ID.', 'cartflows' ),
2214 ),
2215 'show_overview' => array(
2216 'type' => 'string',
2217 'enum' => array( 'yes', 'no' ),
2218 'description' => __( 'Show order overview section.', 'cartflows' ),
2219 ),
2220 'show_details' => array(
2221 'type' => 'string',
2222 'enum' => array( 'yes', 'no' ),
2223 'description' => __( 'Show order details section.', 'cartflows' ),
2224 ),
2225 'show_billing' => array(
2226 'type' => 'string',
2227 'enum' => array( 'yes', 'no' ),
2228 'description' => __( 'Show billing details section.', 'cartflows' ),
2229 ),
2230 'show_shipping' => array(
2231 'type' => 'string',
2232 'enum' => array( 'yes', 'no' ),
2233 'description' => __( 'Show shipping details section.', 'cartflows' ),
2234 ),
2235 ),
2236 ),
2237 'output_schema' => array(
2238 'type' => 'object',
2239 'properties' => array(
2240 'step_id' => array(
2241 'type' => 'integer',
2242 'description' => __( 'Step ID.', 'cartflows' ),
2243 ),
2244 'sections' => array(
2245 'type' => 'object',
2246 'description' => __( 'Updated section visibility state.', 'cartflows' ),
2247 ),
2248 'message' => array(
2249 'type' => 'string',
2250 'description' => __( 'Result message.', 'cartflows' ),
2251 ),
2252 ),
2253 ),
2254 'execute_callback' => function ( $input ) use ( $cf ) {
2255 return $cf->update_thankyou_sections( $input );
2256 },
2257 'meta' => array(
2258 'annotations' => array(
2259 'priority' => 2.0,
2260 'readOnlyHint' => false,
2261 'destructiveHint' => false,
2262 'idempotentHint' => true,
2263 'openWorldHint' => false,
2264 ),
2265 'show_in_rest' => true,
2266 'mcp' => array(
2267 'public' => true,
2268 'type' => 'tool',
2269 ),
2270 ),
2271 ),
2272
2273 // Update thank you redirect settings.
2274 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-thankyou-redirect' => array(
2275 'label' => __( 'Update thank you redirect', 'cartflows' ),
2276 'description' => __( 'Configures post-purchase redirect on a thank you step. When enabled, visitors are redirected to the specified URL instead of seeing the thank you page. Requires WooCommerce.', 'cartflows' ),
2277 'category' => 'cartflows',
2278 'permission_callback' => function () use ( $cf ) {
2279 return (
2280 get_option( 'cartflows_abilities_api_write', true ) &&
2281 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2282 );
2283 },
2284 'input_schema' => array(
2285 'type' => 'object',
2286 'required' => array( 'step_id' ),
2287 'properties' => array(
2288 'step_id' => array(
2289 'type' => 'integer',
2290 'description' => __( 'The thank you step ID.', 'cartflows' ),
2291 ),
2292 'enabled' => array(
2293 'type' => 'string',
2294 'enum' => array( 'yes', 'no' ),
2295 'description' => __( 'Enable or disable redirect after purchase.', 'cartflows' ),
2296 ),
2297 'redirect_url' => array(
2298 'type' => 'string',
2299 'description' => __( 'The URL to redirect to after purchase.', 'cartflows' ),
2300 ),
2301 ),
2302 ),
2303 'output_schema' => array(
2304 'type' => 'object',
2305 'properties' => array(
2306 'step_id' => array(
2307 'type' => 'integer',
2308 'description' => __( 'Step ID.', 'cartflows' ),
2309 ),
2310 'enabled' => array(
2311 'type' => 'string',
2312 'description' => __( 'Redirect enabled state.', 'cartflows' ),
2313 ),
2314 'redirect_url' => array(
2315 'type' => 'string',
2316 'description' => __( 'Redirect URL.', 'cartflows' ),
2317 ),
2318 'message' => array(
2319 'type' => 'string',
2320 'description' => __( 'Result message.', 'cartflows' ),
2321 ),
2322 ),
2323 ),
2324 'execute_callback' => function ( $input ) use ( $cf ) {
2325 return $cf->update_thankyou_redirect( $input );
2326 },
2327 'meta' => array(
2328 'annotations' => array(
2329 'priority' => 2.0,
2330 'readOnlyHint' => false,
2331 'destructiveHint' => false,
2332 'idempotentHint' => true,
2333 'openWorldHint' => false,
2334 ),
2335 'show_in_rest' => true,
2336 'mcp' => array(
2337 'public' => true,
2338 'type' => 'tool',
2339 ),
2340 ),
2341 ),
2342
2343 // Update thank you custom text.
2344 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-thankyou-custom-text' => array(
2345 'label' => __( 'Update thank you custom text', 'cartflows' ),
2346 'description' => __( 'Sets the custom message text displayed on a thank you page. This replaces the default WooCommerce "Thank you. Your order has been received." message. Requires WooCommerce.', 'cartflows' ),
2347 'category' => 'cartflows',
2348 'permission_callback' => function () use ( $cf ) {
2349 return (
2350 get_option( 'cartflows_abilities_api_write', true ) &&
2351 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2352 );
2353 },
2354 'input_schema' => array(
2355 'type' => 'object',
2356 'required' => array( 'step_id', 'text' ),
2357 'properties' => array(
2358 'step_id' => array(
2359 'type' => 'integer',
2360 'description' => __( 'The thank you step ID.', 'cartflows' ),
2361 ),
2362 'text' => array(
2363 'type' => 'string',
2364 'description' => __( 'Custom thank you page message text. Supports shortcodes.', 'cartflows' ),
2365 ),
2366 ),
2367 ),
2368 'output_schema' => array(
2369 'type' => 'object',
2370 'properties' => array(
2371 'step_id' => array(
2372 'type' => 'integer',
2373 'description' => __( 'Step ID.', 'cartflows' ),
2374 ),
2375 'text' => array(
2376 'type' => 'string',
2377 'description' => __( 'Saved custom text.', 'cartflows' ),
2378 ),
2379 'message' => array(
2380 'type' => 'string',
2381 'description' => __( 'Result message.', 'cartflows' ),
2382 ),
2383 ),
2384 ),
2385 'execute_callback' => function ( $input ) use ( $cf ) {
2386 return $cf->update_thankyou_custom_text( $input );
2387 },
2388 'meta' => array(
2389 'annotations' => array(
2390 'priority' => 2.0,
2391 'readOnlyHint' => false,
2392 'destructiveHint' => false,
2393 'idempotentHint' => true,
2394 'openWorldHint' => false,
2395 ),
2396 'show_in_rest' => true,
2397 'mcp' => array(
2398 'public' => true,
2399 'type' => 'tool',
2400 ),
2401 ),
2402 ),
2403
2404 // ============================================================
2405 // Optin — Configuration / Read
2406 // ============================================================
2407
2408 // Get optin step settings.
2409 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-optin-settings' => array(
2410 'label' => __( 'Get optin step settings', 'cartflows' ),
2411 'description' => __( 'Returns the full configuration of an optin step: assigned product, submit button text, pass-fields settings, and billing field list. Requires WooCommerce. Use to inspect or audit an optin step before making changes.', 'cartflows' ),
2412 'category' => 'cartflows',
2413 'permission_callback' => function () use ( $cf ) {
2414 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2415 },
2416 'input_schema' => array(
2417 'type' => 'object',
2418 'required' => array( 'step_id' ),
2419 'properties' => array(
2420 'step_id' => array(
2421 'type' => 'integer',
2422 'description' => __( 'The optin step ID.', 'cartflows' ),
2423 ),
2424 ),
2425 ),
2426 'output_schema' => array(
2427 'type' => 'object',
2428 'properties' => array(
2429 'step_id' => array(
2430 'type' => 'integer',
2431 'description' => __( 'Step ID.', 'cartflows' ),
2432 ),
2433 'product' => array(
2434 'type' => 'object',
2435 'description' => __( 'Assigned product (id, name). Must be simple, virtual, and free.', 'cartflows' ),
2436 ),
2437 'button_text' => array(
2438 'type' => 'string',
2439 'description' => __( 'Submit button text.', 'cartflows' ),
2440 ),
2441 'pass_fields' => array(
2442 'type' => 'object',
2443 'description' => __( 'URL parameter passing settings (enabled, specific_fields).', 'cartflows' ),
2444 ),
2445 ),
2446 ),
2447 'execute_callback' => function ( $input ) use ( $cf ) {
2448 return $cf->get_optin_settings( $input );
2449 },
2450 'meta' => array(
2451 'uri' => 'cartflows://steps/optin/{id}/settings',
2452 'annotations' => array(
2453 'priority' => 1.0,
2454 'readOnlyHint' => true,
2455 'destructiveHint' => false,
2456 'idempotentHint' => true,
2457 'openWorldHint' => false,
2458 ),
2459 'show_in_rest' => true,
2460 'mcp' => array(
2461 'public' => true,
2462 'type' => 'resource',
2463 ),
2464 ),
2465 ),
2466
2467 // ============================================================
2468 // Optin — Configuration / Write
2469 // ============================================================
2470
2471 // Update optin product.
2472 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-optin-product' => array(
2473 'label' => __( 'Update optin product', 'cartflows' ),
2474 'description' => __( 'Sets the WooCommerce product assigned to an optin step. The product must be a Simple, Virtual, and Free (price = 0) product. Requires WooCommerce.', 'cartflows' ),
2475 'category' => 'cartflows',
2476 'permission_callback' => function () use ( $cf ) {
2477 return (
2478 get_option( 'cartflows_abilities_api_write', true ) &&
2479 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2480 );
2481 },
2482 'input_schema' => array(
2483 'type' => 'object',
2484 'required' => array( 'step_id', 'product_id' ),
2485 'properties' => array(
2486 'step_id' => array(
2487 'type' => 'integer',
2488 'description' => __( 'The optin step ID.', 'cartflows' ),
2489 ),
2490 'product_id' => array(
2491 'type' => 'integer',
2492 'description' => __( 'WooCommerce product ID. Must be a simple, virtual, and free product.', 'cartflows' ),
2493 ),
2494 ),
2495 ),
2496 'output_schema' => array(
2497 'type' => 'object',
2498 'properties' => array(
2499 'step_id' => array(
2500 'type' => 'integer',
2501 'description' => __( 'Step ID.', 'cartflows' ),
2502 ),
2503 'product_id' => array(
2504 'type' => 'integer',
2505 'description' => __( 'Assigned product ID.', 'cartflows' ),
2506 ),
2507 'product_name' => array(
2508 'type' => 'string',
2509 'description' => __( 'Assigned product name.', 'cartflows' ),
2510 ),
2511 'message' => array(
2512 'type' => 'string',
2513 'description' => __( 'Result message.', 'cartflows' ),
2514 ),
2515 ),
2516 ),
2517 'execute_callback' => function ( $input ) use ( $cf ) {
2518 return $cf->update_optin_product( $input );
2519 },
2520 'meta' => array(
2521 'annotations' => array(
2522 'priority' => 2.0,
2523 'readOnlyHint' => false,
2524 'destructiveHint' => false,
2525 'idempotentHint' => true,
2526 'openWorldHint' => false,
2527 ),
2528 'show_in_rest' => true,
2529 'mcp' => array(
2530 'public' => true,
2531 'type' => 'tool',
2532 ),
2533 ),
2534 ),
2535
2536 // Update optin button text.
2537 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-optin-button-text' => array(
2538 'label' => __( 'Update optin button text', 'cartflows' ),
2539 'description' => __( 'Changes the submit button text on an optin form. Use to customize the call-to-action, for example "Get Started" or "Subscribe Now". Requires WooCommerce.', 'cartflows' ),
2540 'category' => 'cartflows',
2541 'permission_callback' => function () use ( $cf ) {
2542 return (
2543 get_option( 'cartflows_abilities_api_write', true ) &&
2544 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2545 );
2546 },
2547 'input_schema' => array(
2548 'type' => 'object',
2549 'required' => array( 'step_id', 'button_text' ),
2550 'properties' => array(
2551 'step_id' => array(
2552 'type' => 'integer',
2553 'description' => __( 'The optin step ID.', 'cartflows' ),
2554 ),
2555 'button_text' => array(
2556 'type' => 'string',
2557 'description' => __( 'New submit button text.', 'cartflows' ),
2558 ),
2559 ),
2560 ),
2561 'output_schema' => array(
2562 'type' => 'object',
2563 'properties' => array(
2564 'step_id' => array(
2565 'type' => 'integer',
2566 'description' => __( 'Step ID.', 'cartflows' ),
2567 ),
2568 'button_text' => array(
2569 'type' => 'string',
2570 'description' => __( 'Saved button text.', 'cartflows' ),
2571 ),
2572 'message' => array(
2573 'type' => 'string',
2574 'description' => __( 'Result message.', 'cartflows' ),
2575 ),
2576 ),
2577 ),
2578 'execute_callback' => function ( $input ) use ( $cf ) {
2579 return $cf->update_optin_button_text( $input );
2580 },
2581 'meta' => array(
2582 'annotations' => array(
2583 'priority' => 2.0,
2584 'readOnlyHint' => false,
2585 'destructiveHint' => false,
2586 'idempotentHint' => true,
2587 'openWorldHint' => false,
2588 ),
2589 'show_in_rest' => true,
2590 'mcp' => array(
2591 'public' => true,
2592 'type' => 'tool',
2593 ),
2594 ),
2595 ),
2596
2597 // Update optin pass fields settings.
2598 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-optin-pass-fields' => array(
2599 'label' => __( 'Update optin pass fields', 'cartflows' ),
2600 'description' => __( 'Configures whether optin form fields are passed as URL query parameters to the next funnel step. When enabled, specify which fields to pass (e.g. first_name, last_name, email). Requires WooCommerce.', 'cartflows' ),
2601 'category' => 'cartflows',
2602 'permission_callback' => function () use ( $cf ) {
2603 return (
2604 get_option( 'cartflows_abilities_api_write', true ) &&
2605 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2606 );
2607 },
2608 'input_schema' => array(
2609 'type' => 'object',
2610 'required' => array( 'step_id' ),
2611 'properties' => array(
2612 'step_id' => array(
2613 'type' => 'integer',
2614 'description' => __( 'The optin step ID.', 'cartflows' ),
2615 ),
2616 'enabled' => array(
2617 'type' => 'string',
2618 'enum' => array( 'yes', 'no' ),
2619 'description' => __( 'Enable or disable passing fields as URL parameters.', 'cartflows' ),
2620 ),
2621 'specific_fields' => array(
2622 'type' => 'string',
2623 'description' => __( 'Comma-separated field names to pass (e.g. first_name, last_name).', 'cartflows' ),
2624 ),
2625 ),
2626 ),
2627 'output_schema' => array(
2628 'type' => 'object',
2629 'properties' => array(
2630 'step_id' => array(
2631 'type' => 'integer',
2632 'description' => __( 'Step ID.', 'cartflows' ),
2633 ),
2634 'enabled' => array(
2635 'type' => 'string',
2636 'description' => __( 'Pass fields enabled state.', 'cartflows' ),
2637 ),
2638 'specific_fields' => array(
2639 'type' => 'string',
2640 'description' => __( 'Comma-separated field names.', 'cartflows' ),
2641 ),
2642 'message' => array(
2643 'type' => 'string',
2644 'description' => __( 'Result message.', 'cartflows' ),
2645 ),
2646 ),
2647 ),
2648 'execute_callback' => function ( $input ) use ( $cf ) {
2649 return $cf->update_optin_pass_fields( $input );
2650 },
2651 'meta' => array(
2652 'annotations' => array(
2653 'priority' => 2.0,
2654 'readOnlyHint' => false,
2655 'destructiveHint' => false,
2656 'idempotentHint' => true,
2657 'openWorldHint' => false,
2658 ),
2659 'show_in_rest' => true,
2660 'mcp' => array(
2661 'public' => true,
2662 'type' => 'tool',
2663 ),
2664 ),
2665 ),
2666
2667 // ============================================================
2668 // Landing — Configuration / Read
2669 // ============================================================
2670
2671 // Get landing step settings.
2672 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-landing-settings' => array(
2673 'label' => __( 'Get landing step settings', 'cartflows' ),
2674 'description' => __( 'Returns the configuration of a landing step: step slug, next step link shortcode, and disable-step toggle. Landing pages are page-builder-driven, so this returns only the CartFlows-specific meta. Does not require WooCommerce.', 'cartflows' ),
2675 'category' => 'cartflows',
2676 'permission_callback' => function () use ( $cf ) {
2677 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2678 },
2679 'input_schema' => array(
2680 'type' => 'object',
2681 'required' => array( 'step_id' ),
2682 'properties' => array(
2683 'step_id' => array(
2684 'type' => 'integer',
2685 'description' => __( 'The landing step ID.', 'cartflows' ),
2686 ),
2687 ),
2688 ),
2689 'output_schema' => array(
2690 'type' => 'object',
2691 'properties' => array(
2692 'step_id' => array(
2693 'type' => 'integer',
2694 'description' => __( 'Step ID.', 'cartflows' ),
2695 ),
2696 'slug' => array(
2697 'type' => 'string',
2698 'description' => __( 'Step URL slug.', 'cartflows' ),
2699 ),
2700 'next_step_link' => array(
2701 'type' => 'string',
2702 'description' => __( 'Next step link shortcode/URL for use in page builder.', 'cartflows' ),
2703 ),
2704 'disable_step' => array(
2705 'type' => 'string',
2706 'description' => __( 'Whether step is disabled (yes/no).', 'cartflows' ),
2707 ),
2708 ),
2709 ),
2710 'execute_callback' => function ( $input ) use ( $cf ) {
2711 return $cf->get_landing_settings( $input );
2712 },
2713 'meta' => array(
2714 'uri' => 'cartflows://steps/landing/{id}/settings',
2715 'annotations' => array(
2716 'priority' => 1.0,
2717 'readOnlyHint' => true,
2718 'destructiveHint' => false,
2719 'idempotentHint' => true,
2720 'openWorldHint' => false,
2721 ),
2722 'show_in_rest' => true,
2723 'mcp' => array(
2724 'public' => true,
2725 'type' => 'resource',
2726 ),
2727 ),
2728 ),
2729
2730 // ============================================================
2731 // Email Report — Configuration
2732 // ============================================================
2733
2734 // Get email report settings.
2735 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-email-report-settings' => array(
2736 'label' => __( 'Get email report settings', 'cartflows' ),
2737 'description' => __( 'Returns the weekly email report configuration: whether reports are enabled, the list of recipient email addresses, and the next scheduled send time. Does not require WooCommerce.', 'cartflows' ),
2738 'category' => 'cartflows',
2739 'permission_callback' => function () use ( $cf ) {
2740 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2741 },
2742 'input_schema' => array(
2743 'type' => 'object',
2744 'properties' => array(),
2745 ),
2746 'output_schema' => array(
2747 'type' => 'object',
2748 'properties' => array(
2749 'enabled' => array(
2750 'type' => 'string',
2751 'description' => __( 'Whether weekly reports are enabled (enable/disable).', 'cartflows' ),
2752 ),
2753 'email_ids' => array(
2754 'type' => 'array',
2755 'description' => __( 'List of recipient email addresses.', 'cartflows' ),
2756 'items' => array( 'type' => 'string' ),
2757 ),
2758 'next_scheduled' => array(
2759 'type' => 'string',
2760 'description' => __( 'Next scheduled send time (ISO 8601) or empty if not scheduled.', 'cartflows' ),
2761 ),
2762 ),
2763 ),
2764 'execute_callback' => function ( $input ) use ( $cf ) {
2765 return $cf->get_email_report_settings( $input );
2766 },
2767 'meta' => array(
2768 'uri' => 'cartflows://settings/email-report',
2769 'annotations' => array(
2770 'priority' => 1.0,
2771 'readOnlyHint' => true,
2772 'destructiveHint' => false,
2773 'idempotentHint' => true,
2774 'openWorldHint' => false,
2775 ),
2776 'show_in_rest' => true,
2777 'mcp' => array(
2778 'public' => true,
2779 'type' => 'resource',
2780 ),
2781 ),
2782 ),
2783
2784 // Update email report settings.
2785 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-email-report-settings' => array(
2786 'label' => __( 'Update email report settings', 'cartflows' ),
2787 'description' => __( 'Toggles the weekly email report on or off and/or updates the list of recipient email addresses. The ActionScheduler cron is automatically managed by the module. Does not require WooCommerce.', 'cartflows' ),
2788 'category' => 'cartflows',
2789 'permission_callback' => function () use ( $cf ) {
2790 return (
2791 get_option( 'cartflows_abilities_api_write', true ) &&
2792 $cf->permission_callback( 'cartflows_manage_flows_steps' )
2793 );
2794 },
2795 'input_schema' => array(
2796 'type' => 'object',
2797 'properties' => array(
2798 'enabled' => array(
2799 'type' => 'string',
2800 'enum' => array( 'enable', 'disable' ),
2801 'description' => __( 'Enable or disable the weekly email report.', 'cartflows' ),
2802 ),
2803 'email_ids' => array(
2804 'type' => 'array',
2805 'description' => __( 'List of recipient email addresses. Replaces the entire list.', 'cartflows' ),
2806 'items' => array( 'type' => 'string' ),
2807 ),
2808 ),
2809 ),
2810 'output_schema' => array(
2811 'type' => 'object',
2812 'properties' => array(
2813 'enabled' => array(
2814 'type' => 'string',
2815 'description' => __( 'Saved enabled status.', 'cartflows' ),
2816 ),
2817 'email_ids' => array(
2818 'type' => 'array',
2819 'description' => __( 'Saved recipient email list.', 'cartflows' ),
2820 'items' => array( 'type' => 'string' ),
2821 ),
2822 'message' => array(
2823 'type' => 'string',
2824 'description' => __( 'Result message.', 'cartflows' ),
2825 ),
2826 ),
2827 ),
2828 'execute_callback' => function ( $input ) use ( $cf ) {
2829 return $cf->update_email_report_settings( $input );
2830 },
2831 'meta' => array(
2832 'annotations' => array(
2833 'priority' => 2.0,
2834 'readOnlyHint' => false,
2835 'destructiveHint' => false,
2836 'idempotentHint' => true,
2837 'openWorldHint' => false,
2838 ),
2839 'show_in_rest' => true,
2840 'mcp' => array(
2841 'public' => true,
2842 'type' => 'tool',
2843 ),
2844 ),
2845 ),
2846
2847 // ============================================================
2848 // Woo Dynamic Flow — Product-to-Flow Mapping
2849 // ============================================================
2850
2851 // Get flow mapping for a single WooCommerce product.
2852 CARTFLOWS_ABILITY_API_NAMESPACE . 'get-product-flow-mapping' => array(
2853 'label' => __( 'Get product flow mapping', 'cartflows' ),
2854 'description' => __( 'Returns the CartFlows flow mapping for a WooCommerce product: which flow the product redirects to after add-to-cart, and any custom button text override. Requires WooCommerce.', 'cartflows' ),
2855 'category' => 'cartflows',
2856 'permission_callback' => function () use ( $cf ) {
2857 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2858 },
2859 'input_schema' => array(
2860 'type' => 'object',
2861 'required' => array( 'product_id' ),
2862 'properties' => array(
2863 'product_id' => array(
2864 'type' => 'integer',
2865 'description' => __( 'The WooCommerce product ID.', 'cartflows' ),
2866 ),
2867 ),
2868 ),
2869 'output_schema' => array(
2870 'type' => 'object',
2871 'properties' => array(
2872 'product_id' => array(
2873 'type' => 'integer',
2874 'description' => __( 'Product ID.', 'cartflows' ),
2875 ),
2876 'product_title' => array(
2877 'type' => 'string',
2878 'description' => __( 'Product title.', 'cartflows' ),
2879 ),
2880 'flow_id' => array(
2881 'type' => 'integer',
2882 'description' => __( 'Mapped flow ID (0 if none).', 'cartflows' ),
2883 ),
2884 'flow_title' => array(
2885 'type' => 'string',
2886 'description' => __( 'Mapped flow title (empty if none).', 'cartflows' ),
2887 ),
2888 'add_to_cart_text' => array(
2889 'type' => 'string',
2890 'description' => __( 'Custom add-to-cart button text (empty if default).', 'cartflows' ),
2891 ),
2892 ),
2893 ),
2894 'execute_callback' => function ( $input ) use ( $cf ) {
2895 return $cf->get_product_flow_mapping( $input );
2896 },
2897 'meta' => array(
2898 'uri' => 'cartflows://woo-dynamic-flow/mapping/{product_id}',
2899 'annotations' => array(
2900 'priority' => 1.0,
2901 'readOnlyHint' => true,
2902 'destructiveHint' => false,
2903 'idempotentHint' => true,
2904 'openWorldHint' => false,
2905 ),
2906 'show_in_rest' => true,
2907 'mcp' => array(
2908 'public' => true,
2909 'type' => 'resource',
2910 ),
2911 ),
2912 ),
2913
2914 // List all WooCommerce products that have a flow mapping.
2915 CARTFLOWS_ABILITY_API_NAMESPACE . 'list-product-flow-mappings' => array(
2916 'label' => __( 'List product flow mappings', 'cartflows' ),
2917 'description' => __( 'Returns a paginated list of WooCommerce products that have a CartFlows flow mapping configured. Each entry includes the product, mapped flow, and custom button text. Requires WooCommerce.', 'cartflows' ),
2918 'category' => 'cartflows',
2919 'permission_callback' => function () use ( $cf ) {
2920 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
2921 },
2922 'input_schema' => array(
2923 'type' => 'object',
2924 'properties' => array(
2925 'paged' => array(
2926 'type' => 'integer',
2927 'default' => 1,
2928 'description' => __( 'Page number (1-based).', 'cartflows' ),
2929 ),
2930 'per_page' => array(
2931 'type' => 'integer',
2932 'default' => 10,
2933 'description' => __( 'Products per page (max 100).', 'cartflows' ),
2934 ),
2935 ),
2936 ),
2937 'output_schema' => array(
2938 'type' => 'object',
2939 'properties' => array(
2940 'mappings' => array(
2941 'type' => 'array',
2942 'description' => __( 'Products with flow mappings.', 'cartflows' ),
2943 'items' => array(
2944 'type' => 'object',
2945 'properties' => array(
2946 'product_id' => array(
2947 'type' => 'integer',
2948 'description' => __( 'Product ID.', 'cartflows' ),
2949 ),
2950 'product_title' => array(
2951 'type' => 'string',
2952 'description' => __( 'Product title.', 'cartflows' ),
2953 ),
2954 'flow_id' => array(
2955 'type' => 'integer',
2956 'description' => __( 'Mapped flow ID.', 'cartflows' ),
2957 ),
2958 'flow_title' => array(
2959 'type' => 'string',
2960 'description' => __( 'Mapped flow title.', 'cartflows' ),
2961 ),
2962 'add_to_cart_text' => array(
2963 'type' => 'string',
2964 'description' => __( 'Custom button text.', 'cartflows' ),
2965 ),
2966 ),
2967 ),
2968 ),
2969 'total' => array(
2970 'type' => 'integer',
2971 'description' => __( 'Total products with mappings.', 'cartflows' ),
2972 ),
2973 'total_pages' => array(
2974 'type' => 'integer',
2975 'description' => __( 'Total pages.', 'cartflows' ),
2976 ),
2977 'page' => array(
2978 'type' => 'integer',
2979 'description' => __( 'Current page.', 'cartflows' ),
2980 ),
2981 ),
2982 ),
2983 'execute_callback' => function ( $input ) use ( $cf ) {
2984 return $cf->list_product_flow_mappings( $input );
2985 },
2986 'meta' => array(
2987 'uri' => 'cartflows://woo-dynamic-flow/mappings',
2988 'annotations' => array(
2989 'priority' => 1.0,
2990 'readOnlyHint' => true,
2991 'destructiveHint' => false,
2992 'idempotentHint' => true,
2993 'openWorldHint' => false,
2994 ),
2995 'show_in_rest' => true,
2996 'mcp' => array(
2997 'public' => true,
2998 'type' => 'resource',
2999 ),
3000 ),
3001 ),
3002
3003 // Update flow mapping on a WooCommerce product.
3004 CARTFLOWS_ABILITY_API_NAMESPACE . 'update-product-flow-mapping' => array(
3005 'label' => __( 'Update product flow mapping', 'cartflows' ),
3006 'description' => __( 'Sets or clears the CartFlows flow mapping on a WooCommerce product. When a flow is mapped, adding the product to cart redirects the customer to that flow. Set flow_id to 0 to clear the mapping. Requires WooCommerce.', 'cartflows' ),
3007 'category' => 'cartflows',
3008 'permission_callback' => function () use ( $cf ) {
3009 return (
3010 get_option( 'cartflows_abilities_api_write', true ) &&
3011 $cf->permission_callback( 'cartflows_manage_flows_steps' )
3012 );
3013 },
3014 'input_schema' => array(
3015 'type' => 'object',
3016 'required' => array( 'product_id' ),
3017 'properties' => array(
3018 'product_id' => array(
3019 'type' => 'integer',
3020 'description' => __( 'The WooCommerce product ID.', 'cartflows' ),
3021 ),
3022 'flow_id' => array(
3023 'type' => 'integer',
3024 'description' => __( 'Flow ID to map (0 to clear mapping).', 'cartflows' ),
3025 ),
3026 'add_to_cart_text' => array(
3027 'type' => 'string',
3028 'description' => __( 'Custom add-to-cart button text (empty string to clear).', 'cartflows' ),
3029 ),
3030 ),
3031 ),
3032 'output_schema' => array(
3033 'type' => 'object',
3034 'properties' => array(
3035 'product_id' => array(
3036 'type' => 'integer',
3037 'description' => __( 'Product ID.', 'cartflows' ),
3038 ),
3039 'flow_id' => array(
3040 'type' => 'integer',
3041 'description' => __( 'Saved flow ID.', 'cartflows' ),
3042 ),
3043 'flow_title' => array(
3044 'type' => 'string',
3045 'description' => __( 'Saved flow title.', 'cartflows' ),
3046 ),
3047 'add_to_cart_text' => array(
3048 'type' => 'string',
3049 'description' => __( 'Saved button text.', 'cartflows' ),
3050 ),
3051 'message' => array(
3052 'type' => 'string',
3053 'description' => __( 'Result message.', 'cartflows' ),
3054 ),
3055 ),
3056 ),
3057 'execute_callback' => function ( $input ) use ( $cf ) {
3058 return $cf->update_product_flow_mapping( $input );
3059 },
3060 'meta' => array(
3061 'annotations' => array(
3062 'priority' => 2.0,
3063 'readOnlyHint' => false,
3064 'destructiveHint' => false,
3065 'idempotentHint' => true,
3066 'openWorldHint' => false,
3067 ),
3068 'show_in_rest' => true,
3069 'mcp' => array(
3070 'public' => true,
3071 'type' => 'tool',
3072 ),
3073 ),
3074 ),
3075
3076 // ============================================================
3077 // Flows — Creation / Import
3078 // ============================================================
3079
3080 // Create a new empty funnel.
3081 CARTFLOWS_ABILITY_API_NAMESPACE . 'create-flow' => array(
3082 'label' => __( 'Create funnel', 'cartflows' ),
3083 'description' => __( 'Creates a new empty CartFlows funnel with the given title and optional status. The funnel is created with no steps — use create-step to add steps after creation. Use to start building a funnel from scratch.', 'cartflows' ),
3084 'category' => 'cartflows',
3085 'permission_callback' => function () use ( $cf ) {
3086 return (
3087 get_option( 'cartflows_abilities_api_write', true ) &&
3088 $cf->permission_callback( 'cartflows_manage_flows_steps' )
3089 );
3090 },
3091 'input_schema' => array(
3092 'type' => 'object',
3093 'required' => array( 'title' ),
3094 'properties' => array(
3095 'title' => array(
3096 'type' => 'string',
3097 'description' => __( 'The funnel title.', 'cartflows' ),
3098 ),
3099 'status' => array(
3100 'type' => 'string',
3101 'enum' => array( 'draft', 'publish' ),
3102 'default' => 'draft',
3103 'description' => __( 'Post status for the new funnel.', 'cartflows' ),
3104 ),
3105 ),
3106 ),
3107 'output_schema' => array(
3108 'type' => 'object',
3109 'properties' => array(
3110 'flow_id' => array(
3111 'type' => 'integer',
3112 'description' => __( 'New funnel ID.', 'cartflows' ),
3113 ),
3114 'title' => array(
3115 'type' => 'string',
3116 'description' => __( 'Funnel title.', 'cartflows' ),
3117 ),
3118 'status' => array(
3119 'type' => 'string',
3120 'description' => __( 'Funnel post status.', 'cartflows' ),
3121 ),
3122 'edit_url' => array(
3123 'type' => 'string',
3124 'format' => 'uri',
3125 'description' => __( 'Admin edit URL for the new funnel.', 'cartflows' ),
3126 ),
3127 ),
3128 ),
3129 'execute_callback' => function ( $input ) use ( $cf ) {
3130 return $cf->create_flow( $input );
3131 },
3132 'meta' => array(
3133 'annotations' => array(
3134 'priority' => 2.0,
3135 'readOnlyHint' => false,
3136 'destructiveHint' => false,
3137 'idempotentHint' => false,
3138 'openWorldHint' => false,
3139 ),
3140 'show_in_rest' => true,
3141 'mcp' => array(
3142 'public' => true,
3143 'type' => 'tool',
3144 ),
3145 ),
3146 ),
3147
3148 // Create a new step and attach it to a funnel.
3149 CARTFLOWS_ABILITY_API_NAMESPACE . 'create-step' => array(
3150 'label' => __( 'Create step', 'cartflows' ),
3151 'description' => __( 'Creates a new CartFlows step and attaches it to an existing funnel. Free step types: landing, checkout, optin, thankyou. Upsell and downsell steps require CartFlows Pro. The step is published immediately and appended to the funnel\'s step list.', 'cartflows' ),
3152 'category' => 'cartflows',
3153 'permission_callback' => function () use ( $cf ) {
3154 return (
3155 get_option( 'cartflows_abilities_api_write', true ) &&
3156 $cf->permission_callback( 'cartflows_manage_flows_steps' )
3157 );
3158 },
3159 'input_schema' => array(
3160 'type' => 'object',
3161 'required' => array( 'flow_id', 'title', 'type' ),
3162 'properties' => array(
3163 'flow_id' => array(
3164 'type' => 'integer',
3165 'description' => __( 'The parent funnel ID.', 'cartflows' ),
3166 ),
3167 'title' => array(
3168 'type' => 'string',
3169 'description' => __( 'The step title.', 'cartflows' ),
3170 ),
3171 'type' => array(
3172 'type' => 'string',
3173 'enum' => array( 'landing', 'checkout', 'optin', 'thankyou' ),
3174 'description' => __( 'Step type. Free types: landing, checkout, optin, thankyou.', 'cartflows' ),
3175 ),
3176 ),
3177 ),
3178 'output_schema' => array(
3179 'type' => 'object',
3180 'properties' => array(
3181 'step_id' => array(
3182 'type' => 'integer',
3183 'description' => __( 'New step ID.', 'cartflows' ),
3184 ),
3185 'flow_id' => array(
3186 'type' => 'integer',
3187 'description' => __( 'Parent funnel ID.', 'cartflows' ),
3188 ),
3189 'title' => array(
3190 'type' => 'string',
3191 'description' => __( 'Step title.', 'cartflows' ),
3192 ),
3193 'type' => array(
3194 'type' => 'string',
3195 'description' => __( 'Step type.', 'cartflows' ),
3196 ),
3197 'edit_url' => array(
3198 'type' => 'string',
3199 'format' => 'uri',
3200 'description' => __( 'Admin edit URL for the new step.', 'cartflows' ),
3201 ),
3202 ),
3203 ),
3204 'execute_callback' => function ( $input ) use ( $cf ) {
3205 return $cf->create_step( $input );
3206 },
3207 'meta' => array(
3208 'annotations' => array(
3209 'priority' => 2.0,
3210 'readOnlyHint' => false,
3211 'destructiveHint' => false,
3212 'idempotentHint' => false,
3213 'openWorldHint' => false,
3214 ),
3215 'show_in_rest' => true,
3216 'mcp' => array(
3217 'public' => true,
3218 'type' => 'tool',
3219 ),
3220 ),
3221 ),
3222
3223 // ============================================================
3224 // Templates — Browse
3225 // ============================================================
3226
3227 // List available flow templates from the cached library.
3228 CARTFLOWS_ABILITY_API_NAMESPACE . 'list-flow-templates' => array(
3229 'label' => __( 'List flow templates', 'cartflows' ),
3230 'description' => __( 'Returns a paginated list of CartFlows flow templates from the cached template library. Supports filtering by type (free/pro), page builder, step type, category, and keyword search. Use to browse available templates before importing one with import-flow-template. Pro templates require CartFlows Pro to import.', 'cartflows' ),
3231 'category' => 'cartflows',
3232 'permission_callback' => function () use ( $cf ) {
3233 return $cf->permission_callback( 'cartflows_manage_flows_steps' );
3234 },
3235 'input_schema' => array(
3236 'type' => 'object',
3237 'properties' => array(
3238 'type' => array(
3239 'type' => 'string',
3240 'enum' => array( 'free', 'pro', '' ),
3241 'default' => '',
3242 'description' => __( 'Filter by template type. "free" for free templates, "pro" for pro-only templates. Empty returns all.', 'cartflows' ),
3243 ),
3244 'page_builder' => array(
3245 'type' => 'string',
3246 'default' => '',
3247 'description' => __( 'Filter by page builder slug (e.g. elementor, gutenberg, divi, beaver-builder, bricks-builder). Empty returns templates for the default page builder.', 'cartflows' ),
3248 ),
3249 'step_type' => array(
3250 'type' => 'string',
3251 'default' => '',
3252 'description' => __( 'Filter by step type (e.g. checkout, optin, landing, thankyou, upsell, downsell). Empty returns all types.', 'cartflows' ),
3253 ),
3254 'category' => array(
3255 'type' => 'string',
3256 'default' => '',
3257 'description' => __( 'Filter by category slug (e.g. sales-funnel, product-landing, lead-generation, store-checkout). Empty returns all categories.', 'cartflows' ),
3258 ),
3259 'search' => array(
3260 'type' => 'string',
3261 'default' => '',
3262 'description' => __( 'Keyword to search in template titles.', 'cartflows' ),
3263 ),
3264 'page' => array(
3265 'type' => 'integer',
3266 'default' => 1,
3267 'description' => __( 'Page number (1-based).', 'cartflows' ),
3268 ),
3269 'per_page' => array(
3270 'type' => 'integer',
3271 'default' => 20,
3272 'description' => __( 'Templates per page (max 100).', 'cartflows' ),
3273 ),
3274 ),
3275 ),
3276 'output_schema' => array(
3277 'type' => 'object',
3278 'properties' => array(
3279 'templates' => array(
3280 'type' => 'array',
3281 'description' => __( 'Flow templates.', 'cartflows' ),
3282 'items' => array(
3283 'type' => 'object',
3284 'properties' => array(
3285 'id' => array(
3286 'type' => 'integer',
3287 'description' => __( 'Template ID.', 'cartflows' ),
3288 ),
3289 'title' => array(
3290 'type' => 'string',
3291 'description' => __( 'Template title.', 'cartflows' ),
3292 ),
3293 'type' => array(
3294 'type' => 'string',
3295 'description' => __( 'Template type: "free" or "pro".', 'cartflows' ),
3296 ),
3297 'page_builder' => array(
3298 'type' => 'string',
3299 'description' => __( 'Page builder slug.', 'cartflows' ),
3300 ),
3301 'is_pro' => array(
3302 'type' => 'boolean',
3303 'description' => __( 'Whether this template requires CartFlows Pro.', 'cartflows' ),
3304 ),
3305 'categories' => array(
3306 'type' => 'array',
3307 'description' => __( 'Category slugs for this template.', 'cartflows' ),
3308 'items' => array(
3309 'type' => 'string',
3310 ),
3311 ),
3312 'step_count' => array(
3313 'type' => 'integer',
3314 'description' => __( 'Number of steps in this template.', 'cartflows' ),
3315 ),
3316 'step_types' => array(
3317 'type' => 'array',
3318 'description' => __( 'Step types present in this template.', 'cartflows' ),
3319 'items' => array(
3320 'type' => 'string',
3321 ),
3322 ),
3323 'thumbnail_url' => array(
3324 'type' => 'string',
3325 'format' => 'uri',
3326 'description' => __( 'Template thumbnail URL.', 'cartflows' ),
3327 ),
3328 ),
3329 ),
3330 ),
3331 'total' => array(
3332 'type' => 'integer',
3333 'description' => __( 'Total matching templates.', 'cartflows' ),
3334 ),
3335 'page' => array(
3336 'type' => 'integer',
3337 'description' => __( 'Current page.', 'cartflows' ),
3338 ),
3339 'per_page' => array(
3340 'type' => 'integer',
3341 'description' => __( 'Templates per page.', 'cartflows' ),
3342 ),
3343 'pro_available' => array(
3344 'type' => 'boolean',
3345 'description' => __( 'Whether CartFlows Pro is active on this site. Pro templates can only be imported when this is true.', 'cartflows' ),
3346 ),
3347 ),
3348 ),
3349 'execute_callback' => function ( $input ) use ( $cf ) {
3350 return $cf->list_flow_templates( $input );
3351 },
3352 'meta' => array(
3353 'uri' => 'cartflows://templates',
3354 'annotations' => array(
3355 'priority' => 1.0,
3356 'readOnlyHint' => true,
3357 'destructiveHint' => false,
3358 'idempotentHint' => true,
3359 'openWorldHint' => true,
3360 ),
3361 'show_in_rest' => true,
3362 'mcp' => array(
3363 'public' => true,
3364 'type' => 'resource',
3365 ),
3366 ),
3367 ),
3368
3369 // ============================================================
3370 // Templates — Import
3371 // ============================================================
3372
3373 // Import a flow template from the CartFlows cloud library.
3374 CARTFLOWS_ABILITY_API_NAMESPACE . 'import-flow-template' => array(
3375 'label' => __( 'Import flow template', 'cartflows' ),
3376 'description' => __( 'Imports a flow template from the CartFlows cloud library by template ID. Creates a new funnel with all steps from the template. Upsell/downsell steps are skipped if CartFlows Pro is not active. Use list-flow-templates first to browse available templates. Requires WooCommerce.', 'cartflows' ),
3377 'category' => 'cartflows',
3378 'permission_callback' => function () use ( $cf ) {
3379 return (
3380 get_option( 'cartflows_abilities_api_write', true ) &&
3381 $cf->permission_callback( 'cartflows_manage_flows_steps' )
3382 );
3383 },
3384 'input_schema' => array(
3385 'type' => 'object',
3386 'required' => array( 'template_id' ),
3387 'properties' => array(
3388 'template_id' => array(
3389 'type' => 'integer',
3390 'description' => __( 'Template ID from the CartFlows cloud library (from list-flow-templates).', 'cartflows' ),
3391 ),
3392 ),
3393 ),
3394 'output_schema' => array(
3395 'type' => 'object',
3396 'properties' => array(
3397 'flow_id' => array(
3398 'type' => 'integer',
3399 'description' => __( 'New funnel ID.', 'cartflows' ),
3400 ),
3401 'title' => array(
3402 'type' => 'string',
3403 'description' => __( 'Funnel title.', 'cartflows' ),
3404 ),
3405 'steps' => array(
3406 'type' => 'array',
3407 'description' => __( 'Imported steps.', 'cartflows' ),
3408 'items' => array(
3409 'type' => 'object',
3410 'properties' => array(
3411 'step_id' => array(
3412 'type' => 'integer',
3413 'description' => __( 'Step ID.', 'cartflows' ),
3414 ),
3415 'title' => array(
3416 'type' => 'string',
3417 'description' => __( 'Step title.', 'cartflows' ),
3418 ),
3419 'type' => array(
3420 'type' => 'string',
3421 'description' => __( 'Step type.', 'cartflows' ),
3422 ),
3423 ),
3424 ),
3425 ),
3426 'skipped_steps' => array(
3427 'type' => 'array',
3428 'description' => __( 'Steps that were skipped during import.', 'cartflows' ),
3429 'items' => array(
3430 'type' => 'object',
3431 'properties' => array(
3432 'title' => array(
3433 'type' => 'string',
3434 'description' => __( 'Skipped step title.', 'cartflows' ),
3435 ),
3436 'type' => array(
3437 'type' => 'string',
3438 'description' => __( 'Skipped step type.', 'cartflows' ),
3439 ),
3440 'reason' => array(
3441 'type' => 'string',
3442 'description' => __( 'Reason for skipping.', 'cartflows' ),
3443 ),
3444 ),
3445 ),
3446 ),
3447 ),
3448 ),
3449 'execute_callback' => function ( $input ) use ( $cf ) {
3450 return $cf->import_flow_template( $input );
3451 },
3452 'meta' => array(
3453 'annotations' => array(
3454 'priority' => 2.0,
3455 'readOnlyHint' => false,
3456 'destructiveHint' => false,
3457 'idempotentHint' => false,
3458 'openWorldHint' => true,
3459 ),
3460 'show_in_rest' => true,
3461 'mcp' => array(
3462 'public' => true,
3463 'type' => 'tool',
3464 ),
3465 ),
3466 ),
3467
3468 ); // end $abilities.
3469
3470 // Allow extensions to add or modify abilities.
3471 $abilities = apply_filters( 'cartflows_config_abilities', $abilities );
3472 if ( ! is_array( $abilities ) ) {
3473 $abilities = array();
3474 }
3475
3476 self::$abilities = $abilities;
3477
3478 return $abilities;
3479 }
3480
3481 /**
3482 * Get a single ability config by fully-qualified name.
3483 *
3484 * @param string $ability_name Ability identifier (e.g. 'cartflows/list-flows').
3485 * @return array|false
3486 */
3487 public static function get_ability( $ability_name ) {
3488 if ( false === self::$abilities ) {
3489 self::$abilities = self::get_abilities();
3490 }
3491 return isset( self::$abilities[ $ability_name ] ) ? self::$abilities[ $ability_name ] : false;
3492 }
3493
3494 /**
3495 * Get the input schema for a named ability.
3496 *
3497 * @param string $ability_name Ability identifier.
3498 * @return array|false
3499 */
3500 public static function get_ability_input_schema( $ability_name ) {
3501 $ability = self::get_ability( $ability_name );
3502 if ( false === $ability ) {
3503 return false;
3504 }
3505 return isset( $ability['input_schema'] ) ? $ability['input_schema'] : false;
3506 }
3507
3508 /**
3509 * Get the output schema for a named ability.
3510 *
3511 * @param string $ability_name Ability identifier.
3512 * @return array|false
3513 */
3514 public static function get_ability_output_schema( $ability_name ) {
3515 $ability = self::get_ability( $ability_name );
3516 if ( false === $ability ) {
3517 return false;
3518 }
3519 return isset( $ability['output_schema'] ) ? $ability['output_schema'] : false;
3520 }
3521 }
3522