@santi020k/lumen-mcp 0.3.0 → 1.0.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/dist/data.d.ts CHANGED
@@ -69,6 +69,7 @@ export interface LumenData {
69
69
  recipes: LumenRecipeSnapshot[];
70
70
  rules: string;
71
71
  tokens: {
72
+ chart: Record<string, string>;
72
73
  colors: Record<string, string>;
73
74
  glass: Record<string, string>;
74
75
  semantic: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Server as HttpServer } from 'node:http';
2
- export { loadLumenData } from './data.js';
3
2
  export type { LumenData } from './data.js';
3
+ export { loadLumenData } from './data.js';
4
4
  export { createLumenServer } from './server.js';
5
5
  export * from './tools.js';
6
6
  /** Start the Lumen MCP server over stdio. Called by the `lumen-mcp` bin. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAYrD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,cAAc,YAAY,CAAA;AAE1B,4EAA4E;AAC5E,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAKlD,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,EAAE,GAAG,CAAA;CACT;AAoDD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAC5B,UAAS,mBAAwB,KAChC,OAAO,CAAC,kBAAkB,CA+F5B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAYrD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,cAAc,YAAY,CAAA;AAE1B,4EAA4E;AAC5E,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAKlD,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,EAAE,GAAG,CAAA;CACT;AAmDD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAC5B,UAAS,mBAAwB,KAChC,OAAO,CAAC,kBAAkB,CA+F5B,CAAA"}
package/dist/index.js CHANGED
@@ -111,7 +111,7 @@ export const startLumenMcpHttp = async (options = {}) => {
111
111
  await server.close();
112
112
  }));
113
113
  await new Promise((resolve, reject) => {
114
- httpServer.close((error) => {
114
+ httpServer.close(error => {
115
115
  if (error)
116
116
  reject(error);
117
117
  else
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAA;AA2JrF,eAAO,MAAM,iBAAiB,QAAO,SAgTpC,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAA;AA2JrF,eAAO,MAAM,iBAAiB,QAAO,SAmQpC,CAAA"}
package/dist/server.js CHANGED
@@ -46,6 +46,7 @@ const searchOutputSchema = z.strictObject({
46
46
  });
47
47
  const tokensOutputSchema = z.strictObject({
48
48
  tokens: z.strictObject({
49
+ chart: z.record(z.string(), z.string().trim()),
49
50
  colors: z.record(z.string(), z.string().trim()),
50
51
  glass: z.record(z.string(), z.string().trim()),
51
52
  semantic: z.array(z.string().trim()),
@@ -101,9 +102,9 @@ const diagnosticsOutputSchema = z.strictObject({
101
102
  }),
102
103
  status: z.enum(['healthy', 'issues'])
103
104
  });
104
- const structuredData = (data) => typeof data === 'object' && data !== null
105
- ? data
106
- : { value: data };
105
+ const structuredData = (data) => typeof data === 'object' && data !== null ?
106
+ data :
107
+ { value: data };
107
108
  const toMcpResult = (result) => ({
108
109
  content: [{ text: result.text, type: 'text' }],
109
110
  isError: result.isError ?? false,
@@ -138,7 +139,7 @@ export const createLumenServer = () => {
138
139
  .meta({ description: 'Only list components that belong to this recipe.' })
139
140
  }),
140
141
  outputSchema: listComponentsOutputSchema
141
- }, (args) => toMcpResult(listComponents(args)));
142
+ }, args => toMcpResult(listComponents(args)));
142
143
  server.registerTool('lumen_get_component', {
143
144
  annotations: readOnlyAnnotations,
144
145
  description: 'Get framework-specific Lumen component usage: description, imports, styles, typed props or ' +
@@ -156,7 +157,7 @@ export const createLumenServer = () => {
156
157
  .meta({ description: 'Component name, for example "Button" or "data-table".' })
157
158
  }),
158
159
  outputSchema: componentOutputSchema
159
- }, (args) => toMcpResult(getComponent(args)));
160
+ }, args => toMcpResult(getComponent(args)));
160
161
  server.registerTool('lumen_get_recipe', {
161
162
  annotations: readOnlyAnnotations,
162
163
  description: 'Get a Lumen recipe or component set with its purpose, categories, components, files, and ' +
@@ -169,7 +170,7 @@ export const createLumenServer = () => {
169
170
  .meta({ description: 'Recipe name, for example "scheduler" or "advanced-fields".' })
170
171
  }),
171
172
  outputSchema: recipeOutputSchema
172
- }, (args) => toMcpResult(getRecipe(args)));
173
+ }, args => toMcpResult(getRecipe(args)));
173
174
  server.registerTool('lumen_search', {
174
175
  annotations: readOnlyAnnotations,
175
176
  description: 'Rank natural-language matches across descriptions, categories, curated collections, ' +
@@ -185,7 +186,7 @@ export const createLumenServer = () => {
185
186
  .meta({ description: 'Keyword or natural-language use-case to search for.' })
186
187
  }),
187
188
  outputSchema: searchOutputSchema
188
- }, (args) => toMcpResult(search(args)));
189
+ }, args => toMcpResult(search(args)));
189
190
  server.registerTool('lumen_get_meta', {
190
191
  annotations: readOnlyAnnotations,
191
192
  description: 'Return snapshot provenance: server and package versions, schema version, component count, ' +
@@ -210,7 +211,7 @@ export const createLumenServer = () => {
210
211
  .meta({ description: 'Optional previous catalog hash for a fast unchanged check.' })
211
212
  }),
212
213
  outputSchema: catalogDiffOutputSchema
213
- }, (args) => toMcpResult(diffCatalog(args)));
214
+ }, args => toMcpResult(diffCatalog(args)));
214
215
  server.registerTool('lumen_diagnose', {
215
216
  annotations: readOnlyAnnotations,
216
217
  description: 'Run deterministic snapshot integrity checks and report framework coverage. Useful when testing a new MCP connection.',
@@ -232,19 +233,19 @@ export const createLumenServer = () => {
232
233
  server.registerResource('lumen-meta', 'lumen://meta', {
233
234
  description: 'Lumen MCP snapshot provenance and package versions.',
234
235
  mimeType: 'application/json'
235
- }, (uri) => jsonResource(uri, getMeta().data));
236
+ }, uri => jsonResource(uri, getMeta().data));
236
237
  server.registerResource('lumen-catalog-manifest', 'lumen://catalog-manifest', {
237
238
  description: 'Stable component and recipe fingerprints for catalog change detection.',
238
239
  mimeType: 'application/json'
239
- }, (uri) => jsonResource(uri, getCatalogManifest().data));
240
+ }, uri => jsonResource(uri, getCatalogManifest().data));
240
241
  server.registerResource('lumen-diagnostics', 'lumen://diagnostics', {
241
242
  description: 'Lumen MCP snapshot integrity checks and framework coverage.',
242
243
  mimeType: 'application/json'
243
- }, (uri) => jsonResource(uri, diagnose().data));
244
+ }, uri => jsonResource(uri, diagnose().data));
244
245
  server.registerResource('lumen-rules', 'lumen://rules', {
245
246
  description: 'Lumen agent rules (llms.txt).',
246
247
  mimeType: 'text/markdown'
247
- }, (uri) => ({
248
+ }, uri => ({
248
249
  contents: [{
249
250
  mimeType: 'text/markdown',
250
251
  text: getRules().text,
@@ -254,20 +255,20 @@ export const createLumenServer = () => {
254
255
  server.registerResource('lumen-tokens', 'lumen://tokens', {
255
256
  description: 'Structured Lumen design tokens.',
256
257
  mimeType: 'application/json'
257
- }, (uri) => jsonResource(uri, getTokens().data));
258
+ }, uri => jsonResource(uri, getTokens().data));
258
259
  server.registerResource('lumen-components', 'lumen://components', {
259
260
  description: 'Compact structured component catalog.',
260
261
  mimeType: 'application/json'
261
- }, (uri) => jsonResource(uri, listComponents().data));
262
+ }, uri => jsonResource(uri, listComponents().data));
262
263
  server.registerResource('lumen-component', new ResourceTemplate('lumen://components/{name}', {
263
264
  complete: {
264
- name: (value) => data.components
265
- .map((component) => component.name)
266
- .filter((name) => name.toLowerCase().includes(value.toLowerCase()))
265
+ name: value => data.components
266
+ .map(component => component.name)
267
+ .filter(name => name.toLowerCase().includes(value.toLowerCase()))
267
268
  .slice(0, 30)
268
269
  },
269
270
  list: () => ({
270
- resources: data.components.map((component) => ({
271
+ resources: data.components.map(component => ({
271
272
  description: component.description,
272
273
  mimeType: 'application/json',
273
274
  name: component.name,
@@ -284,12 +285,12 @@ export const createLumenServer = () => {
284
285
  });
285
286
  server.registerResource('lumen-recipe', new ResourceTemplate('lumen://recipes/{name}', {
286
287
  complete: {
287
- name: (value) => data.recipes
288
- .map((recipe) => recipe.name)
289
- .filter((name) => name.includes(value.toLowerCase()))
288
+ name: value => data.recipes
289
+ .map(recipe => recipe.name)
290
+ .filter(name => name.includes(value.toLowerCase()))
290
291
  },
291
292
  list: () => ({
292
- resources: data.recipes.map((recipe) => ({
293
+ resources: data.recipes.map(recipe => ({
293
294
  description: recipe.description,
294
295
  mimeType: 'application/json',
295
296
  name: recipe.name,
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,cAAc,EAEd,mBAAmB,EACpB,MAAM,WAAW,CAAA;AAGlB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AACD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,CAAA;AAE5C,MAAM,WAAW,eAAe,CAAC,IAAI,GAAG,OAAO;IAC7C,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;IAC7B,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAoED,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,sBAAsB,GAAG,SAQ3B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,mBAAmB,GAAG,SAIxB,CAAA;AAsKD,eAAO,MAAM,cAAc,GACzB,OAAM;IACJ,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvB,EACN,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAoDnE,CAAA;AA8BD,QAAA,MAAM,eAAe,GACnB,WAAW,sBAAsB,EACjC,WAAW,cAAc,EACzB,QAAQ,oBAAoB;;;;;;;;;;;;;sBA9S5B,CAAC;;;;;;uBAGe,CAAC;gBAAiB,CAAC;;mBAK9B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA7EI,MAAM;iBACH,MAAM,EAAE;iBACR,MAAM;gBACP,cAAc,EAAE;WACrB,MAAM;UACP,MAAM;aACH,MAAM,EAAE;;;;;;;;;;;;cANP,MAAM;iBACH,MAAM,EAAE;iBACR,MAAM;gBACP,cAAc,EAAE;WACrB,MAAM;UACP,MAAM;aACH,MAAM,EAAE;CAgZlB,CAAA;AA+ID,eAAO,MAAM,YAAY,GACvB,MAAM;IACJ,MAAM,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAA;IACzC,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACnC,IAAI,EAAE,MAAM,CAAA;CACb,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;IAC9C,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAqCA,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,MAAM;IAAE,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC/D,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,mBAAmB,CAAA;CAC7B,CAoCA,CAAA;AAED,eAAO,MAAM,MAAM,GACjB,MAAM;IACJ,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;CACd,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;CACd,CA6CA,CAAA;AAED,eAAO,MAAM,OAAO,GAClB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;CAAE,CAc5C,CAAA;AAkCF,eAAO,MAAM,kBAAkB,GAC7B,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;CACtB,CAcC,CAAA;AAEF,eAAO,MAAM,WAAW,GACtB,MAAM;IACJ,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,UAAU,EAAE,cAAc,CAAA;IAC1B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,OAAO,EAAE,cAAc,CAAA;IACvB,SAAS,EAAE,OAAO,CAAA;CACnB,CA0CA,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,OAAM,SAA2B,KAChC,eAAe,CAAC;IACjB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAAE,CAAA;IACpE,iBAAiB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IACjD,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAA;CAC7B,CA2EA,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;CAAE,CAiCjD,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAanC,CAAA"}
package/dist/tools.js CHANGED
@@ -1,21 +1,44 @@
1
1
  import { loadLumenData } from './data.js';
2
- const normalize = (value) => value.replaceAll(/([a-z0-9])([A-Z])/g, '$1-$2').replaceAll(/[\s_]+/g, '-').toLowerCase();
3
- const tokenize = (value) => normalize(value).split(/[^a-z0-9]+/).filter(Boolean);
2
+ const normalize = (value) => value
3
+ .replaceAll(/([a-z0-9])([A-Z])/g, '$1-$2')
4
+ .replaceAll(/[\s_]+/g, '-')
5
+ .toLowerCase();
6
+ const tokenize = (value) => normalize(value)
7
+ .split(/[^a-z0-9]+/)
8
+ .filter(Boolean);
4
9
  const searchStopWords = new Set([
5
- 'a', 'accessibility', 'accessible', 'admin', 'an', 'and', 'app', 'application', 'component', 'for',
6
- 'in', 'lumen', 'not', 'of', 'or', 'the', 'to', 'ui', 'with'
10
+ 'a',
11
+ 'accessibility',
12
+ 'accessible',
13
+ 'admin',
14
+ 'an',
15
+ 'and',
16
+ 'app',
17
+ 'application',
18
+ 'component',
19
+ 'for',
20
+ 'in',
21
+ 'lumen',
22
+ 'not',
23
+ 'of',
24
+ 'or',
25
+ 'the',
26
+ 'to',
27
+ 'ui',
28
+ 'with'
7
29
  ]);
8
30
  const searchTermAliases = {
9
31
  booking: ['booking', 'schedule', 'calendar', 'appointment', 'date'],
10
32
  dark: ['dark', 'theme'],
11
33
  dashboard: ['dashboard', 'data-table', 'sidebar', 'chart', 'stat', 'metric'],
12
34
  mode: ['mode', 'theme'],
35
+ paginated: ['paginated', 'pagination'],
13
36
  pagination: ['pagination', 'paginated'],
14
37
  sortable: ['sortable', 'sort']
15
38
  };
16
39
  const meaningfulSearchTerms = (value) => {
17
40
  const terms = tokenize(value);
18
- const meaningful = terms.filter((term) => !searchStopWords.has(term));
41
+ const meaningful = terms.filter(term => !searchStopWords.has(term));
19
42
  return meaningful.length > 0 ? meaningful : terms;
20
43
  };
21
44
  const availableFrameworks = (component) => Object.entries(component.frameworks)
@@ -28,17 +51,17 @@ const componentSummary = (component) => ({
28
51
  frameworks: availableFrameworks(component),
29
52
  kebab: component.kebab,
30
53
  name: component.name,
31
- recipes: component.recipes.map((recipe) => recipe.name)
54
+ recipes: component.recipes.map(recipe => recipe.name)
32
55
  });
33
56
  export const resolveComponent = (name, data = loadLumenData()) => {
34
57
  const target = normalize(name);
35
- return data.components.find((component) => component.name === name) ??
36
- data.components.find((component) => component.kebab === target) ??
37
- data.components.find((component) => normalize(component.name) === target);
58
+ return (data.components.find(component => component.name === name) ??
59
+ data.components.find(component => component.kebab === target) ??
60
+ data.components.find(component => normalize(component.name) === target));
38
61
  };
39
62
  export const resolveRecipe = (name, data = loadLumenData()) => {
40
63
  const target = normalize(name);
41
- return data.recipes.find((recipe) => normalize(recipe.name) === target);
64
+ return data.recipes.find(recipe => normalize(recipe.name) === target);
42
65
  };
43
66
  const frameworkBehaviorSearchText = (behavior) => [
44
67
  behavior?.description ?? '',
@@ -51,13 +74,13 @@ const frameworkDetailsSearchText = (framework) => [
51
74
  ...frameworkBehaviorSearchText(framework.behavior),
52
75
  framework.example,
53
76
  framework.propsExtends ?? '',
54
- framework.props.map((prop) => `${prop.name} ${prop.type}`).join(' '),
77
+ framework.props.map(prop => `${prop.name} ${prop.type}`).join(' '),
55
78
  framework.attributes?.join(' ') ?? '',
56
79
  framework.tagName ?? ''
57
80
  ];
58
- const frameworkSearchText = (component, framework) => (framework
59
- ? [Reflect.get(component.frameworkDetails, framework)]
60
- : Object.values(component.frameworkDetails))
81
+ const frameworkSearchText = (component, framework) => (framework ?
82
+ [Reflect.get(component.frameworkDetails, framework)] :
83
+ Object.values(component.frameworkDetails))
61
84
  .flatMap(frameworkDetailsSearchText)
62
85
  .join(' ');
63
86
  const componentSearchText = (component, framework) => [
@@ -66,31 +89,32 @@ const componentSearchText = (component, framework) => [
66
89
  component.description,
67
90
  component.category,
68
91
  component.collections.join(' '),
69
- component.recipes.map((recipe) => recipe.name).join(' '),
92
+ component.recipes.map(recipe => recipe.name).join(' '),
70
93
  component.keywords.join(' '),
71
94
  component.dependencies.join(' '),
72
95
  component.guidance?.when ?? '',
73
96
  component.guidance?.distinction ?? '',
74
97
  component.apiReference
75
- .map((row) => `${row.attribute} ${row.values} ${row.description}`)
98
+ .map(row => `${row.attribute} ${row.values} ${row.description}`)
76
99
  .join(' '),
77
100
  frameworkSearchText(component, framework)
78
101
  ].join(' ');
79
102
  const scoreCandidate = (query, terms, searchableText, primaryName = '') => {
80
103
  const normalizedText = normalize(searchableText);
81
- const matchedTerms = terms.filter((term) => (Reflect.get(searchTermAliases, term) ?? [term]).some((candidate) => normalizedText.includes(candidate)));
104
+ const matchedTerms = terms.filter(term => (Reflect.get(searchTermAliases, term) ?? [term]).some(candidate => normalizedText.includes(candidate)));
82
105
  if (matchedTerms.length === 0)
83
106
  return { matchedTerms, score: 0 };
84
107
  const normalizedQuery = terms.join('-');
85
108
  const normalizedName = normalize(primaryName);
86
109
  const coverage = matchedTerms.length / terms.length;
87
- let score = matchedTerms.reduce((total, term) => total + ((Reflect.get(searchTermAliases, term) ?? [term]).some((candidate) => normalizedName.includes(candidate))
88
- ? 20
89
- : 5), 0);
110
+ let score = matchedTerms.reduce((total, term) => total +
111
+ ((Reflect.get(searchTermAliases, term) ?? [term]).some(candidate => normalizedName.includes(candidate)) ?
112
+ 20 :
113
+ 5), 0);
90
114
  score += Math.round(coverage * 80);
91
115
  score -= (terms.length - matchedTerms.length) * 3;
92
- if (terms.includes(normalizedName))
93
- score += 50;
116
+ if (terms.some(term => (Reflect.get(searchTermAliases, term) ?? [term]).includes(normalizedName)))
117
+ score += 150;
94
118
  if (normalizedText.includes(normalizedQuery))
95
119
  score += 100;
96
120
  if (normalizedName === normalizedQuery)
@@ -130,7 +154,7 @@ const collectSearchResults = (query, terms, data, framework) => {
130
154
  name: token
131
155
  }, query, terms, token);
132
156
  }
133
- for (const line of data.rules.split('\n').filter((rule) => rule.trim())) {
157
+ for (const line of data.rules.split('\n').filter(rule => rule.trim())) {
134
158
  appendSearchResult(results, {
135
159
  description: line.trim(),
136
160
  kind: 'rule',
@@ -144,11 +168,11 @@ export const listComponents = (args = {}, data = loadLumenData()) => {
144
168
  const queryTerms = query ? meaningfulSearchTerms(query) : [];
145
169
  const recipe = args.recipe ? resolveRecipe(args.recipe, data) : undefined;
146
170
  const recipeName = recipe?.name ?? (args.recipe ? normalize(args.recipe) : undefined);
147
- const matches = data.components.filter((component) => {
171
+ const matches = data.components.filter(component => {
148
172
  if (args.framework && !component.frameworks[args.framework])
149
173
  return false;
150
174
  if (recipeName &&
151
- !component.recipes.some((componentRecipe) => normalize(componentRecipe.name) === recipeName))
175
+ !component.recipes.some(componentRecipe => normalize(componentRecipe.name) === recipeName))
152
176
  return false;
153
177
  if (query &&
154
178
  scoreCandidate(query, queryTerms, componentSearchText(component, args.framework), component.name).score === 0)
@@ -162,10 +186,10 @@ export const listComponents = (args = {}, data = loadLumenData()) => {
162
186
  text: 'No components matched the given filters.'
163
187
  };
164
188
  }
165
- const lines = summaries.map((component) => {
166
- const recipeNote = component.recipes.length > 0
167
- ? ` [recipes: ${component.recipes.join(', ')}]`
168
- : '';
189
+ const lines = summaries.map(component => {
190
+ const recipeNote = component.recipes.length > 0 ?
191
+ ` [recipes: ${component.recipes.join(', ')}]` :
192
+ '';
169
193
  return `${component.name} (${component.kebab}) — ${component.description} — ${component.frameworks.join(', ')}${recipeNote}`;
170
194
  });
171
195
  return {
@@ -216,23 +240,23 @@ const componentDetail = (component, framework, detail) => {
216
240
  keyboardInteractions: component.keyboardInteractions,
217
241
  runtimeEvents: component.runtimeEvents
218
242
  };
219
- return detail === 'source'
220
- ? { ...usage, framework: selectedFramework }
221
- : usage;
243
+ return detail === 'source' ?
244
+ { ...usage, framework: selectedFramework } :
245
+ usage;
222
246
  };
223
247
  const formatProps = (framework) => {
224
248
  if (framework.attributes && framework.attributes.length > 0) {
225
- return `Attributes:\n${framework.attributes.map((attribute) => `- ${attribute}`).join('\n')}`;
249
+ return `Attributes:\n${framework.attributes.map(attribute => `- ${attribute}`).join('\n')}`;
226
250
  }
227
251
  if (framework.props.length === 0) {
228
- return framework.propsExtends
229
- ? `Props extend ${framework.propsExtends}; no additional local props were detected.`
230
- : 'No typed props detected.';
252
+ return framework.propsExtends ?
253
+ `Props extend ${framework.propsExtends}; no additional local props were detected.` :
254
+ 'No typed props detected.';
231
255
  }
232
- const lines = framework.props.map((prop) => `- ${prop.name}${prop.optional ? '?' : ''}: ${prop.type}`);
233
- const header = framework.propsExtends
234
- ? `Props (extends ${framework.propsExtends}):`
235
- : 'Props:';
256
+ const lines = framework.props.map(prop => `- ${prop.name}${prop.optional ? '?' : ''}: ${prop.type}`);
257
+ const header = framework.propsExtends ?
258
+ `Props (extends ${framework.propsExtends}):` :
259
+ 'Props:';
236
260
  return `${header}\n${lines.join('\n')}`;
237
261
  };
238
262
  const buildSummarySections = (component, frameworkName, framework) => [
@@ -244,9 +268,9 @@ const buildSummarySections = (component, frameworkName, framework) => [
244
268
  `Import: ${framework.importStatement}`,
245
269
  `Styles: ${framework.styleImport}`,
246
270
  framework.tagName ? `Custom element: <${framework.tagName}>` : '',
247
- component.recipes.length > 0
248
- ? `Recipes: ${component.recipes.map((recipe) => recipe.name).join(', ')}`
249
- : 'Recipes: none'
271
+ component.recipes.length > 0 ?
272
+ `Recipes: ${component.recipes.map(recipe => recipe.name).join(', ')}` :
273
+ 'Recipes: none'
250
274
  ].filter(Boolean);
251
275
  const appendBehaviorSections = (sections, behavior) => {
252
276
  if (!behavior)
@@ -257,10 +281,10 @@ const appendBehaviorSections = (sections, behavior) => {
257
281
  if (behavior.description)
258
282
  sections.push(behavior.description);
259
283
  if (behavior.options && behavior.options.length > 0) {
260
- sections.push('', 'Hook options:', ...behavior.options.map((option) => `- ${option.name}: ${option.type} — ${option.description}`));
284
+ sections.push('', 'Hook options:', ...behavior.options.map(option => `- ${option.name}: ${option.type} — ${option.description}`));
261
285
  }
262
286
  if (behavior.controller && behavior.controller.length > 0) {
263
- sections.push('', 'Controller values:', ...behavior.controller.map((value) => `- ${value.name}: ${value.type} — ${value.description}`));
287
+ sections.push('', 'Controller values:', ...behavior.controller.map(value => `- ${value.name}: ${value.type} — ${value.description}`));
264
288
  }
265
289
  };
266
290
  const appendGuidanceSections = (sections, component) => {
@@ -271,15 +295,15 @@ const appendGuidanceSections = (sections, component) => {
271
295
  }
272
296
  if (component.keyboardInteractions.length > 0) {
273
297
  sections.push('', '## Keyboard interactions');
274
- sections.push(...component.keyboardInteractions.map((interaction) => `- ${interaction.key}: ${interaction.action}`));
298
+ sections.push(...component.keyboardInteractions.map(interaction => `- ${interaction.key}: ${interaction.action}`));
275
299
  }
276
300
  if (component.apiReference.length > 0) {
277
301
  sections.push('', '## API reference');
278
- sections.push(...component.apiReference.map((row) => `- \`${row.attribute}\` ${row.values} — ${row.description}`));
302
+ sections.push(...component.apiReference.map(row => `- \`${row.attribute}\` ${row.values} — ${row.description}`));
279
303
  }
280
304
  if (component.runtimeEvents.length > 0) {
281
305
  sections.push('', '## Runtime events');
282
- sections.push(...component.runtimeEvents.map((event) => `- ${event.name}: ${event.when}`));
306
+ sections.push(...component.runtimeEvents.map(event => `- ${event.name}: ${event.when}`));
283
307
  }
284
308
  };
285
309
  const formatComponentUsage = (component, frameworkName, detail) => {
@@ -335,9 +359,11 @@ export const getRecipe = (args, data = loadLumenData()) => {
335
359
  };
336
360
  }
337
361
  const framework = args.framework ?? 'astro';
338
- const componentLines = (recipe.components ?? []).map((name) => {
362
+ const componentLines = (recipe.components ?? []).map(name => {
339
363
  const component = resolveComponent(name, data);
340
- return component ? `- ${component.name}: ${component.description}` : `- ${name}`;
364
+ return component ?
365
+ `- ${component.name}: ${component.description}` :
366
+ `- ${name}`;
341
367
  });
342
368
  return {
343
369
  data: { found: true, recipe },
@@ -382,7 +408,7 @@ export const search = (args, data = loadLumenData()) => {
382
408
  }
383
409
  return {
384
410
  data: { query, results: shown, total: results.length },
385
- text: `${results.length} match(es) for "${args.query}"${results.length > shown.length ? ` (showing ${shown.length})` : ''}:\n\n${shown.map((result) => `${result.kind}: ${result.name} — ${result.description} [matched: ${result.matchedTerms.join(', ')}]`).join('\n')}`
411
+ text: `${results.length} match(es) for "${args.query}"${results.length > shown.length ? ` (showing ${shown.length})` : ''}:\n\n${shown.map(result => `${result.kind}: ${result.name} — ${result.description} [matched: ${result.matchedTerms.join(', ')}]`).join('\n')}`
386
412
  };
387
413
  };
388
414
  export const getMeta = (data = loadLumenData()) => ({
@@ -402,12 +428,19 @@ const diffManifestSection = (current, baseline) => {
402
428
  const currentNames = Object.keys(current);
403
429
  const baselineNames = Object.keys(baseline);
404
430
  return {
405
- added: currentNames.filter((name) => Reflect.get(baseline, name) === undefined).sort(),
431
+ added: currentNames
432
+ .filter(name => Reflect.get(baseline, name) === undefined)
433
+ .sort(),
406
434
  changed: currentNames
407
- .filter((name) => Reflect.get(baseline, name) !== undefined && Reflect.get(baseline, name) !== Reflect.get(current, name))
435
+ .filter(name => Reflect.get(baseline, name) !== undefined &&
436
+ Reflect.get(baseline, name) !== Reflect.get(current, name))
437
+ .sort(),
438
+ removed: baselineNames
439
+ .filter(name => Reflect.get(current, name) === undefined)
408
440
  .sort(),
409
- removed: baselineNames.filter((name) => Reflect.get(current, name) === undefined).sort(),
410
- unchanged: currentNames.filter((name) => Reflect.get(baseline, name) === Reflect.get(current, name)).sort()
441
+ unchanged: currentNames
442
+ .filter(name => Reflect.get(baseline, name) === Reflect.get(current, name))
443
+ .sort()
411
444
  };
412
445
  };
413
446
  export const getCatalogManifest = (data = loadLumenData()) => ({
@@ -446,23 +479,27 @@ export const diffCatalog = (args, data = loadLumenData()) => {
446
479
  recipes,
447
480
  unchanged
448
481
  },
449
- text: unchanged
450
- ? `The Lumen catalog is unchanged (${data.meta.catalogHash}).`
451
- : [
482
+ text: unchanged ?
483
+ `The Lumen catalog is unchanged (${data.meta.catalogHash}).` :
484
+ [
452
485
  '# Lumen catalog changes',
453
486
  `Current catalog hash: ${data.meta.catalogHash}`,
454
487
  `Changed entries: ${changedCount}`,
455
- `Components — added: ${components.added.length}, changed: ${components.changed.length}, removed: ${components.removed.length}`,
456
- `Recipes — added: ${recipes.added.length}, changed: ${recipes.changed.length}, removed: ${recipes.removed.length}`
488
+ `Components — added: ${components.added.length}, changed: ${components.changed.length}, ` +
489
+ `removed: ${components.removed.length}`,
490
+ `Recipes — added: ${recipes.added.length}, changed: ${recipes.changed.length}, ` +
491
+ `removed: ${recipes.removed.length}`
457
492
  ].join('\n')
458
493
  };
459
494
  };
460
495
  export const diagnose = (data = loadLumenData()) => {
461
- const componentNames = data.components.map((component) => component.name);
496
+ const componentNames = data.components.map(component => component.name);
462
497
  const frameworkCoverage = {
463
- astro: data.components.filter((component) => component.frameworks.astro).length,
464
- elements: data.components.filter((component) => component.frameworks.elements).length,
465
- react: data.components.filter((component) => component.frameworks.react).length
498
+ astro: data.components.filter(component => component.frameworks.astro)
499
+ .length,
500
+ elements: data.components.filter(component => component.frameworks.elements).length,
501
+ react: data.components.filter(component => component.frameworks.react)
502
+ .length
466
503
  };
467
504
  const checks = [
468
505
  {
@@ -473,39 +510,50 @@ export const diagnose = (data = loadLumenData()) => {
473
510
  {
474
511
  message: 'Component names are unique.',
475
512
  name: 'unique-components',
476
- status: new Set(componentNames).size === componentNames.length ? 'pass' : 'fail'
513
+ status: new Set(componentNames).size === componentNames.length ?
514
+ 'pass' :
515
+ 'fail'
477
516
  },
478
517
  {
479
518
  message: 'Every component has a manifest fingerprint.',
480
519
  name: 'component-manifest',
481
- status: componentNames.every((name) => Reflect.get(data.catalogManifest.components, name)) ? 'pass' : 'fail'
520
+ status: componentNames.every(name => Reflect.get(data.catalogManifest.components, name)) ?
521
+ 'pass' :
522
+ 'fail'
482
523
  },
483
524
  {
484
525
  message: 'Every available framework contract has an example and import statement.',
485
526
  name: 'framework-contracts',
486
- status: data.components.every((component) => Object.entries(component.frameworks).every(([framework, available]) => {
527
+ status: data.components.every(component => Object.entries(component.frameworks).every(([framework, available]) => {
487
528
  if (!available)
488
529
  return true;
489
530
  const details = Reflect.get(component.frameworkDetails, framework);
490
- return Boolean(details?.example.trim()) && Boolean(details?.importStatement.trim());
491
- })) ? 'pass' : 'fail'
531
+ return (Boolean(details?.example.trim()) &&
532
+ Boolean(details?.importStatement.trim()));
533
+ })) ?
534
+ 'pass' :
535
+ 'fail'
492
536
  }
493
537
  ];
494
- const status = checks.every((check) => check.status === 'pass') ? 'healthy' : 'issues';
538
+ const status = checks.every(check => check.status === 'pass') ?
539
+ 'healthy' :
540
+ 'issues';
495
541
  return {
496
542
  data: { checks, frameworkCoverage, status },
497
543
  isError: status === 'issues',
498
544
  text: [
499
545
  `# Lumen MCP diagnostics: ${status}`,
500
546
  `Catalog hash: ${data.meta.catalogHash}`,
501
- `Framework coverage — Astro: ${frameworkCoverage.astro}, React: ${frameworkCoverage.react}, Elements: ${frameworkCoverage.elements}`,
547
+ `Framework coverage — Astro: ${frameworkCoverage.astro}, ` +
548
+ `React: ${frameworkCoverage.react}, Elements: ${frameworkCoverage.elements}`,
502
549
  '',
503
- ...checks.map((check) => `- ${check.status.toUpperCase()} ${check.name}: ${check.message}`)
550
+ ...checks.map(check => `- ${check.status.toUpperCase()} ${check.name}: ${check.message}`)
504
551
  ].join('\n')
505
552
  };
506
553
  };
507
554
  export const getTokens = (data = loadLumenData()) => {
508
555
  const { tokens } = data;
556
+ const chartLines = Object.entries(tokens.chart).map(([name, value]) => `- ${name}: ${value}`);
509
557
  const colorLines = Object.entries(tokens.colors).map(([name, value]) => `- ${name}: hsl(${value})`);
510
558
  const glassLines = Object.entries(tokens.glass).map(([name, value]) => `- ${name}: ${value}`);
511
559
  const text = [
@@ -513,11 +561,14 @@ export const getTokens = (data = loadLumenData()) => {
513
561
  `Theme attribute: ${tokens.themeAttribute} (values: light, dark)`,
514
562
  '',
515
563
  '## Semantic token names (use as `text-ink`, `bg-surface`, `border-line`, etc.)',
516
- tokens.semantic.map((token) => `- ${token}`).join('\n'),
564
+ tokens.semantic.map(token => `- ${token}`).join('\n'),
517
565
  '',
518
566
  '## Base color values',
519
567
  colorLines.join('\n'),
520
568
  '',
569
+ '## Data visualization tokens',
570
+ chartLines.join('\n'),
571
+ '',
521
572
  '## Glass surface tokens',
522
573
  glassLines.join('\n')
523
574
  ].join('\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@santi020k/lumen-mcp",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -83,8 +83,8 @@
83
83
  "typecheck": "tsc -p tsconfig.json --noEmit",
84
84
  "test": "vitest run --config ../../vitest.config.ts --project mcp",
85
85
  "test:coverage": "vitest run --config ../../vitest.config.ts --project mcp --coverage",
86
- "lint": "eslint . --no-warn-ignored",
87
- "lint:fix": "eslint . --fix --no-warn-ignored",
86
+ "lint": "eslint . --no-warn-ignored --max-warnings=0",
87
+ "lint:fix": "eslint . --fix --no-warn-ignored --max-warnings=0",
88
88
  "clean": "rm -rf dist coverage"
89
89
  }
90
90
  }