@respira/wordpress-mcp-server 6.11.0 → 6.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/__tests__/rest-route-fallback.test.d.ts +14 -0
- package/dist/__tests__/rest-route-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/rest-route-fallback.test.js +265 -0
- package/dist/__tests__/rest-route-fallback.test.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +151 -84
- package/dist/server.js.map +1 -1
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/wordpress-client.d.ts +63 -4
- package/dist/wordpress-client.d.ts.map +1 -1
- package/dist/wordpress-client.js +327 -27
- package/dist/wordpress-client.js.map +1 -1
- package/package.json +3 -2
package/dist/server.js
CHANGED
|
@@ -43,7 +43,7 @@ export class RespiraWordPressServer {
|
|
|
43
43
|
allowedSites = null;
|
|
44
44
|
/** Whether the plugin version warning has already been shown this session. */
|
|
45
45
|
versionWarningShown = false;
|
|
46
|
-
static MCP_SERVER_VERSION = '6.
|
|
46
|
+
static MCP_SERVER_VERSION = '6.11.2';
|
|
47
47
|
/**
|
|
48
48
|
* Normalize a tool name: respira_* → wordpress_* for switch dispatch.
|
|
49
49
|
* Tracks whether the deprecated wordpress_* name was used.
|
|
@@ -196,7 +196,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
196
196
|
- Module names use et_pb_ prefix: et_pb_text, et_pb_blurb, et_pb_image, et_pb_button, et_pb_cta, et_pb_slider, etc.
|
|
197
197
|
- Settings are shortcode attributes: [et_pb_text text_font="Roboto" text_text_color="#333333"]
|
|
198
198
|
- Button uses url/url_new_window attributes (different from Divi 5's linkUrl/linkTarget)
|
|
199
|
-
- IMPORTANT: When injecting content, set
|
|
199
|
+
- IMPORTANT: When injecting content, set divi_version to "4" in respira_inject_builder_content
|
|
200
200
|
- Respira auto-detects whether the site runs Divi 4 or Divi 5 — check respira_get_builder_info for the version
|
|
201
201
|
- Element-level operations work via shortcode tree parsing
|
|
202
202
|
|
|
@@ -668,7 +668,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
668
668
|
type: 'number',
|
|
669
669
|
description: 'Page number for pagination',
|
|
670
670
|
},
|
|
671
|
-
|
|
671
|
+
per_page: {
|
|
672
672
|
type: 'number',
|
|
673
673
|
description: 'Number of items per page',
|
|
674
674
|
},
|
|
@@ -705,7 +705,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
705
705
|
inputSchema: {
|
|
706
706
|
type: 'object',
|
|
707
707
|
properties: {
|
|
708
|
-
|
|
708
|
+
original_id: {
|
|
709
709
|
type: 'number',
|
|
710
710
|
description: 'ID of the original page to duplicate',
|
|
711
711
|
},
|
|
@@ -714,7 +714,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
714
714
|
description: 'Optional suffix for the duplicated page title',
|
|
715
715
|
},
|
|
716
716
|
},
|
|
717
|
-
required: ['
|
|
717
|
+
required: ['original_id'],
|
|
718
718
|
},
|
|
719
719
|
},
|
|
720
720
|
{
|
|
@@ -743,7 +743,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
743
743
|
type: 'string',
|
|
744
744
|
description: 'URL slug (post_name). Example: "about-us" produces /about-us/.',
|
|
745
745
|
},
|
|
746
|
-
|
|
746
|
+
custom_css: {
|
|
747
747
|
type: 'string',
|
|
748
748
|
description: 'Custom CSS for the page. Auto-detects builder: Divi → _et_pb_custom_css, Elementor → _elementor_page_settings.custom_css.',
|
|
749
749
|
},
|
|
@@ -751,7 +751,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
751
751
|
type: 'object',
|
|
752
752
|
description: 'Post meta data',
|
|
753
753
|
},
|
|
754
|
-
|
|
754
|
+
edit_target: {
|
|
755
755
|
type: 'string',
|
|
756
756
|
description: 'Choose ask, live, or duplicate when the target is an original page.',
|
|
757
757
|
enum: ['ask', 'live', 'duplicate'],
|
|
@@ -760,7 +760,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
760
760
|
type: 'boolean',
|
|
761
761
|
description: 'Backward-compatible alias for explicit live editing when direct editing is enabled.',
|
|
762
762
|
},
|
|
763
|
-
|
|
763
|
+
skip_security_check: {
|
|
764
764
|
type: 'boolean',
|
|
765
765
|
description: 'Advanced: bypass Respira content security checks and sanitization for this update. Use only with trusted content.',
|
|
766
766
|
},
|
|
@@ -806,7 +806,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
806
806
|
type: 'number',
|
|
807
807
|
description: 'Page number',
|
|
808
808
|
},
|
|
809
|
-
|
|
809
|
+
per_page: {
|
|
810
810
|
type: 'number',
|
|
811
811
|
description: 'Items per page',
|
|
812
812
|
},
|
|
@@ -843,7 +843,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
843
843
|
inputSchema: {
|
|
844
844
|
type: 'object',
|
|
845
845
|
properties: {
|
|
846
|
-
|
|
846
|
+
original_id: {
|
|
847
847
|
type: 'number',
|
|
848
848
|
description: 'Original post ID',
|
|
849
849
|
},
|
|
@@ -852,7 +852,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
852
852
|
description: 'Optional suffix',
|
|
853
853
|
},
|
|
854
854
|
},
|
|
855
|
-
required: ['
|
|
855
|
+
required: ['original_id'],
|
|
856
856
|
},
|
|
857
857
|
},
|
|
858
858
|
{
|
|
@@ -912,19 +912,19 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
912
912
|
type: 'object',
|
|
913
913
|
description: 'Generic map of taxonomy slug to array of term ids/slugs for custom taxonomies (e.g. product_cat). Example: { "product_cat": [12, "featured"] }.',
|
|
914
914
|
},
|
|
915
|
-
|
|
915
|
+
featured_media: {
|
|
916
916
|
type: 'number',
|
|
917
917
|
description: 'Attachment ID to set as the featured image. Pass 0 to clear.',
|
|
918
918
|
},
|
|
919
|
-
|
|
919
|
+
create_missing_terms: {
|
|
920
920
|
type: 'boolean',
|
|
921
921
|
description: 'When true, auto-create taxonomy terms that do not exist by name. Default false (strict: unknown slug returns 400).',
|
|
922
922
|
},
|
|
923
|
-
|
|
923
|
+
append_terms: {
|
|
924
924
|
type: 'boolean',
|
|
925
925
|
description: 'When true, append to existing taxonomy terms instead of replacing. Default false (replace).',
|
|
926
926
|
},
|
|
927
|
-
|
|
927
|
+
custom_css: {
|
|
928
928
|
type: 'string',
|
|
929
929
|
description: 'Custom CSS for the post. Auto-detects builder: Divi → _et_pb_custom_css, Elementor → _elementor_page_settings.custom_css.',
|
|
930
930
|
},
|
|
@@ -932,7 +932,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
932
932
|
type: 'object',
|
|
933
933
|
description: 'Post meta data',
|
|
934
934
|
},
|
|
935
|
-
|
|
935
|
+
edit_target: {
|
|
936
936
|
type: 'string',
|
|
937
937
|
description: 'Choose ask, live, or duplicate when the target is an original post.',
|
|
938
938
|
enum: ['ask', 'live', 'duplicate'],
|
|
@@ -941,7 +941,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
941
941
|
type: 'boolean',
|
|
942
942
|
description: 'Backward-compatible alias for explicit live editing when direct editing is enabled.',
|
|
943
943
|
},
|
|
944
|
-
|
|
944
|
+
skip_security_check: {
|
|
945
945
|
type: 'boolean',
|
|
946
946
|
description: 'Advanced: bypass Respira content security checks and sanitization for this update. Use only with trusted content.',
|
|
947
947
|
},
|
|
@@ -983,7 +983,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
983
983
|
type: 'number',
|
|
984
984
|
description: 'Page number',
|
|
985
985
|
},
|
|
986
|
-
|
|
986
|
+
per_page: {
|
|
987
987
|
type: 'number',
|
|
988
988
|
description: 'Items per page',
|
|
989
989
|
},
|
|
@@ -1005,7 +1005,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1005
1005
|
type: 'string',
|
|
1006
1006
|
description: 'Filename for the uploaded file',
|
|
1007
1007
|
},
|
|
1008
|
-
|
|
1008
|
+
mime_type: {
|
|
1009
1009
|
type: 'string',
|
|
1010
1010
|
description: 'MIME type of the file (e.g., image/jpeg, image/png, application/pdf)',
|
|
1011
1011
|
},
|
|
@@ -1035,12 +1035,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1035
1035
|
type: 'string',
|
|
1036
1036
|
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. Use get_builder_info to discover the active builder first.',
|
|
1037
1037
|
},
|
|
1038
|
-
|
|
1038
|
+
page_id: {
|
|
1039
1039
|
type: 'number',
|
|
1040
1040
|
description: 'Page ID',
|
|
1041
1041
|
},
|
|
1042
1042
|
},
|
|
1043
|
-
required: ['builder', '
|
|
1043
|
+
required: ['builder', 'page_id'],
|
|
1044
1044
|
},
|
|
1045
1045
|
readOnlyHint: true,
|
|
1046
1046
|
},
|
|
@@ -1054,7 +1054,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1054
1054
|
type: 'string',
|
|
1055
1055
|
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. Use get_builder_info to discover the active builder first.',
|
|
1056
1056
|
},
|
|
1057
|
-
|
|
1057
|
+
page_id: {
|
|
1058
1058
|
type: 'number',
|
|
1059
1059
|
description: 'Page or post ID',
|
|
1060
1060
|
},
|
|
@@ -1067,13 +1067,13 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1067
1067
|
description: 'Maximum number of matches to return (default 10)',
|
|
1068
1068
|
},
|
|
1069
1069
|
},
|
|
1070
|
-
required: ['builder', '
|
|
1070
|
+
required: ['builder', 'page_id'],
|
|
1071
1071
|
},
|
|
1072
1072
|
readOnlyHint: true,
|
|
1073
1073
|
},
|
|
1074
1074
|
{
|
|
1075
1075
|
name: 'wordpress_inject_builder_content',
|
|
1076
|
-
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content — use mode:"append" to add content without destroying existing elements. For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. For Divi,
|
|
1076
|
+
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content — use mode:"append" to add content without destroying existing elements. For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. For Divi, divi_version is required ("4" or "5").',
|
|
1077
1077
|
inputSchema: {
|
|
1078
1078
|
type: 'object',
|
|
1079
1079
|
properties: {
|
|
@@ -1081,7 +1081,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1081
1081
|
type: 'string',
|
|
1082
1082
|
description: 'Builder identifier. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery.',
|
|
1083
1083
|
},
|
|
1084
|
-
|
|
1084
|
+
page_id: {
|
|
1085
1085
|
type: 'number',
|
|
1086
1086
|
description: 'Page ID',
|
|
1087
1087
|
},
|
|
@@ -1094,18 +1094,18 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1094
1094
|
description: 'replace (default): OVERWRITES all existing page content. append: adds new content after existing elements, preserving the current layout.',
|
|
1095
1095
|
enum: ['replace', 'append'],
|
|
1096
1096
|
},
|
|
1097
|
-
|
|
1097
|
+
edit_target: {
|
|
1098
1098
|
type: 'string',
|
|
1099
1099
|
description: 'When editing an original, choose ask, live, or duplicate. Defaults to ask when direct editing is enabled.',
|
|
1100
1100
|
enum: ['ask', 'live', 'duplicate'],
|
|
1101
1101
|
},
|
|
1102
|
-
|
|
1102
|
+
divi_version: {
|
|
1103
1103
|
type: 'string',
|
|
1104
1104
|
description: 'Divi generation hint ("4" for shortcode format, "5" for block format). Required for all Divi inject calls.',
|
|
1105
1105
|
enum: ['4', '5'],
|
|
1106
1106
|
},
|
|
1107
1107
|
},
|
|
1108
|
-
required: ['builder', '
|
|
1108
|
+
required: ['builder', 'page_id', 'content'],
|
|
1109
1109
|
},
|
|
1110
1110
|
idempotentHint: true,
|
|
1111
1111
|
},
|
|
@@ -1119,11 +1119,11 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1119
1119
|
type: 'string',
|
|
1120
1120
|
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery.',
|
|
1121
1121
|
},
|
|
1122
|
-
|
|
1122
|
+
page_id: {
|
|
1123
1123
|
type: 'number',
|
|
1124
1124
|
description: 'Page ID',
|
|
1125
1125
|
},
|
|
1126
|
-
|
|
1126
|
+
module_identifier: {
|
|
1127
1127
|
type: 'object',
|
|
1128
1128
|
description: 'Module identifier - use one of: admin_label, path, or type. For Elementor: prefer id or path (dot notation like "0.0.1"). admin_label maps to Navigator label or CSS ID. For Divi: admin_label maps to Admin Label field.',
|
|
1129
1129
|
properties: {
|
|
@@ -1163,13 +1163,13 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1163
1163
|
},
|
|
1164
1164
|
},
|
|
1165
1165
|
},
|
|
1166
|
-
|
|
1166
|
+
edit_target: {
|
|
1167
1167
|
type: 'string',
|
|
1168
1168
|
description: 'When editing an original, choose ask, live, or duplicate. Defaults to ask when direct editing is enabled.',
|
|
1169
1169
|
enum: ['ask', 'live', 'duplicate'],
|
|
1170
1170
|
},
|
|
1171
1171
|
},
|
|
1172
|
-
required: ['builder', '
|
|
1172
|
+
required: ['builder', 'page_id', 'module_identifier', 'updates'],
|
|
1173
1173
|
},
|
|
1174
1174
|
idempotentHint: true,
|
|
1175
1175
|
},
|
|
@@ -1262,7 +1262,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1262
1262
|
type: 'string',
|
|
1263
1263
|
description: 'Builder slug',
|
|
1264
1264
|
},
|
|
1265
|
-
|
|
1265
|
+
post_id: {
|
|
1266
1266
|
type: 'number',
|
|
1267
1267
|
description: 'Post ID',
|
|
1268
1268
|
},
|
|
@@ -1275,13 +1275,13 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1275
1275
|
description: 'Patch operations[]',
|
|
1276
1276
|
items: { type: 'object' },
|
|
1277
1277
|
},
|
|
1278
|
-
|
|
1278
|
+
edit_target: {
|
|
1279
1279
|
type: 'string',
|
|
1280
1280
|
description: 'When editing an original, choose ask, live, or duplicate. Defaults to ask when direct editing is enabled.',
|
|
1281
1281
|
enum: ['ask', 'live', 'duplicate'],
|
|
1282
1282
|
},
|
|
1283
1283
|
},
|
|
1284
|
-
required: ['builder', '
|
|
1284
|
+
required: ['builder', 'post_id', 'operations'],
|
|
1285
1285
|
},
|
|
1286
1286
|
idempotentHint: true,
|
|
1287
1287
|
},
|
|
@@ -1334,12 +1334,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1334
1334
|
inputSchema: {
|
|
1335
1335
|
type: 'object',
|
|
1336
1336
|
properties: {
|
|
1337
|
-
|
|
1337
|
+
page_id: {
|
|
1338
1338
|
type: 'number',
|
|
1339
1339
|
description: 'Page ID to analyze',
|
|
1340
1340
|
},
|
|
1341
1341
|
},
|
|
1342
|
-
required: ['
|
|
1342
|
+
required: ['page_id'],
|
|
1343
1343
|
},
|
|
1344
1344
|
readOnlyHint: true,
|
|
1345
1345
|
},
|
|
@@ -1349,12 +1349,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1349
1349
|
inputSchema: {
|
|
1350
1350
|
type: 'object',
|
|
1351
1351
|
properties: {
|
|
1352
|
-
|
|
1352
|
+
page_id: {
|
|
1353
1353
|
type: 'number',
|
|
1354
1354
|
description: 'Page ID to analyze',
|
|
1355
1355
|
},
|
|
1356
1356
|
},
|
|
1357
|
-
required: ['
|
|
1357
|
+
required: ['page_id'],
|
|
1358
1358
|
},
|
|
1359
1359
|
readOnlyHint: true,
|
|
1360
1360
|
},
|
|
@@ -1364,12 +1364,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1364
1364
|
inputSchema: {
|
|
1365
1365
|
type: 'object',
|
|
1366
1366
|
properties: {
|
|
1367
|
-
|
|
1367
|
+
page_id: {
|
|
1368
1368
|
type: 'number',
|
|
1369
1369
|
description: 'Page ID to analyze',
|
|
1370
1370
|
},
|
|
1371
1371
|
},
|
|
1372
|
-
required: ['
|
|
1372
|
+
required: ['page_id'],
|
|
1373
1373
|
},
|
|
1374
1374
|
readOnlyHint: true,
|
|
1375
1375
|
},
|
|
@@ -1380,12 +1380,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1380
1380
|
inputSchema: {
|
|
1381
1381
|
type: 'object',
|
|
1382
1382
|
properties: {
|
|
1383
|
-
|
|
1383
|
+
page_id: {
|
|
1384
1384
|
type: 'number',
|
|
1385
1385
|
description: 'Page ID to analyze',
|
|
1386
1386
|
},
|
|
1387
1387
|
},
|
|
1388
|
-
required: ['
|
|
1388
|
+
required: ['page_id'],
|
|
1389
1389
|
},
|
|
1390
1390
|
readOnlyHint: true,
|
|
1391
1391
|
},
|
|
@@ -1395,12 +1395,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1395
1395
|
inputSchema: {
|
|
1396
1396
|
type: 'object',
|
|
1397
1397
|
properties: {
|
|
1398
|
-
|
|
1398
|
+
page_id: {
|
|
1399
1399
|
type: 'number',
|
|
1400
1400
|
description: 'Page ID to analyze',
|
|
1401
1401
|
},
|
|
1402
1402
|
},
|
|
1403
|
-
required: ['
|
|
1403
|
+
required: ['page_id'],
|
|
1404
1404
|
},
|
|
1405
1405
|
readOnlyHint: true,
|
|
1406
1406
|
},
|
|
@@ -1410,12 +1410,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1410
1410
|
inputSchema: {
|
|
1411
1411
|
type: 'object',
|
|
1412
1412
|
properties: {
|
|
1413
|
-
|
|
1413
|
+
page_id: {
|
|
1414
1414
|
type: 'number',
|
|
1415
1415
|
description: 'Page ID to analyze',
|
|
1416
1416
|
},
|
|
1417
1417
|
},
|
|
1418
|
-
required: ['
|
|
1418
|
+
required: ['page_id'],
|
|
1419
1419
|
},
|
|
1420
1420
|
readOnlyHint: true,
|
|
1421
1421
|
},
|
|
@@ -1425,12 +1425,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1425
1425
|
inputSchema: {
|
|
1426
1426
|
type: 'object',
|
|
1427
1427
|
properties: {
|
|
1428
|
-
|
|
1428
|
+
post_id: {
|
|
1429
1429
|
type: 'number',
|
|
1430
1430
|
description: 'Post or page ID to analyze',
|
|
1431
1431
|
},
|
|
1432
1432
|
},
|
|
1433
|
-
required: ['
|
|
1433
|
+
required: ['post_id'],
|
|
1434
1434
|
},
|
|
1435
1435
|
readOnlyHint: true,
|
|
1436
1436
|
},
|
|
@@ -1441,12 +1441,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1441
1441
|
inputSchema: {
|
|
1442
1442
|
type: 'object',
|
|
1443
1443
|
properties: {
|
|
1444
|
-
|
|
1444
|
+
page_id: {
|
|
1445
1445
|
type: 'number',
|
|
1446
1446
|
description: 'Page ID to analyze',
|
|
1447
1447
|
},
|
|
1448
1448
|
},
|
|
1449
|
-
required: ['
|
|
1449
|
+
required: ['page_id'],
|
|
1450
1450
|
},
|
|
1451
1451
|
readOnlyHint: true,
|
|
1452
1452
|
},
|
|
@@ -1456,12 +1456,12 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1456
1456
|
inputSchema: {
|
|
1457
1457
|
type: 'object',
|
|
1458
1458
|
properties: {
|
|
1459
|
-
|
|
1459
|
+
page_id: {
|
|
1460
1460
|
type: 'number',
|
|
1461
1461
|
description: 'Page ID to analyze',
|
|
1462
1462
|
},
|
|
1463
1463
|
},
|
|
1464
|
-
required: ['
|
|
1464
|
+
required: ['page_id'],
|
|
1465
1465
|
},
|
|
1466
1466
|
readOnlyHint: true,
|
|
1467
1467
|
},
|
|
@@ -1531,7 +1531,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1531
1531
|
inputSchema: {
|
|
1532
1532
|
type: 'object',
|
|
1533
1533
|
properties: {
|
|
1534
|
-
|
|
1534
|
+
slug_or_url: {
|
|
1535
1535
|
type: 'string',
|
|
1536
1536
|
description: 'Plugin slug (from WordPress.org) or ZIP file URL',
|
|
1537
1537
|
},
|
|
@@ -1541,7 +1541,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1541
1541
|
enum: ['wordpress.org', 'url'],
|
|
1542
1542
|
},
|
|
1543
1543
|
},
|
|
1544
|
-
required: ['
|
|
1544
|
+
required: ['slug_or_url'],
|
|
1545
1545
|
},
|
|
1546
1546
|
},
|
|
1547
1547
|
{
|
|
@@ -1617,7 +1617,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1617
1617
|
type: 'number',
|
|
1618
1618
|
description: 'Page number',
|
|
1619
1619
|
},
|
|
1620
|
-
|
|
1620
|
+
per_page: {
|
|
1621
1621
|
type: 'number',
|
|
1622
1622
|
description: 'Items per page',
|
|
1623
1623
|
},
|
|
@@ -1735,7 +1735,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1735
1735
|
type: 'number',
|
|
1736
1736
|
description: 'Page number',
|
|
1737
1737
|
},
|
|
1738
|
-
|
|
1738
|
+
per_page: {
|
|
1739
1739
|
type: 'number',
|
|
1740
1740
|
description: 'Items per page',
|
|
1741
1741
|
},
|
|
@@ -1873,7 +1873,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
1873
1873
|
type: 'number',
|
|
1874
1874
|
description: 'Page number',
|
|
1875
1875
|
},
|
|
1876
|
-
|
|
1876
|
+
per_page: {
|
|
1877
1877
|
type: 'number',
|
|
1878
1878
|
description: 'Items per page',
|
|
1879
1879
|
},
|
|
@@ -2032,7 +2032,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
2032
2032
|
type: 'number',
|
|
2033
2033
|
description: 'Page number',
|
|
2034
2034
|
},
|
|
2035
|
-
|
|
2035
|
+
per_page: {
|
|
2036
2036
|
type: 'number',
|
|
2037
2037
|
description: 'Items per page',
|
|
2038
2038
|
},
|
|
@@ -2133,11 +2133,11 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
2133
2133
|
type: 'object',
|
|
2134
2134
|
description: 'Generic map of taxonomy slug to array of term ids/slugs for custom taxonomies (e.g. product_cat). Example: { "product_cat": [12, "featured"] }.',
|
|
2135
2135
|
},
|
|
2136
|
-
|
|
2136
|
+
featured_media: {
|
|
2137
2137
|
type: 'number',
|
|
2138
2138
|
description: 'Attachment ID to set as the featured image.',
|
|
2139
2139
|
},
|
|
2140
|
-
|
|
2140
|
+
create_missing_terms: {
|
|
2141
2141
|
type: 'boolean',
|
|
2142
2142
|
description: 'When true, auto-create taxonomy terms that do not exist by name. Default false (strict: unknown slug returns 400 and the post is rolled back).',
|
|
2143
2143
|
},
|
|
@@ -2210,15 +2210,15 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
2210
2210
|
type: 'object',
|
|
2211
2211
|
description: 'Generic map of taxonomy slug to array of term ids/slugs for custom taxonomies.',
|
|
2212
2212
|
},
|
|
2213
|
-
|
|
2213
|
+
featured_media: {
|
|
2214
2214
|
type: 'number',
|
|
2215
2215
|
description: 'Attachment ID to set as the featured image. Pass 0 to clear.',
|
|
2216
2216
|
},
|
|
2217
|
-
|
|
2217
|
+
create_missing_terms: {
|
|
2218
2218
|
type: 'boolean',
|
|
2219
2219
|
description: 'When true, auto-create taxonomy terms that do not exist by name. Default false (strict).',
|
|
2220
2220
|
},
|
|
2221
|
-
|
|
2221
|
+
append_terms: {
|
|
2222
2222
|
type: 'boolean',
|
|
2223
2223
|
description: 'When true, append to existing taxonomy terms instead of replacing. Default false (replace).',
|
|
2224
2224
|
},
|
|
@@ -2226,11 +2226,11 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
2226
2226
|
type: 'object',
|
|
2227
2227
|
description: 'Post meta data (e.g., { "_et_pb_custom_css": "/* CSS */" })',
|
|
2228
2228
|
},
|
|
2229
|
-
|
|
2229
|
+
custom_css: {
|
|
2230
2230
|
type: 'string',
|
|
2231
2231
|
description: 'Custom CSS for page builders (Divi/Elementor). Automatically saved to the appropriate meta field based on detected builder.',
|
|
2232
2232
|
},
|
|
2233
|
-
|
|
2233
|
+
edit_target: {
|
|
2234
2234
|
type: 'string',
|
|
2235
2235
|
description: 'Choose ask, live, or duplicate when the target is an original item.',
|
|
2236
2236
|
enum: ['ask', 'live', 'duplicate'],
|
|
@@ -3073,12 +3073,79 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3073
3073
|
},
|
|
3074
3074
|
];
|
|
3075
3075
|
}
|
|
3076
|
+
/**
|
|
3077
|
+
* camelCase → snake_case rename map (mcp-v6.11.1).
|
|
3078
|
+
*
|
|
3079
|
+
* Schemas advertise snake_case only. Handlers can read either form for one
|
|
3080
|
+
* release; camelCase emits a deprecation warning to stderr and will be
|
|
3081
|
+
* removed in mcp-v6.13.
|
|
3082
|
+
*
|
|
3083
|
+
* Mirrors both directions so wordpress-client.ts (which still reads
|
|
3084
|
+
* camelCase fields like data.customCss / data.featuredMedia / args.edit_target
|
|
3085
|
+
* before mapping them to plugin-side snake_case) keeps working unchanged.
|
|
3086
|
+
* The wordpress-client surface is purely internal — its rename can ride
|
|
3087
|
+
* along in a follow-up release without breaking callers.
|
|
3088
|
+
*/
|
|
3089
|
+
static CAMEL_TO_SNAKE_PARAMS = {
|
|
3090
|
+
pageId: 'page_id',
|
|
3091
|
+
postId: 'post_id',
|
|
3092
|
+
perPage: 'per_page',
|
|
3093
|
+
editTarget: 'edit_target',
|
|
3094
|
+
originalId: 'original_id',
|
|
3095
|
+
customCss: 'custom_css',
|
|
3096
|
+
skipSecurityCheck: 'skip_security_check',
|
|
3097
|
+
featuredMedia: 'featured_media',
|
|
3098
|
+
createMissingTerms: 'create_missing_terms',
|
|
3099
|
+
appendTerms: 'append_terms',
|
|
3100
|
+
mimeType: 'mime_type',
|
|
3101
|
+
moduleIdentifier: 'module_identifier',
|
|
3102
|
+
diviVersion: 'divi_version',
|
|
3103
|
+
slugOrUrl: 'slug_or_url',
|
|
3104
|
+
};
|
|
3105
|
+
/**
|
|
3106
|
+
* Normalize tool args so handlers see both snake_case (new, advertised in
|
|
3107
|
+
* the schema) and camelCase (legacy, kept working for one release with a
|
|
3108
|
+
* deprecation warning). Mutates the args object in place and returns it.
|
|
3109
|
+
*/
|
|
3110
|
+
normalizeArgsForBackCompat(toolName, args) {
|
|
3111
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
3112
|
+
return args;
|
|
3113
|
+
}
|
|
3114
|
+
for (const [camel, snake] of Object.entries(RespiraWordPressServer.CAMEL_TO_SNAKE_PARAMS)) {
|
|
3115
|
+
const hasCamel = Object.prototype.hasOwnProperty.call(args, camel);
|
|
3116
|
+
const hasSnake = Object.prototype.hasOwnProperty.call(args, snake);
|
|
3117
|
+
if (hasCamel && !hasSnake) {
|
|
3118
|
+
// Caller is on the legacy camelCase path. Mirror to snake_case so
|
|
3119
|
+
// schema-aware downstream code can read it; warn once.
|
|
3120
|
+
args[snake] = args[camel];
|
|
3121
|
+
try {
|
|
3122
|
+
process.stderr.write(`[respira-mcp] deprecated: '${camel}' is renamed to '${snake}', will be removed in mcp-v6.13 (tool: ${toolName})\n`);
|
|
3123
|
+
}
|
|
3124
|
+
catch {
|
|
3125
|
+
// ignore stderr write failures.
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
else if (!hasCamel && hasSnake) {
|
|
3129
|
+
// Caller is on the new snake_case path. Mirror to camelCase so the
|
|
3130
|
+
// wordpress-client.ts layer (which still reads camelCase) keeps
|
|
3131
|
+
// working without further surface changes this release.
|
|
3132
|
+
args[camel] = args[snake];
|
|
3133
|
+
}
|
|
3134
|
+
// If both are present, prefer snake_case as source of truth and leave
|
|
3135
|
+
// both in place. If neither, no-op.
|
|
3136
|
+
}
|
|
3137
|
+
return args;
|
|
3138
|
+
}
|
|
3076
3139
|
async handleToolCall(name, args) {
|
|
3077
3140
|
if (!this.currentSite) {
|
|
3078
3141
|
throw new Error('No WordPress site configured');
|
|
3079
3142
|
}
|
|
3080
3143
|
// Normalize respira_* ↔ wordpress_* names.
|
|
3081
3144
|
const { canonical, deprecated } = this.normalizeToolName(name);
|
|
3145
|
+
// mcp-v6.11.1: snake_case sweep across tool catalog. Schemas advertise
|
|
3146
|
+
// snake_case; legacy camelCase still accepted with a deprecation warning
|
|
3147
|
+
// for one release.
|
|
3148
|
+
args = this.normalizeArgsForBackCompat(canonical, args);
|
|
3082
3149
|
const result = await this.dispatchToolCall(canonical, args);
|
|
3083
3150
|
if (deprecated && result && typeof result === 'object' && !Array.isArray(result)) {
|
|
3084
3151
|
return {
|
|
@@ -3120,7 +3187,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3120
3187
|
return await this.currentSite.getPage(args.id, args.include);
|
|
3121
3188
|
case 'wordpress_create_page_duplicate':
|
|
3122
3189
|
return {
|
|
3123
|
-
...(await this.currentSite.duplicatePage(args.
|
|
3190
|
+
...(await this.currentSite.duplicatePage(args.original_id, args.suffix, args.include)),
|
|
3124
3191
|
respira_approvals_url: this.currentSite.getApprovalsUrl(),
|
|
3125
3192
|
};
|
|
3126
3193
|
case 'wordpress_update_page': {
|
|
@@ -3153,7 +3220,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3153
3220
|
return await this.currentSite.getPost(args.id, args.include);
|
|
3154
3221
|
case 'wordpress_create_post_duplicate':
|
|
3155
3222
|
return {
|
|
3156
|
-
...(await this.currentSite.duplicatePost(args.
|
|
3223
|
+
...(await this.currentSite.duplicatePost(args.original_id, args.suffix, args.include)),
|
|
3157
3224
|
respira_approvals_url: this.currentSite.getApprovalsUrl(),
|
|
3158
3225
|
};
|
|
3159
3226
|
case 'wordpress_update_post': {
|
|
@@ -3183,19 +3250,19 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3183
3250
|
case 'wordpress_list_media':
|
|
3184
3251
|
return await this.currentSite.listMedia(args);
|
|
3185
3252
|
case 'wordpress_upload_media':
|
|
3186
|
-
return await this.currentSite.uploadMedia(args.file, args.filename, args.
|
|
3253
|
+
return await this.currentSite.uploadMedia(args.file, args.filename, args.mime_type, args.title, args.alt, args.caption);
|
|
3187
3254
|
case 'wordpress_extract_builder_content':
|
|
3188
|
-
return await this.currentSite.extractBuilderContent(args.builder, args.
|
|
3255
|
+
return await this.currentSite.extractBuilderContent(args.builder, args.page_id);
|
|
3189
3256
|
case 'wordpress_find_builder_targets':
|
|
3190
|
-
return await this.currentSite.findBuilderTargets(args.builder, args.
|
|
3257
|
+
return await this.currentSite.findBuilderTargets(args.builder, args.page_id, args.query, args.limit);
|
|
3191
3258
|
case 'wordpress_inject_builder_content':
|
|
3192
3259
|
return {
|
|
3193
|
-
...(await this.currentSite.injectBuilderContent(args.builder, args.
|
|
3260
|
+
...(await this.currentSite.injectBuilderContent(args.builder, args.page_id, args.content, args.divi_version, args.edit_target, args.mode)),
|
|
3194
3261
|
respira_approvals_url: this.currentSite.getApprovalsUrl(),
|
|
3195
3262
|
};
|
|
3196
3263
|
case 'wordpress_update_module':
|
|
3197
3264
|
return {
|
|
3198
|
-
...(await this.currentSite.updateModule(args.builder, args.
|
|
3265
|
+
...(await this.currentSite.updateModule(args.builder, args.page_id, args.module_identifier, args.updates, args.edit_target)),
|
|
3199
3266
|
respira_approvals_url: this.currentSite.getApprovalsUrl(),
|
|
3200
3267
|
};
|
|
3201
3268
|
case 'wordpress_validate_security':
|
|
@@ -3220,25 +3287,25 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3220
3287
|
return await this.currentSite.diagnoseConnection({ post_id: args.post_id });
|
|
3221
3288
|
// Page Speed Analysis
|
|
3222
3289
|
case 'wordpress_analyze_performance':
|
|
3223
|
-
return await this.currentSite.analyzePerformance(args.
|
|
3290
|
+
return await this.currentSite.analyzePerformance(args.page_id);
|
|
3224
3291
|
case 'wordpress_get_core_web_vitals':
|
|
3225
|
-
return await this.currentSite.getCoreWebVitals(args.
|
|
3292
|
+
return await this.currentSite.getCoreWebVitals(args.page_id);
|
|
3226
3293
|
case 'wordpress_analyze_images':
|
|
3227
|
-
return await this.currentSite.analyzeImages(args.
|
|
3294
|
+
return await this.currentSite.analyzeImages(args.page_id);
|
|
3228
3295
|
// SEO Analysis
|
|
3229
3296
|
case 'wordpress_analyze_seo':
|
|
3230
|
-
return await this.currentSite.analyzeSEO(args.
|
|
3297
|
+
return await this.currentSite.analyzeSEO(args.page_id);
|
|
3231
3298
|
case 'wordpress_check_seo_issues':
|
|
3232
|
-
return await this.currentSite.checkSEOIssues(args.
|
|
3299
|
+
return await this.currentSite.checkSEOIssues(args.page_id);
|
|
3233
3300
|
case 'wordpress_analyze_readability':
|
|
3234
|
-
return await this.currentSite.analyzeReadability(args.
|
|
3301
|
+
return await this.currentSite.analyzeReadability(args.page_id);
|
|
3235
3302
|
case 'wordpress_analyze_rankmath':
|
|
3236
|
-
return await this.currentSite.analyzeRankMath(args.
|
|
3303
|
+
return await this.currentSite.analyzeRankMath(args.post_id);
|
|
3237
3304
|
// AEO Analysis
|
|
3238
3305
|
case 'wordpress_analyze_aeo':
|
|
3239
|
-
return await this.currentSite.analyzeAEO(args.
|
|
3306
|
+
return await this.currentSite.analyzeAEO(args.page_id);
|
|
3240
3307
|
case 'wordpress_check_structured_data':
|
|
3241
|
-
return await this.currentSite.checkStructuredData(args.
|
|
3308
|
+
return await this.currentSite.checkStructuredData(args.page_id);
|
|
3242
3309
|
// Accessibility
|
|
3243
3310
|
case 'wordpress_list_accessibility_scans':
|
|
3244
3311
|
return await this.currentSite.listAccessibilityScans();
|
|
@@ -3252,7 +3319,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3252
3319
|
case 'wordpress_list_plugins':
|
|
3253
3320
|
return await this.currentSite.listPlugins();
|
|
3254
3321
|
case 'wordpress_install_plugin':
|
|
3255
|
-
return await this.currentSite.installPlugin(args.
|
|
3322
|
+
return await this.currentSite.installPlugin(args.slug_or_url, args.source || 'wordpress.org');
|
|
3256
3323
|
case 'wordpress_activate_plugin':
|
|
3257
3324
|
return await this.currentSite.activatePlugin(args.slug);
|
|
3258
3325
|
case 'wordpress_deactivate_plugin':
|
|
@@ -3367,7 +3434,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
3367
3434
|
case 'wordpress_restore_snapshot':
|
|
3368
3435
|
return await this.currentSite.restoreSnapshot(args.snapshot_uuid);
|
|
3369
3436
|
case 'wordpress_apply_builder_patch':
|
|
3370
|
-
return await this.currentSite.applyBuilderPatch(args.builder, args.
|
|
3437
|
+
return await this.currentSite.applyBuilderPatch(args.builder, args.post_id, args.operations, args.include, args.edit_target);
|
|
3371
3438
|
case 'woocommerce_list_products':
|
|
3372
3439
|
return await this.currentSite.woocommerceListProducts(args);
|
|
3373
3440
|
case 'woocommerce_get_product':
|