PluginProbe
Code Engine – PHP Snippets, AI Functions & Automation for WordPress / 0.3.2
Code Engine – PHP Snippets, AI Functions & Automation for WordPress v0.3.2
0.5.6 0.5.5 0.5.4 0.5.3 0.5.2 0.5.1 0.5.0 0.4.9 0.4.8 0.4.7 0.4.6 trunk 0.0.1 0.0.2 0.2.8 0.2.9 0.3.0 0.3.1 0.3.2 0.3.3 0.3.4 0.3.5 0.3.6 0.3.7 0.3.8 All 32 releases
← All changes | classes/mcp.php +59 -241 trunk0.3.2 View file →
@@ -2,20 +2,9 @@
2 2
3 3 class Meow_MWCODE_MCP {
4 4 private $core;
5 5 private $api;
6 - // Per-request memo for the opted-in Callable list, so listing tools and executing
7 - // one don't each reload every snippet from the database. Reset on any mutation.
8 - private $mcp_functions_cache = null;
9 -
10 - // Shared, model-facing explanation of what each scope means. Without this an agent
11 - // sees a bare enum and has to guess which scope to pick.
12 - const SCOPE_DESC = "Where the snippet lives and runs: 'function' = Callable, run on demand (via REST, AI Engine, MCP); 'persistent' = Global, always loaded on both the front-end and wp-admin; 'frontend' = loaded on the front-end only; 'backend' = loaded in wp-admin only; 'scheduled' = run automatically on a schedule (cron); 'content_php' = a PHP snippet output where its [code-engine id=...] shortcode/block is placed; 'content_js' = a JavaScript snippet emitted as a <script> tag via the same shortcode/block.";
13 -
14 - // Scope enums that appear across every management tool. Kept in one place so the
15 - // list can never drift between tools (all seven scopes the API actually accepts).
16 - const SCOPES = ['function', 'backend', 'frontend', 'scheduled', 'persistent', 'content_php', 'content_js'];
17 -
6 +
18 7 public function __construct( $core ) {
19 8 $this->core = $core;
20 9
21 10 // Initialize everything on 'init' to ensure options are loaded
@@ -24,128 +13,23 @@
24 13
25 14 public function init() {
26 15 global $mwcode, $mwai;
27 16 $this->api = $mwcode;
28 -
29 - // Nothing to do without AI Engine's MCP server.
30 - if ( !isset( $mwai ) ) {
31 - return;
17 +
18 + // Only register MCP if enabled AND AI Engine is available
19 + if ( $this->core->get_option( 'mcp_support', false ) && isset( $mwai ) ) {
20 + // Register MCP tools
21 + add_filter( 'mwai_mcp_tools', array( $this, 'register_tools' ) );
22 +
23 + // Handle MCP tool execution
24 + add_filter( 'mwai_mcp_callback', array( $this, 'handle_tool_execution' ), 10, 4 );
32 25 }
33 -
34 - // Two independent surfaces share AI Engine's MCP server, each behind its own
35 - // global master switch (and AI Engine's own MCP auth gate upstream):
36 - // - the management/internal API (the 'mcp_support' option)
37 - // - individual Callable functions, opted-in per snippet via 'functionMcp' and
38 - // only exposed when the 'mcp_functions' option is enabled
39 - // Either one alone is enough to justify hooking the filters.
40 - add_filter( 'mwai_mcp_tools', array( $this, 'register_tools' ) );
41 - add_filter( 'mwai_mcp_callback', array( $this, 'handle_tool_execution' ), 10, 4 );
42 26 }
43 -
27 +
44 28 public function register_tools( $tools ) {
45 - // Individual Callable functions that opted in to MCP, exposed as first-class tools.
46 - // Gated behind a global master switch (Settings > For Developers > MCP Functions)
47 - // in addition to each snippet's per-function opt-in.
48 - if ( $this->core->get_option( 'mcp_functions', false ) ) {
49 - $tools = $this->register_function_tools( $tools );
50 - }
51 -
52 - // Code Engine's management/internal API (Settings > For Developers > MCP Support).
53 - if ( $this->core->get_option( 'mcp_support', false ) ) {
54 - $tools = $this->register_management_tools( $tools );
55 - }
56 -
57 - return $tools;
58 - }
59 -
60 - /**
61 - * Map a Code Engine argument type to a JSON Schema type.
62 - * Returns null for 'mixed'/unknown so the schema leaves the type open.
63 - */
64 - private function mcp_type( $type ) {
65 - switch ( $type ) {
66 - case 'number': return 'number';
67 - case 'boolean': return 'boolean';
68 - case 'array': return 'array';
69 - case 'object': return 'object';
70 - case 'string': return 'string';
71 - default: return null;
72 - }
73 - }
74 -
75 - /**
76 - * Return the active Callable (function) snippets that opted in to MCP exposure.
77 - */
78 - private function get_mcp_functions() {
79 - if ( $this->mcp_functions_cache !== null ) {
80 - return $this->mcp_functions_cache;
81 - }
82 - global $mwcode;
83 - if ( !isset( $mwcode ) || !method_exists( $mwcode, 'getSnippets' ) ) {
84 - return ( $this->mcp_functions_cache = [] );
85 - }
86 - $functions = $mwcode->getSnippets( true, 'function' );
87 - if ( empty( $functions ) ) {
88 - return ( $this->mcp_functions_cache = [] );
89 - }
90 - return ( $this->mcp_functions_cache = array_values( array_filter( $functions, function ( $fn ) {
91 - return !empty( $fn['functionMcp'] ) && !empty( $fn['functionName'] );
92 - } ) ) );
93 - }
94 -
95 - /**
96 - * Register each opted-in Callable function as its own MCP tool, named after the
97 - * function, with an input schema derived from its declared arguments.
98 - */
99 - public function register_function_tools( $tools ) {
100 - foreach ( $this->get_mcp_functions() as $fn ) {
101 - $properties = [];
102 - $required = [];
103 -
104 - $argsDict = isset( $fn['functionArgsDict'] ) && is_array( $fn['functionArgsDict'] ) ? $fn['functionArgsDict'] : [];
105 - foreach ( $argsDict as $argName => $arg ) {
106 - $name = ltrim( $argName, '$' );
107 - if ( $name === '' ) {
108 - continue;
109 - }
110 - $prop = [];
111 - $type = $this->mcp_type( $arg['type'] ?? 'string' );
112 - if ( $type !== null ) {
113 - $prop['type'] = $type;
114 - }
115 - if ( !empty( $arg['desc'] ) ) {
116 - $prop['description'] = $arg['desc'];
117 - }
118 - $properties[ $name ] = $prop;
119 - if ( !empty( $arg['required'] ) ) {
120 - $required[] = $name;
121 - }
122 - }
123 -
124 - $schema = [
125 - 'type' => 'object',
126 - // Cast so an argument-less function still serializes as {} and not [].
127 - 'properties' => (object) $properties,
128 - ];
129 - if ( !empty( $required ) ) {
130 - $schema['required'] = $required;
131 - }
132 -
133 - $tools[] = [
134 - 'name' => $fn['functionName'],
135 - 'description' => !empty( $fn['description'] ) ? $fn['description'] : ( 'Code Engine function: ' . $fn['functionName'] ),
136 - 'category' => 'Code Engine (Functions)',
137 - 'inputSchema' => $schema,
138 - 'annotations' => [ 'openWorldHint' => true ],
139 - ];
140 - }
141 - return $tools;
142 - }
143 -
144 - public function register_management_tools( $tools ) {
145 29 // Get Snippet
146 30 $tools[] = [
147 - 'name' => 'mwcode_get_snippet',
31 + 'name' => 'code_engine_get_snippet',
148 32 'description' => 'Get a Code Engine snippet by its ID',
149 33 'category' => 'Code Engine',
150 34 'inputSchema' => [
151 35 'type' => 'object',
@@ -159,9 +43,9 @@
159 43 'description' => 'Optional filtering options',
160 44 'properties' => [
161 45 'php_ready_args' => [
162 46 'type' => 'boolean',
163 - 'description' => 'When true (default), function argument names are returned PHP-ready with a leading $ (e.g. "$id"). Set false to get plain names (e.g. "id").'
47 + 'description' => 'If false, arguments will not be formatted for PHP (no $ before names)'
164 48 ]
165 49 ]
166 50 ]
167 51 ],
@@ -170,9 +54,9 @@
170 54 ];
171 55
172 56 // Get Snippet by Name
173 57 $tools[] = [
174 - 'name' => 'mwcode_get_snippet_by_name',
58 + 'name' => 'code_engine_get_snippet_by_name',
175 59 'description' => 'Get a Code Engine snippet by its name',
176 60 'category' => 'Code Engine',
177 61 'inputSchema' => [
178 62 'type' => 'object',
@@ -186,9 +70,9 @@
186 70 'description' => 'Optional filtering options',
187 71 'properties' => [
188 72 'php_ready_args' => [
189 73 'type' => 'boolean',
190 - 'description' => 'When true (default), function argument names are returned PHP-ready with a leading $ (e.g. "$id"). Set false to get plain names (e.g. "id").'
74 + 'description' => 'If false, arguments will not be formatted for PHP (no $ before names)'
191 75 ]
192 76 ]
193 77 ]
194 78 ],
@@ -197,9 +81,9 @@
197 81 ];
198 82
199 83 // Get Snippets
200 84 $tools[] = [
201 - 'name' => 'mwcode_get_snippets',
85 + 'name' => 'code_engine_get_snippets',
202 86 'description' => 'Get all Code Engine snippets, optionally filtered by scope',
203 87 'category' => 'Code Engine',
204 88 'inputSchema' => [
205 89 'type' => 'object',
@@ -205,23 +89,23 @@
205 89 'type' => 'object',
206 90 'properties' => [
207 91 'safe' => [
208 92 'type' => 'boolean',
209 - 'description' => 'When true (default), skip function snippets whose function name is empty or invalid. Leave true unless you specifically need to inspect malformed snippets.',
93 + 'description' => 'Whether to filter out snippets with invalid names',
210 94 'default' => true
211 95 ],
212 96 'scope' => [
213 97 'type' => 'string',
214 - 'description' => 'Optional scope filter. ' . self::SCOPE_DESC,
215 - 'enum' => self::SCOPES
98 + 'description' => 'Optional scope filter',
99 + 'enum' => ['function', 'backend', 'frontend', 'scheduled', 'persistent']
216 100 ]
217 101 ]
218 102 ]
219 103 ];
220 -
104 +
221 105 // Execute Snippet
222 106 $tools[] = [
223 - 'name' => 'mwcode_execute_snippet',
107 + 'name' => 'code_engine_execute_snippet',
224 108 'description' => 'Execute a Code Engine snippet by its ID',
225 109 'category' => 'Code Engine',
226 110 'inputSchema' => [
227 111 'type' => 'object',
@@ -241,9 +125,9 @@
241 125 ];
242 126
243 127 // Execute Snippet by Name
244 128 $tools[] = [
245 - 'name' => 'mwcode_execute_snippet_by_name',
129 + 'name' => 'code_engine_execute_snippet_by_name',
246 130 'description' => 'Execute a Code Engine snippet by its name',
247 131 'category' => 'Code Engine',
248 132 'inputSchema' => [
249 133 'type' => 'object',
@@ -263,9 +147,9 @@
263 147 ];
264 148
265 149 // Create Snippet
266 150 $tools[] = [
267 - 'name' => 'mwcode_create_snippet',
151 + 'name' => 'code_engine_create_snippet',
268 152 'description' => 'Create a new Code Engine snippet',
269 153 'category' => 'Code Engine',
270 154 'inputSchema' => [
271 155 'type' => 'object',
@@ -279,10 +163,10 @@
279 163 'description' => 'Code of the snippet'
280 164 ],
281 165 'scope' => [
282 166 'type' => 'string',
283 - 'description' => 'Scope of the snippet. ' . self::SCOPE_DESC . ' Defaults to "function".',
284 - 'enum' => self::SCOPES,
167 + 'description' => 'Scope of the snippet',
168 + 'enum' => ['function', 'backend', 'frontend', 'scheduled', 'persistent'],
285 169 'default' => 'function'
286 170 ],
287 171 'options' => [
288 172 'type' => 'object',
@@ -318,12 +202,8 @@
318 202 'type' => 'string',
319 203 'enum' => ['dynamic', 'static'],
320 204 'description' => 'Behavior for function snippets'
321 205 ],
322 - 'mcp' => [
323 - 'type' => 'boolean',
324 - 'description' => 'For function snippets: expose this function as its own MCP tool in AI Engine, named after the function and callable directly by external agents. Defaults to false.'
325 - ],
326 206 'tags' => [
327 207 'type' => 'array',
328 208 'description' => 'Array of tags',
329 209 'items' => [ 'type' => 'string' ]
@@ -361,9 +241,9 @@
361 241 ];
362 242
363 243 // Update Snippet
364 244 $tools[] = [
365 - 'name' => 'mwcode_update_snippet',
245 + 'name' => 'code_engine_update_snippet',
366 246 'description' => 'Update an existing Code Engine snippet',
367 247 'category' => 'Code Engine',
368 248 'inputSchema' => [
369 249 'type' => 'object',
@@ -379,10 +259,9 @@
379 259 'name' => [ 'type' => 'string' ],
380 260 'code' => [ 'type' => 'string' ],
381 261 'scope' => [
382 262 'type' => 'string',
383 - 'description' => self::SCOPE_DESC,
384 - 'enum' => self::SCOPES
263 + 'enum' => ['function', 'backend', 'frontend', 'scheduled', 'persistent']
385 264 ],
386 265 'description' => [ 'type' => 'string' ],
387 266 'active' => [ 'type' => 'boolean' ],
388 267 'priority' => [ 'type' => 'integer' ],
@@ -410,12 +289,8 @@
410 289 'behavior' => [
411 290 'type' => 'string',
412 291 'enum' => ['dynamic', 'static']
413 292 ],
414 - 'mcp' => [
415 - 'type' => 'boolean',
416 - 'description' => 'For function snippets: expose this function as its own MCP tool in AI Engine, named after the function and callable directly by external agents.'
417 - ],
418 293 'intervalHours' => [ 'type' => 'integer' ],
419 294 'intervalMinutes' => [ 'type' => 'integer' ]
420 295 ]
421 296 ]
@@ -425,9 +300,9 @@
425 300 ];
426 301
427 302 // Delete Snippet
428 303 $tools[] = [
429 - 'name' => 'mwcode_delete_snippet',
304 + 'name' => 'code_engine_delete_snippet',
430 305 'description' => 'Delete a Code Engine snippet by its ID',
431 306 'category' => 'Code Engine',
432 307 'inputSchema' => [
433 308 'type' => 'object',
@@ -442,9 +317,9 @@
442 317 ];
443 318
444 319 // Delete Snippet by Name
445 320 $tools[] = [
446 - 'name' => 'mwcode_delete_snippet_by_name',
321 + 'name' => 'code_engine_delete_snippet_by_name',
447 322 'description' => 'Delete a Code Engine snippet by its name',
448 323 'category' => 'Code Engine',
449 324 'inputSchema' => [
450 325 'type' => 'object',
@@ -459,9 +334,9 @@
459 334 ];
460 335
461 336 // Activate Snippet
462 337 $tools[] = [
463 - 'name' => 'mwcode_activate_snippet',
338 + 'name' => 'code_engine_activate_snippet',
464 339 'description' => 'Activate a Code Engine snippet',
465 340 'category' => 'Code Engine',
466 341 'inputSchema' => [
467 342 'type' => 'object',
@@ -476,9 +351,9 @@
476 351 ];
477 352
478 353 // Deactivate Snippet
479 354 $tools[] = [
480 - 'name' => 'mwcode_deactivate_snippet',
355 + 'name' => 'code_engine_deactivate_snippet',
481 356 'description' => 'Deactivate a Code Engine snippet',
482 357 'category' => 'Code Engine',
483 358 'inputSchema' => [
484 359 'type' => 'object',
@@ -493,9 +368,9 @@
493 368 ];
494 369
495 370 // Get Snippets by Scope
496 371 $tools[] = [
497 - 'name' => 'mwcode_get_snippets_by_scope',
372 + 'name' => 'code_engine_get_snippets_by_scope',
498 373 'description' => 'Get Code Engine snippets filtered by scope',
499 374 'category' => 'Code Engine',
500 375 'inputSchema' => [
501 376 'type' => 'object',
@@ -501,10 +376,10 @@
501 376 'type' => 'object',
502 377 'properties' => [
503 378 'scope' => [
504 379 'type' => 'string',
505 - 'description' => 'The scope to filter by. ' . self::SCOPE_DESC,
506 - 'enum' => self::SCOPES
380 + 'description' => 'The scope to filter by',
381 + 'enum' => ['function', 'backend', 'frontend', 'scheduled', 'persistent']
507 382 ],
508 383 'filters' => [
509 384 'type' => 'object',
510 385 'description' => 'Additional filters',
@@ -526,9 +401,9 @@
526 401 ];
527 402
528 403 // Get Active Snippets
529 404 $tools[] = [
530 - 'name' => 'mwcode_get_active_snippets',
405 + 'name' => 'code_engine_get_active_snippets',
531 406 'description' => 'Get all active Code Engine snippets',
532 407 'category' => 'Code Engine',
533 408 'inputSchema' => [
534 409 'type' => 'object',
@@ -534,18 +409,18 @@
534 409 'type' => 'object',
535 410 'properties' => [
536 411 'scope' => [
537 412 'type' => 'string',
538 - 'description' => 'Optional scope filter. ' . self::SCOPE_DESC,
539 - 'enum' => self::SCOPES
413 + 'description' => 'Optional scope filter',
414 + 'enum' => ['function', 'backend', 'frontend', 'scheduled', 'persistent']
540 415 ]
541 416 ]
542 417 ]
543 418 ];
544 -
419 +
545 420 // Snippet Exists
546 421 $tools[] = [
547 - 'name' => 'mwcode_snippet_exists',
422 + 'name' => 'code_engine_snippet_exists',
548 423 'description' => 'Check if a Code Engine snippet exists by ID',
549 424 'category' => 'Code Engine',
550 425 'inputSchema' => [
551 426 'type' => 'object',
@@ -560,9 +435,9 @@
560 435 ];
561 436
562 437 // Snippet Exists by Name
563 438 $tools[] = [
564 - 'name' => 'mwcode_snippet_exists_by_name',
439 + 'name' => 'code_engine_snippet_exists_by_name',
565 440 'description' => 'Check if a Code Engine snippet exists by name',
566 441 'category' => 'Code Engine',
567 442 'inputSchema' => [
568 443 'type' => 'object',
@@ -577,9 +452,9 @@
577 452 ];
578 453
579 454 // Validate Snippet Code
580 455 $tools[] = [
581 - 'name' => 'mwcode_validate_snippet_code',
456 + 'name' => 'code_engine_validate_snippet_code',
582 457 'description' => 'Validate snippet code syntax',
583 458 'category' => 'Code Engine',
584 459 'inputSchema' => [
585 460 'type' => 'object',
@@ -601,68 +476,14 @@
601 476
602 477 return $tools;
603 478 }
604 479
605 - /**
606 - * Execute a Callable function exposed via MCP. Returns $result unchanged when the
607 - * tool name does not match one of our opted-in functions, so the filter chain
608 - * continues to the management tools (and other plugins).
609 - */
610 - private function handle_function_execution( $result, $tool, $args ) {
611 - // Master switch: even an opted-in Callable is unreachable via MCP unless the
612 - // site has explicitly enabled function exposure. Returning $result unchanged
613 - // lets the filter chain fall through to the management tools and other plugins.
614 - if ( !$this->core->get_option( 'mcp_functions', false ) ) {
615 - return $result;
616 - }
617 -
618 - $match = null;
619 - foreach ( $this->get_mcp_functions() as $fn ) {
620 - if ( $fn['functionName'] === $tool ) {
621 - $match = $fn;
622 - break;
623 - }
624 - }
625 - if ( $match === null ) {
626 - return $result;
627 - }
628 -
629 - if ( !$this->api ) {
630 - return [ 'success' => false, 'error' => 'Code Engine API not initialized' ];
631 - }
632 -
633 - // getSnippets() rows expose the database id as 'id' (function metadata uses 'snippetId').
634 - $snippetId = $match['id'] ?? $match['snippetId'] ?? null;
635 -
636 - try {
637 - $output = $this->api->executeSnippet( $snippetId, is_array( $args ) ? $args : [] );
638 - return [ 'success' => true, 'data' => $output ];
639 - }
640 - // Snippet code is arbitrary PHP: a fatal surfaces as Error/TypeError/ParseError,
641 - // none of which are Exceptions. Catch Throwable so a bad snippet can never take
642 - // down the MCP request.
643 - catch ( \Throwable $e ) {
644 - return [ 'success' => false, 'error' => $e->getMessage() ];
645 - }
646 - }
647 -
648 480 public function handle_tool_execution( $result, $tool, $args, $id ) {
649 - // Individual Callable functions exposed via MCP take priority (named after the function).
650 - $handled = $this->handle_function_execution( $result, $tool, $args );
651 - if ( $handled !== $result ) {
652 - return $handled;
653 - }
654 -
655 - // Management/internal API tools are gated behind the master switch.
656 - if ( !$this->core->get_option( 'mcp_support', false ) ) {
657 - return $result;
658 - }
659 -
660 481 // Only handle our tools
661 - if ( strpos( $tool, 'mwcode_' ) !== 0 ) {
482 + if ( strpos( $tool, 'code_engine_' ) !== 0 ) {
662 483 return $result;
663 484 }
664 -
485 +
665 486 // Ensure API is initialized
666 487 if ( !$this->api ) {
667 488 return [ 'success' => false, 'error' => 'Code Engine API not initialized' ];
668 489 }
@@ -668,29 +489,29 @@
668 489 }
669 490
670 491 try {
671 492 switch ( $tool ) {
672 - case 'mwcode_get_snippet':
493 + case 'code_engine_get_snippet':
673 494 $data = $this->api->getSnippet( $args['id'], $args['options'] ?? [] );
674 495 return [ 'success' => true, 'data' => $data ];
675 496
676 - case 'mwcode_get_snippet_by_name':
497 + case 'code_engine_get_snippet_by_name':
677 498 $data = $this->api->getSnippetByName( $args['name'], $args['options'] ?? [] );
678 499 return [ 'success' => true, 'data' => $data ];
679 500
680 - case 'mwcode_get_snippets':
501 + case 'code_engine_get_snippets':
681 502 $data = $this->api->getSnippets( $args['safe'] ?? true, $args['scope'] ?? null );
682 503 return [ 'success' => true, 'data' => $data ];
683 504
684 - case 'mwcode_execute_snippet':
505 + case 'code_engine_execute_snippet':
685 506 $data = $this->api->executeSnippet( $args['id'], $args['args'] ?? [] );
686 507 return [ 'success' => true, 'data' => $data ];
687 508
688 - case 'mwcode_execute_snippet_by_name':
509 + case 'code_engine_execute_snippet_by_name':
689 510 $data = $this->api->executeSnippetByName( $args['name'], $args['args'] ?? [] );
690 511 return [ 'success' => true, 'data' => $data ];
691 512
692 - case 'mwcode_create_snippet':
513 + case 'code_engine_create_snippet':
693 514 $data = $this->api->createSnippet(
694 515 $args['name'],
695 516 $args['code'],
696 517 $args['scope'] ?? 'function',
@@ -697,53 +518,50 @@
697 518 $args['options'] ?? []
698 519 );
699 520 return [ 'success' => true, 'data' => $data ];
700 521
701 - case 'mwcode_update_snippet':
522 + case 'code_engine_update_snippet':
702 523 $data = $this->api->updateSnippet( $args['id'], $args['params'] ?? [] );
703 524 return [ 'success' => true, 'data' => $data ];
704 525
705 - case 'mwcode_delete_snippet':
526 + case 'code_engine_delete_snippet':
706 527 $success = $this->api->deleteSnippet( $args['id'] );
707 528 return [ 'success' => true, 'data' => [ 'deleted' => $success ] ];
708 529
709 - case 'mwcode_delete_snippet_by_name':
530 + case 'code_engine_delete_snippet_by_name':
710 531 $success = $this->api->deleteSnippetByName( $args['name'] );
711 532 return [ 'success' => true, 'data' => [ 'deleted' => $success ] ];
712 533
713 - case 'mwcode_activate_snippet':
534 + case 'code_engine_activate_snippet':
714 535 $success = $this->api->activateSnippet( $args['id'] );
715 536 return [ 'success' => true, 'data' => [ 'activated' => $success ] ];
716 537
717 - case 'mwcode_deactivate_snippet':
538 + case 'code_engine_deactivate_snippet':
718 539 $success = $this->api->deactivateSnippet( $args['id'] );
719 540 return [ 'success' => true, 'data' => [ 'deactivated' => $success ] ];
720 541
721 - case 'mwcode_get_snippets_by_scope':
542 + case 'code_engine_get_snippets_by_scope':
722 543 $data = $this->api->getSnippetsByScope( $args['scope'], $args['filters'] ?? [] );
723 544 return [ 'success' => true, 'data' => $data ];
724 545
725 - case 'mwcode_get_active_snippets':
546 + case 'code_engine_get_active_snippets':
726 547 $data = $this->api->getActiveSnippets( $args['scope'] ?? null );
727 548 return [ 'success' => true, 'data' => $data ];
728 549
729 - case 'mwcode_snippet_exists':
550 + case 'code_engine_snippet_exists':
730 551 $exists = $this->api->snippetExists( $args['id'] );
731 552 return [ 'success' => true, 'data' => [ 'exists' => $exists ] ];
732 553
733 - case 'mwcode_snippet_exists_by_name':
554 + case 'code_engine_snippet_exists_by_name':
734 555 $exists = $this->api->snippetExistsByName( $args['name'] );
735 556 return [ 'success' => true, 'data' => [ 'exists' => $exists ] ];
736 557
737 - case 'mwcode_validate_snippet_code':
558 + case 'code_engine_validate_snippet_code':
738 559 $validation = $this->api->validateSnippetCode( $args['code'], $args['target'] ?? 'php' );
739 560 return [ 'success' => true, 'data' => $validation ];
740 561 }
741 562 }
742 - // executeSnippet() runs arbitrary snippet PHP, whose fatals are Errors, not
743 - // Exceptions. Catch Throwable so a broken snippet returns a clean error rather
744 - // than crashing the MCP request.
745 - catch ( \Throwable $e ) {
563 + catch ( Exception $e ) {
746 564 return [ 'success' => false, 'error' => $e->getMessage() ];
747 565 }
748 566
749 567 return $result;