@iress-oss/ids-mcp-server 0.0.1-dev.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.
- package/LICENSE.txt +201 -0
- package/README.md +93 -0
- package/dist/componentHandlers.js +241 -0
- package/dist/componentHandlers.test.js +380 -0
- package/dist/config.js +16 -0
- package/dist/index.js +53 -0
- package/dist/iressHandlers.js +144 -0
- package/dist/iressHandlers.test.js +316 -0
- package/dist/resourceHandlers.js +67 -0
- package/dist/resourceHandlers.test.js +352 -0
- package/dist/searchHandlers.js +287 -0
- package/dist/searchHandlers.test.js +524 -0
- package/dist/toolHandler.js +31 -0
- package/dist/toolHandler.test.js +369 -0
- package/dist/tools.js +165 -0
- package/dist/types.js +4 -0
- package/dist/utils.js +59 -0
- package/dist/utils.test.js +286 -0
- package/generated/docs/components-alert-docs.md +130 -0
- package/generated/docs/components-autocomplete-docs.md +754 -0
- package/generated/docs/components-autocomplete-recipes-docs.md +104 -0
- package/generated/docs/components-badge-docs.md +148 -0
- package/generated/docs/components-button-docs.md +362 -0
- package/generated/docs/components-button-recipes-docs.md +76 -0
- package/generated/docs/components-buttongroup-docs.md +310 -0
- package/generated/docs/components-card-docs.md +494 -0
- package/generated/docs/components-card-recipes-docs.md +89 -0
- package/generated/docs/components-checkbox-docs.md +193 -0
- package/generated/docs/components-checkboxgroup-docs.md +692 -0
- package/generated/docs/components-checkboxgroup-recipes-docs.md +119 -0
- package/generated/docs/components-col-docs.md +466 -0
- package/generated/docs/components-combobox-docs.md +1016 -0
- package/generated/docs/components-container-docs.md +91 -0
- package/generated/docs/components-divider-docs.md +176 -0
- package/generated/docs/components-expander-docs.md +215 -0
- package/generated/docs/components-field-docs.md +675 -0
- package/generated/docs/components-filter-docs.md +1109 -0
- package/generated/docs/components-form-docs.md +2442 -0
- package/generated/docs/components-form-recipes-docs.md +892 -0
- package/generated/docs/components-hide-docs.md +265 -0
- package/generated/docs/components-icon-docs.md +553 -0
- package/generated/docs/components-inline-docs.md +868 -0
- package/generated/docs/components-input-docs.md +335 -0
- package/generated/docs/components-input-recipes-docs.md +140 -0
- package/generated/docs/components-inputcurrency-docs.md +157 -0
- package/generated/docs/components-inputcurrency-recipes-docs.md +116 -0
- package/generated/docs/components-label-docs.md +135 -0
- package/generated/docs/components-menu-docs.md +704 -0
- package/generated/docs/components-menu-menuitem-docs.md +193 -0
- package/generated/docs/components-modal-docs.md +587 -0
- package/generated/docs/components-navbar-docs.md +291 -0
- package/generated/docs/components-navbar-recipes-docs.md +413 -0
- package/generated/docs/components-panel-docs.md +380 -0
- package/generated/docs/components-placeholder-docs.md +27 -0
- package/generated/docs/components-popover-docs.md +464 -0
- package/generated/docs/components-popover-recipes-docs.md +245 -0
- package/generated/docs/components-progress-docs.md +104 -0
- package/generated/docs/components-radio-docs.md +107 -0
- package/generated/docs/components-radiogroup-docs.md +683 -0
- package/generated/docs/components-readonly-docs.md +89 -0
- package/generated/docs/components-richselect-docs.md +2433 -0
- package/generated/docs/components-row-docs.md +877 -0
- package/generated/docs/components-select-docs.md +456 -0
- package/generated/docs/components-skeleton-docs.md +214 -0
- package/generated/docs/components-skeleton-recipes-docs.md +76 -0
- package/generated/docs/components-skiplink-docs.md +66 -0
- package/generated/docs/components-slideout-docs.md +538 -0
- package/generated/docs/components-slider-docs.md +346 -0
- package/generated/docs/components-spinner-docs.md +59 -0
- package/generated/docs/components-stack-docs.md +265 -0
- package/generated/docs/components-table-ag-grid-docs.md +2666 -0
- package/generated/docs/components-table-docs.md +1305 -0
- package/generated/docs/components-tabset-docs.md +341 -0
- package/generated/docs/components-tabset-tab-docs.md +86 -0
- package/generated/docs/components-tag-docs.md +115 -0
- package/generated/docs/components-text-docs.md +394 -0
- package/generated/docs/components-toaster-docs.md +294 -0
- package/generated/docs/components-toaster-toast-docs.md +157 -0
- package/generated/docs/components-toggle-docs.md +158 -0
- package/generated/docs/components-tooltip-docs.md +311 -0
- package/generated/docs/components-validationmessage-docs.md +241 -0
- package/generated/docs/contact-us-docs.md +27 -0
- package/generated/docs/extensions-editor-docs.md +288 -0
- package/generated/docs/extensions-editor-recipes-docs.md +39 -0
- package/generated/docs/foundations-accessibility-docs.md +62 -0
- package/generated/docs/foundations-colours-docs.md +257 -0
- package/generated/docs/foundations-consistency-docs.md +52 -0
- package/generated/docs/foundations-content-docs.md +23 -0
- package/generated/docs/foundations-introduction-docs.md +17 -0
- package/generated/docs/foundations-principles-docs.md +70 -0
- package/generated/docs/foundations-typography-docs.md +191 -0
- package/generated/docs/foundations-user-experience-docs.md +63 -0
- package/generated/docs/foundations-visual-design-docs.md +46 -0
- package/generated/docs/frequently-asked-questions-docs.md +53 -0
- package/generated/docs/get-started-develop-docs.md +48 -0
- package/generated/docs/get-started-using-storybook-docs.md +68 -0
- package/generated/docs/guidelines.md +812 -0
- package/generated/docs/introduction-docs.md +43 -0
- package/generated/docs/patterns-loading-docs.md +1304 -0
- package/generated/docs/resources-changelog-docs.md +6 -0
- package/generated/docs/resources-code-katas-docs.md +29 -0
- package/generated/docs/resources-migration-guides-from-v4-to-v5-docs.md +437 -0
- package/generated/docs/themes-available-themes-docs.md +66 -0
- package/generated/docs/themes-introduction-docs.md +121 -0
- package/generated/docs/themes-tokens-docs.md +1200 -0
- package/generated/docs/versions-docs.md +17 -0
- package/package.json +81 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for toolHandler.ts
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
5
|
+
import { handleToolCall } from './toolHandler.js';
|
|
6
|
+
import { handleFindComponent, handleGetComponentProps, handleListComponents, } from './componentHandlers.js';
|
|
7
|
+
import { handleGetUsageExamples, handleSearchIdsDocs, handleGetDesignTokens, handleGetDesignGuidelines, } from './searchHandlers.js';
|
|
8
|
+
import { handleGetIressComponentInfo, handleAnalyzeComponentMentions, } from './iressHandlers.js';
|
|
9
|
+
// Mock all handler modules
|
|
10
|
+
vi.mock('./componentHandlers.js', () => ({
|
|
11
|
+
handleFindComponent: vi.fn(),
|
|
12
|
+
handleGetComponentProps: vi.fn(),
|
|
13
|
+
handleListComponents: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('./searchHandlers.js', () => ({
|
|
16
|
+
handleGetUsageExamples: vi.fn(),
|
|
17
|
+
handleSearchIdsDocs: vi.fn(),
|
|
18
|
+
handleGetDesignTokens: vi.fn(),
|
|
19
|
+
handleGetDesignGuidelines: vi.fn(),
|
|
20
|
+
}));
|
|
21
|
+
vi.mock('./iressHandlers.js', () => ({
|
|
22
|
+
handleGetIressComponentInfo: vi.fn(),
|
|
23
|
+
handleAnalyzeComponentMentions: vi.fn(),
|
|
24
|
+
}));
|
|
25
|
+
// Type the mocked functions
|
|
26
|
+
const mockedHandleFindComponent = vi.mocked(handleFindComponent);
|
|
27
|
+
const mockedHandleGetComponentProps = vi.mocked(handleGetComponentProps);
|
|
28
|
+
const mockedHandleListComponents = vi.mocked(handleListComponents);
|
|
29
|
+
const mockedHandleGetUsageExamples = vi.mocked(handleGetUsageExamples);
|
|
30
|
+
const mockedHandleSearchIdsDocs = vi.mocked(handleSearchIdsDocs);
|
|
31
|
+
const mockedHandleGetDesignTokens = vi.mocked(handleGetDesignTokens);
|
|
32
|
+
const mockedHandleGetDesignGuidelines = vi.mocked(handleGetDesignGuidelines);
|
|
33
|
+
const mockedHandleGetIressComponentInfo = vi.mocked(handleGetIressComponentInfo);
|
|
34
|
+
const mockedHandleAnalyzeComponentMentions = vi.mocked(handleAnalyzeComponentMentions);
|
|
35
|
+
describe('handleToolCall', () => {
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
vi.clearAllMocks();
|
|
38
|
+
});
|
|
39
|
+
describe('component handlers', () => {
|
|
40
|
+
it('should handle find_component tool call', () => {
|
|
41
|
+
const mockResponse = {
|
|
42
|
+
content: [{ type: 'text', text: 'Component found' }],
|
|
43
|
+
};
|
|
44
|
+
mockedHandleFindComponent.mockReturnValue(mockResponse);
|
|
45
|
+
const request = {
|
|
46
|
+
params: {
|
|
47
|
+
name: 'find_component',
|
|
48
|
+
arguments: { query: 'Button' },
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
const result = handleToolCall(request);
|
|
52
|
+
expect(mockedHandleFindComponent).toHaveBeenCalledWith({
|
|
53
|
+
query: 'Button',
|
|
54
|
+
});
|
|
55
|
+
expect(result).toEqual(mockResponse);
|
|
56
|
+
});
|
|
57
|
+
it('should handle get_component_props tool call', () => {
|
|
58
|
+
const mockResponse = {
|
|
59
|
+
content: [{ type: 'text', text: 'Component props listed' }],
|
|
60
|
+
};
|
|
61
|
+
mockedHandleGetComponentProps.mockReturnValue(mockResponse);
|
|
62
|
+
const request = {
|
|
63
|
+
params: {
|
|
64
|
+
name: 'get_component_props',
|
|
65
|
+
arguments: { component: 'Button' },
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
const result = handleToolCall(request);
|
|
69
|
+
expect(mockedHandleGetComponentProps).toHaveBeenCalledWith({
|
|
70
|
+
component: 'Button',
|
|
71
|
+
});
|
|
72
|
+
expect(result).toEqual(mockResponse);
|
|
73
|
+
});
|
|
74
|
+
it('should handle list_components tool call', () => {
|
|
75
|
+
const mockResponse = {
|
|
76
|
+
content: [{ type: 'text', text: 'Components listed' }],
|
|
77
|
+
};
|
|
78
|
+
mockedHandleListComponents.mockReturnValue(mockResponse);
|
|
79
|
+
const request = {
|
|
80
|
+
params: {
|
|
81
|
+
name: 'list_components',
|
|
82
|
+
arguments: { category: 'forms' },
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const result = handleToolCall(request);
|
|
86
|
+
expect(mockedHandleListComponents).toHaveBeenCalledWith({
|
|
87
|
+
category: 'forms',
|
|
88
|
+
});
|
|
89
|
+
expect(result).toEqual(mockResponse);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('search handlers', () => {
|
|
93
|
+
it('should handle get_usage_examples tool call', () => {
|
|
94
|
+
const mockResponse = {
|
|
95
|
+
content: [{ type: 'text', text: 'Usage examples found' }],
|
|
96
|
+
};
|
|
97
|
+
mockedHandleGetUsageExamples.mockReturnValue(mockResponse);
|
|
98
|
+
const request = {
|
|
99
|
+
params: {
|
|
100
|
+
name: 'get_usage_examples',
|
|
101
|
+
arguments: { component: 'Button', pattern: 'primary' },
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
const result = handleToolCall(request);
|
|
105
|
+
expect(mockedHandleGetUsageExamples).toHaveBeenCalledWith({
|
|
106
|
+
component: 'Button',
|
|
107
|
+
pattern: 'primary',
|
|
108
|
+
});
|
|
109
|
+
expect(result).toEqual(mockResponse);
|
|
110
|
+
});
|
|
111
|
+
it('should handle search_ids_docs tool call', () => {
|
|
112
|
+
const mockResponse = {
|
|
113
|
+
content: [{ type: 'text', text: 'Documentation searched' }],
|
|
114
|
+
};
|
|
115
|
+
mockedHandleSearchIdsDocs.mockReturnValue(mockResponse);
|
|
116
|
+
const request = {
|
|
117
|
+
params: {
|
|
118
|
+
name: 'search_ids_docs',
|
|
119
|
+
arguments: { query: 'accessibility' },
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
const result = handleToolCall(request);
|
|
123
|
+
expect(mockedHandleSearchIdsDocs).toHaveBeenCalledWith({
|
|
124
|
+
query: 'accessibility',
|
|
125
|
+
});
|
|
126
|
+
expect(result).toEqual(mockResponse);
|
|
127
|
+
});
|
|
128
|
+
it('should handle get_design_tokens tool call', () => {
|
|
129
|
+
const mockResponse = {
|
|
130
|
+
content: [{ type: 'text', text: 'Design tokens found' }],
|
|
131
|
+
};
|
|
132
|
+
mockedHandleGetDesignTokens.mockReturnValue(mockResponse);
|
|
133
|
+
const request = {
|
|
134
|
+
params: {
|
|
135
|
+
name: 'get_design_tokens',
|
|
136
|
+
arguments: { category: 'colors' },
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const result = handleToolCall(request);
|
|
140
|
+
expect(mockedHandleGetDesignTokens).toHaveBeenCalledWith({
|
|
141
|
+
category: 'colors',
|
|
142
|
+
});
|
|
143
|
+
expect(result).toEqual(mockResponse);
|
|
144
|
+
});
|
|
145
|
+
it('should handle get_design_guidelines tool call', () => {
|
|
146
|
+
const mockResponse = {
|
|
147
|
+
content: [{ type: 'text', text: 'Design guidelines found' }],
|
|
148
|
+
};
|
|
149
|
+
mockedHandleGetDesignGuidelines.mockReturnValue(mockResponse);
|
|
150
|
+
const request = {
|
|
151
|
+
params: {
|
|
152
|
+
name: 'get_design_guidelines',
|
|
153
|
+
arguments: { topic: 'spacing' },
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
const result = handleToolCall(request);
|
|
157
|
+
expect(mockedHandleGetDesignGuidelines).toHaveBeenCalledWith({
|
|
158
|
+
topic: 'spacing',
|
|
159
|
+
});
|
|
160
|
+
expect(result).toEqual(mockResponse);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('iress handlers', () => {
|
|
164
|
+
it('should handle get_iress_component_info tool call', () => {
|
|
165
|
+
const mockResponse = {
|
|
166
|
+
content: [{ type: 'text', text: 'Iress component info' }],
|
|
167
|
+
};
|
|
168
|
+
mockedHandleGetIressComponentInfo.mockReturnValue(mockResponse);
|
|
169
|
+
const request = {
|
|
170
|
+
params: {
|
|
171
|
+
name: 'get_iress_component_info',
|
|
172
|
+
arguments: {
|
|
173
|
+
component_name: 'IressButton',
|
|
174
|
+
include_examples: true,
|
|
175
|
+
include_props: false,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
const result = handleToolCall(request);
|
|
180
|
+
expect(mockedHandleGetIressComponentInfo).toHaveBeenCalledWith({
|
|
181
|
+
component_name: 'IressButton',
|
|
182
|
+
include_examples: true,
|
|
183
|
+
include_props: false,
|
|
184
|
+
});
|
|
185
|
+
expect(result).toEqual(mockResponse);
|
|
186
|
+
});
|
|
187
|
+
it('should handle analyze_component_mentions tool call', () => {
|
|
188
|
+
const mockResponse = {
|
|
189
|
+
content: [{ type: 'text', text: 'Component mentions analyzed' }],
|
|
190
|
+
};
|
|
191
|
+
mockedHandleAnalyzeComponentMentions.mockReturnValue(mockResponse);
|
|
192
|
+
const request = {
|
|
193
|
+
params: {
|
|
194
|
+
name: 'analyze_component_mentions',
|
|
195
|
+
arguments: { content: 'This uses IressButton component' },
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
const result = handleToolCall(request);
|
|
199
|
+
expect(mockedHandleAnalyzeComponentMentions).toHaveBeenCalledWith({
|
|
200
|
+
content: 'This uses IressButton component',
|
|
201
|
+
});
|
|
202
|
+
expect(result).toEqual(mockResponse);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
describe('edge cases', () => {
|
|
206
|
+
it('should handle tool call without arguments', () => {
|
|
207
|
+
const mockResponse = {
|
|
208
|
+
content: [{ type: 'text', text: 'Components listed' }],
|
|
209
|
+
};
|
|
210
|
+
mockedHandleListComponents.mockReturnValue(mockResponse);
|
|
211
|
+
const request = {
|
|
212
|
+
params: {
|
|
213
|
+
name: 'list_components',
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
const result = handleToolCall(request);
|
|
217
|
+
expect(mockedHandleListComponents).toHaveBeenCalledWith({});
|
|
218
|
+
expect(result).toEqual(mockResponse);
|
|
219
|
+
});
|
|
220
|
+
it('should handle tool call with null arguments', () => {
|
|
221
|
+
const mockResponse = {
|
|
222
|
+
content: [{ type: 'text', text: 'Component found' }],
|
|
223
|
+
};
|
|
224
|
+
mockedHandleFindComponent.mockReturnValue(mockResponse);
|
|
225
|
+
const request = {
|
|
226
|
+
params: {
|
|
227
|
+
name: 'find_component',
|
|
228
|
+
arguments: null,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
const result = handleToolCall(request);
|
|
232
|
+
expect(mockedHandleFindComponent).toHaveBeenCalledWith(null);
|
|
233
|
+
expect(result).toEqual(mockResponse);
|
|
234
|
+
});
|
|
235
|
+
it('should handle tool call with undefined arguments', () => {
|
|
236
|
+
const mockResponse = {
|
|
237
|
+
content: [{ type: 'text', text: 'Component found' }],
|
|
238
|
+
};
|
|
239
|
+
mockedHandleFindComponent.mockReturnValue(mockResponse);
|
|
240
|
+
const request = {
|
|
241
|
+
params: {
|
|
242
|
+
name: 'find_component',
|
|
243
|
+
arguments: undefined,
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
const result = handleToolCall(request);
|
|
247
|
+
expect(mockedHandleFindComponent).toHaveBeenCalledWith({});
|
|
248
|
+
expect(result).toEqual(mockResponse);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
describe('error handling', () => {
|
|
252
|
+
it('should throw error for unknown tool name', () => {
|
|
253
|
+
const request = {
|
|
254
|
+
params: {
|
|
255
|
+
name: 'unknown_tool',
|
|
256
|
+
arguments: { query: 'test' },
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
expect(() => handleToolCall(request)).toThrow('Unknown tool: unknown_tool');
|
|
260
|
+
});
|
|
261
|
+
it('should handle empty tool name', () => {
|
|
262
|
+
const request = {
|
|
263
|
+
params: {
|
|
264
|
+
name: '',
|
|
265
|
+
arguments: { query: 'test' },
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
expect(() => handleToolCall(request)).toThrow('Unknown tool: ');
|
|
269
|
+
});
|
|
270
|
+
it('should propagate errors from handler functions', () => {
|
|
271
|
+
const mockError = new Error('Handler error');
|
|
272
|
+
mockedHandleFindComponent.mockImplementation(() => {
|
|
273
|
+
throw mockError;
|
|
274
|
+
});
|
|
275
|
+
const request = {
|
|
276
|
+
params: {
|
|
277
|
+
name: 'find_component',
|
|
278
|
+
arguments: { query: 'Button' },
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
expect(() => handleToolCall(request)).toThrow('Handler error');
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
describe('type checking', () => {
|
|
285
|
+
it('should pass correct argument types to handlers', () => {
|
|
286
|
+
const complexArgs = {
|
|
287
|
+
component: 'Button',
|
|
288
|
+
options: {
|
|
289
|
+
includeExamples: true,
|
|
290
|
+
includeProps: false,
|
|
291
|
+
},
|
|
292
|
+
filters: ['primary', 'secondary'],
|
|
293
|
+
metadata: {
|
|
294
|
+
timestamp: Date.now(),
|
|
295
|
+
version: '1.0.0',
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
mockedHandleGetComponentProps.mockReturnValue({
|
|
299
|
+
content: [{ type: 'text', text: 'Success' }],
|
|
300
|
+
});
|
|
301
|
+
const request = {
|
|
302
|
+
params: {
|
|
303
|
+
name: 'get_component_props',
|
|
304
|
+
arguments: complexArgs,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
handleToolCall(request);
|
|
308
|
+
expect(mockedHandleGetComponentProps).toHaveBeenCalledWith(complexArgs);
|
|
309
|
+
});
|
|
310
|
+
it('should handle boolean and number arguments', () => {
|
|
311
|
+
const booleanArgs = {
|
|
312
|
+
include_examples: true,
|
|
313
|
+
include_props: false,
|
|
314
|
+
max_results: 10,
|
|
315
|
+
threshold: 0.5,
|
|
316
|
+
};
|
|
317
|
+
mockedHandleGetIressComponentInfo.mockReturnValue({
|
|
318
|
+
content: [{ type: 'text', text: 'Success' }],
|
|
319
|
+
});
|
|
320
|
+
const request = {
|
|
321
|
+
params: {
|
|
322
|
+
name: 'get_iress_component_info',
|
|
323
|
+
arguments: booleanArgs,
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
handleToolCall(request);
|
|
327
|
+
expect(mockedHandleGetIressComponentInfo).toHaveBeenCalledWith(booleanArgs);
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
describe('all supported tools', () => {
|
|
331
|
+
const supportedTools = [
|
|
332
|
+
'find_component',
|
|
333
|
+
'get_component_props',
|
|
334
|
+
'get_usage_examples',
|
|
335
|
+
'search_ids_docs',
|
|
336
|
+
'list_components',
|
|
337
|
+
'get_design_tokens',
|
|
338
|
+
'get_iress_component_info',
|
|
339
|
+
'analyze_component_mentions',
|
|
340
|
+
'get_design_guidelines',
|
|
341
|
+
];
|
|
342
|
+
it.each(supportedTools)('should handle %s tool', (toolName) => {
|
|
343
|
+
// Mock all handlers to return a standard response
|
|
344
|
+
const mockResponse = {
|
|
345
|
+
content: [{ type: 'text', text: `${toolName} executed` }],
|
|
346
|
+
};
|
|
347
|
+
const handlerMocks = [
|
|
348
|
+
mockedHandleFindComponent,
|
|
349
|
+
mockedHandleGetComponentProps,
|
|
350
|
+
mockedHandleListComponents,
|
|
351
|
+
mockedHandleGetUsageExamples,
|
|
352
|
+
mockedHandleSearchIdsDocs,
|
|
353
|
+
mockedHandleGetDesignTokens,
|
|
354
|
+
mockedHandleGetDesignGuidelines,
|
|
355
|
+
mockedHandleGetIressComponentInfo,
|
|
356
|
+
mockedHandleAnalyzeComponentMentions,
|
|
357
|
+
];
|
|
358
|
+
handlerMocks.forEach((mock) => mock.mockReturnValue(mockResponse));
|
|
359
|
+
const request = {
|
|
360
|
+
params: {
|
|
361
|
+
name: toolName,
|
|
362
|
+
arguments: { test: 'value' },
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
const result = handleToolCall(request);
|
|
366
|
+
expect(result).toEqual(mockResponse);
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
});
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool definitions for the IDS MCP Server
|
|
3
|
+
*/
|
|
4
|
+
export const toolDefinitions = [
|
|
5
|
+
{
|
|
6
|
+
name: 'find_component',
|
|
7
|
+
description: 'Find IDS components by name or functionality. Perfect for discovering which component to use for specific UI needs.',
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
query: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: "Component name (e.g., 'button', 'input') or functionality (e.g., 'form submission', 'navigation')",
|
|
14
|
+
},
|
|
15
|
+
category: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Optional: filter by category (components, foundations, resources)',
|
|
18
|
+
enum: ['components', 'foundations', 'resources'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
required: ['query'],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'get_component_props',
|
|
26
|
+
description: 'Get detailed prop information and usage examples for IDS components. Essential for implementing components correctly.',
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
component: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: "Component name (e.g., 'button', 'input', 'table')",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ['component'],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'get_usage_examples',
|
|
40
|
+
description: 'Get code examples and implementation patterns for IDS components. Shows real-world usage in React applications.',
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
component: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'Component name to get examples for',
|
|
47
|
+
},
|
|
48
|
+
pattern: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: "Optional: specific usage pattern (e.g., 'form', 'modal', 'table')",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
required: ['component'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'search_ids_docs',
|
|
58
|
+
description: 'Search across all IDS documentation for specific terms, patterns, or implementation details.',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
query: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'Search term (component names, props, CSS classes, implementation patterns)',
|
|
65
|
+
},
|
|
66
|
+
case_sensitive: {
|
|
67
|
+
type: 'boolean',
|
|
68
|
+
description: 'Whether to perform case-sensitive search',
|
|
69
|
+
default: false,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
required: ['query'],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'list_components',
|
|
77
|
+
description: 'List all available IDS components, organized by category. Great for component discovery.',
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
category: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
description: 'Filter by category: components, foundations, or resources',
|
|
84
|
+
enum: ['components', 'foundations', 'resources', 'all'],
|
|
85
|
+
default: 'all',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'get_design_tokens',
|
|
92
|
+
description: 'Get information about IDS design tokens (colors, spacing, typography) for consistent UI implementation.',
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
type: {
|
|
97
|
+
type: 'string',
|
|
98
|
+
description: 'Type of design token to search for',
|
|
99
|
+
enum: ['colors', 'spacing', 'typography', 'breakpoints', 'all'],
|
|
100
|
+
default: 'all',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'get_iress_component_info',
|
|
107
|
+
description: 'Get comprehensive information about Iress components mentioned by their full name (e.g., IressButton, IressInput, IressTable). Perfect for when components are mentioned with the Iress prefix.',
|
|
108
|
+
inputSchema: {
|
|
109
|
+
type: 'object',
|
|
110
|
+
properties: {
|
|
111
|
+
component_name: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
description: "Full Iress component name (e.g., 'IressButton', 'IressInput', 'IressTable')",
|
|
114
|
+
},
|
|
115
|
+
include_examples: {
|
|
116
|
+
type: 'boolean',
|
|
117
|
+
description: 'Whether to include usage examples in the response',
|
|
118
|
+
default: true,
|
|
119
|
+
},
|
|
120
|
+
include_props: {
|
|
121
|
+
type: 'boolean',
|
|
122
|
+
description: 'Whether to include prop information in the response',
|
|
123
|
+
default: true,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
required: ['component_name'],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'analyze_component_mentions',
|
|
131
|
+
description: 'Analyze text to find all Iress component mentions (e.g., IressButton, IressInput) and provide information about each one.',
|
|
132
|
+
inputSchema: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
text: {
|
|
136
|
+
type: 'string',
|
|
137
|
+
description: 'Text content to analyze for Iress component mentions',
|
|
138
|
+
},
|
|
139
|
+
detailed: {
|
|
140
|
+
type: 'boolean',
|
|
141
|
+
description: 'Whether to provide detailed information for each component found',
|
|
142
|
+
default: false,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
required: ['text'],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'get_design_guidelines',
|
|
150
|
+
description: 'Get IDS design guidelines covering core principles, visual standards, accessibility requirements, and best practices for consistent design implementation.',
|
|
151
|
+
inputSchema: {
|
|
152
|
+
type: 'object',
|
|
153
|
+
properties: {
|
|
154
|
+
section: {
|
|
155
|
+
type: 'string',
|
|
156
|
+
description: "Optional: specific guideline section (e.g., 'principles', 'typography', 'accessibility', 'layout', 'colors')",
|
|
157
|
+
},
|
|
158
|
+
query: {
|
|
159
|
+
type: 'string',
|
|
160
|
+
description: 'Optional: search for specific guidelines or best practices',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
];
|
package/dist/types.js
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for file operations and component mapping
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { DOCS_DIR } from './config.js';
|
|
6
|
+
/**
|
|
7
|
+
* Utility function to get all markdown files in the docs directory
|
|
8
|
+
*/
|
|
9
|
+
export function getMarkdownFiles() {
|
|
10
|
+
try {
|
|
11
|
+
if (!fs.existsSync(DOCS_DIR)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const files = fs.readdirSync(DOCS_DIR, { recursive: true });
|
|
15
|
+
return files
|
|
16
|
+
.filter((file) => typeof file === 'string' && file.endsWith('.md'))
|
|
17
|
+
.map((file) => file);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
console.error('Error reading docs directory:', error);
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Map Iress component names (e.g., IressButton) to their documentation files
|
|
26
|
+
*/
|
|
27
|
+
export function mapIressComponentToFile(componentName) {
|
|
28
|
+
// Remove 'Iress' prefix and convert to lowercase
|
|
29
|
+
const baseComponentName = componentName.replace(/^Iress/, '').toLowerCase();
|
|
30
|
+
const markdownFiles = getMarkdownFiles();
|
|
31
|
+
// Try to find exact match first
|
|
32
|
+
let matchingFile = markdownFiles.find((file) => file === `components-${baseComponentName}-docs.md`);
|
|
33
|
+
// If no exact match, try partial matching
|
|
34
|
+
matchingFile ??= markdownFiles.find((file) => file.startsWith(`components-${baseComponentName}`) &&
|
|
35
|
+
file.endsWith('-docs.md'));
|
|
36
|
+
// If still no match, try fuzzy matching
|
|
37
|
+
matchingFile ??= markdownFiles.find((file) => file.includes(baseComponentName) && file.startsWith('components-'));
|
|
38
|
+
return matchingFile ?? null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract Iress component names from text (e.g., IressButton, IressInput)
|
|
42
|
+
*/
|
|
43
|
+
export function extractIressComponents(text) {
|
|
44
|
+
const iressComponentRegex = /Iress[A-Z][a-zA-Z]*/g;
|
|
45
|
+
const matches = text.match(iressComponentRegex) ?? [];
|
|
46
|
+
return [...new Set(matches)]; // Remove duplicates
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read file content safely
|
|
50
|
+
*/
|
|
51
|
+
export function readFileContent(filePath) {
|
|
52
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if file exists
|
|
56
|
+
*/
|
|
57
|
+
export function fileExists(filePath) {
|
|
58
|
+
return fs.existsSync(filePath);
|
|
59
|
+
}
|