@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.
@@ -3,25 +3,15 @@ import {
3
3
  CallToolRequestSchema,
4
4
  ListToolsRequestSchema
5
5
  } from "@modelcontextprotocol/sdk/types.js";
6
- import { capitalize } from "../../utils/helpers/casing.js";
7
- import { DOC_TYPES, SEARCH_CONFIG } from "./constants.js";
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
- buildResourceUri,
12
- findComponent,
13
- findIcon,
14
- loadComponentsIndex,
15
- loadGlobalIndex,
16
- loadIconsIndex,
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="balance"
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="balance"
854
+ text-wrap="pretty"
855
855
  max-width="80ch"
856
856
  >
857
857
  ${this.summary}