@sebgroup/green-core 2.33.0 → 2.34.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/README.md +24 -0
- package/bin/context-cli/framework.d.ts +3 -0
- package/bin/context-cli/framework.js +23 -0
- package/bin/context-cli/index.d.ts +2 -0
- package/bin/context-cli/index.js +363 -0
- package/bin/context-cli/parse-args.d.ts +22 -0
- package/bin/context-cli/parse-args.js +46 -0
- package/bin/mcp-server/errors.d.ts +2 -7
- package/bin/mcp-server/handlers.d.ts +86 -0
- package/bin/mcp-server/handlers.js +356 -0
- package/bin/mcp-server/search.js +8 -1
- package/bin/mcp-server/tools.d.ts +13 -1
- package/bin/mcp-server/tools.js +8 -303
- package/components/table/table.component.js +2 -2
- package/custom-elements.json +3182 -2916
- package/gds-element.js +1 -1
- package/generated/mcp/components.json +1 -1
- package/generated/mcp/icons.json +1 -1
- package/generated/mcp/index.json +1 -1
- package/generated/react/index.d.ts +7 -7
- package/generated/react/index.js +7 -7
- package/package.json +3 -2
- package/utils/helpers/custom-element-scoping.js +1 -1
- package/utils/testing/index.js +6 -2
package/bin/mcp-server/tools.js
CHANGED
|
@@ -3,25 +3,15 @@ import {
|
|
|
3
3
|
CallToolRequestSchema,
|
|
4
4
|
ListToolsRequestSchema
|
|
5
5
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { formatErrorResponse, logError, NotFoundError } from "./errors.js";
|
|
9
|
-
import { parseSearchQuery, performSearch } from "./search.js";
|
|
6
|
+
import { SEARCH_CONFIG } from "./constants.js";
|
|
7
|
+
import { formatErrorResponse, logError } from "./errors.js";
|
|
10
8
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readMcpFile
|
|
18
|
-
} from "./utils.js";
|
|
19
|
-
import {
|
|
20
|
-
validateGetComponentDocsInput,
|
|
21
|
-
validateGetGuideInput,
|
|
22
|
-
validateListGuidesInput,
|
|
23
|
-
validateSearchComponentsInput
|
|
24
|
-
} from "./validation.js";
|
|
9
|
+
handleGetComponentDocs,
|
|
10
|
+
handleGetGuide,
|
|
11
|
+
handleGetInstructions,
|
|
12
|
+
handleListGuides,
|
|
13
|
+
handleSearchComponents
|
|
14
|
+
} from "./handlers.js";
|
|
25
15
|
function setupToolHandlers(server) {
|
|
26
16
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
27
17
|
return {
|
|
@@ -174,291 +164,6 @@ function setupToolHandlers(server) {
|
|
|
174
164
|
}
|
|
175
165
|
});
|
|
176
166
|
}
|
|
177
|
-
async function handleSearchComponents(input) {
|
|
178
|
-
const validatedInput = validateSearchComponentsInput(input);
|
|
179
|
-
const {
|
|
180
|
-
query,
|
|
181
|
-
category = "all",
|
|
182
|
-
splitTerms = true,
|
|
183
|
-
matchAll = false,
|
|
184
|
-
useRegex = false,
|
|
185
|
-
maxResults = SEARCH_CONFIG.DEFAULT_MAX_RESULTS
|
|
186
|
-
} = validatedInput;
|
|
187
|
-
const loadComponents = category === "component" || category === "all";
|
|
188
|
-
const loadIcons = category === "icon" || category === "all";
|
|
189
|
-
const [componentsIndex, iconsIndex] = await Promise.all([
|
|
190
|
-
loadComponents ? loadComponentsIndex() : Promise.resolve(null),
|
|
191
|
-
loadIcons ? loadIconsIndex() : Promise.resolve(null)
|
|
192
|
-
]);
|
|
193
|
-
const components = componentsIndex?.components || [];
|
|
194
|
-
const icons = iconsIndex?.icons || [];
|
|
195
|
-
const { searchTerms, regexPattern } = parseSearchQuery(
|
|
196
|
-
query,
|
|
197
|
-
splitTerms,
|
|
198
|
-
useRegex
|
|
199
|
-
);
|
|
200
|
-
const buildUris = (item, cat) => {
|
|
201
|
-
const shortName = item.tagName.replace(/^gds-/, "");
|
|
202
|
-
const resourceCategory = cat === "component" ? "components" : "icons";
|
|
203
|
-
const uris = {};
|
|
204
|
-
for (const docType of item.files) {
|
|
205
|
-
uris[docType] = buildResourceUri(resourceCategory, shortName, docType);
|
|
206
|
-
}
|
|
207
|
-
return uris;
|
|
208
|
-
};
|
|
209
|
-
const results = performSearch(
|
|
210
|
-
components,
|
|
211
|
-
icons,
|
|
212
|
-
query,
|
|
213
|
-
searchTerms,
|
|
214
|
-
regexPattern,
|
|
215
|
-
matchAll,
|
|
216
|
-
splitTerms,
|
|
217
|
-
maxResults,
|
|
218
|
-
buildUris
|
|
219
|
-
);
|
|
220
|
-
return {
|
|
221
|
-
content: [
|
|
222
|
-
{
|
|
223
|
-
type: "text",
|
|
224
|
-
text: JSON.stringify(
|
|
225
|
-
{
|
|
226
|
-
query,
|
|
227
|
-
resultCount: results.length,
|
|
228
|
-
results
|
|
229
|
-
},
|
|
230
|
-
null,
|
|
231
|
-
2
|
|
232
|
-
)
|
|
233
|
-
}
|
|
234
|
-
]
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
async function handleGetComponentDocs(input) {
|
|
238
|
-
const validatedInput = validateGetComponentDocsInput(input);
|
|
239
|
-
const {
|
|
240
|
-
componentName,
|
|
241
|
-
framework,
|
|
242
|
-
includeGuidelines = true,
|
|
243
|
-
includeInstructions = true
|
|
244
|
-
} = validatedInput;
|
|
245
|
-
const [componentsIndex, iconsIndex] = await Promise.all([
|
|
246
|
-
loadComponentsIndex(),
|
|
247
|
-
loadIconsIndex()
|
|
248
|
-
]);
|
|
249
|
-
if (!componentsIndex || !iconsIndex) {
|
|
250
|
-
throw new NotFoundError(
|
|
251
|
-
"Failed to load component indexes",
|
|
252
|
-
"index",
|
|
253
|
-
"components/icons"
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
const component = findComponent(componentName, componentsIndex.components);
|
|
257
|
-
const icon = component ? null : findIcon(componentName, iconsIndex.icons);
|
|
258
|
-
const found = component || icon;
|
|
259
|
-
if (!found) {
|
|
260
|
-
throw new NotFoundError(
|
|
261
|
-
`Component not found: ${componentName}. Try using the search_components tool to find available components.`,
|
|
262
|
-
"component",
|
|
263
|
-
componentName
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
const shortName = found.tagName.replace(/^gds-/, "");
|
|
267
|
-
const sections = [];
|
|
268
|
-
let primaryDoc;
|
|
269
|
-
if (framework === "angular") {
|
|
270
|
-
primaryDoc = DOC_TYPES.ANGULAR;
|
|
271
|
-
} else if (framework === "react") {
|
|
272
|
-
primaryDoc = DOC_TYPES.REACT;
|
|
273
|
-
} else {
|
|
274
|
-
primaryDoc = DOC_TYPES.API;
|
|
275
|
-
}
|
|
276
|
-
sections.push(`# ${found.tagName} - ${capitalize(framework)}`);
|
|
277
|
-
sections.push("");
|
|
278
|
-
if (framework === "angular" || framework === "react") {
|
|
279
|
-
sections.push(`\u26A0\uFE0F **${capitalize(framework)}-Specific Documentation**`);
|
|
280
|
-
sections.push(
|
|
281
|
-
`The import paths and syntax below are for ${capitalize(framework)} applications.`
|
|
282
|
-
);
|
|
283
|
-
sections.push("");
|
|
284
|
-
}
|
|
285
|
-
if (found.files.includes(primaryDoc)) {
|
|
286
|
-
const content = await readMcpFile(`${shortName}/${primaryDoc}.md`);
|
|
287
|
-
if (content) {
|
|
288
|
-
const contentWithoutTitle = content.replace(/^#\s+.*?\n/, "");
|
|
289
|
-
sections.push(contentWithoutTitle);
|
|
290
|
-
sections.push("");
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if ((framework === "angular" || framework === "react") && found.files.includes(DOC_TYPES.API)) {
|
|
294
|
-
const apiContent = await readMcpFile(`${shortName}/${DOC_TYPES.API}.md`);
|
|
295
|
-
if (apiContent) {
|
|
296
|
-
sections.push("---");
|
|
297
|
-
sections.push("");
|
|
298
|
-
sections.push("## Component API Reference");
|
|
299
|
-
sections.push("");
|
|
300
|
-
sections.push(
|
|
301
|
-
"The following properties, events, slots, and methods are available:"
|
|
302
|
-
);
|
|
303
|
-
sections.push("");
|
|
304
|
-
const apiWithoutHeader = apiContent.replace(/^#\s+.*?\n/, "").replace(/\*\*Class\*\*:.*?\n/, "").replace(/\*\*Tag\*\*:.*?\n/, "").trim();
|
|
305
|
-
sections.push(apiWithoutHeader);
|
|
306
|
-
sections.push("");
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
if (includeGuidelines && found.files.includes(DOC_TYPES.GUIDELINES)) {
|
|
310
|
-
const guidelines = await readMcpFile(
|
|
311
|
-
`${shortName}/${DOC_TYPES.GUIDELINES}.md`
|
|
312
|
-
);
|
|
313
|
-
if (guidelines) {
|
|
314
|
-
sections.push("---");
|
|
315
|
-
sections.push("");
|
|
316
|
-
sections.push("## Design Guidelines");
|
|
317
|
-
sections.push("");
|
|
318
|
-
sections.push(guidelines);
|
|
319
|
-
sections.push("");
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
if (includeInstructions && found.files.includes(DOC_TYPES.INSTRUCTIONS)) {
|
|
323
|
-
const instructions = await readMcpFile(
|
|
324
|
-
`${shortName}/${DOC_TYPES.INSTRUCTIONS}.md`
|
|
325
|
-
);
|
|
326
|
-
if (instructions) {
|
|
327
|
-
sections.push("---");
|
|
328
|
-
sections.push("");
|
|
329
|
-
sections.push("## Usage Instructions");
|
|
330
|
-
sections.push("");
|
|
331
|
-
sections.push(instructions);
|
|
332
|
-
sections.push("");
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
sections.push("---");
|
|
336
|
-
sections.push("");
|
|
337
|
-
sections.push("\u{1F4A1} **Using a different framework?**");
|
|
338
|
-
sections.push("Call this tool again with:");
|
|
339
|
-
if (framework !== "angular")
|
|
340
|
-
sections.push('- `framework: "angular"` for Angular documentation');
|
|
341
|
-
if (framework !== "react")
|
|
342
|
-
sections.push('- `framework: "react"` for React documentation');
|
|
343
|
-
if (framework !== "web-component")
|
|
344
|
-
sections.push('- `framework: "web-component"` for vanilla JS usage');
|
|
345
|
-
return {
|
|
346
|
-
content: [
|
|
347
|
-
{
|
|
348
|
-
type: "text",
|
|
349
|
-
text: sections.join("\n")
|
|
350
|
-
}
|
|
351
|
-
]
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
async function handleListGuides(input) {
|
|
355
|
-
const validatedInput = validateListGuidesInput(input);
|
|
356
|
-
const { category = "all", framework } = validatedInput;
|
|
357
|
-
const globalIndex = await loadGlobalIndex();
|
|
358
|
-
if (!globalIndex) {
|
|
359
|
-
throw new NotFoundError("Failed to load global index", "index", "global");
|
|
360
|
-
}
|
|
361
|
-
let guides = globalIndex.guides;
|
|
362
|
-
if (category !== "all") {
|
|
363
|
-
guides = guides.filter((g) => g.category === category);
|
|
364
|
-
}
|
|
365
|
-
if (framework && framework !== "all") {
|
|
366
|
-
guides = guides.filter((g) => g.tags.includes(framework));
|
|
367
|
-
}
|
|
368
|
-
const guidesWithUris = guides.map((guide) => {
|
|
369
|
-
const name = guide.path.replace(/^(guides|concepts)\//, "").replace(/\.md$/, "");
|
|
370
|
-
const guideCategory = guide.path.startsWith("guides/") ? "guides" : "concepts";
|
|
371
|
-
const uri = buildResourceUri(guideCategory, name);
|
|
372
|
-
return {
|
|
373
|
-
title: guide.title,
|
|
374
|
-
category: guide.category,
|
|
375
|
-
description: guide.description,
|
|
376
|
-
tags: guide.tags,
|
|
377
|
-
resourceUri: uri
|
|
378
|
-
};
|
|
379
|
-
});
|
|
380
|
-
return {
|
|
381
|
-
content: [
|
|
382
|
-
{
|
|
383
|
-
type: "text",
|
|
384
|
-
text: JSON.stringify(
|
|
385
|
-
{
|
|
386
|
-
guideCount: guidesWithUris.length,
|
|
387
|
-
guides: guidesWithUris
|
|
388
|
-
},
|
|
389
|
-
null,
|
|
390
|
-
2
|
|
391
|
-
)
|
|
392
|
-
}
|
|
393
|
-
]
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
async function handleGetGuide(input) {
|
|
397
|
-
const validatedInput = validateGetGuideInput(input);
|
|
398
|
-
const { name } = validatedInput;
|
|
399
|
-
const globalIndex = await loadGlobalIndex();
|
|
400
|
-
if (!globalIndex) {
|
|
401
|
-
throw new NotFoundError("Failed to load global index", "index", "global");
|
|
402
|
-
}
|
|
403
|
-
const guide = globalIndex.guides.find((g) => {
|
|
404
|
-
const guideName = g.path.replace(/^(guides|concepts)\//, "").replace(/\.md$/, "");
|
|
405
|
-
return guideName === name;
|
|
406
|
-
});
|
|
407
|
-
if (!guide) {
|
|
408
|
-
throw new NotFoundError(
|
|
409
|
-
`Guide not found: ${name}. Use list_guides to see available guides.`,
|
|
410
|
-
"guide",
|
|
411
|
-
name
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
const content = await readMcpFile(guide.path);
|
|
415
|
-
if (!content) {
|
|
416
|
-
throw new NotFoundError(
|
|
417
|
-
`Guide file not found: ${guide.path}`,
|
|
418
|
-
"file",
|
|
419
|
-
guide.path
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
return {
|
|
423
|
-
content: [
|
|
424
|
-
{
|
|
425
|
-
type: "text",
|
|
426
|
-
text: `# ${guide.title}
|
|
427
|
-
|
|
428
|
-
${content}`
|
|
429
|
-
}
|
|
430
|
-
]
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
async function handleGetInstructions() {
|
|
434
|
-
const globalIndex = await loadGlobalIndex();
|
|
435
|
-
if (!globalIndex) {
|
|
436
|
-
throw new NotFoundError("Failed to load global index", "index", "global");
|
|
437
|
-
}
|
|
438
|
-
if (!globalIndex.instructions) {
|
|
439
|
-
throw new NotFoundError(
|
|
440
|
-
"Instructions not available. The MCP may not have been generated with instructions support.",
|
|
441
|
-
"file",
|
|
442
|
-
"INSTRUCTIONS.md"
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
const content = await readMcpFile("INSTRUCTIONS.md");
|
|
446
|
-
if (!content) {
|
|
447
|
-
throw new NotFoundError(
|
|
448
|
-
"Instructions file not found",
|
|
449
|
-
"file",
|
|
450
|
-
"INSTRUCTIONS.md"
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
return {
|
|
454
|
-
content: [
|
|
455
|
-
{
|
|
456
|
-
type: "text",
|
|
457
|
-
text: content
|
|
458
|
-
}
|
|
459
|
-
]
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
167
|
export {
|
|
463
168
|
setupToolHandlers
|
|
464
169
|
};
|
|
@@ -843,7 +843,7 @@ renderHeadline_fn = function() {
|
|
|
843
843
|
<gds-text
|
|
844
844
|
tag="${this.headlineTag}"
|
|
845
845
|
font="heading-s"
|
|
846
|
-
text-wrap="
|
|
846
|
+
text-wrap="pretty"
|
|
847
847
|
max-width="80ch"
|
|
848
848
|
>
|
|
849
849
|
${this.headline}
|
|
@@ -851,7 +851,7 @@ renderHeadline_fn = function() {
|
|
|
851
851
|
<gds-text
|
|
852
852
|
tag="p"
|
|
853
853
|
font=${this.density === "compact" ? "body-regular-s" : "body-regular-m"}
|
|
854
|
-
text-wrap="
|
|
854
|
+
text-wrap="pretty"
|
|
855
855
|
max-width="80ch"
|
|
856
856
|
>
|
|
857
857
|
${this.summary}
|