@respira/wordpress-mcp-server 6.3.1 → 6.6.0

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.
@@ -0,0 +1,758 @@
1
+ /**
2
+ * ACF tool definitions for the Respira MCP server.
3
+ *
4
+ * 54 tools covering field ops (free ACF) plus ACF Pro repeaters, flexible
5
+ * content, galleries, options pages, and relationships. Registered only on
6
+ * sites where ACF is active. Pro-only endpoints return PRO_FEATURE_REQUIRED
7
+ * from the plugin when ACF Pro is not installed.
8
+ *
9
+ * @since 6.6.0
10
+ */
11
+ /**
12
+ * Full ACF tool catalog. Imported by server.ts and pushed into getTools()
13
+ * when isAcfAvailable() is true.
14
+ */
15
+ export function getAcfTools() {
16
+ // Type assertion matches the pattern used in server.ts getTools(): SDK type
17
+ // for Tool does not include the optional *_Hint properties in every version.
18
+ return [
19
+ // =========================================================================
20
+ // Field operations (18)
21
+ // =========================================================================
22
+ {
23
+ name: 'respira_acf_get_field',
24
+ description: 'Read a single ACF field value from a post. Works for all field types. Returns null if the field is not set.',
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ post_id: { type: 'number', description: 'Post or page ID' },
29
+ field_key: { type: 'string', description: 'ACF field key or field name' },
30
+ },
31
+ required: ['post_id', 'field_key'],
32
+ },
33
+ readOnlyHint: true,
34
+ },
35
+ {
36
+ name: 'respira_acf_get_fields',
37
+ description: 'Read every ACF field value attached to a post. Returns a map of field_name to value.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ post_id: { type: 'number', description: 'Post or page ID' },
42
+ },
43
+ required: ['post_id'],
44
+ },
45
+ readOnlyHint: true,
46
+ },
47
+ {
48
+ name: 'respira_acf_update_field',
49
+ description: 'Update a single ACF field value on a post. Creates a before/after snapshot for rollback. Supports dry_run.',
50
+ inputSchema: {
51
+ type: 'object',
52
+ properties: {
53
+ post_id: { type: 'number' },
54
+ field_key: { type: 'string', description: 'ACF field key or field name' },
55
+ value: { description: 'New value. Type depends on the field.' },
56
+ dry_run: { type: 'boolean', description: 'Preview the change without writing.' },
57
+ },
58
+ required: ['post_id', 'field_key', 'value'],
59
+ },
60
+ },
61
+ {
62
+ name: 'respira_acf_update_fields',
63
+ description: 'Bulk-update multiple ACF fields on a single post in one snapshot. Fields is a map of field_key to value.',
64
+ inputSchema: {
65
+ type: 'object',
66
+ properties: {
67
+ post_id: { type: 'number' },
68
+ fields: { type: 'object', description: 'Map of field_key to new value.' },
69
+ dry_run: { type: 'boolean' },
70
+ },
71
+ required: ['post_id', 'fields'],
72
+ },
73
+ },
74
+ {
75
+ name: 'respira_acf_delete_field',
76
+ description: 'Remove a single ACF field value from a post. Does not delete the field definition, only the stored value.',
77
+ inputSchema: {
78
+ type: 'object',
79
+ properties: {
80
+ post_id: { type: 'number' },
81
+ field_key: { type: 'string' },
82
+ dry_run: { type: 'boolean' },
83
+ },
84
+ required: ['post_id', 'field_key'],
85
+ },
86
+ },
87
+ {
88
+ name: 'respira_acf_list_field_groups',
89
+ description: 'List every ACF field group registered on the site, with title, location rules, and status.',
90
+ inputSchema: { type: 'object', properties: {} },
91
+ readOnlyHint: true,
92
+ },
93
+ {
94
+ name: 'respira_acf_get_field_group',
95
+ description: 'Fetch a single ACF field group by key, including every field definition inside it.',
96
+ inputSchema: {
97
+ type: 'object',
98
+ properties: { group_key: { type: 'string' } },
99
+ required: ['group_key'],
100
+ },
101
+ readOnlyHint: true,
102
+ },
103
+ {
104
+ name: 'respira_acf_create_field_group',
105
+ description: 'Create a new ACF field group. Provide name, location_rules, and an array of fields.',
106
+ inputSchema: {
107
+ type: 'object',
108
+ properties: {
109
+ name: { type: 'string' },
110
+ location_rules: { type: 'array', items: { type: 'object' }, description: 'ACF location rule groups.' },
111
+ fields: { type: 'array', items: { type: 'object' } },
112
+ dry_run: { type: 'boolean' },
113
+ },
114
+ required: ['name'],
115
+ },
116
+ },
117
+ {
118
+ name: 'respira_acf_update_field_group',
119
+ description: 'Update properties on an existing ACF field group. Changes is a partial field group object.',
120
+ inputSchema: {
121
+ type: 'object',
122
+ properties: {
123
+ group_key: { type: 'string' },
124
+ changes: { type: 'object' },
125
+ dry_run: { type: 'boolean' },
126
+ },
127
+ required: ['group_key', 'changes'],
128
+ },
129
+ },
130
+ {
131
+ name: 'respira_acf_delete_field_group',
132
+ description: 'Delete an ACF field group. The group definition is removed; existing field values on posts are retained.',
133
+ inputSchema: {
134
+ type: 'object',
135
+ properties: { group_key: { type: 'string' } },
136
+ required: ['group_key'],
137
+ },
138
+ },
139
+ {
140
+ name: 'respira_acf_export_field_group',
141
+ description: 'Export a field group as JSON. Useful for moving a group between staging and production.',
142
+ inputSchema: {
143
+ type: 'object',
144
+ properties: { group_key: { type: 'string' } },
145
+ required: ['group_key'],
146
+ },
147
+ readOnlyHint: true,
148
+ },
149
+ {
150
+ name: 'respira_acf_import_field_group',
151
+ description: 'Import a field group from JSON. Auto-generates a new group key if none provided.',
152
+ inputSchema: {
153
+ type: 'object',
154
+ properties: {
155
+ json: { description: 'Field group JSON as object or stringified JSON.' },
156
+ dry_run: { type: 'boolean' },
157
+ },
158
+ required: ['json'],
159
+ },
160
+ },
161
+ {
162
+ name: 'respira_acf_clone_field_group',
163
+ description: 'Duplicate an existing field group under a new name. Field keys are regenerated to avoid collisions.',
164
+ inputSchema: {
165
+ type: 'object',
166
+ properties: {
167
+ group_key: { type: 'string' },
168
+ new_name: { type: 'string' },
169
+ dry_run: { type: 'boolean' },
170
+ },
171
+ required: ['group_key', 'new_name'],
172
+ },
173
+ },
174
+ {
175
+ name: 'respira_acf_validate_field',
176
+ description: 'Validate a value against a field definition without writing. Returns {valid, message}.',
177
+ inputSchema: {
178
+ type: 'object',
179
+ properties: {
180
+ post_id: { type: 'number' },
181
+ field_key: { type: 'string' },
182
+ value: {},
183
+ },
184
+ required: ['post_id', 'field_key', 'value'],
185
+ },
186
+ readOnlyHint: true,
187
+ },
188
+ {
189
+ name: 'respira_acf_get_field_object',
190
+ description: 'Fetch the full field definition object for a given field key.',
191
+ inputSchema: {
192
+ type: 'object',
193
+ properties: { field_key: { type: 'string' } },
194
+ required: ['field_key'],
195
+ },
196
+ readOnlyHint: true,
197
+ },
198
+ {
199
+ name: 'respira_acf_search_fields',
200
+ description: 'Full-text search across every registered ACF field definition (name, label, instructions).',
201
+ inputSchema: {
202
+ type: 'object',
203
+ properties: { q: { type: 'string', description: 'Search query' } },
204
+ required: ['q'],
205
+ },
206
+ readOnlyHint: true,
207
+ },
208
+ {
209
+ name: 'respira_acf_bulk_get_fields',
210
+ description: 'Read the same ACF field keys from multiple posts in one call. Max 500 post IDs.',
211
+ inputSchema: {
212
+ type: 'object',
213
+ properties: {
214
+ post_ids: { type: 'array', items: { type: 'number' }, maxItems: 500 },
215
+ field_keys: { type: 'array', items: { type: 'string' } },
216
+ },
217
+ required: ['post_ids', 'field_keys'],
218
+ },
219
+ readOnlyHint: true,
220
+ },
221
+ {
222
+ name: 'respira_acf_compare_fields',
223
+ description: 'Diff ACF field values between two posts. Returns per-field {a, b, equal}.',
224
+ inputSchema: {
225
+ type: 'object',
226
+ properties: {
227
+ post_id_a: { type: 'number' },
228
+ post_id_b: { type: 'number' },
229
+ field_keys: { type: 'array', items: { type: 'string' } },
230
+ },
231
+ required: ['post_id_a', 'post_id_b', 'field_keys'],
232
+ },
233
+ readOnlyHint: true,
234
+ },
235
+ // =========================================================================
236
+ // ACF Pro: Repeaters, Flexible Content, Galleries (18)
237
+ // =========================================================================
238
+ {
239
+ name: 'respira_acf_get_repeater',
240
+ description: 'Get every row from a repeater field. ACF Pro only.',
241
+ inputSchema: {
242
+ type: 'object',
243
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
244
+ required: ['post_id', 'field_key'],
245
+ },
246
+ readOnlyHint: true,
247
+ },
248
+ {
249
+ name: 'respira_acf_get_repeater_row',
250
+ description: 'Get a single row by zero-based index from a repeater field. ACF Pro only.',
251
+ inputSchema: {
252
+ type: 'object',
253
+ properties: {
254
+ post_id: { type: 'number' },
255
+ field_key: { type: 'string' },
256
+ row_index: { type: 'number', description: 'Zero-based row index.' },
257
+ },
258
+ required: ['post_id', 'field_key', 'row_index'],
259
+ },
260
+ readOnlyHint: true,
261
+ },
262
+ {
263
+ name: 'respira_acf_add_repeater_row',
264
+ description: 'Append a new row to a repeater field. Values is a map matching the repeater sub-fields. ACF Pro only.',
265
+ inputSchema: {
266
+ type: 'object',
267
+ properties: {
268
+ post_id: { type: 'number' },
269
+ field_key: { type: 'string' },
270
+ values: { type: 'object' },
271
+ dry_run: { type: 'boolean' },
272
+ },
273
+ required: ['post_id', 'field_key', 'values'],
274
+ },
275
+ },
276
+ {
277
+ name: 'respira_acf_update_repeater_row',
278
+ description: 'Update values on a specific row of a repeater field by zero-based index. ACF Pro only.',
279
+ inputSchema: {
280
+ type: 'object',
281
+ properties: {
282
+ post_id: { type: 'number' },
283
+ field_key: { type: 'string' },
284
+ row_index: { type: 'number' },
285
+ values: { type: 'object' },
286
+ dry_run: { type: 'boolean' },
287
+ },
288
+ required: ['post_id', 'field_key', 'row_index', 'values'],
289
+ },
290
+ },
291
+ {
292
+ name: 'respira_acf_delete_repeater_row',
293
+ description: 'Remove a row from a repeater field by zero-based index. ACF Pro only.',
294
+ inputSchema: {
295
+ type: 'object',
296
+ properties: {
297
+ post_id: { type: 'number' },
298
+ field_key: { type: 'string' },
299
+ row_index: { type: 'number' },
300
+ dry_run: { type: 'boolean' },
301
+ },
302
+ required: ['post_id', 'field_key', 'row_index'],
303
+ },
304
+ },
305
+ {
306
+ name: 'respira_acf_reorder_repeater',
307
+ description: 'Reorder repeater rows by providing new_order: the list of old indexes in new sequence. ACF Pro only.',
308
+ inputSchema: {
309
+ type: 'object',
310
+ properties: {
311
+ post_id: { type: 'number' },
312
+ field_key: { type: 'string' },
313
+ new_order: { type: 'array', items: { type: 'number' } },
314
+ dry_run: { type: 'boolean' },
315
+ },
316
+ required: ['post_id', 'field_key', 'new_order'],
317
+ },
318
+ },
319
+ {
320
+ name: 'respira_acf_count_repeater_rows',
321
+ description: 'Count how many rows are stored in a repeater field. ACF Pro only.',
322
+ inputSchema: {
323
+ type: 'object',
324
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
325
+ required: ['post_id', 'field_key'],
326
+ },
327
+ readOnlyHint: true,
328
+ },
329
+ {
330
+ name: 'respira_acf_get_flexible_content',
331
+ description: 'Get every layout (block) from a flexible content field. ACF Pro only.',
332
+ inputSchema: {
333
+ type: 'object',
334
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
335
+ required: ['post_id', 'field_key'],
336
+ },
337
+ readOnlyHint: true,
338
+ },
339
+ {
340
+ name: 'respira_acf_get_flexible_layout',
341
+ description: 'Get a single layout from a flexible content field by zero-based index. ACF Pro only.',
342
+ inputSchema: {
343
+ type: 'object',
344
+ properties: {
345
+ post_id: { type: 'number' },
346
+ field_key: { type: 'string' },
347
+ layout_index: { type: 'number' },
348
+ },
349
+ required: ['post_id', 'field_key', 'layout_index'],
350
+ },
351
+ readOnlyHint: true,
352
+ },
353
+ {
354
+ name: 'respira_acf_add_flexible_layout',
355
+ description: 'Append a new layout to a flexible content field. Layout_type must match one of the layouts defined on the field. ACF Pro only.',
356
+ inputSchema: {
357
+ type: 'object',
358
+ properties: {
359
+ post_id: { type: 'number' },
360
+ field_key: { type: 'string' },
361
+ layout_type: { type: 'string', description: 'Name of the layout to add.' },
362
+ values: { type: 'object' },
363
+ dry_run: { type: 'boolean' },
364
+ },
365
+ required: ['post_id', 'field_key', 'layout_type'],
366
+ },
367
+ },
368
+ {
369
+ name: 'respira_acf_update_flexible_layout',
370
+ description: 'Update values inside a specific layout of a flexible content field. ACF Pro only.',
371
+ inputSchema: {
372
+ type: 'object',
373
+ properties: {
374
+ post_id: { type: 'number' },
375
+ field_key: { type: 'string' },
376
+ layout_index: { type: 'number' },
377
+ values: { type: 'object' },
378
+ dry_run: { type: 'boolean' },
379
+ },
380
+ required: ['post_id', 'field_key', 'layout_index', 'values'],
381
+ },
382
+ },
383
+ {
384
+ name: 'respira_acf_delete_flexible_layout',
385
+ description: 'Remove a layout from a flexible content field by zero-based index. ACF Pro only.',
386
+ inputSchema: {
387
+ type: 'object',
388
+ properties: {
389
+ post_id: { type: 'number' },
390
+ field_key: { type: 'string' },
391
+ layout_index: { type: 'number' },
392
+ dry_run: { type: 'boolean' },
393
+ },
394
+ required: ['post_id', 'field_key', 'layout_index'],
395
+ },
396
+ },
397
+ {
398
+ name: 'respira_acf_reorder_flexible_layouts',
399
+ description: 'Reorder layouts inside a flexible content field. ACF Pro only.',
400
+ inputSchema: {
401
+ type: 'object',
402
+ properties: {
403
+ post_id: { type: 'number' },
404
+ field_key: { type: 'string' },
405
+ new_order: { type: 'array', items: { type: 'number' } },
406
+ dry_run: { type: 'boolean' },
407
+ },
408
+ required: ['post_id', 'field_key', 'new_order'],
409
+ },
410
+ },
411
+ {
412
+ name: 'respira_acf_get_gallery',
413
+ description: 'List images stored in a gallery field with attachment metadata. ACF Pro only.',
414
+ inputSchema: {
415
+ type: 'object',
416
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
417
+ required: ['post_id', 'field_key'],
418
+ },
419
+ readOnlyHint: true,
420
+ },
421
+ {
422
+ name: 'respira_acf_update_gallery',
423
+ description: 'Replace the gallery with a new array of attachment IDs. ACF Pro only.',
424
+ inputSchema: {
425
+ type: 'object',
426
+ properties: {
427
+ post_id: { type: 'number' },
428
+ field_key: { type: 'string' },
429
+ attachment_ids: { type: 'array', items: { type: 'number' } },
430
+ dry_run: { type: 'boolean' },
431
+ },
432
+ required: ['post_id', 'field_key', 'attachment_ids'],
433
+ },
434
+ },
435
+ {
436
+ name: 'respira_acf_add_to_gallery',
437
+ description: 'Append a single image to a gallery field. No-op if the image is already in the gallery. ACF Pro only.',
438
+ inputSchema: {
439
+ type: 'object',
440
+ properties: {
441
+ post_id: { type: 'number' },
442
+ field_key: { type: 'string' },
443
+ attachment_id: { type: 'number' },
444
+ dry_run: { type: 'boolean' },
445
+ },
446
+ required: ['post_id', 'field_key', 'attachment_id'],
447
+ },
448
+ },
449
+ {
450
+ name: 'respira_acf_remove_from_gallery',
451
+ description: 'Remove a single image from a gallery field. ACF Pro only.',
452
+ inputSchema: {
453
+ type: 'object',
454
+ properties: {
455
+ post_id: { type: 'number' },
456
+ field_key: { type: 'string' },
457
+ attachment_id: { type: 'number' },
458
+ dry_run: { type: 'boolean' },
459
+ },
460
+ required: ['post_id', 'field_key', 'attachment_id'],
461
+ },
462
+ },
463
+ {
464
+ name: 'respira_acf_reorder_gallery',
465
+ description: 'Reorder images in a gallery field. new_order is a list of attachment IDs in new sequence. ACF Pro only.',
466
+ inputSchema: {
467
+ type: 'object',
468
+ properties: {
469
+ post_id: { type: 'number' },
470
+ field_key: { type: 'string' },
471
+ new_order: { type: 'array', items: { type: 'number' } },
472
+ dry_run: { type: 'boolean' },
473
+ },
474
+ required: ['post_id', 'field_key', 'new_order'],
475
+ },
476
+ },
477
+ // =========================================================================
478
+ // ACF Pro: Options Pages (8)
479
+ // =========================================================================
480
+ {
481
+ name: 'respira_acf_list_options_pages',
482
+ description: 'List every ACF options page registered on the site. ACF Pro only.',
483
+ inputSchema: { type: 'object', properties: {} },
484
+ readOnlyHint: true,
485
+ },
486
+ {
487
+ name: 'respira_acf_get_option',
488
+ description: 'Read a single option value from an ACF options page. ACF Pro only.',
489
+ inputSchema: {
490
+ type: 'object',
491
+ properties: {
492
+ page_id: { type: 'string', description: 'Options page id (usually "option" or the custom slug).' },
493
+ field_key: { type: 'string' },
494
+ },
495
+ required: ['page_id', 'field_key'],
496
+ },
497
+ readOnlyHint: true,
498
+ },
499
+ {
500
+ name: 'respira_acf_get_options',
501
+ description: 'Read every option stored on an ACF options page. ACF Pro only.',
502
+ inputSchema: {
503
+ type: 'object',
504
+ properties: { page_id: { type: 'string' } },
505
+ required: ['page_id'],
506
+ },
507
+ readOnlyHint: true,
508
+ },
509
+ {
510
+ name: 'respira_acf_update_option',
511
+ description: 'Update a single option on an ACF options page. ACF Pro only.',
512
+ inputSchema: {
513
+ type: 'object',
514
+ properties: {
515
+ page_id: { type: 'string' },
516
+ field_key: { type: 'string' },
517
+ value: {},
518
+ dry_run: { type: 'boolean' },
519
+ },
520
+ required: ['page_id', 'field_key', 'value'],
521
+ },
522
+ },
523
+ {
524
+ name: 'respira_acf_update_options',
525
+ description: 'Bulk-update multiple options on an ACF options page. ACF Pro only.',
526
+ inputSchema: {
527
+ type: 'object',
528
+ properties: {
529
+ page_id: { type: 'string' },
530
+ fields: { type: 'object' },
531
+ dry_run: { type: 'boolean' },
532
+ },
533
+ required: ['page_id', 'fields'],
534
+ },
535
+ },
536
+ {
537
+ name: 'respira_acf_delete_option',
538
+ description: 'Remove a single option value from an ACF options page. ACF Pro only.',
539
+ inputSchema: {
540
+ type: 'object',
541
+ properties: {
542
+ page_id: { type: 'string' },
543
+ field_key: { type: 'string' },
544
+ dry_run: { type: 'boolean' },
545
+ },
546
+ required: ['page_id', 'field_key'],
547
+ },
548
+ },
549
+ {
550
+ name: 'respira_acf_create_options_page',
551
+ description: 'Register a new ACF options page at runtime. page_config must include page_title. ACF Pro only.',
552
+ inputSchema: {
553
+ type: 'object',
554
+ properties: {
555
+ page_config: { type: 'object', description: 'ACF options-page config (page_title, menu_slug, capability, position, parent_slug, etc.).' },
556
+ dry_run: { type: 'boolean' },
557
+ },
558
+ required: ['page_config'],
559
+ },
560
+ },
561
+ {
562
+ name: 'respira_acf_export_options',
563
+ description: 'Export every option value from an ACF options page as JSON. ACF Pro only.',
564
+ inputSchema: {
565
+ type: 'object',
566
+ properties: { page_id: { type: 'string' } },
567
+ required: ['page_id'],
568
+ },
569
+ readOnlyHint: true,
570
+ },
571
+ // =========================================================================
572
+ // Relationships & Post Objects (6)
573
+ // =========================================================================
574
+ {
575
+ name: 'respira_acf_get_relationship',
576
+ description: 'Read the related post IDs stored in a relationship field.',
577
+ inputSchema: {
578
+ type: 'object',
579
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
580
+ required: ['post_id', 'field_key'],
581
+ },
582
+ readOnlyHint: true,
583
+ },
584
+ {
585
+ name: 'respira_acf_update_relationship',
586
+ description: 'Set the related post IDs on a relationship field. Fully replaces existing relationships.',
587
+ inputSchema: {
588
+ type: 'object',
589
+ properties: {
590
+ post_id: { type: 'number' },
591
+ field_key: { type: 'string' },
592
+ related_post_ids: { type: 'array', items: { type: 'number' } },
593
+ dry_run: { type: 'boolean' },
594
+ },
595
+ required: ['post_id', 'field_key', 'related_post_ids'],
596
+ },
597
+ },
598
+ {
599
+ name: 'respira_acf_get_reverse_relationships',
600
+ description: 'Find every post that references the given post ID through any ACF field (relationship, post object, post object array).',
601
+ inputSchema: {
602
+ type: 'object',
603
+ properties: { post_id: { type: 'number' } },
604
+ required: ['post_id'],
605
+ },
606
+ readOnlyHint: true,
607
+ },
608
+ {
609
+ name: 'respira_acf_get_post_object',
610
+ description: 'Read a post object field, returning a normalized {ID, post_title, post_type} structure.',
611
+ inputSchema: {
612
+ type: 'object',
613
+ properties: { post_id: { type: 'number' }, field_key: { type: 'string' } },
614
+ required: ['post_id', 'field_key'],
615
+ },
616
+ readOnlyHint: true,
617
+ },
618
+ {
619
+ name: 'respira_acf_get_user_field',
620
+ description: 'Read an ACF field attached to a user profile.',
621
+ inputSchema: {
622
+ type: 'object',
623
+ properties: { user_id: { type: 'number' }, field_key: { type: 'string' } },
624
+ required: ['user_id', 'field_key'],
625
+ },
626
+ readOnlyHint: true,
627
+ },
628
+ {
629
+ name: 'respira_acf_update_user_field',
630
+ description: 'Update an ACF field attached to a user profile.',
631
+ inputSchema: {
632
+ type: 'object',
633
+ properties: {
634
+ user_id: { type: 'number' },
635
+ field_key: { type: 'string' },
636
+ value: {},
637
+ dry_run: { type: 'boolean' },
638
+ },
639
+ required: ['user_id', 'field_key', 'value'],
640
+ },
641
+ },
642
+ // =========================================================================
643
+ // Term + bulk (4)
644
+ // =========================================================================
645
+ {
646
+ name: 'respira_acf_get_term_field',
647
+ description: 'Read an ACF field attached to a taxonomy term.',
648
+ inputSchema: {
649
+ type: 'object',
650
+ properties: { term_id: { type: 'number' }, field_key: { type: 'string' } },
651
+ required: ['term_id', 'field_key'],
652
+ },
653
+ readOnlyHint: true,
654
+ },
655
+ {
656
+ name: 'respira_acf_update_term_field',
657
+ description: 'Update an ACF field attached to a taxonomy term.',
658
+ inputSchema: {
659
+ type: 'object',
660
+ properties: {
661
+ term_id: { type: 'number' },
662
+ field_key: { type: 'string' },
663
+ value: {},
664
+ dry_run: { type: 'boolean' },
665
+ },
666
+ required: ['term_id', 'field_key', 'value'],
667
+ },
668
+ },
669
+ {
670
+ name: 'respira_acf_clone_fields',
671
+ description: 'Copy selected ACF field values from a source post to a target post. Requires Builder tier or above (bulk scope).',
672
+ inputSchema: {
673
+ type: 'object',
674
+ properties: {
675
+ source_post_id: { type: 'number' },
676
+ target_post_id: { type: 'number' },
677
+ field_keys: { type: 'array', items: { type: 'string' } },
678
+ dry_run: { type: 'boolean' },
679
+ },
680
+ required: ['source_post_id', 'target_post_id', 'field_keys'],
681
+ },
682
+ },
683
+ {
684
+ name: 'respira_acf_bulk_update_fields',
685
+ description: 'Apply the same field updates across up to 500 posts. Each post gets its own snapshot. Requires Builder tier or above.',
686
+ inputSchema: {
687
+ type: 'object',
688
+ properties: {
689
+ post_ids: { type: 'array', items: { type: 'number' }, maxItems: 500 },
690
+ fields: { type: 'object', description: 'Map of field_key to new value applied to every post_id.' },
691
+ dry_run: { type: 'boolean' },
692
+ },
693
+ required: ['post_ids', 'fields'],
694
+ },
695
+ },
696
+ ];
697
+ }
698
+ /**
699
+ * Canonical list of ACF tool names. Used by dispatchToolCall() to filter
700
+ * gracefully when ACF is not active on the target site.
701
+ */
702
+ export const ACF_TOOL_NAMES = new Set([
703
+ 'respira_acf_get_field',
704
+ 'respira_acf_get_fields',
705
+ 'respira_acf_update_field',
706
+ 'respira_acf_update_fields',
707
+ 'respira_acf_delete_field',
708
+ 'respira_acf_list_field_groups',
709
+ 'respira_acf_get_field_group',
710
+ 'respira_acf_create_field_group',
711
+ 'respira_acf_update_field_group',
712
+ 'respira_acf_delete_field_group',
713
+ 'respira_acf_export_field_group',
714
+ 'respira_acf_import_field_group',
715
+ 'respira_acf_clone_field_group',
716
+ 'respira_acf_validate_field',
717
+ 'respira_acf_get_field_object',
718
+ 'respira_acf_search_fields',
719
+ 'respira_acf_bulk_get_fields',
720
+ 'respira_acf_compare_fields',
721
+ 'respira_acf_get_repeater',
722
+ 'respira_acf_get_repeater_row',
723
+ 'respira_acf_add_repeater_row',
724
+ 'respira_acf_update_repeater_row',
725
+ 'respira_acf_delete_repeater_row',
726
+ 'respira_acf_reorder_repeater',
727
+ 'respira_acf_count_repeater_rows',
728
+ 'respira_acf_get_flexible_content',
729
+ 'respira_acf_get_flexible_layout',
730
+ 'respira_acf_add_flexible_layout',
731
+ 'respira_acf_update_flexible_layout',
732
+ 'respira_acf_delete_flexible_layout',
733
+ 'respira_acf_reorder_flexible_layouts',
734
+ 'respira_acf_get_gallery',
735
+ 'respira_acf_update_gallery',
736
+ 'respira_acf_add_to_gallery',
737
+ 'respira_acf_remove_from_gallery',
738
+ 'respira_acf_reorder_gallery',
739
+ 'respira_acf_list_options_pages',
740
+ 'respira_acf_get_option',
741
+ 'respira_acf_get_options',
742
+ 'respira_acf_update_option',
743
+ 'respira_acf_update_options',
744
+ 'respira_acf_delete_option',
745
+ 'respira_acf_create_options_page',
746
+ 'respira_acf_export_options',
747
+ 'respira_acf_get_relationship',
748
+ 'respira_acf_update_relationship',
749
+ 'respira_acf_get_reverse_relationships',
750
+ 'respira_acf_get_post_object',
751
+ 'respira_acf_get_user_field',
752
+ 'respira_acf_update_user_field',
753
+ 'respira_acf_get_term_field',
754
+ 'respira_acf_update_term_field',
755
+ 'respira_acf_clone_fields',
756
+ 'respira_acf_bulk_update_fields',
757
+ ]);
758
+ //# sourceMappingURL=acf-tools.js.map