scorecard-ai-mcp 1.0.0-alpha.6 → 1.0.0-alpha.7

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 (165) hide show
  1. package/README.md +32 -5
  2. package/dynamic-tools.d.mts +12 -0
  3. package/dynamic-tools.d.mts.map +1 -0
  4. package/dynamic-tools.d.ts +12 -0
  5. package/dynamic-tools.d.ts.map +1 -0
  6. package/dynamic-tools.js +133 -0
  7. package/dynamic-tools.js.map +1 -0
  8. package/dynamic-tools.mjs +130 -0
  9. package/dynamic-tools.mjs.map +1 -0
  10. package/index.js +15 -18
  11. package/index.js.map +1 -1
  12. package/index.mjs +17 -20
  13. package/index.mjs.map +1 -1
  14. package/options.d.mts +2 -0
  15. package/options.d.mts.map +1 -1
  16. package/options.d.ts +2 -0
  17. package/options.d.ts.map +1 -1
  18. package/options.js +17 -0
  19. package/options.js.map +1 -1
  20. package/options.mjs +17 -0
  21. package/options.mjs.map +1 -1
  22. package/package.json +13 -20
  23. package/server.d.mts +6 -1
  24. package/server.d.mts.map +1 -1
  25. package/server.d.ts +6 -1
  26. package/server.d.ts.map +1 -1
  27. package/server.js +20 -1
  28. package/server.js.map +1 -1
  29. package/server.mjs +21 -3
  30. package/server.mjs.map +1 -1
  31. package/src/dynamic-tools.ts +152 -0
  32. package/src/index.ts +19 -23
  33. package/src/options.ts +22 -0
  34. package/src/server.ts +33 -3
  35. package/src/tools/index.ts +5 -5
  36. package/src/tools/projects/create-projects.ts +36 -0
  37. package/src/tools/scores/upsert-scores.ts +40 -0
  38. package/tools/index.d.mts.map +1 -1
  39. package/tools/index.d.ts.map +1 -1
  40. package/tools/index.js +5 -4
  41. package/tools/index.js.map +1 -1
  42. package/tools/index.mjs +5 -4
  43. package/tools/index.mjs.map +1 -1
  44. package/tools/projects/create-projects.d.mts +32 -0
  45. package/tools/projects/create-projects.d.mts.map +1 -0
  46. package/tools/projects/create-projects.d.ts +32 -0
  47. package/tools/projects/create-projects.d.ts.map +1 -0
  48. package/tools/projects/create-projects.js +33 -0
  49. package/tools/projects/create-projects.js.map +1 -0
  50. package/tools/projects/create-projects.mjs +29 -0
  51. package/tools/projects/create-projects.mjs.map +1 -0
  52. package/tools/projects/list-projects.d.mts +10 -2
  53. package/tools/projects/list-projects.d.mts.map +1 -1
  54. package/tools/projects/list-projects.d.ts +10 -2
  55. package/tools/projects/list-projects.d.ts.map +1 -1
  56. package/tools/records/create-records.d.mts +8 -0
  57. package/tools/records/create-records.d.mts.map +1 -1
  58. package/tools/records/create-records.d.ts +8 -0
  59. package/tools/records/create-records.d.ts.map +1 -1
  60. package/tools/runs/create-runs.d.mts +8 -0
  61. package/tools/runs/create-runs.d.mts.map +1 -1
  62. package/tools/runs/create-runs.d.ts +8 -0
  63. package/tools/runs/create-runs.d.ts.map +1 -1
  64. package/tools/runs/update-runs.d.mts +8 -0
  65. package/tools/runs/update-runs.d.mts.map +1 -1
  66. package/tools/runs/update-runs.d.ts +8 -0
  67. package/tools/runs/update-runs.d.ts.map +1 -1
  68. package/tools/scores/upsert-scores.d.mts +32 -0
  69. package/tools/scores/upsert-scores.d.mts.map +1 -0
  70. package/tools/scores/upsert-scores.d.ts +32 -0
  71. package/tools/scores/upsert-scores.d.ts.map +1 -0
  72. package/tools/scores/upsert-scores.js +35 -0
  73. package/tools/scores/upsert-scores.js.map +1 -0
  74. package/tools/scores/upsert-scores.mjs +31 -0
  75. package/tools/scores/upsert-scores.mjs.map +1 -0
  76. package/tools/system-configs/create-system-configs.d.mts +8 -0
  77. package/tools/system-configs/create-system-configs.d.mts.map +1 -1
  78. package/tools/system-configs/create-system-configs.d.ts +8 -0
  79. package/tools/system-configs/create-system-configs.d.ts.map +1 -1
  80. package/tools/system-configs/get-system-configs.d.mts +8 -0
  81. package/tools/system-configs/get-system-configs.d.mts.map +1 -1
  82. package/tools/system-configs/get-system-configs.d.ts +8 -0
  83. package/tools/system-configs/get-system-configs.d.ts.map +1 -1
  84. package/tools/system-configs/list-system-configs.d.mts +8 -0
  85. package/tools/system-configs/list-system-configs.d.mts.map +1 -1
  86. package/tools/system-configs/list-system-configs.d.ts +8 -0
  87. package/tools/system-configs/list-system-configs.d.ts.map +1 -1
  88. package/tools/systems/create-systems.d.mts +8 -0
  89. package/tools/systems/create-systems.d.mts.map +1 -1
  90. package/tools/systems/create-systems.d.ts +8 -0
  91. package/tools/systems/create-systems.d.ts.map +1 -1
  92. package/tools/systems/delete-systems.d.mts +8 -0
  93. package/tools/systems/delete-systems.d.mts.map +1 -1
  94. package/tools/systems/delete-systems.d.ts +8 -0
  95. package/tools/systems/delete-systems.d.ts.map +1 -1
  96. package/tools/systems/get-systems.d.mts +8 -0
  97. package/tools/systems/get-systems.d.mts.map +1 -1
  98. package/tools/systems/get-systems.d.ts +8 -0
  99. package/tools/systems/get-systems.d.ts.map +1 -1
  100. package/tools/systems/list-systems.d.mts +8 -0
  101. package/tools/systems/list-systems.d.mts.map +1 -1
  102. package/tools/systems/list-systems.d.ts +8 -0
  103. package/tools/systems/list-systems.d.ts.map +1 -1
  104. package/tools/systems/update-systems.d.mts +8 -0
  105. package/tools/systems/update-systems.d.mts.map +1 -1
  106. package/tools/systems/update-systems.d.ts +8 -0
  107. package/tools/systems/update-systems.d.ts.map +1 -1
  108. package/tools/testcases/create-testcases.d.mts +8 -0
  109. package/tools/testcases/create-testcases.d.mts.map +1 -1
  110. package/tools/testcases/create-testcases.d.ts +8 -0
  111. package/tools/testcases/create-testcases.d.ts.map +1 -1
  112. package/tools/testcases/delete-testcases.d.mts +8 -0
  113. package/tools/testcases/delete-testcases.d.mts.map +1 -1
  114. package/tools/testcases/delete-testcases.d.ts +8 -0
  115. package/tools/testcases/delete-testcases.d.ts.map +1 -1
  116. package/tools/testcases/get-testcases.d.mts +8 -0
  117. package/tools/testcases/get-testcases.d.mts.map +1 -1
  118. package/tools/testcases/get-testcases.d.ts +8 -0
  119. package/tools/testcases/get-testcases.d.ts.map +1 -1
  120. package/tools/testcases/list-testcases.d.mts +8 -0
  121. package/tools/testcases/list-testcases.d.mts.map +1 -1
  122. package/tools/testcases/list-testcases.d.ts +8 -0
  123. package/tools/testcases/list-testcases.d.ts.map +1 -1
  124. package/tools/testcases/update-testcases.d.mts +8 -0
  125. package/tools/testcases/update-testcases.d.mts.map +1 -1
  126. package/tools/testcases/update-testcases.d.ts +8 -0
  127. package/tools/testcases/update-testcases.d.ts.map +1 -1
  128. package/tools/testsets/create-testsets.d.mts +8 -0
  129. package/tools/testsets/create-testsets.d.mts.map +1 -1
  130. package/tools/testsets/create-testsets.d.ts +8 -0
  131. package/tools/testsets/create-testsets.d.ts.map +1 -1
  132. package/tools/testsets/delete-testsets.d.mts +8 -0
  133. package/tools/testsets/delete-testsets.d.mts.map +1 -1
  134. package/tools/testsets/delete-testsets.d.ts +8 -0
  135. package/tools/testsets/delete-testsets.d.ts.map +1 -1
  136. package/tools/testsets/get-testsets.d.mts +8 -0
  137. package/tools/testsets/get-testsets.d.mts.map +1 -1
  138. package/tools/testsets/get-testsets.d.ts +8 -0
  139. package/tools/testsets/get-testsets.d.ts.map +1 -1
  140. package/tools/testsets/list-testsets.d.mts +8 -0
  141. package/tools/testsets/list-testsets.d.mts.map +1 -1
  142. package/tools/testsets/list-testsets.d.ts +8 -0
  143. package/tools/testsets/list-testsets.d.ts.map +1 -1
  144. package/tools/testsets/update-testsets.d.mts +8 -0
  145. package/tools/testsets/update-testsets.d.mts.map +1 -1
  146. package/tools/testsets/update-testsets.d.ts +8 -0
  147. package/tools/testsets/update-testsets.d.ts.map +1 -1
  148. package/compat.test.d.mts +0 -2
  149. package/compat.test.d.mts.map +0 -1
  150. package/compat.test.d.ts +0 -2
  151. package/compat.test.d.ts.map +0 -1
  152. package/compat.test.js +0 -950
  153. package/compat.test.js.map +0 -1
  154. package/compat.test.mjs +0 -948
  155. package/compat.test.mjs.map +0 -1
  156. package/options.test.d.mts +0 -2
  157. package/options.test.d.mts.map +0 -1
  158. package/options.test.d.ts +0 -2
  159. package/options.test.d.ts.map +0 -1
  160. package/options.test.js +0 -154
  161. package/options.test.js.map +0 -1
  162. package/options.test.mjs +0 -152
  163. package/options.test.mjs.map +0 -1
  164. package/src/compat.test.ts +0 -1068
  165. package/src/options.test.ts +0 -193
package/compat.test.mjs DELETED
@@ -1,948 +0,0 @@
1
- import { truncateToolNames, removeTopLevelUnions, removeAnyOf, inlineRefs, applyCompatibilityTransformations, removeFormats, } from "./compat.mjs";
2
- describe('truncateToolNames', () => {
3
- it('should return original names when maxLength is 0 or negative', () => {
4
- const names = ['tool1', 'tool2', 'tool3'];
5
- expect(truncateToolNames(names, 0)).toEqual(new Map());
6
- expect(truncateToolNames(names, -1)).toEqual(new Map());
7
- });
8
- it('should return original names when all names are shorter than maxLength', () => {
9
- const names = ['tool1', 'tool2', 'tool3'];
10
- expect(truncateToolNames(names, 10)).toEqual(new Map());
11
- });
12
- it('should truncate names longer than maxLength', () => {
13
- const names = ['very-long-tool-name', 'another-long-tool-name', 'short'];
14
- expect(truncateToolNames(names, 10)).toEqual(new Map([
15
- ['very-long-tool-name', 'very-long-'],
16
- ['another-long-tool-name', 'another-lo'],
17
- ]));
18
- });
19
- it('should handle duplicate truncated names by appending numbers', () => {
20
- const names = ['tool-name-a', 'tool-name-b', 'tool-name-c'];
21
- expect(truncateToolNames(names, 8)).toEqual(new Map([
22
- ['tool-name-a', 'tool-na1'],
23
- ['tool-name-b', 'tool-na2'],
24
- ['tool-name-c', 'tool-na3'],
25
- ]));
26
- });
27
- });
28
- describe('removeTopLevelUnions', () => {
29
- const createTestTool = (overrides = {}) => ({
30
- name: 'test-tool',
31
- description: 'Test tool',
32
- inputSchema: {
33
- type: 'object',
34
- properties: {},
35
- },
36
- ...overrides,
37
- });
38
- it('should return the original tool if it has no anyOf at the top level', () => {
39
- const tool = createTestTool({
40
- inputSchema: {
41
- type: 'object',
42
- properties: {
43
- foo: { type: 'string' },
44
- },
45
- },
46
- });
47
- expect(removeTopLevelUnions(tool)).toEqual([tool]);
48
- });
49
- it('should split a tool with top-level anyOf into multiple tools', () => {
50
- const tool = createTestTool({
51
- name: 'union-tool',
52
- description: 'A tool with unions',
53
- inputSchema: {
54
- type: 'object',
55
- properties: {
56
- common: { type: 'string' },
57
- },
58
- anyOf: [
59
- {
60
- title: 'first variant',
61
- description: 'Its the first variant',
62
- properties: {
63
- variant1: { type: 'string' },
64
- },
65
- required: ['variant1'],
66
- },
67
- {
68
- title: 'second variant',
69
- properties: {
70
- variant2: { type: 'number' },
71
- },
72
- required: ['variant2'],
73
- },
74
- ],
75
- },
76
- });
77
- const result = removeTopLevelUnions(tool);
78
- expect(result).toEqual([
79
- {
80
- name: 'union-tool_first_variant',
81
- description: 'Its the first variant',
82
- inputSchema: {
83
- type: 'object',
84
- title: 'first variant',
85
- description: 'Its the first variant',
86
- properties: {
87
- common: { type: 'string' },
88
- variant1: { type: 'string' },
89
- },
90
- required: ['variant1'],
91
- },
92
- },
93
- {
94
- name: 'union-tool_second_variant',
95
- description: 'A tool with unions',
96
- inputSchema: {
97
- type: 'object',
98
- title: 'second variant',
99
- description: 'A tool with unions',
100
- properties: {
101
- common: { type: 'string' },
102
- variant2: { type: 'number' },
103
- },
104
- required: ['variant2'],
105
- },
106
- },
107
- ]);
108
- });
109
- it('should handle $defs and only include those used by the variant', () => {
110
- const tool = createTestTool({
111
- name: 'defs-tool',
112
- description: 'A tool with $defs',
113
- inputSchema: {
114
- type: 'object',
115
- properties: {
116
- common: { type: 'string' },
117
- },
118
- $defs: {
119
- def1: { type: 'string', format: 'email' },
120
- def2: { type: 'number', minimum: 0 },
121
- unused: { type: 'boolean' },
122
- },
123
- anyOf: [
124
- {
125
- properties: {
126
- email: { $ref: '#/$defs/def1' },
127
- },
128
- },
129
- {
130
- properties: {
131
- count: { $ref: '#/$defs/def2' },
132
- },
133
- },
134
- ],
135
- },
136
- });
137
- const result = removeTopLevelUnions(tool);
138
- expect(result).toEqual([
139
- {
140
- name: 'defs-tool_variant1',
141
- description: 'A tool with $defs',
142
- inputSchema: {
143
- type: 'object',
144
- description: 'A tool with $defs',
145
- properties: {
146
- common: { type: 'string' },
147
- email: { $ref: '#/$defs/def1' },
148
- },
149
- $defs: {
150
- def1: { type: 'string', format: 'email' },
151
- },
152
- },
153
- },
154
- {
155
- name: 'defs-tool_variant2',
156
- description: 'A tool with $defs',
157
- inputSchema: {
158
- type: 'object',
159
- description: 'A tool with $defs',
160
- properties: {
161
- common: { type: 'string' },
162
- count: { $ref: '#/$defs/def2' },
163
- },
164
- $defs: {
165
- def2: { type: 'number', minimum: 0 },
166
- },
167
- },
168
- },
169
- ]);
170
- });
171
- });
172
- describe('removeAnyOf', () => {
173
- it('should return original schema if it has no anyOf', () => {
174
- const schema = {
175
- type: 'object',
176
- properties: {
177
- foo: { type: 'string' },
178
- bar: { type: 'number' },
179
- },
180
- };
181
- expect(removeAnyOf(schema)).toEqual(schema);
182
- });
183
- it('should remove anyOf field and use the first variant', () => {
184
- const schema = {
185
- type: 'object',
186
- properties: {
187
- common: { type: 'string' },
188
- },
189
- anyOf: [
190
- {
191
- properties: {
192
- variant1: { type: 'string' },
193
- },
194
- required: ['variant1'],
195
- },
196
- {
197
- properties: {
198
- variant2: { type: 'number' },
199
- },
200
- required: ['variant2'],
201
- },
202
- ],
203
- };
204
- const expected = {
205
- type: 'object',
206
- properties: {
207
- common: { type: 'string' },
208
- variant1: { type: 'string' },
209
- },
210
- required: ['variant1'],
211
- };
212
- expect(removeAnyOf(schema)).toEqual(expected);
213
- });
214
- it('should recursively remove anyOf fields from nested properties', () => {
215
- const schema = {
216
- type: 'object',
217
- properties: {
218
- foo: { type: 'string' },
219
- nested: {
220
- type: 'object',
221
- properties: {
222
- bar: { type: 'number' },
223
- },
224
- anyOf: [
225
- {
226
- properties: {
227
- option1: { type: 'boolean' },
228
- },
229
- },
230
- {
231
- properties: {
232
- option2: { type: 'array' },
233
- },
234
- },
235
- ],
236
- },
237
- },
238
- };
239
- const expected = {
240
- type: 'object',
241
- properties: {
242
- foo: { type: 'string' },
243
- nested: {
244
- type: 'object',
245
- properties: {
246
- bar: { type: 'number' },
247
- option1: { type: 'boolean' },
248
- },
249
- },
250
- },
251
- };
252
- expect(removeAnyOf(schema)).toEqual(expected);
253
- });
254
- it('should handle arrays', () => {
255
- const schema = {
256
- type: 'object',
257
- properties: {
258
- items: {
259
- type: 'array',
260
- items: {
261
- anyOf: [{ type: 'string' }, { type: 'number' }],
262
- },
263
- },
264
- },
265
- };
266
- const expected = {
267
- type: 'object',
268
- properties: {
269
- items: {
270
- type: 'array',
271
- items: {
272
- type: 'string',
273
- },
274
- },
275
- },
276
- };
277
- expect(removeAnyOf(schema)).toEqual(expected);
278
- });
279
- });
280
- describe('inlineRefs', () => {
281
- it('should return the original schema if it does not contain $refs', () => {
282
- const schema = {
283
- type: 'object',
284
- properties: {
285
- name: { type: 'string' },
286
- age: { type: 'number' },
287
- },
288
- };
289
- expect(inlineRefs(schema)).toEqual(schema);
290
- });
291
- it('should inline simple $refs', () => {
292
- const schema = {
293
- type: 'object',
294
- properties: {
295
- user: { $ref: '#/$defs/user' },
296
- },
297
- $defs: {
298
- user: {
299
- type: 'object',
300
- properties: {
301
- name: { type: 'string' },
302
- email: { type: 'string' },
303
- },
304
- },
305
- },
306
- };
307
- const expected = {
308
- type: 'object',
309
- properties: {
310
- user: {
311
- type: 'object',
312
- properties: {
313
- name: { type: 'string' },
314
- email: { type: 'string' },
315
- },
316
- },
317
- },
318
- };
319
- expect(inlineRefs(schema)).toEqual(expected);
320
- });
321
- it('should inline nested $refs', () => {
322
- const schema = {
323
- type: 'object',
324
- properties: {
325
- order: { $ref: '#/$defs/order' },
326
- },
327
- $defs: {
328
- order: {
329
- type: 'object',
330
- properties: {
331
- id: { type: 'string' },
332
- items: { type: 'array', items: { $ref: '#/$defs/item' } },
333
- },
334
- },
335
- item: {
336
- type: 'object',
337
- properties: {
338
- product: { type: 'string' },
339
- quantity: { type: 'integer' },
340
- },
341
- },
342
- },
343
- };
344
- const expected = {
345
- type: 'object',
346
- properties: {
347
- order: {
348
- type: 'object',
349
- properties: {
350
- id: { type: 'string' },
351
- items: {
352
- type: 'array',
353
- items: {
354
- type: 'object',
355
- properties: {
356
- product: { type: 'string' },
357
- quantity: { type: 'integer' },
358
- },
359
- },
360
- },
361
- },
362
- },
363
- },
364
- };
365
- expect(inlineRefs(schema)).toEqual(expected);
366
- });
367
- it('should handle circular references by removing the circular part', () => {
368
- const schema = {
369
- type: 'object',
370
- properties: {
371
- person: { $ref: '#/$defs/person' },
372
- },
373
- $defs: {
374
- person: {
375
- type: 'object',
376
- properties: {
377
- name: { type: 'string' },
378
- friend: { $ref: '#/$defs/person' }, // Circular reference
379
- },
380
- },
381
- },
382
- };
383
- const expected = {
384
- type: 'object',
385
- properties: {
386
- person: {
387
- type: 'object',
388
- properties: {
389
- name: { type: 'string' },
390
- // friend property is removed to break the circular reference
391
- },
392
- },
393
- },
394
- };
395
- expect(inlineRefs(schema)).toEqual(expected);
396
- });
397
- it('should handle indirect circular references', () => {
398
- const schema = {
399
- type: 'object',
400
- properties: {
401
- node: { $ref: '#/$defs/node' },
402
- },
403
- $defs: {
404
- node: {
405
- type: 'object',
406
- properties: {
407
- value: { type: 'string' },
408
- child: { $ref: '#/$defs/childNode' },
409
- },
410
- },
411
- childNode: {
412
- type: 'object',
413
- properties: {
414
- value: { type: 'string' },
415
- parent: { $ref: '#/$defs/node' }, // Circular reference through childNode
416
- },
417
- },
418
- },
419
- };
420
- const expected = {
421
- type: 'object',
422
- properties: {
423
- node: {
424
- type: 'object',
425
- properties: {
426
- value: { type: 'string' },
427
- child: {
428
- type: 'object',
429
- properties: {
430
- value: { type: 'string' },
431
- // parent property is removed to break the circular reference
432
- },
433
- },
434
- },
435
- },
436
- },
437
- };
438
- expect(inlineRefs(schema)).toEqual(expected);
439
- });
440
- it('should preserve other properties when inlining references', () => {
441
- const schema = {
442
- type: 'object',
443
- properties: {
444
- address: { $ref: '#/$defs/address', description: 'User address' },
445
- },
446
- $defs: {
447
- address: {
448
- type: 'object',
449
- properties: {
450
- street: { type: 'string' },
451
- city: { type: 'string' },
452
- },
453
- required: ['street'],
454
- },
455
- },
456
- };
457
- const expected = {
458
- type: 'object',
459
- properties: {
460
- address: {
461
- type: 'object',
462
- description: 'User address',
463
- properties: {
464
- street: { type: 'string' },
465
- city: { type: 'string' },
466
- },
467
- required: ['street'],
468
- },
469
- },
470
- };
471
- expect(inlineRefs(schema)).toEqual(expected);
472
- });
473
- });
474
- describe('removeFormats', () => {
475
- it('should return original schema if formats capability is true', () => {
476
- const schema = {
477
- type: 'object',
478
- properties: {
479
- date: { type: 'string', description: 'A date field', format: 'date' },
480
- email: { type: 'string', description: 'An email field', format: 'email' },
481
- },
482
- };
483
- expect(removeFormats(schema, true)).toEqual(schema);
484
- });
485
- it('should move format to description when formats capability is false', () => {
486
- const schema = {
487
- type: 'object',
488
- properties: {
489
- date: { type: 'string', description: 'A date field', format: 'date' },
490
- email: { type: 'string', description: 'An email field', format: 'email' },
491
- },
492
- };
493
- const expected = {
494
- type: 'object',
495
- properties: {
496
- date: { type: 'string', description: 'A date field (format: "date")' },
497
- email: { type: 'string', description: 'An email field (format: "email")' },
498
- },
499
- };
500
- expect(removeFormats(schema, false)).toEqual(expected);
501
- });
502
- it('should handle properties without description', () => {
503
- const schema = {
504
- type: 'object',
505
- properties: {
506
- date: { type: 'string', format: 'date' },
507
- },
508
- };
509
- const expected = {
510
- type: 'object',
511
- properties: {
512
- date: { type: 'string', description: '(format: "date")' },
513
- },
514
- };
515
- expect(removeFormats(schema, false)).toEqual(expected);
516
- });
517
- it('should handle nested properties', () => {
518
- const schema = {
519
- type: 'object',
520
- properties: {
521
- user: {
522
- type: 'object',
523
- properties: {
524
- created_at: { type: 'string', description: 'Creation date', format: 'date-time' },
525
- },
526
- },
527
- },
528
- };
529
- const expected = {
530
- type: 'object',
531
- properties: {
532
- user: {
533
- type: 'object',
534
- properties: {
535
- created_at: { type: 'string', description: 'Creation date (format: "date-time")' },
536
- },
537
- },
538
- },
539
- };
540
- expect(removeFormats(schema, false)).toEqual(expected);
541
- });
542
- it('should handle arrays of objects', () => {
543
- const schema = {
544
- type: 'object',
545
- properties: {
546
- dates: {
547
- type: 'array',
548
- items: {
549
- type: 'object',
550
- properties: {
551
- start: { type: 'string', description: 'Start date', format: 'date' },
552
- end: { type: 'string', description: 'End date', format: 'date' },
553
- },
554
- },
555
- },
556
- },
557
- };
558
- const expected = {
559
- type: 'object',
560
- properties: {
561
- dates: {
562
- type: 'array',
563
- items: {
564
- type: 'object',
565
- properties: {
566
- start: { type: 'string', description: 'Start date (format: "date")' },
567
- end: { type: 'string', description: 'End date (format: "date")' },
568
- },
569
- },
570
- },
571
- },
572
- };
573
- expect(removeFormats(schema, false)).toEqual(expected);
574
- });
575
- it('should handle schemas with $defs', () => {
576
- const schema = {
577
- type: 'object',
578
- properties: {
579
- date: { type: 'string', description: 'A date field', format: 'date' },
580
- },
581
- $defs: {
582
- timestamp: {
583
- type: 'string',
584
- description: 'A timestamp field',
585
- format: 'date-time',
586
- },
587
- },
588
- };
589
- const expected = {
590
- type: 'object',
591
- properties: {
592
- date: { type: 'string', description: 'A date field (format: "date")' },
593
- },
594
- $defs: {
595
- timestamp: {
596
- type: 'string',
597
- description: 'A timestamp field (format: "date-time")',
598
- },
599
- },
600
- };
601
- expect(removeFormats(schema, false)).toEqual(expected);
602
- });
603
- });
604
- describe('applyCompatibilityTransformations', () => {
605
- const createTestTool = (name, overrides = {}) => ({
606
- name,
607
- description: 'Test tool',
608
- inputSchema: {
609
- type: 'object',
610
- properties: {},
611
- },
612
- ...overrides,
613
- });
614
- const createTestEndpoint = (tool) => ({
615
- tool,
616
- handler: jest.fn(),
617
- metadata: {
618
- resource: 'test',
619
- operation: 'read',
620
- tags: [],
621
- },
622
- });
623
- it('should not modify endpoints when all capabilities are enabled', () => {
624
- const tool = createTestTool('test-tool');
625
- const endpoints = [createTestEndpoint(tool)];
626
- const capabilities = {
627
- topLevelUnions: true,
628
- validJson: true,
629
- refs: true,
630
- unions: true,
631
- formats: true,
632
- toolNameLength: undefined,
633
- };
634
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
635
- expect(transformed).toEqual(endpoints);
636
- });
637
- it('should split tools with top-level unions when topLevelUnions is disabled', () => {
638
- const tool = createTestTool('union-tool', {
639
- inputSchema: {
640
- type: 'object',
641
- properties: {
642
- common: { type: 'string' },
643
- },
644
- anyOf: [
645
- {
646
- title: 'first variant',
647
- properties: {
648
- variant1: { type: 'string' },
649
- },
650
- },
651
- {
652
- title: 'second variant',
653
- properties: {
654
- variant2: { type: 'number' },
655
- },
656
- },
657
- ],
658
- },
659
- });
660
- const endpoints = [createTestEndpoint(tool)];
661
- const capabilities = {
662
- topLevelUnions: false,
663
- validJson: true,
664
- refs: true,
665
- unions: true,
666
- formats: true,
667
- toolNameLength: undefined,
668
- };
669
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
670
- expect(transformed.length).toBe(2);
671
- expect(transformed[0].tool.name).toBe('union-tool_first_variant');
672
- expect(transformed[1].tool.name).toBe('union-tool_second_variant');
673
- });
674
- it('should handle variants without titles in removeTopLevelUnions', () => {
675
- const tool = createTestTool('union-tool', {
676
- inputSchema: {
677
- type: 'object',
678
- properties: {
679
- common: { type: 'string' },
680
- },
681
- anyOf: [
682
- {
683
- properties: {
684
- variant1: { type: 'string' },
685
- },
686
- },
687
- {
688
- properties: {
689
- variant2: { type: 'number' },
690
- },
691
- },
692
- ],
693
- },
694
- });
695
- const endpoints = [createTestEndpoint(tool)];
696
- const capabilities = {
697
- topLevelUnions: false,
698
- validJson: true,
699
- refs: true,
700
- unions: true,
701
- formats: true,
702
- toolNameLength: undefined,
703
- };
704
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
705
- expect(transformed.length).toBe(2);
706
- expect(transformed[0].tool.name).toBe('union-tool_variant1');
707
- expect(transformed[1].tool.name).toBe('union-tool_variant2');
708
- });
709
- it('should truncate tool names when toolNameLength is set', () => {
710
- const tools = [
711
- createTestTool('very-long-tool-name-that-exceeds-limit'),
712
- createTestTool('another-long-tool-name-to-truncate'),
713
- createTestTool('short-name'),
714
- ];
715
- const endpoints = tools.map(createTestEndpoint);
716
- const capabilities = {
717
- topLevelUnions: true,
718
- validJson: true,
719
- refs: true,
720
- unions: true,
721
- formats: true,
722
- toolNameLength: 20,
723
- };
724
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
725
- expect(transformed[0].tool.name).toBe('very-long-tool-name-');
726
- expect(transformed[1].tool.name).toBe('another-long-tool-na');
727
- expect(transformed[2].tool.name).toBe('short-name');
728
- });
729
- it('should inline refs when refs capability is disabled', () => {
730
- const tool = createTestTool('ref-tool', {
731
- inputSchema: {
732
- type: 'object',
733
- properties: {
734
- user: { $ref: '#/$defs/user' },
735
- },
736
- $defs: {
737
- user: {
738
- type: 'object',
739
- properties: {
740
- name: { type: 'string' },
741
- email: { type: 'string' },
742
- },
743
- },
744
- },
745
- },
746
- });
747
- const endpoints = [createTestEndpoint(tool)];
748
- const capabilities = {
749
- topLevelUnions: true,
750
- validJson: true,
751
- refs: false,
752
- unions: true,
753
- formats: true,
754
- toolNameLength: undefined,
755
- };
756
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
757
- const schema = transformed[0].tool.inputSchema;
758
- expect(schema.$defs).toBeUndefined();
759
- if (schema.properties) {
760
- expect(schema.properties['user']).toEqual({
761
- type: 'object',
762
- properties: {
763
- name: { type: 'string' },
764
- email: { type: 'string' },
765
- },
766
- });
767
- }
768
- });
769
- it('should preserve external refs when inlining', () => {
770
- const tool = createTestTool('ref-tool', {
771
- inputSchema: {
772
- type: 'object',
773
- properties: {
774
- internal: { $ref: '#/$defs/internal' },
775
- external: { $ref: 'https://example.com/schemas/external.json' },
776
- },
777
- $defs: {
778
- internal: {
779
- type: 'object',
780
- properties: {
781
- name: { type: 'string' },
782
- },
783
- },
784
- },
785
- },
786
- });
787
- const endpoints = [createTestEndpoint(tool)];
788
- const capabilities = {
789
- topLevelUnions: true,
790
- validJson: true,
791
- refs: false,
792
- unions: true,
793
- formats: true,
794
- toolNameLength: undefined,
795
- };
796
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
797
- const schema = transformed[0].tool.inputSchema;
798
- if (schema.properties) {
799
- expect(schema.properties['internal']).toEqual({
800
- type: 'object',
801
- properties: {
802
- name: { type: 'string' },
803
- },
804
- });
805
- expect(schema.properties['external']).toEqual({
806
- $ref: 'https://example.com/schemas/external.json',
807
- });
808
- }
809
- });
810
- it('should remove anyOf fields when unions capability is disabled', () => {
811
- const tool = createTestTool('union-tool', {
812
- inputSchema: {
813
- type: 'object',
814
- properties: {
815
- field: {
816
- anyOf: [{ type: 'string' }, { type: 'number' }],
817
- },
818
- },
819
- },
820
- });
821
- const endpoints = [createTestEndpoint(tool)];
822
- const capabilities = {
823
- topLevelUnions: true,
824
- validJson: true,
825
- refs: true,
826
- unions: false,
827
- formats: true,
828
- toolNameLength: undefined,
829
- };
830
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
831
- const schema = transformed[0].tool.inputSchema;
832
- if (schema.properties && schema.properties['field']) {
833
- const field = schema.properties['field'];
834
- expect(field.anyOf).toBeUndefined();
835
- expect(field.type).toBe('string');
836
- }
837
- });
838
- it('should correctly combine topLevelUnions and toolNameLength transformations', () => {
839
- const tool = createTestTool('very-long-union-tool-name', {
840
- inputSchema: {
841
- type: 'object',
842
- properties: {
843
- common: { type: 'string' },
844
- },
845
- anyOf: [
846
- {
847
- title: 'first variant',
848
- properties: {
849
- variant1: { type: 'string' },
850
- },
851
- },
852
- {
853
- title: 'second variant',
854
- properties: {
855
- variant2: { type: 'number' },
856
- },
857
- },
858
- ],
859
- },
860
- });
861
- const endpoints = [createTestEndpoint(tool)];
862
- const capabilities = {
863
- topLevelUnions: false,
864
- validJson: true,
865
- refs: true,
866
- unions: true,
867
- formats: true,
868
- toolNameLength: 20,
869
- };
870
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
871
- expect(transformed.length).toBe(2);
872
- // Both names should be truncated because they exceed 20 characters
873
- expect(transformed[0].tool.name).toBe('very-long-union-too1');
874
- expect(transformed[1].tool.name).toBe('very-long-union-too2');
875
- });
876
- it('should correctly combine refs and unions transformations', () => {
877
- const tool = createTestTool('complex-tool', {
878
- inputSchema: {
879
- type: 'object',
880
- properties: {
881
- user: { $ref: '#/$defs/user' },
882
- },
883
- $defs: {
884
- user: {
885
- type: 'object',
886
- properties: {
887
- preference: {
888
- anyOf: [{ type: 'string' }, { type: 'number' }],
889
- },
890
- },
891
- },
892
- },
893
- },
894
- });
895
- const endpoints = [createTestEndpoint(tool)];
896
- const capabilities = {
897
- topLevelUnions: true,
898
- validJson: true,
899
- refs: false,
900
- unions: false,
901
- formats: true,
902
- toolNameLength: undefined,
903
- };
904
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
905
- const schema = transformed[0].tool.inputSchema;
906
- // Refs should be inlined
907
- expect(schema.$defs).toBeUndefined();
908
- // Safely access nested properties
909
- if (schema.properties && schema.properties['user']) {
910
- const user = schema.properties['user'];
911
- // User should be inlined
912
- expect(user.type).toBe('object');
913
- // AnyOf in the inlined user.preference should be removed
914
- if (user.properties && user.properties['preference']) {
915
- const preference = user.properties['preference'];
916
- expect(preference.anyOf).toBeUndefined();
917
- expect(preference.type).toBe('string');
918
- }
919
- }
920
- });
921
- it('should handle formats capability being false', () => {
922
- const tool = createTestTool('format-tool', {
923
- inputSchema: {
924
- type: 'object',
925
- properties: {
926
- date: { type: 'string', description: 'A date', format: 'date' },
927
- },
928
- },
929
- });
930
- const endpoints = [createTestEndpoint(tool)];
931
- const capabilities = {
932
- topLevelUnions: true,
933
- validJson: true,
934
- refs: true,
935
- unions: true,
936
- formats: false,
937
- toolNameLength: undefined,
938
- };
939
- const transformed = applyCompatibilityTransformations(endpoints, capabilities);
940
- const schema = transformed[0].tool.inputSchema;
941
- if (schema.properties && schema.properties['date']) {
942
- const dateField = schema.properties['date'];
943
- expect(dateField['format']).toBeUndefined();
944
- expect(dateField['description']).toBe('A date (format: "date")');
945
- }
946
- });
947
- });
948
- //# sourceMappingURL=compat.test.mjs.map