@santi020k/lumen-mcp 1.0.0 → 1.2.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 +30 -6
- package/data/lumen-data.json +5412 -111
- package/dist/data.d.ts +36 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +84 -4
- package/dist/tools.d.ts +81 -7
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +238 -22
- package/package.json +3 -3
package/dist/tools.js
CHANGED
|
@@ -53,6 +53,16 @@ const componentSummary = (component) => ({
|
|
|
53
53
|
name: component.name,
|
|
54
54
|
recipes: component.recipes.map(recipe => recipe.name)
|
|
55
55
|
});
|
|
56
|
+
const availableNativePlatforms = (component) => Object.keys(component.implementations);
|
|
57
|
+
const nativeComponentSummary = (component) => ({
|
|
58
|
+
accessibility: component.accessibility,
|
|
59
|
+
category: component.category,
|
|
60
|
+
id: component.id,
|
|
61
|
+
name: component.name,
|
|
62
|
+
platforms: availableNativePlatforms(component),
|
|
63
|
+
summary: component.summary,
|
|
64
|
+
tier: component.tier
|
|
65
|
+
});
|
|
56
66
|
export const resolveComponent = (name, data = loadLumenData()) => {
|
|
57
67
|
const target = normalize(name);
|
|
58
68
|
return (data.components.find(component => component.name === name) ??
|
|
@@ -63,6 +73,14 @@ export const resolveRecipe = (name, data = loadLumenData()) => {
|
|
|
63
73
|
const target = normalize(name);
|
|
64
74
|
return data.recipes.find(recipe => normalize(recipe.name) === target);
|
|
65
75
|
};
|
|
76
|
+
export const resolveNativeComponent = (name, data = loadLumenData()) => {
|
|
77
|
+
const target = normalize(name);
|
|
78
|
+
return data.nativeComponents.find(component => (component.name === name ||
|
|
79
|
+
normalize(component.name) === target ||
|
|
80
|
+
normalize(component.id) === target ||
|
|
81
|
+
Object.values(component.implementations).some(implementation => (normalize(implementation.exportName) === target ||
|
|
82
|
+
normalize(implementation.symbol) === target))));
|
|
83
|
+
};
|
|
66
84
|
const frameworkBehaviorSearchText = (behavior) => [
|
|
67
85
|
behavior?.description ?? '',
|
|
68
86
|
behavior?.hook ?? '',
|
|
@@ -99,6 +117,28 @@ const componentSearchText = (component, framework) => [
|
|
|
99
117
|
.join(' '),
|
|
100
118
|
frameworkSearchText(component, framework)
|
|
101
119
|
].join(' ');
|
|
120
|
+
const nativeImplementationSearchText = (implementation) => [
|
|
121
|
+
implementation.exportName,
|
|
122
|
+
implementation.symbol,
|
|
123
|
+
implementation.packageName,
|
|
124
|
+
implementation.importStatement,
|
|
125
|
+
implementation.api.map(row => (`${row.name} ${row.values} ${row.description}`)).join(' '),
|
|
126
|
+
implementation.example
|
|
127
|
+
].join(' ');
|
|
128
|
+
const nativeComponentSearchText = (component, platform) => [
|
|
129
|
+
component.name,
|
|
130
|
+
component.id,
|
|
131
|
+
component.summary,
|
|
132
|
+
component.category,
|
|
133
|
+
component.contract,
|
|
134
|
+
component.guidance,
|
|
135
|
+
component.accessibility,
|
|
136
|
+
component.tier,
|
|
137
|
+
platform ?? '',
|
|
138
|
+
...(platform ?
|
|
139
|
+
[component.implementations[platform]].filter((implementation) => Boolean(implementation)) :
|
|
140
|
+
Object.values(component.implementations)).map(nativeImplementationSearchText)
|
|
141
|
+
].join(' ');
|
|
102
142
|
const scoreCandidate = (query, terms, searchableText, primaryName = '') => {
|
|
103
143
|
const normalizedText = normalize(searchableText);
|
|
104
144
|
const matchedTerms = terms.filter(term => (Reflect.get(searchTermAliases, term) ?? [term]).some(candidate => normalizedText.includes(candidate)));
|
|
@@ -121,14 +161,19 @@ const scoreCandidate = (query, terms, searchableText, primaryName = '') => {
|
|
|
121
161
|
score += 500;
|
|
122
162
|
return { matchedTerms, score };
|
|
123
163
|
};
|
|
124
|
-
const appendSearchResult = (results, candidate, query, terms, searchableText) => {
|
|
164
|
+
const appendSearchResult = (results, candidate, query, terms, searchableText, scoreAdjustment = 0) => {
|
|
125
165
|
const match = scoreCandidate(query, terms, searchableText, candidate.kind === 'rule' ? '' : candidate.name);
|
|
126
|
-
if (match.score > 0)
|
|
127
|
-
results.push({
|
|
166
|
+
if (match.score > 0) {
|
|
167
|
+
results.push({
|
|
168
|
+
...candidate,
|
|
169
|
+
...match,
|
|
170
|
+
score: Math.max(1, match.score + scoreAdjustment)
|
|
171
|
+
});
|
|
172
|
+
}
|
|
128
173
|
};
|
|
129
|
-
const
|
|
174
|
+
const collectComponentSearchResults = (query, terms, data, framework, platform) => {
|
|
130
175
|
const results = [];
|
|
131
|
-
for (const component of data.components) {
|
|
176
|
+
for (const component of platform ? [] : data.components) {
|
|
132
177
|
if (framework && !Reflect.get(component.frameworks, framework))
|
|
133
178
|
continue;
|
|
134
179
|
appendSearchResult(results, {
|
|
@@ -139,6 +184,23 @@ const collectSearchResults = (query, terms, data, framework) => {
|
|
|
139
184
|
name: component.name
|
|
140
185
|
}, query, terms, componentSearchText(component, framework));
|
|
141
186
|
}
|
|
187
|
+
if (!platform || framework)
|
|
188
|
+
return results;
|
|
189
|
+
for (const component of data.nativeComponents) {
|
|
190
|
+
if (!component.implementations[platform])
|
|
191
|
+
continue;
|
|
192
|
+
appendSearchResult(results, {
|
|
193
|
+
category: component.category,
|
|
194
|
+
description: component.summary,
|
|
195
|
+
kind: 'native-component',
|
|
196
|
+
name: component.name,
|
|
197
|
+
platforms: availableNativePlatforms(component)
|
|
198
|
+
}, query, terms, nativeComponentSearchText(component, platform));
|
|
199
|
+
}
|
|
200
|
+
return results;
|
|
201
|
+
};
|
|
202
|
+
const collectReferenceSearchResults = (query, terms, data) => {
|
|
203
|
+
const results = [];
|
|
142
204
|
for (const recipe of data.recipes) {
|
|
143
205
|
appendSearchResult(results, {
|
|
144
206
|
category: recipe.categories.join(', '),
|
|
@@ -163,6 +225,10 @@ const collectSearchResults = (query, terms, data, framework) => {
|
|
|
163
225
|
}
|
|
164
226
|
return results;
|
|
165
227
|
};
|
|
228
|
+
const collectSearchResults = (query, terms, data, framework, platform) => [
|
|
229
|
+
...collectComponentSearchResults(query, terms, data, framework, platform),
|
|
230
|
+
...collectReferenceSearchResults(query, terms, data)
|
|
231
|
+
];
|
|
166
232
|
export const listComponents = (args = {}, data = loadLumenData()) => {
|
|
167
233
|
const query = args.query?.trim();
|
|
168
234
|
const queryTerms = query ? meaningfulSearchTerms(query) : [];
|
|
@@ -348,6 +414,101 @@ export const getComponent = (args, data = loadLumenData()) => {
|
|
|
348
414
|
text: formatComponentUsage(component, framework, detail)
|
|
349
415
|
};
|
|
350
416
|
};
|
|
417
|
+
export const listNativeComponents = (args = {}, data = loadLumenData()) => {
|
|
418
|
+
const query = args.query?.trim();
|
|
419
|
+
const terms = query ? meaningfulSearchTerms(query) : [];
|
|
420
|
+
const components = data.nativeComponents.filter(component => ((!args.platform || Boolean(component.implementations[args.platform])) &&
|
|
421
|
+
(!query || scoreCandidate(query, terms, nativeComponentSearchText(component, args.platform), component.name).score > 0))).map(nativeComponentSummary);
|
|
422
|
+
return {
|
|
423
|
+
data: { components, count: components.length },
|
|
424
|
+
text: components.length === 0 ?
|
|
425
|
+
'No native components matched the given filters.' :
|
|
426
|
+
`${components.length} native component(s):\n\n${components.map(component => (`${component.name} (${component.id}) — ${component.summary} — ${component.platforms.join(', ')}`)).join('\n')}`
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
const nativeComponentDetail = (component, platform, detail, data) => {
|
|
430
|
+
const implementation = component.implementations[platform];
|
|
431
|
+
if (!implementation)
|
|
432
|
+
return undefined;
|
|
433
|
+
const common = {
|
|
434
|
+
...nativeComponentSummary(component),
|
|
435
|
+
contract: component.contract,
|
|
436
|
+
guidance: component.guidance,
|
|
437
|
+
platform
|
|
438
|
+
};
|
|
439
|
+
if (detail === 'summary') {
|
|
440
|
+
return {
|
|
441
|
+
...common,
|
|
442
|
+
implementation: {
|
|
443
|
+
exportName: implementation.exportName,
|
|
444
|
+
packageName: implementation.packageName,
|
|
445
|
+
symbol: implementation.symbol
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
const usage = { ...common, implementation };
|
|
450
|
+
return detail === 'source' ?
|
|
451
|
+
{
|
|
452
|
+
...usage,
|
|
453
|
+
source: data.nativeSources[platform][implementation.sourceFile]
|
|
454
|
+
} :
|
|
455
|
+
usage;
|
|
456
|
+
};
|
|
457
|
+
const formatNativeComponent = (component, platform, detail, data) => {
|
|
458
|
+
const implementation = component.implementations[platform];
|
|
459
|
+
if (!implementation)
|
|
460
|
+
return '';
|
|
461
|
+
const sections = [
|
|
462
|
+
`# ${component.name}`,
|
|
463
|
+
component.summary,
|
|
464
|
+
`Category: ${component.category}`,
|
|
465
|
+
`Tier: ${component.tier}`,
|
|
466
|
+
`Platform: ${platform}`,
|
|
467
|
+
`Available platforms: ${availableNativePlatforms(component).join(', ')}`,
|
|
468
|
+
`Package: ${implementation.packageName}`,
|
|
469
|
+
`Install: ${implementation.install}`,
|
|
470
|
+
`Import: ${implementation.importStatement}`,
|
|
471
|
+
`Setup: ${implementation.setup}`,
|
|
472
|
+
'',
|
|
473
|
+
'## Accessibility',
|
|
474
|
+
component.accessibility,
|
|
475
|
+
'',
|
|
476
|
+
'## Contract',
|
|
477
|
+
component.contract,
|
|
478
|
+
'',
|
|
479
|
+
'## Guidance',
|
|
480
|
+
component.guidance
|
|
481
|
+
];
|
|
482
|
+
if (detail === 'summary')
|
|
483
|
+
return sections.join('\n');
|
|
484
|
+
if (implementation.api.length > 0) {
|
|
485
|
+
sections.push('', '## API', ...implementation.api.map(row => (`- \`${row.name}\` ${row.values} (default: ${row.defaultValue}) — ${row.description}`)));
|
|
486
|
+
}
|
|
487
|
+
sections.push('', '## Example', `\`\`\`${implementation.language}`, implementation.example, '```');
|
|
488
|
+
if (detail === 'source') {
|
|
489
|
+
sections.push('', `## Reference source (${implementation.sourceFile})`, `\`\`\`${implementation.language}`, data.nativeSources[platform][implementation.sourceFile]?.trimEnd() ?? '', '```');
|
|
490
|
+
}
|
|
491
|
+
return sections.join('\n');
|
|
492
|
+
};
|
|
493
|
+
export const getNativeComponent = (args, data = loadLumenData()) => {
|
|
494
|
+
const component = resolveNativeComponent(args.name, data);
|
|
495
|
+
if (!component) {
|
|
496
|
+
const message = `Unknown native component "${args.name}". Use lumen_list_native_components to see available names.`;
|
|
497
|
+
return { data: { found: false, message }, isError: true, text: message };
|
|
498
|
+
}
|
|
499
|
+
if (!component.implementations[args.platform]) {
|
|
500
|
+
const message = `${component.name} is not available for ${args.platform}. Available platforms: ${availableNativePlatforms(component).join(', ')}.`;
|
|
501
|
+
return { data: { found: false, message }, isError: true, text: message };
|
|
502
|
+
}
|
|
503
|
+
const detail = args.detail ?? 'usage';
|
|
504
|
+
return {
|
|
505
|
+
data: {
|
|
506
|
+
component: nativeComponentDetail(component, args.platform, detail, data),
|
|
507
|
+
found: true
|
|
508
|
+
},
|
|
509
|
+
text: formatNativeComponent(component, args.platform, detail, data)
|
|
510
|
+
};
|
|
511
|
+
};
|
|
351
512
|
export const getRecipe = (args, data = loadLumenData()) => {
|
|
352
513
|
const recipe = resolveRecipe(args.name, data);
|
|
353
514
|
if (!recipe) {
|
|
@@ -389,12 +550,13 @@ export const search = (args, data = loadLumenData()) => {
|
|
|
389
550
|
};
|
|
390
551
|
}
|
|
391
552
|
const limit = Math.max(1, Math.min(args.limit ?? 20, 100));
|
|
392
|
-
const results = collectSearchResults(query, meaningfulSearchTerms(query), data, args.framework);
|
|
553
|
+
const results = collectSearchResults(query, meaningfulSearchTerms(query), data, args.framework, args.platform);
|
|
393
554
|
const kindPriority = {
|
|
394
555
|
component: 0,
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
556
|
+
'native-component': 1,
|
|
557
|
+
recipe: 2,
|
|
558
|
+
rule: 4,
|
|
559
|
+
token: 3
|
|
398
560
|
};
|
|
399
561
|
results.sort((left, right) => right.score - left.score ||
|
|
400
562
|
kindPriority[left.kind] - kindPriority[right.kind] ||
|
|
@@ -418,7 +580,8 @@ export const getMeta = (data = loadLumenData()) => ({
|
|
|
418
580
|
`Server version: ${data.meta.serverVersion}`,
|
|
419
581
|
`Schema version: ${data.meta.schemaVersion}`,
|
|
420
582
|
`Catalog hash: ${data.meta.catalogHash}`,
|
|
421
|
-
`
|
|
583
|
+
`Web components: ${data.meta.componentCount}`,
|
|
584
|
+
`Native components: ${data.meta.nativeComponentCount}`,
|
|
422
585
|
'',
|
|
423
586
|
'## Package versions',
|
|
424
587
|
...Object.entries(data.meta.packageVersions).map(([name, version]) => `- ${name}: ${version}`)
|
|
@@ -453,6 +616,7 @@ export const getCatalogManifest = (data = loadLumenData()) => ({
|
|
|
453
616
|
'# Lumen catalog manifest',
|
|
454
617
|
`Catalog hash: ${data.meta.catalogHash}`,
|
|
455
618
|
`Components: ${Object.keys(data.catalogManifest.components).length}`,
|
|
619
|
+
`Native components: ${Object.keys(data.catalogManifest.nativeComponents ?? {}).length}`,
|
|
456
620
|
`Recipes: ${Object.keys(data.catalogManifest.recipes).length}`,
|
|
457
621
|
'',
|
|
458
622
|
'Keep this structured result and pass its manifest to lumen_diff_catalog after an MCP update.'
|
|
@@ -461,10 +625,14 @@ export const getCatalogManifest = (data = loadLumenData()) => ({
|
|
|
461
625
|
export const diffCatalog = (args, data = loadLumenData()) => {
|
|
462
626
|
const components = diffManifestSection(data.catalogManifest.components, args.baseline.components);
|
|
463
627
|
const recipes = diffManifestSection(data.catalogManifest.recipes, args.baseline.recipes);
|
|
628
|
+
const nativeComponents = diffManifestSection(data.catalogManifest.nativeComponents ?? {}, args.baseline.nativeComponents ?? {});
|
|
464
629
|
const changedCount = [
|
|
465
630
|
...components.added,
|
|
466
631
|
...components.changed,
|
|
467
632
|
...components.removed,
|
|
633
|
+
...nativeComponents.added,
|
|
634
|
+
...nativeComponents.changed,
|
|
635
|
+
...nativeComponents.removed,
|
|
468
636
|
...recipes.added,
|
|
469
637
|
...recipes.changed,
|
|
470
638
|
...recipes.removed
|
|
@@ -476,6 +644,7 @@ export const diffCatalog = (args, data = loadLumenData()) => {
|
|
|
476
644
|
data: {
|
|
477
645
|
components,
|
|
478
646
|
currentCatalogHash: data.meta.catalogHash,
|
|
647
|
+
nativeComponents,
|
|
479
648
|
recipes,
|
|
480
649
|
unchanged
|
|
481
650
|
},
|
|
@@ -487,21 +656,16 @@ export const diffCatalog = (args, data = loadLumenData()) => {
|
|
|
487
656
|
`Changed entries: ${changedCount}`,
|
|
488
657
|
`Components — added: ${components.added.length}, changed: ${components.changed.length}, ` +
|
|
489
658
|
`removed: ${components.removed.length}`,
|
|
659
|
+
`Native components — added: ${nativeComponents.added.length}, changed: ${nativeComponents.changed.length}, ` +
|
|
660
|
+
`removed: ${nativeComponents.removed.length}`,
|
|
490
661
|
`Recipes — added: ${recipes.added.length}, changed: ${recipes.changed.length}, ` +
|
|
491
662
|
`removed: ${recipes.removed.length}`
|
|
492
663
|
].join('\n')
|
|
493
664
|
};
|
|
494
665
|
};
|
|
495
|
-
|
|
666
|
+
const webDiagnosticChecks = (data) => {
|
|
496
667
|
const componentNames = data.components.map(component => component.name);
|
|
497
|
-
|
|
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
|
|
503
|
-
};
|
|
504
|
-
const checks = [
|
|
668
|
+
return [
|
|
505
669
|
{
|
|
506
670
|
message: `${data.components.length} component records match metadata.`,
|
|
507
671
|
name: 'component-count',
|
|
@@ -528,24 +692,76 @@ export const diagnose = (data = loadLumenData()) => {
|
|
|
528
692
|
if (!available)
|
|
529
693
|
return true;
|
|
530
694
|
const details = Reflect.get(component.frameworkDetails, framework);
|
|
531
|
-
return
|
|
532
|
-
Boolean(details?.importStatement.trim()));
|
|
695
|
+
return Boolean(details?.example.trim()) && Boolean(details?.importStatement.trim());
|
|
533
696
|
})) ?
|
|
534
697
|
'pass' :
|
|
535
698
|
'fail'
|
|
536
699
|
}
|
|
537
700
|
];
|
|
701
|
+
};
|
|
702
|
+
const nativeDiagnosticChecks = (data) => {
|
|
703
|
+
const nativeComponentNames = data.nativeComponents.map(component => component.name);
|
|
704
|
+
return [
|
|
705
|
+
{
|
|
706
|
+
message: `${data.nativeComponents.length} native component records match metadata.`,
|
|
707
|
+
name: 'native-component-count',
|
|
708
|
+
status: data.nativeComponents.length === data.meta.nativeComponentCount ?
|
|
709
|
+
'pass' :
|
|
710
|
+
'fail'
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
message: 'Native component names and ids are unique.',
|
|
714
|
+
name: 'unique-native-components',
|
|
715
|
+
status: new Set(nativeComponentNames).size === nativeComponentNames.length &&
|
|
716
|
+
new Set(data.nativeComponents.map(component => component.id)).size === data.nativeComponents.length ?
|
|
717
|
+
'pass' :
|
|
718
|
+
'fail'
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
message: 'Every native component has a manifest fingerprint.',
|
|
722
|
+
name: 'native-component-manifest',
|
|
723
|
+
status: nativeComponentNames.every(name => (Reflect.get(data.catalogManifest.nativeComponents ?? {}, name))) ?
|
|
724
|
+
'pass' :
|
|
725
|
+
'fail'
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
message: 'Every native implementation has usage, import, and bundled reference source.',
|
|
729
|
+
name: 'native-contracts',
|
|
730
|
+
status: data.nativeComponents.every(component => (Object.entries(component.implementations).every(([platform, implementation]) => (Boolean(implementation.example.trim()) &&
|
|
731
|
+
Boolean(implementation.importStatement.trim()) &&
|
|
732
|
+
Boolean(data.nativeSources[platform][implementation.sourceFile]?.trim()))))) ?
|
|
733
|
+
'pass' :
|
|
734
|
+
'fail'
|
|
735
|
+
}
|
|
736
|
+
];
|
|
737
|
+
};
|
|
738
|
+
export const diagnose = (data = loadLumenData()) => {
|
|
739
|
+
const frameworkCoverage = {
|
|
740
|
+
astro: data.components.filter(component => component.frameworks.astro)
|
|
741
|
+
.length,
|
|
742
|
+
elements: data.components.filter(component => component.frameworks.elements).length,
|
|
743
|
+
react: data.components.filter(component => component.frameworks.react)
|
|
744
|
+
.length
|
|
745
|
+
};
|
|
746
|
+
const nativeCoverage = {
|
|
747
|
+
compose: data.nativeComponents.filter(component => component.implementations.compose).length,
|
|
748
|
+
'react-native': data.nativeComponents.filter(component => component.implementations['react-native']).length,
|
|
749
|
+
swiftui: data.nativeComponents.filter(component => component.implementations.swiftui).length
|
|
750
|
+
};
|
|
751
|
+
const checks = [...webDiagnosticChecks(data), ...nativeDiagnosticChecks(data)];
|
|
538
752
|
const status = checks.every(check => check.status === 'pass') ?
|
|
539
753
|
'healthy' :
|
|
540
754
|
'issues';
|
|
541
755
|
return {
|
|
542
|
-
data: { checks, frameworkCoverage, status },
|
|
756
|
+
data: { checks, frameworkCoverage, nativeCoverage, status },
|
|
543
757
|
isError: status === 'issues',
|
|
544
758
|
text: [
|
|
545
759
|
`# Lumen MCP diagnostics: ${status}`,
|
|
546
760
|
`Catalog hash: ${data.meta.catalogHash}`,
|
|
547
761
|
`Framework coverage — Astro: ${frameworkCoverage.astro}, ` +
|
|
548
762
|
`React: ${frameworkCoverage.react}, Elements: ${frameworkCoverage.elements}`,
|
|
763
|
+
`Native coverage — React Native: ${nativeCoverage['react-native']}, ` +
|
|
764
|
+
`SwiftUI: ${nativeCoverage.swiftui}, Compose: ${nativeCoverage.compose}`,
|
|
549
765
|
'',
|
|
550
766
|
...checks.map(check => `- ${check.status.toUpperCase()} ${check.name}: ${check.message}`)
|
|
551
767
|
].join('\n')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@santi020k/lumen-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"lumen-mcp-http": "./bin/lumen-mcp-http.mjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
37
37
|
"zod": "^4.4.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"url": "https://github.com/santi020k/lumen.git",
|
|
53
53
|
"directory": "packages/mcp"
|
|
54
54
|
},
|
|
55
|
-
"homepage": "https://lumen.santi020k.com",
|
|
55
|
+
"homepage": "https://lumen.santi020k.com/docs/mcp",
|
|
56
56
|
"bugs": {
|
|
57
57
|
"url": "https://github.com/santi020k/lumen/issues"
|
|
58
58
|
},
|