@kontent-ai/mcp-server 0.31.0 → 0.33.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.
Files changed (119) hide show
  1. package/README.md +57 -61
  2. package/build/schemas/bulkGetItemsWithVariantsSchemas.js +1 -1
  3. package/build/schemas/contentItemSchemas.js +1 -1
  4. package/build/schemas/filterVariantSchemas.js +8 -3
  5. package/build/schemas/searchOperationSchemas.js +2 -1
  6. package/build/server.js +4 -112
  7. package/build/test/bm25/bm25.js +47 -0
  8. package/build/test/bm25/toolSearchBm25.spec.js +874 -0
  9. package/build/tools/bulk-get-content-item-variants.js +31 -0
  10. package/build/tools/change-content-item-variant-workflow-step.js +35 -0
  11. package/build/tools/create-content-item-variant.js +44 -0
  12. package/build/tools/create-content-item.js +47 -0
  13. package/build/tools/create-content-type-snippet.js +34 -0
  14. package/build/tools/create-content-type.js +37 -0
  15. package/build/tools/create-language.js +24 -0
  16. package/build/tools/create-new-content-item-variant-version.js +27 -0
  17. package/build/tools/create-space.js +22 -0
  18. package/build/tools/create-taxonomy-group.js +18 -0
  19. package/build/tools/create-workflow.js +23 -0
  20. package/build/tools/delete-content-item-variant.js +25 -0
  21. package/build/tools/delete-content-item.js +23 -0
  22. package/build/tools/delete-content-type-snippet.js +19 -0
  23. package/build/tools/delete-content-type.js +23 -0
  24. package/build/tools/delete-space.js +19 -0
  25. package/build/tools/delete-taxonomy-group.js +19 -0
  26. package/build/tools/delete-workflow.js +19 -0
  27. package/build/tools/get-asset.js +17 -0
  28. package/build/tools/get-content-item-translations.js +20 -0
  29. package/build/tools/get-content-item-variant.js +22 -0
  30. package/build/tools/get-content-item.js +17 -0
  31. package/build/tools/get-content-type-snippet.js +20 -0
  32. package/build/tools/get-content-type.js +17 -0
  33. package/build/tools/get-patch-guide.js +12 -12
  34. package/build/tools/get-published-content-item-variant-version.js +23 -0
  35. package/build/tools/get-taxonomy-group.js +17 -0
  36. package/build/tools/index.js +106 -0
  37. package/build/tools/list-asset-folders.js +14 -0
  38. package/build/tools/list-assets.js +23 -0
  39. package/build/tools/list-collections.js +14 -0
  40. package/build/tools/list-content-item-variants.js +50 -0
  41. package/build/tools/list-content-type-snippets.js +23 -0
  42. package/build/tools/list-content-types.js +23 -0
  43. package/build/tools/list-languages.js +24 -0
  44. package/build/tools/list-roles.js +14 -0
  45. package/build/tools/list-spaces.js +14 -0
  46. package/build/tools/list-taxonomy-groups.js +23 -0
  47. package/build/tools/list-workflows.js +14 -0
  48. package/build/tools/patch-asset-folders.js +25 -0
  49. package/build/tools/patch-collections.js +25 -0
  50. package/build/tools/patch-content-type-snippet.js +30 -0
  51. package/build/tools/patch-content-type.js +33 -0
  52. package/build/tools/patch-language.js +24 -0
  53. package/build/tools/patch-space.js +28 -0
  54. package/build/tools/patch-taxonomy-group.js +28 -0
  55. package/build/tools/publish-content-item-variant.js +72 -0
  56. package/build/tools/referencedToolNames.js +10 -0
  57. package/build/tools/search-content-item-variants.js +108 -0
  58. package/build/tools/toolDefinition.js +1 -0
  59. package/build/tools/unpublish-content-item-variant.js +72 -0
  60. package/build/tools/update-asset.js +23 -0
  61. package/build/tools/update-content-item-variant.js +36 -0
  62. package/build/tools/update-content-item.js +74 -0
  63. package/build/tools/update-workflow.js +31 -0
  64. package/package.json +18 -17
  65. package/build/tools/add-content-item-mapi.js +0 -47
  66. package/build/tools/add-content-type-mapi.js +0 -38
  67. package/build/tools/add-content-type-snippet-mapi.js +0 -35
  68. package/build/tools/add-language-mapi.js +0 -25
  69. package/build/tools/add-space-mapi.js +0 -23
  70. package/build/tools/add-taxonomy-group-mapi.js +0 -19
  71. package/build/tools/add-workflow-mapi.js +0 -24
  72. package/build/tools/bulk-get-items-variants-mapi.js +0 -31
  73. package/build/tools/change-variant-workflow-step-mapi.js +0 -36
  74. package/build/tools/create-language-variant-mapi.js +0 -44
  75. package/build/tools/create-variant-version-mapi.js +0 -28
  76. package/build/tools/delete-content-item-mapi.js +0 -24
  77. package/build/tools/delete-content-type-mapi.js +0 -24
  78. package/build/tools/delete-language-variant-mapi.js +0 -26
  79. package/build/tools/delete-space-mapi.js +0 -20
  80. package/build/tools/delete-taxonomy-group-mapi.js +0 -20
  81. package/build/tools/delete-type-snippet-mapi.js +0 -23
  82. package/build/tools/delete-workflow-mapi.js +0 -20
  83. package/build/tools/filter-variants-mapi.js +0 -49
  84. package/build/tools/get-asset-mapi.js +0 -21
  85. package/build/tools/get-item-mapi.js +0 -21
  86. package/build/tools/get-latest-variant-mapi.js +0 -23
  87. package/build/tools/get-published-variant-mapi.js +0 -24
  88. package/build/tools/get-taxonomy-group-mapi.js +0 -21
  89. package/build/tools/get-type-mapi.js +0 -21
  90. package/build/tools/get-type-snippet-mapi.js +0 -21
  91. package/build/tools/list-asset-folders-mapi.js +0 -15
  92. package/build/tools/list-assets-mapi.js +0 -24
  93. package/build/tools/list-collections-mapi.js +0 -15
  94. package/build/tools/list-content-type-snippets-mapi.js +0 -24
  95. package/build/tools/list-content-types-mapi.js +0 -24
  96. package/build/tools/list-languages-mapi.js +0 -24
  97. package/build/tools/list-roles-mapi.js +0 -15
  98. package/build/tools/list-spaces-mapi.js +0 -15
  99. package/build/tools/list-taxonomy-groups-mapi.js +0 -24
  100. package/build/tools/list-variants-collection-mapi.js +0 -26
  101. package/build/tools/list-variants-components-type-mapi.js +0 -26
  102. package/build/tools/list-variants-item-mapi.js +0 -21
  103. package/build/tools/list-variants-space-mapi.js +0 -24
  104. package/build/tools/list-variants-type-mapi.js +0 -26
  105. package/build/tools/list-workflows-mapi.js +0 -15
  106. package/build/tools/patch-asset-folders-mapi.js +0 -25
  107. package/build/tools/patch-collections-mapi.js +0 -25
  108. package/build/tools/patch-content-type-mapi.js +0 -33
  109. package/build/tools/patch-language-mapi.js +0 -24
  110. package/build/tools/patch-space-mapi.js +0 -28
  111. package/build/tools/patch-taxonomy-group-mapi.js +0 -28
  112. package/build/tools/patch-type-snippet-mapi.js +0 -30
  113. package/build/tools/publish-variant-mapi.js +0 -73
  114. package/build/tools/search-variants-mapi.js +0 -108
  115. package/build/tools/unpublish-variant-mapi.js +0 -73
  116. package/build/tools/update-asset-mapi.js +0 -24
  117. package/build/tools/update-content-item-mapi.js +0 -74
  118. package/build/tools/update-language-variant-mapi.js +0 -37
  119. package/build/tools/update-workflow-mapi.js +0 -32
@@ -0,0 +1,874 @@
1
+ import * as assert from "node:assert";
2
+ import { before, describe, it } from "mocha";
3
+ import { allTools } from "../../tools/index.js";
4
+ import { createToolSearchIndex, searchTools } from "./bm25.js";
5
+ const topK = 5;
6
+ const assertToolsFound = (index, query, expectedTools) => {
7
+ // Search with a wider window so we can report the actual position of missed tools
8
+ const wideResults = searchTools(index, query, 20);
9
+ const wideNames = wideResults.map((r) => r.name);
10
+ for (const expected of expectedTools) {
11
+ const actualPosition = wideNames.indexOf(expected) + 1; // 0 means not found in top 20
12
+ assert.ok(actualPosition >= 1 && actualPosition <= topK, `Query "${query}": "${expected}" found at position ${actualPosition || "beyond top 20"}, expected within top ${topK}. Top ${topK}: [${wideNames.slice(0, topK).join(", ")}]`);
13
+ }
14
+ };
15
+ // ---------------------------------------------------------------------------
16
+ // Test data — each group covers one entity/domain with query variations
17
+ // ---------------------------------------------------------------------------
18
+ const testGroups = [
19
+ {
20
+ name: "content type operations",
21
+ cases: [
22
+ // Action verb variations: create / add / new
23
+ {
24
+ query: "create content type",
25
+ expected: [allTools.createContentType.name],
26
+ },
27
+ {
28
+ query: "add content type",
29
+ expected: [allTools.createContentType.name],
30
+ },
31
+ {
32
+ query: "new content type",
33
+ expected: [allTools.createContentType.name],
34
+ },
35
+ // Synonym: model / schema / definition
36
+ {
37
+ query: "content model schema",
38
+ expected: [allTools.createContentType.name],
39
+ },
40
+ // Action verb variations: get / retrieve / fetch
41
+ {
42
+ query: "get content type",
43
+ expected: [
44
+ allTools.getContentType.name,
45
+ allTools.listContentTypes.name,
46
+ ],
47
+ },
48
+ {
49
+ query: "retrieve content type",
50
+ expected: [allTools.getContentType.name],
51
+ },
52
+ { query: "fetch content type", expected: [allTools.getContentType.name] },
53
+ // Action verb variations: delete / remove
54
+ {
55
+ query: "delete content type",
56
+ expected: [allTools.deleteContentType.name],
57
+ },
58
+ {
59
+ query: "remove content type",
60
+ expected: [allTools.deleteContentType.name],
61
+ },
62
+ // Action verb variations: modify / patch / edit / update
63
+ {
64
+ query: "modify content type elements",
65
+ expected: [allTools.patchContentType.name],
66
+ },
67
+ {
68
+ query: "patch content type",
69
+ expected: [allTools.patchContentType.name],
70
+ },
71
+ {
72
+ query: "edit content type fields",
73
+ expected: [allTools.patchContentType.name],
74
+ },
75
+ // Action verb variations: list / all / browse
76
+ {
77
+ query: "list content types",
78
+ expected: [allTools.listContentTypes.name],
79
+ },
80
+ {
81
+ query: "all content types",
82
+ expected: [allTools.listContentTypes.name],
83
+ },
84
+ // Synonym: structure / definition / template
85
+ {
86
+ query: "content type structure",
87
+ expected: [allTools.getContentType.name],
88
+ },
89
+ {
90
+ query: "content type definition",
91
+ expected: [allTools.getContentType.name],
92
+ },
93
+ {
94
+ query: "content template fields",
95
+ expected: [allTools.createContentType.name],
96
+ },
97
+ ],
98
+ },
99
+ {
100
+ name: "content type snippet operations",
101
+ cases: [
102
+ {
103
+ query: "content type snippet",
104
+ expected: [
105
+ allTools.createContentTypeSnippet.name,
106
+ allTools.getContentTypeSnippet.name,
107
+ allTools.listContentTypeSnippets.name,
108
+ ],
109
+ },
110
+ {
111
+ query: "reusable snippet elements",
112
+ expected: [
113
+ allTools.createContentTypeSnippet.name,
114
+ allTools.getContentTypeSnippet.name,
115
+ ],
116
+ },
117
+ {
118
+ query: "create snippet",
119
+ expected: [allTools.createContentTypeSnippet.name],
120
+ },
121
+ { query: "get snippet", expected: [allTools.getContentTypeSnippet.name] },
122
+ {
123
+ query: "modify snippet",
124
+ expected: [allTools.patchContentTypeSnippet.name],
125
+ },
126
+ {
127
+ query: "patch snippet",
128
+ expected: [allTools.patchContentTypeSnippet.name],
129
+ },
130
+ {
131
+ query: "delete snippet",
132
+ expected: [allTools.deleteContentTypeSnippet.name],
133
+ },
134
+ {
135
+ query: "remove snippet",
136
+ expected: [allTools.deleteContentTypeSnippet.name],
137
+ },
138
+ ],
139
+ },
140
+ {
141
+ name: "content item operations",
142
+ cases: [
143
+ // create / add / new
144
+ {
145
+ query: "create content item",
146
+ expected: [allTools.createContentItem.name],
147
+ },
148
+ {
149
+ query: "add content item",
150
+ expected: [allTools.createContentItem.name],
151
+ },
152
+ {
153
+ query: "new content item",
154
+ expected: [allTools.createContentItem.name],
155
+ },
156
+ // get / retrieve
157
+ { query: "get content item", expected: [allTools.getContentItem.name] },
158
+ {
159
+ query: "retrieve content item",
160
+ expected: [allTools.getContentItem.name],
161
+ },
162
+ // update / edit
163
+ {
164
+ query: "update content item name",
165
+ expected: [allTools.updateContentItem.name],
166
+ },
167
+ {
168
+ query: "edit content item",
169
+ expected: [allTools.updateContentItem.name],
170
+ },
171
+ // delete / remove
172
+ {
173
+ query: "delete content item",
174
+ expected: [allTools.deleteContentItem.name],
175
+ },
176
+ {
177
+ query: "remove content item",
178
+ expected: [allTools.deleteContentItem.name],
179
+ },
180
+ // Synonym: page / entry / record
181
+ {
182
+ query: "create page entry",
183
+ expected: [allTools.createContentItem.name],
184
+ },
185
+ { query: "get content entry", expected: [allTools.getContentItem.name] },
186
+ // Finding specific content items should also surface filter/search
187
+ {
188
+ query: "find content item",
189
+ expected: [allTools.listContentItemVariants.name],
190
+ },
191
+ {
192
+ query: "search for content item",
193
+ expected: [allTools.searchContentItemVariants.name],
194
+ },
195
+ ],
196
+ },
197
+ {
198
+ name: "content item variant / translation operations",
199
+ cases: [
200
+ // Translation-related
201
+ {
202
+ query: "translate content language",
203
+ expected: [
204
+ allTools.createContentItemVariant.name,
205
+ allTools.getContentItemTranslations.name,
206
+ ],
207
+ },
208
+ {
209
+ query: "add translation",
210
+ expected: [allTools.createContentItemVariant.name],
211
+ },
212
+ {
213
+ query: "create language version",
214
+ expected: [allTools.createContentItemVariant.name],
215
+ },
216
+ // create / add / new — full and partial name combinations
217
+ {
218
+ query: "create content item variant",
219
+ expected: [allTools.createContentItemVariant.name],
220
+ },
221
+ {
222
+ query: "create item variant",
223
+ expected: [allTools.createContentItemVariant.name],
224
+ },
225
+ {
226
+ query: "create content variant",
227
+ expected: [allTools.createContentItemVariant.name],
228
+ },
229
+ {
230
+ query: "add item variant",
231
+ expected: [allTools.createContentItemVariant.name],
232
+ },
233
+ // get all translations of a single item
234
+ {
235
+ query: "get item translations",
236
+ expected: [allTools.getContentItemTranslations.name],
237
+ },
238
+ {
239
+ query: "content item translations",
240
+ expected: [allTools.getContentItemTranslations.name],
241
+ },
242
+ {
243
+ query: "all language versions item",
244
+ expected: [allTools.getContentItemTranslations.name],
245
+ },
246
+ {
247
+ query: "available translations item",
248
+ expected: [allTools.getContentItemTranslations.name],
249
+ },
250
+ // get / retrieve / fetch — full and partial name combinations
251
+ {
252
+ query: "get content item variant",
253
+ expected: [allTools.getContentItemVariant.name],
254
+ },
255
+ {
256
+ query: "get item variant",
257
+ expected: [allTools.getContentItemVariant.name],
258
+ },
259
+ {
260
+ query: "get content variant",
261
+ expected: [allTools.getContentItemVariant.name],
262
+ },
263
+ {
264
+ query: "retrieve variant content",
265
+ expected: [allTools.getContentItemVariant.name],
266
+ },
267
+ {
268
+ query: "fetch variant draft",
269
+ expected: [allTools.getContentItemVariant.name],
270
+ },
271
+ // get published version — when a newer draft exists and you need the live content
272
+ {
273
+ query: "get published variant version",
274
+ expected: [allTools.getPublishedContentItemVariantVersion.name],
275
+ },
276
+ {
277
+ query: "published version variant",
278
+ expected: [allTools.getPublishedContentItemVariantVersion.name],
279
+ },
280
+ {
281
+ query: "live published content",
282
+ expected: [allTools.getPublishedContentItemVariantVersion.name],
283
+ },
284
+ {
285
+ query: "published content delivery",
286
+ expected: [allTools.getPublishedContentItemVariantVersion.name],
287
+ },
288
+ // update / edit / write — full and partial name combinations
289
+ {
290
+ query: "update content item variant",
291
+ expected: [allTools.updateContentItemVariant.name],
292
+ },
293
+ {
294
+ query: "update item variant content",
295
+ expected: [allTools.updateContentItemVariant.name],
296
+ },
297
+ {
298
+ query: "update content variant",
299
+ expected: [allTools.updateContentItemVariant.name],
300
+ },
301
+ {
302
+ query: "edit variant elements",
303
+ expected: [allTools.updateContentItemVariant.name],
304
+ },
305
+ {
306
+ query: "write variant content",
307
+ expected: [allTools.updateContentItemVariant.name],
308
+ },
309
+ // New version
310
+ {
311
+ query: "create new draft version",
312
+ expected: [allTools.createNewContentItemVariantVersion.name],
313
+ },
314
+ {
315
+ query: "new version published variant",
316
+ expected: [allTools.createNewContentItemVariantVersion.name],
317
+ },
318
+ // Bulk — full and partial name combinations
319
+ {
320
+ query: "bulk get content item variants",
321
+ expected: [allTools.bulkGetContentItemVariants.name],
322
+ },
323
+ {
324
+ query: "bulk get item variants",
325
+ expected: [allTools.bulkGetContentItemVariants.name],
326
+ },
327
+ {
328
+ query: "bulk get content variants",
329
+ expected: [allTools.bulkGetContentItemVariants.name],
330
+ },
331
+ {
332
+ query: "fetch multiple items",
333
+ expected: [allTools.bulkGetContentItemVariants.name],
334
+ },
335
+ {
336
+ query: "bulk retrieve variants",
337
+ expected: [allTools.bulkGetContentItemVariants.name],
338
+ },
339
+ // delete / remove — full and partial name combinations
340
+ {
341
+ query: "delete content item variant",
342
+ expected: [allTools.deleteContentItemVariant.name],
343
+ },
344
+ {
345
+ query: "delete item variant",
346
+ expected: [allTools.deleteContentItemVariant.name],
347
+ },
348
+ {
349
+ query: "delete content variant",
350
+ expected: [allTools.deleteContentItemVariant.name],
351
+ },
352
+ {
353
+ query: "remove variant translation",
354
+ expected: [allTools.deleteContentItemVariant.name],
355
+ },
356
+ // Synonym: localize / i18n / multilingual
357
+ {
358
+ query: "localize content",
359
+ expected: [allTools.createContentItemVariant.name],
360
+ },
361
+ {
362
+ query: "multilingual content variant",
363
+ expected: [allTools.createContentItemVariant.name],
364
+ },
365
+ // Synonym: batch / mass
366
+ {
367
+ query: "batch retrieve content",
368
+ expected: [allTools.bulkGetContentItemVariants.name],
369
+ },
370
+ {
371
+ query: "mass get items variants",
372
+ expected: [allTools.bulkGetContentItemVariants.name],
373
+ },
374
+ ],
375
+ },
376
+ {
377
+ name: "filtering and searching content",
378
+ cases: [
379
+ // Partial name combinations for list/filter
380
+ {
381
+ query: "list content item variants",
382
+ expected: [allTools.listContentItemVariants.name],
383
+ },
384
+ {
385
+ query: "list item variants",
386
+ expected: [allTools.listContentItemVariants.name],
387
+ },
388
+ {
389
+ query: "list content variants",
390
+ expected: [allTools.listContentItemVariants.name],
391
+ },
392
+ {
393
+ query: "filter items keyword",
394
+ expected: [allTools.listContentItemVariants.name],
395
+ },
396
+ {
397
+ query: "find content exact keyword",
398
+ expected: [allTools.listContentItemVariants.name],
399
+ },
400
+ // Partial name combinations for search
401
+ {
402
+ query: "search content item variants",
403
+ expected: [allTools.searchContentItemVariants.name],
404
+ },
405
+ {
406
+ query: "search item variants",
407
+ expected: [
408
+ allTools.listContentItemVariants.name,
409
+ allTools.searchContentItemVariants.name,
410
+ ],
411
+ },
412
+ {
413
+ query: "search content semantic",
414
+ expected: [allTools.searchContentItemVariants.name],
415
+ },
416
+ {
417
+ query: "search content topic",
418
+ expected: [allTools.searchContentItemVariants.name],
419
+ },
420
+ {
421
+ query: "find content by meaning",
422
+ expected: [allTools.searchContentItemVariants.name],
423
+ },
424
+ // Generic "find content" should surface both filter and search
425
+ {
426
+ query: "find content items",
427
+ expected: [
428
+ allTools.listContentItemVariants.name,
429
+ allTools.searchContentItemVariants.name,
430
+ ],
431
+ },
432
+ {
433
+ query: "search items",
434
+ expected: [
435
+ allTools.listContentItemVariants.name,
436
+ allTools.searchContentItemVariants.name,
437
+ ],
438
+ },
439
+ // List variants by various dimensions — listContentItemVariants can also filter by these
440
+ {
441
+ query: "items by content type",
442
+ expected: [allTools.listContentItemVariants.name],
443
+ },
444
+ {
445
+ query: "variants filtered by type",
446
+ expected: [allTools.listContentItemVariants.name],
447
+ },
448
+ {
449
+ query: "items in collection",
450
+ expected: [allTools.listContentItemVariants.name],
451
+ },
452
+ {
453
+ query: "variants by collection",
454
+ expected: [allTools.listContentItemVariants.name],
455
+ },
456
+ {
457
+ query: "content in space",
458
+ expected: [allTools.listContentItemVariants.name],
459
+ },
460
+ {
461
+ query: "variants by space",
462
+ expected: [allTools.listContentItemVariants.name],
463
+ },
464
+ {
465
+ query: "items with inline components",
466
+ expected: [allTools.listContentItemVariants.name],
467
+ },
468
+ // listContentItemVariants can also filter by workflow step, taxonomy, publishing state
469
+ {
470
+ query: "items by workflow step",
471
+ expected: [allTools.listContentItemVariants.name],
472
+ },
473
+ {
474
+ query: "filter by publishing state",
475
+ expected: [allTools.listContentItemVariants.name],
476
+ },
477
+ {
478
+ query: "items by taxonomy",
479
+ expected: [
480
+ allTools.listContentItemVariants.name,
481
+ allTools.getTaxonomyGroup.name,
482
+ ],
483
+ },
484
+ // Synonym: query / lookup
485
+ {
486
+ query: "query content items",
487
+ expected: [allTools.listContentItemVariants.name],
488
+ },
489
+ {
490
+ query: "lookup items by keyword",
491
+ expected: [allTools.listContentItemVariants.name],
492
+ },
493
+ ],
494
+ },
495
+ {
496
+ name: "workflow operations",
497
+ cases: [
498
+ // create / add / new
499
+ { query: "create workflow", expected: [allTools.createWorkflow.name] },
500
+ { query: "add workflow", expected: [allTools.createWorkflow.name] },
501
+ {
502
+ query: "new workflow steps",
503
+ expected: [allTools.createWorkflow.name],
504
+ },
505
+ // change / move / transition
506
+ {
507
+ query: "change workflow step",
508
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
509
+ },
510
+ {
511
+ query: "move to review step",
512
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
513
+ },
514
+ {
515
+ query: "transition workflow step",
516
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
517
+ },
518
+ // publish
519
+ {
520
+ query: "publish item variant",
521
+ expected: [allTools.publishContentItemVariant.name],
522
+ },
523
+ {
524
+ query: "publish content",
525
+ expected: [allTools.publishContentItemVariant.name],
526
+ },
527
+ {
528
+ query: "schedule publishing",
529
+ expected: [allTools.publishContentItemVariant.name],
530
+ },
531
+ // unpublish
532
+ {
533
+ query: "unpublish content",
534
+ expected: [allTools.unpublishContentItemVariant.name],
535
+ },
536
+ {
537
+ query: "take content offline",
538
+ expected: [allTools.unpublishContentItemVariant.name],
539
+ },
540
+ // Synonym: approve / review / lifecycle / archive
541
+ {
542
+ query: "approve content review",
543
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
544
+ },
545
+ {
546
+ query: "content lifecycle status",
547
+ expected: [allTools.listWorkflows.name],
548
+ },
549
+ {
550
+ query: "archive content",
551
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
552
+ },
553
+ // list / get
554
+ { query: "list workflows", expected: [allTools.listWorkflows.name] },
555
+ { query: "get workflows", expected: [allTools.listWorkflows.name] },
556
+ {
557
+ query: "workflow draft review",
558
+ expected: [allTools.listWorkflows.name],
559
+ },
560
+ // update / edit / modify
561
+ {
562
+ query: "update workflow steps",
563
+ expected: [allTools.updateWorkflow.name],
564
+ },
565
+ { query: "edit workflow", expected: [allTools.updateWorkflow.name] },
566
+ {
567
+ query: "modify workflow",
568
+ expected: [allTools.updateWorkflow.name],
569
+ },
570
+ // delete / remove
571
+ {
572
+ query: "delete workflow",
573
+ expected: [allTools.deleteWorkflow.name],
574
+ },
575
+ {
576
+ query: "remove workflow",
577
+ expected: [allTools.deleteWorkflow.name],
578
+ },
579
+ ],
580
+ },
581
+ {
582
+ name: "taxonomy operations",
583
+ cases: [
584
+ // create / add / new
585
+ {
586
+ query: "create taxonomy group",
587
+ expected: [allTools.createTaxonomyGroup.name],
588
+ },
589
+ {
590
+ query: "add taxonomy group",
591
+ expected: [allTools.createTaxonomyGroup.name],
592
+ },
593
+ {
594
+ query: "new taxonomy categories",
595
+ expected: [allTools.createTaxonomyGroup.name],
596
+ },
597
+ // get / retrieve
598
+ {
599
+ query: "get taxonomy group",
600
+ expected: [
601
+ allTools.getTaxonomyGroup.name,
602
+ allTools.listTaxonomyGroups.name,
603
+ ],
604
+ },
605
+ {
606
+ query: "retrieve taxonomy",
607
+ expected: [allTools.getTaxonomyGroup.name],
608
+ },
609
+ // Synonym: categories / tags
610
+ {
611
+ query: "taxonomy categories tags",
612
+ expected: [
613
+ allTools.createTaxonomyGroup.name,
614
+ allTools.getTaxonomyGroup.name,
615
+ ],
616
+ },
617
+ // modify / patch / edit
618
+ {
619
+ query: "modify taxonomy terms",
620
+ expected: [allTools.patchTaxonomyGroup.name],
621
+ },
622
+ {
623
+ query: "patch taxonomy",
624
+ expected: [allTools.patchTaxonomyGroup.name],
625
+ },
626
+ {
627
+ query: "edit taxonomy group",
628
+ expected: [allTools.patchTaxonomyGroup.name],
629
+ },
630
+ // list
631
+ {
632
+ query: "list taxonomy groups",
633
+ expected: [allTools.listTaxonomyGroups.name],
634
+ },
635
+ // delete / remove
636
+ {
637
+ query: "delete taxonomy group",
638
+ expected: [allTools.deleteTaxonomyGroup.name],
639
+ },
640
+ {
641
+ query: "remove taxonomy group",
642
+ expected: [allTools.deleteTaxonomyGroup.name],
643
+ },
644
+ // Synonym: hierarchy / classification / organize
645
+ {
646
+ query: "classification hierarchy",
647
+ expected: [allTools.getTaxonomyGroup.name],
648
+ },
649
+ {
650
+ query: "content categorization",
651
+ expected: [allTools.getTaxonomyGroup.name],
652
+ },
653
+ {
654
+ query: "organize content terms",
655
+ expected: [allTools.patchTaxonomyGroup.name],
656
+ },
657
+ ],
658
+ },
659
+ {
660
+ name: "asset operations",
661
+ cases: [
662
+ // get / retrieve / fetch
663
+ { query: "get asset", expected: [allTools.getAsset.name] },
664
+ { query: "retrieve asset by id", expected: [allTools.getAsset.name] },
665
+ { query: "fetch asset", expected: [allTools.getAsset.name] },
666
+ // list / all
667
+ { query: "list assets", expected: [allTools.listAssets.name] },
668
+ { query: "all assets", expected: [allTools.listAssets.name] },
669
+ // update / edit / modify
670
+ {
671
+ query: "update asset metadata",
672
+ expected: [allTools.updateAsset.name],
673
+ },
674
+ { query: "edit asset title", expected: [allTools.updateAsset.name] },
675
+ { query: "modify asset", expected: [allTools.updateAsset.name] },
676
+ // Folders
677
+ {
678
+ query: "asset folders",
679
+ expected: [
680
+ allTools.listAssetFolders.name,
681
+ allTools.patchAssetFolders.name,
682
+ ],
683
+ },
684
+ {
685
+ query: "list asset folders",
686
+ expected: [allTools.listAssetFolders.name],
687
+ },
688
+ {
689
+ query: "modify asset folders",
690
+ expected: [allTools.patchAssetFolders.name],
691
+ },
692
+ {
693
+ query: "edit asset folders",
694
+ expected: [allTools.patchAssetFolders.name],
695
+ },
696
+ // Synonym: image / file / media / document
697
+ { query: "get image file", expected: [allTools.getAsset.name] },
698
+ { query: "list media files", expected: [allTools.listAssets.name] },
699
+ {
700
+ query: "documents videos assets",
701
+ expected: [allTools.listAssets.name],
702
+ },
703
+ ],
704
+ },
705
+ {
706
+ name: "language operations",
707
+ cases: [
708
+ // create / add / new
709
+ { query: "add language", expected: [allTools.createLanguage.name] },
710
+ { query: "create language", expected: [allTools.createLanguage.name] },
711
+ {
712
+ query: "new language locale",
713
+ expected: [allTools.createLanguage.name],
714
+ },
715
+ // list / get
716
+ { query: "list languages", expected: [allTools.listLanguages.name] },
717
+ { query: "get languages", expected: [allTools.listLanguages.name] },
718
+ {
719
+ query: "available languages",
720
+ expected: [allTools.listLanguages.name],
721
+ },
722
+ // modify / patch / edit
723
+ {
724
+ query: "modify language fallback",
725
+ expected: [allTools.patchLanguage.name],
726
+ },
727
+ { query: "patch language", expected: [allTools.patchLanguage.name] },
728
+ { query: "edit language", expected: [allTools.patchLanguage.name] },
729
+ // Synonym: localization / translations
730
+ {
731
+ query: "localization translations",
732
+ expected: [allTools.createLanguage.name, allTools.listLanguages.name],
733
+ },
734
+ // Synonym: locale / i18n / fallback
735
+ { query: "configure locale", expected: [allTools.createLanguage.name] },
736
+ {
737
+ query: "language fallback inheritance",
738
+ expected: [allTools.patchLanguage.name],
739
+ },
740
+ ],
741
+ },
742
+ {
743
+ name: "space operations",
744
+ cases: [
745
+ // create / add / new
746
+ { query: "create space", expected: [allTools.createSpace.name] },
747
+ { query: "add space", expected: [allTools.createSpace.name] },
748
+ { query: "new space website", expected: [allTools.createSpace.name] },
749
+ // list / get
750
+ { query: "list spaces", expected: [allTools.listSpaces.name] },
751
+ { query: "get spaces", expected: [allTools.listSpaces.name] },
752
+ // delete / remove
753
+ { query: "delete space", expected: [allTools.deleteSpace.name] },
754
+ { query: "remove space", expected: [allTools.deleteSpace.name] },
755
+ // modify / patch / edit
756
+ { query: "patch space", expected: [allTools.patchSpace.name] },
757
+ { query: "update space", expected: [allTools.patchSpace.name] },
758
+ // Synonym: channel / site / website
759
+ {
760
+ query: "website channel setup",
761
+ expected: [allTools.createSpace.name],
762
+ },
763
+ { query: "site configuration", expected: [allTools.listSpaces.name] },
764
+ ],
765
+ },
766
+ {
767
+ name: "collection operations",
768
+ cases: [
769
+ {
770
+ query: "list collections",
771
+ expected: [allTools.listCollections.name],
772
+ },
773
+ {
774
+ query: "get collections",
775
+ expected: [allTools.listCollections.name],
776
+ },
777
+ {
778
+ query: "modify collections",
779
+ expected: [allTools.patchCollections.name],
780
+ },
781
+ {
782
+ query: "patch collections",
783
+ expected: [allTools.patchCollections.name],
784
+ },
785
+ {
786
+ query: "edit collections",
787
+ expected: [allTools.patchCollections.name],
788
+ },
789
+ ],
790
+ },
791
+ {
792
+ name: "role operations",
793
+ cases: [
794
+ { query: "list roles", expected: [allTools.listRoles.name] },
795
+ { query: "roles permissions", expected: [allTools.listRoles.name] },
796
+ { query: "get roles", expected: [allTools.listRoles.name] },
797
+ // Synonym: access / security / users
798
+ {
799
+ query: "user access permissions",
800
+ expected: [allTools.listRoles.name],
801
+ },
802
+ { query: "security roles", expected: [allTools.listRoles.name] },
803
+ ],
804
+ },
805
+ {
806
+ name: "patch guide",
807
+ cases: [
808
+ {
809
+ query: "patch operations guide",
810
+ expected: [allTools.getPatchGuide.name],
811
+ },
812
+ { query: "patch guide", expected: [allTools.getPatchGuide.name] },
813
+ {
814
+ query: "patch reference guide",
815
+ expected: [allTools.getPatchGuide.name],
816
+ },
817
+ ],
818
+ },
819
+ {
820
+ name: "agent-style natural language queries",
821
+ cases: [
822
+ {
823
+ query: "create blog post content type",
824
+ expected: [allTools.createContentType.name],
825
+ },
826
+ {
827
+ query: "content models schemas",
828
+ expected: [allTools.listContentTypes.name],
829
+ },
830
+ {
831
+ query: "add field to content type",
832
+ expected: [allTools.patchContentType.name],
833
+ },
834
+ {
835
+ query: "publish language version",
836
+ expected: [allTools.publishContentItemVariant.name],
837
+ },
838
+ {
839
+ query: "create taxonomy categories",
840
+ expected: [allTools.createTaxonomyGroup.name],
841
+ },
842
+ {
843
+ query: "move to published workflow step",
844
+ expected: [allTools.changeContentItemVariantWorkflowStep.name],
845
+ },
846
+ {
847
+ query: "images assets media",
848
+ expected: [allTools.listAssets.name, allTools.getAsset.name],
849
+ },
850
+ {
851
+ query: "add translation language",
852
+ expected: [allTools.createContentItemVariant.name],
853
+ },
854
+ ],
855
+ },
856
+ ];
857
+ // ---------------------------------------------------------------------------
858
+ // Generate tests from data
859
+ // ---------------------------------------------------------------------------
860
+ describe(`BM25 tool search — finds appropriate tools in top ${topK} results`, () => {
861
+ let index;
862
+ before(() => {
863
+ index = createToolSearchIndex(Object.values(allTools));
864
+ });
865
+ for (const group of testGroups) {
866
+ describe(group.name, () => {
867
+ for (const { query, expected } of group.cases) {
868
+ it(`"${query}" → [${expected.join(", ")}]`, () => {
869
+ assertToolsFound(index, query, expected);
870
+ });
871
+ }
872
+ });
873
+ }
874
+ });