@totemsdk/mcp-server 0.1.0 → 0.3.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 +9 -2
- package/data/sdk-index.json +1 -0
- package/dist/index-store.d.ts +18 -0
- package/dist/index-store.js +38 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +104 -101
- package/dist/indexer.d.ts +27 -1
- package/dist/indexer.js +358 -116
- package/dist/resources.d.ts +4 -0
- package/dist/resources.js +249 -3
- package/dist/template-catalog.d.ts +12 -0
- package/dist/template-catalog.js +406 -0
- package/dist/tools.d.ts +7 -1
- package/dist/tools.js +215 -24
- package/dist/types.d.ts +24 -1
- package/package.json +31 -17
package/dist/tools.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TOOL_DEFINITIONS = void 0;
|
|
3
4
|
exports.handleToolCall = handleToolCall;
|
|
5
|
+
const template_catalog_js_1 = require("./template-catalog.js");
|
|
6
|
+
const indexer_js_1 = require("./indexer.js");
|
|
7
|
+
const index_store_js_1 = require("./index-store.js");
|
|
8
|
+
/**
|
|
9
|
+
* The single source of truth for the MCP tool catalog. `index.ts` advertises
|
|
10
|
+
* these and `handleToolCall` dispatches them; the `mcp.test.ts` drift guard
|
|
11
|
+
* asserts the two never diverge.
|
|
12
|
+
*/
|
|
13
|
+
exports.TOOL_DEFINITIONS = [
|
|
14
|
+
{ name: 'search-symbol', description: 'Search for a symbol (function, type, class) across all packages', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Partial symbol name to search' } }, required: ['query'] } },
|
|
15
|
+
{ name: 'find-type', description: 'Find type definitions (interfaces, classes, type aliases) matching a pattern', inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: 'Type name pattern to search' } }, required: ['pattern'] } },
|
|
16
|
+
{ name: 'dependency-graph', description: 'Get dependency graph for a package — inbound dependents or outbound dependencies', inputSchema: { type: 'object', properties: { package: { type: 'string', description: 'Package name (e.g. @totemsdk/edge-opcua)' }, direction: { type: 'string', enum: ['in', 'out', 'all'], description: 'Dependency direction' } }, required: ['package'] } },
|
|
17
|
+
{ name: 'validate-import', description: 'Check whether a cross-package import is valid', inputSchema: { type: 'object', properties: { from: { type: 'string', description: 'Source package name' }, to: { type: 'string', description: 'Target package name' }, symbol: { type: 'string', description: 'Optional: specific symbol to check' } }, required: ['from', 'to'] } },
|
|
18
|
+
{ name: 'scaffold-adapter', description: 'Generate boilerplate for a new edge protocol adapter', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Package name suffix' }, protocol: { type: 'string', description: 'Protocol name (PascalCase)' }, commands: { type: 'array', items: { type: 'string' }, description: 'Transport port methods' } }, required: ['name', 'protocol'] } },
|
|
19
|
+
{ name: 'scaffold-package', description: 'Generate boilerplate for a new @totemsdk package', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Package name (without @totemsdk/ prefix)' }, deps: { type: 'array', items: { type: 'string' }, description: 'Dependency package names' } }, required: ['name'] } },
|
|
20
|
+
{ name: 'package-stats', description: 'Get statistics about a package — export counts, Rust/Go, tests, deps', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Package name' } }, required: ['name'] } },
|
|
21
|
+
{ name: 'list-exports', description: 'List exports of a package', inputSchema: { type: 'object', properties: { package: { type: 'string', description: 'Package name' }, kind: { type: 'string', enum: ['function', 'type', 'interface', 'class', 'const', ''], description: 'Filter by export kind' }, filter: { type: 'string', description: 'Filter by name substring' } }, required: ['package'] } },
|
|
22
|
+
{ name: 'suggest-template', description: 'Suggest KISSVM script templates matching a use case — describes what you want to do and returns matching templates with import paths', inputSchema: { type: 'object', properties: { usecase: { type: 'string', description: 'Describe what you want to do (e.g. "time-lock funds until a block height", "vote tally with quorum", "identity verification")' } }, required: ['usecase'] } },
|
|
23
|
+
{ name: 'read-source', description: "Read a source file from a package's src/ directory (e.g. package '@totemsdk/core', path 'treekey.ts')", inputSchema: { type: 'object', properties: { package: { type: 'string', description: 'Package name (e.g. @totemsdk/core)' }, path: { type: 'string', description: 'Path relative to the package src/ directory' } }, required: ['package', 'path'] } },
|
|
24
|
+
{ name: 'list-packages', description: 'List SDK packages, optionally filtered by domain or name substring', inputSchema: { type: 'object', properties: { domain: { type: 'string', description: 'Optional domain filter (e.g. edge/runtime... see totemsdk://domain-map)' }, filter: { type: 'string', description: 'Optional package-name substring filter' } } } },
|
|
25
|
+
{ name: 'search-packages', description: 'Search packages by keyword across name, description, keywords and exports (e.g. "wots lease coordination")', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Free-text query' }, domain: { type: 'string', description: 'Optional domain filter' }, limit: { type: 'number', description: 'Max results (default 15)' } }, required: ['query'] } },
|
|
26
|
+
{ name: 'refresh-index', description: 'Rebuild the SDK index from the filesystem (development convenience) and report counts', inputSchema: { type: 'object', properties: {} } },
|
|
27
|
+
];
|
|
4
28
|
function handleToolCall(name, args, index) {
|
|
5
29
|
switch (name) {
|
|
6
30
|
case 'search-symbol': return searchSymbol(args, index);
|
|
@@ -11,9 +35,94 @@ function handleToolCall(name, args, index) {
|
|
|
11
35
|
case 'scaffold-package': return scaffoldPackage(args);
|
|
12
36
|
case 'package-stats': return packageStats(args, index);
|
|
13
37
|
case 'list-exports': return listExports(args, index);
|
|
38
|
+
case 'suggest-template': return suggestTemplate(args);
|
|
39
|
+
case 'read-source': return readSource(args);
|
|
40
|
+
case 'list-packages': return listPackages(args, index);
|
|
41
|
+
case 'search-packages': return searchPackages(args, index);
|
|
42
|
+
case 'refresh-index': return refreshIndexTool();
|
|
14
43
|
default: return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
15
44
|
}
|
|
16
45
|
}
|
|
46
|
+
function refreshIndexTool() {
|
|
47
|
+
const idx = (0, index_store_js_1.refreshIndex)();
|
|
48
|
+
return {
|
|
49
|
+
content: [{
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: `Index rebuilt: ${Object.keys(idx.packages).length} packages, ${Object.keys(idx.symbolIndex).length} symbols, ${Object.keys(idx.domainMap).length} domains.`,
|
|
52
|
+
}],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function searchPackages(args, index) {
|
|
56
|
+
const query = String(args.query || '').toLowerCase().trim();
|
|
57
|
+
if (!query)
|
|
58
|
+
return { content: [{ type: 'text', text: 'query is required' }], isError: true };
|
|
59
|
+
const domain = args.domain;
|
|
60
|
+
const limit = Number.isFinite(args.limit) ? Number(args.limit) : 15;
|
|
61
|
+
const terms = query.split(/\s+/).filter(Boolean);
|
|
62
|
+
const scored = Object.values(index.packages)
|
|
63
|
+
.filter(p => !domain || p.domain === domain)
|
|
64
|
+
.map(p => {
|
|
65
|
+
const haystackName = p.name.toLowerCase();
|
|
66
|
+
const haystackDesc = p.description.toLowerCase();
|
|
67
|
+
const haystackKw = (p.keywords ?? []).join(' ').toLowerCase();
|
|
68
|
+
const haystackExports = [
|
|
69
|
+
...p.exports.functions, ...p.exports.types, ...p.exports.classes, ...p.exports.interfaces, ...p.exports.consts,
|
|
70
|
+
].join(' ').toLowerCase();
|
|
71
|
+
let score = 0;
|
|
72
|
+
for (const t of terms) {
|
|
73
|
+
if (haystackName.includes(t))
|
|
74
|
+
score += 4;
|
|
75
|
+
if (haystackKw.includes(t))
|
|
76
|
+
score += 3;
|
|
77
|
+
if (haystackExports.includes(t))
|
|
78
|
+
score += 2;
|
|
79
|
+
if (haystackDesc.includes(t))
|
|
80
|
+
score += 1;
|
|
81
|
+
}
|
|
82
|
+
return { p, score };
|
|
83
|
+
})
|
|
84
|
+
.filter(r => r.score > 0)
|
|
85
|
+
.sort((a, b) => b.score - a.score || a.p.name.localeCompare(b.p.name))
|
|
86
|
+
.slice(0, limit);
|
|
87
|
+
if (scored.length === 0) {
|
|
88
|
+
return { content: [{ type: 'text', text: `No packages matched '${query}'` }] };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
content: [{
|
|
92
|
+
type: 'text',
|
|
93
|
+
text: `Found ${scored.length} package(s) for '${query}':\n\n` +
|
|
94
|
+
scored.map(r => ` ${r.p.name}@${r.p.version} [${r.p.domain}] (score ${r.score}) — ${r.p.description}`).join('\n'),
|
|
95
|
+
}],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function readSource(args) {
|
|
99
|
+
const pkg = args.package;
|
|
100
|
+
const file = args.path;
|
|
101
|
+
if (!pkg || !file)
|
|
102
|
+
return { content: [{ type: 'text', text: 'package and path are required' }], isError: true };
|
|
103
|
+
const content = (0, indexer_js_1.readSourceFile)(pkg, file);
|
|
104
|
+
if (content === null) {
|
|
105
|
+
return { content: [{ type: 'text', text: `Source not found: ${pkg}/src/${file}` }], isError: true };
|
|
106
|
+
}
|
|
107
|
+
return { content: [{ type: 'text', text: content }] };
|
|
108
|
+
}
|
|
109
|
+
function listPackages(args, index) {
|
|
110
|
+
const domain = args.domain;
|
|
111
|
+
const filter = args.filter?.toLowerCase();
|
|
112
|
+
const rows = Object.values(index.packages)
|
|
113
|
+
.filter(p => (!domain || p.domain === domain) && (!filter || p.name.toLowerCase().includes(filter)))
|
|
114
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
115
|
+
if (rows.length === 0) {
|
|
116
|
+
return { content: [{ type: 'text', text: 'No packages matched' }] };
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
content: [{
|
|
120
|
+
type: 'text',
|
|
121
|
+
text: `${rows.length} package(s):\n\n` +
|
|
122
|
+
rows.map(p => ` ${p.name}@${p.version} [${p.domain}] — ${p.description}`).join('\n'),
|
|
123
|
+
}],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
17
126
|
function searchSymbol(args, index) {
|
|
18
127
|
const query = (args.query || '').toLowerCase();
|
|
19
128
|
if (!query)
|
|
@@ -22,7 +131,13 @@ function searchSymbol(args, index) {
|
|
|
22
131
|
for (const [symbol, entries] of Object.entries(index.symbolIndex)) {
|
|
23
132
|
if (symbol.toLowerCase().includes(query)) {
|
|
24
133
|
for (const entry of entries) {
|
|
25
|
-
results.push({
|
|
134
|
+
results.push({
|
|
135
|
+
symbol,
|
|
136
|
+
package: entry.package,
|
|
137
|
+
kind: entry.kind,
|
|
138
|
+
...(entry.signature !== undefined ? { signature: entry.signature } : {}),
|
|
139
|
+
...(entry.deprecated ? { deprecated: true } : {}),
|
|
140
|
+
});
|
|
26
141
|
}
|
|
27
142
|
}
|
|
28
143
|
}
|
|
@@ -34,7 +149,10 @@ function searchSymbol(args, index) {
|
|
|
34
149
|
content: [{
|
|
35
150
|
type: 'text',
|
|
36
151
|
text: `Found ${results.length} match(es) for '${query}':\n\n` +
|
|
37
|
-
results
|
|
152
|
+
results
|
|
153
|
+
.map(r => ` ${r.symbol} (${r.kind}) — ${r.package}${r.deprecated ? ' [deprecated]' : ''}` +
|
|
154
|
+
(r.signature ? `\n ${r.signature}` : ''))
|
|
155
|
+
.join('\n'),
|
|
38
156
|
}],
|
|
39
157
|
};
|
|
40
158
|
}
|
|
@@ -44,17 +162,16 @@ function findType(args, index) {
|
|
|
44
162
|
return { content: [{ type: 'text', text: 'pattern is required' }], isError: true };
|
|
45
163
|
const results = [];
|
|
46
164
|
for (const [pkgName, pkg] of Object.entries(index.packages)) {
|
|
47
|
-
for (const
|
|
48
|
-
if (
|
|
49
|
-
results.push({
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
results.push({ package: pkgName, type: c, kind: 'class' });
|
|
165
|
+
for (const entry of typeEntries(pkg)) {
|
|
166
|
+
if (entry.name.toLowerCase().includes(pattern)) {
|
|
167
|
+
results.push({
|
|
168
|
+
package: pkgName,
|
|
169
|
+
type: entry.name,
|
|
170
|
+
kind: entry.kind,
|
|
171
|
+
...(entry.signature !== undefined ? { signature: entry.signature } : {}),
|
|
172
|
+
...(entry.deprecated ? { deprecated: true } : {}),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
58
175
|
}
|
|
59
176
|
}
|
|
60
177
|
results.sort((a, b) => a.type.localeCompare(b.type));
|
|
@@ -65,10 +182,31 @@ function findType(args, index) {
|
|
|
65
182
|
content: [{
|
|
66
183
|
type: 'text',
|
|
67
184
|
text: `Found ${results.length} type(s) for '${pattern}':\n\n` +
|
|
68
|
-
results
|
|
185
|
+
results
|
|
186
|
+
.map(r => ` ${r.type} (${r.kind}) — ${r.package}${r.deprecated ? ' [deprecated]' : ''}` +
|
|
187
|
+
(r.signature ? `\n ${r.signature}` : ''))
|
|
188
|
+
.join('\n'),
|
|
69
189
|
}],
|
|
70
190
|
};
|
|
71
191
|
}
|
|
192
|
+
/** Type/interface/class entries for a package (uses `symbols` when present, else `exports`). */
|
|
193
|
+
function typeEntries(pkg) {
|
|
194
|
+
if (pkg.symbols && Object.keys(pkg.symbols).length > 0) {
|
|
195
|
+
return Object.entries(pkg.symbols)
|
|
196
|
+
.filter(([, m]) => m.kind === 'type' || m.kind === 'interface' || m.kind === 'class')
|
|
197
|
+
.map(([name, m]) => ({
|
|
198
|
+
name,
|
|
199
|
+
kind: m.kind,
|
|
200
|
+
...(m.signature !== undefined ? { signature: m.signature } : {}),
|
|
201
|
+
...(m.deprecated ? { deprecated: true } : {}),
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
return [
|
|
205
|
+
...pkg.exports.interfaces.map(n => ({ name: n, kind: 'interface' })),
|
|
206
|
+
...pkg.exports.types.map(n => ({ name: n, kind: 'type' })),
|
|
207
|
+
...pkg.exports.classes.map(n => ({ name: n, kind: 'class' })),
|
|
208
|
+
];
|
|
209
|
+
}
|
|
72
210
|
function dependencyGraph(args, index) {
|
|
73
211
|
const pkgName = args.package;
|
|
74
212
|
const direction = args.direction || 'out';
|
|
@@ -338,6 +476,40 @@ function scaffoldPackage(args) {
|
|
|
338
476
|
}],
|
|
339
477
|
};
|
|
340
478
|
}
|
|
479
|
+
function suggestTemplate(args) {
|
|
480
|
+
const usecase = (args.usecase || '').toLowerCase();
|
|
481
|
+
if (!usecase) {
|
|
482
|
+
return { content: [{ type: 'text', text: 'usecase is required — describe what you want to do (e.g. "time-lock funds until a block height")' }], isError: true };
|
|
483
|
+
}
|
|
484
|
+
const results = (0, template_catalog_js_1.searchTemplates)(usecase);
|
|
485
|
+
if (results.length === 0) {
|
|
486
|
+
return { content: [{ type: 'text', text: `No templates found matching '${usecase}'. Try different keywords (e.g. "lock", "vote", "payment", "identity", "state machine").` }] };
|
|
487
|
+
}
|
|
488
|
+
const lines = [`Found ${results.length} template(s) matching '${args.usecase}':`, ''];
|
|
489
|
+
for (const r of results) {
|
|
490
|
+
lines.push(`## ${r.template}`);
|
|
491
|
+
lines.push(`${r.description}`);
|
|
492
|
+
lines.push('');
|
|
493
|
+
lines.push(`**Functions:**`);
|
|
494
|
+
for (const fn of r.functions) {
|
|
495
|
+
lines.push(` - \`import { ${fn} } from '@totemsdk/kissvm'\``);
|
|
496
|
+
}
|
|
497
|
+
if (r.configTypes.length > 0) {
|
|
498
|
+
lines.push('');
|
|
499
|
+
lines.push(`**Config types:**`);
|
|
500
|
+
for (const t of r.configTypes) {
|
|
501
|
+
lines.push(` - \`${t}\``);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (r.package) {
|
|
505
|
+
const pkgs = Array.isArray(r.package) ? r.package : [r.package];
|
|
506
|
+
lines.push('');
|
|
507
|
+
lines.push(`**Related package(s):** ${pkgs.map(p => `\`@totemsdk/${p}\``).join(', ')}`);
|
|
508
|
+
}
|
|
509
|
+
lines.push('');
|
|
510
|
+
}
|
|
511
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
512
|
+
}
|
|
341
513
|
function packageStats(args, index) {
|
|
342
514
|
const pkgName = args.name;
|
|
343
515
|
if (!pkgName || !index.packages[pkgName]) {
|
|
@@ -348,6 +520,18 @@ function packageStats(args, index) {
|
|
|
348
520
|
pkg.exports.classes.length + pkg.exports.interfaces.length + pkg.exports.consts.length;
|
|
349
521
|
const totemDeps = pkg.dependencies.filter(d => d.startsWith('@totemsdk/'));
|
|
350
522
|
const externalDeps = pkg.dependencies.filter(d => !d.startsWith('@totemsdk/'));
|
|
523
|
+
const pkgDir = pkg.name.replace('@totemsdk/', '');
|
|
524
|
+
const templates = (0, template_catalog_js_1.getTemplatesForPackage)(pkgDir);
|
|
525
|
+
const templateSection = templates.length > 0
|
|
526
|
+
? [
|
|
527
|
+
``,
|
|
528
|
+
`**KISSVM Templates:**`,
|
|
529
|
+
...templates.flatMap(t => [
|
|
530
|
+
` - **${t.template}** — ${t.description}`,
|
|
531
|
+
...t.functions.map(fn => ` - \`import { ${fn} } from '@totemsdk/kissvm'\``),
|
|
532
|
+
]),
|
|
533
|
+
]
|
|
534
|
+
: [];
|
|
351
535
|
return {
|
|
352
536
|
content: [{
|
|
353
537
|
type: 'text',
|
|
@@ -371,6 +555,7 @@ function packageStats(args, index) {
|
|
|
371
555
|
`| Tests | ${pkg.hasTests ? 'Yes' : 'No'} |`,
|
|
372
556
|
`| @totemsdk/* deps | ${totemDeps.length} |`,
|
|
373
557
|
`| External deps | ${externalDeps.length} |`,
|
|
558
|
+
...templateSection,
|
|
374
559
|
``,
|
|
375
560
|
].join('\n'),
|
|
376
561
|
}],
|
|
@@ -385,30 +570,36 @@ function listExports(args, index) {
|
|
|
385
570
|
}
|
|
386
571
|
const pkg = index.packages[pkgName];
|
|
387
572
|
const sections = [];
|
|
573
|
+
const render = (s) => {
|
|
574
|
+
const m = pkg.symbols?.[s];
|
|
575
|
+
const dep = m?.deprecated ? ' · deprecated' : '';
|
|
576
|
+
return ` - \`${s}\`${dep}${m?.signature ? `\n ${m.signature}` : ''}`;
|
|
577
|
+
};
|
|
578
|
+
const pick = (list) => (filter ? list.filter(s => s.toLowerCase().includes(filter)) : list);
|
|
388
579
|
if (!kind || kind === 'function') {
|
|
389
|
-
const items =
|
|
580
|
+
const items = pick(pkg.exports.functions);
|
|
390
581
|
if (items.length)
|
|
391
|
-
sections.push(`**Functions (${items.length}):**\n` + items.map(
|
|
582
|
+
sections.push(`**Functions (${items.length}):**\n` + items.map(render).join('\n'));
|
|
392
583
|
}
|
|
393
584
|
if (!kind || kind === 'interface') {
|
|
394
|
-
const items =
|
|
585
|
+
const items = pick(pkg.exports.interfaces);
|
|
395
586
|
if (items.length)
|
|
396
|
-
sections.push(`**Interfaces (${items.length}):**\n` + items.map(
|
|
587
|
+
sections.push(`**Interfaces (${items.length}):**\n` + items.map(render).join('\n'));
|
|
397
588
|
}
|
|
398
589
|
if (!kind || kind === 'type') {
|
|
399
|
-
const items =
|
|
590
|
+
const items = pick(pkg.exports.types);
|
|
400
591
|
if (items.length)
|
|
401
|
-
sections.push(`**Named Types (${items.length}):**\n` + items.map(
|
|
592
|
+
sections.push(`**Named Types (${items.length}):**\n` + items.map(render).join('\n'));
|
|
402
593
|
}
|
|
403
594
|
if (!kind || kind === 'class') {
|
|
404
|
-
const items =
|
|
595
|
+
const items = pick(pkg.exports.classes);
|
|
405
596
|
if (items.length)
|
|
406
|
-
sections.push(`**Classes (${items.length}):**\n` + items.map(
|
|
597
|
+
sections.push(`**Classes (${items.length}):**\n` + items.map(render).join('\n'));
|
|
407
598
|
}
|
|
408
599
|
if (!kind || kind === 'const') {
|
|
409
|
-
const items =
|
|
600
|
+
const items = pick(pkg.exports.consts);
|
|
410
601
|
if (items.length)
|
|
411
|
-
sections.push(`**Constants (${items.length}):**\n` + items.map(
|
|
602
|
+
sections.push(`**Constants (${items.length}):**\n` + items.map(render).join('\n'));
|
|
412
603
|
}
|
|
413
604
|
return {
|
|
414
605
|
content: [{ type: 'text', text: sections.join('\n\n') || `No exports found for '${pkgName}'` }],
|
package/dist/types.d.ts
CHANGED
|
@@ -3,12 +3,17 @@ export interface PackageIndex {
|
|
|
3
3
|
dir: string;
|
|
4
4
|
version: string;
|
|
5
5
|
description: string;
|
|
6
|
+
keywords?: string[];
|
|
6
7
|
dependencies: string[];
|
|
7
8
|
devDependencies: string[];
|
|
8
9
|
hasRust: boolean;
|
|
9
10
|
hasGo: boolean;
|
|
10
11
|
hasTests: boolean;
|
|
11
12
|
exports: PackageExports;
|
|
13
|
+
/** Per-symbol metadata (signature, doc, deprecation) keyed by symbol name. */
|
|
14
|
+
symbols?: {
|
|
15
|
+
[name: string]: SymbolMeta;
|
|
16
|
+
};
|
|
12
17
|
domain: string;
|
|
13
18
|
}
|
|
14
19
|
export interface PackageExports {
|
|
@@ -18,9 +23,22 @@ export interface PackageExports {
|
|
|
18
23
|
interfaces: string[];
|
|
19
24
|
consts: string[];
|
|
20
25
|
}
|
|
26
|
+
export type SymbolKind = 'function' | 'type' | 'class' | 'interface' | 'const' | 'variable';
|
|
27
|
+
export interface SymbolMeta {
|
|
28
|
+
kind: SymbolKind;
|
|
29
|
+
/** Best-effort declaration text (params/return/extends), whitespace-normalized. */
|
|
30
|
+
signature?: string;
|
|
31
|
+
/** Leading JSDoc/line-comment text, if any. */
|
|
32
|
+
doc?: string;
|
|
33
|
+
/** True when the doc contains an `@deprecated` tag. */
|
|
34
|
+
deprecated?: boolean;
|
|
35
|
+
}
|
|
21
36
|
export interface SymbolEntry {
|
|
22
37
|
package: string;
|
|
23
|
-
kind:
|
|
38
|
+
kind: SymbolKind;
|
|
39
|
+
signature?: string;
|
|
40
|
+
doc?: string;
|
|
41
|
+
deprecated?: boolean;
|
|
24
42
|
}
|
|
25
43
|
export interface DomainMap {
|
|
26
44
|
[domain: string]: string[];
|
|
@@ -35,6 +53,11 @@ export interface SdkIndex {
|
|
|
35
53
|
};
|
|
36
54
|
domainMap: DomainMap;
|
|
37
55
|
}
|
|
56
|
+
export interface ToolDefinition {
|
|
57
|
+
name: string;
|
|
58
|
+
description: string;
|
|
59
|
+
inputSchema: unknown;
|
|
60
|
+
}
|
|
38
61
|
export interface ToolResponse {
|
|
39
62
|
content: Array<{
|
|
40
63
|
type: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totemsdk/mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server exposing the full Totem SDK package set — metadata, types, exports, dependency graphs, and scaffolding tools
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "MCP server exposing the full Totem SDK package set — metadata, types, exports, dependency graphs, and scaffolding tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -14,18 +14,20 @@
|
|
|
14
14
|
"import": "./dist/index.js"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"files": ["dist", "README.md", "LICENSE"],
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"data",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
24
23
|
"dependencies": {
|
|
25
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
27
|
+
"@types/jest": "^30.0.0",
|
|
28
28
|
"@types/node": "^20.0.0",
|
|
29
|
+
"jest": "^30.4.2",
|
|
30
|
+
"ts-jest": "^29.0.0",
|
|
29
31
|
"typescript": "^7.0.2"
|
|
30
32
|
},
|
|
31
33
|
"engines": {
|
|
@@ -36,14 +38,26 @@
|
|
|
36
38
|
},
|
|
37
39
|
"license": "MIT",
|
|
38
40
|
"author": "Totem SDK",
|
|
39
|
-
"homepage": "https://totem.ing",
|
|
41
|
+
"homepage": "https://docs.totem.ing",
|
|
40
42
|
"bugs": {
|
|
41
|
-
"url": "https://github.com/
|
|
43
|
+
"url": "https://github.com/Totem-Edge/totem-sdk/issues"
|
|
42
44
|
},
|
|
43
45
|
"repository": {
|
|
44
46
|
"type": "git",
|
|
45
|
-
"url": "git+https://github.com/
|
|
46
|
-
"directory": "packages/
|
|
47
|
-
},
|
|
48
|
-
"keywords": [
|
|
49
|
-
|
|
47
|
+
"url": "git+https://github.com/Totem-Edge/totem-sdk.git",
|
|
48
|
+
"directory": "packages/mcp-server"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"totem",
|
|
52
|
+
"totemsdk",
|
|
53
|
+
"mcp",
|
|
54
|
+
"model-context-protocol",
|
|
55
|
+
"sdk-index"
|
|
56
|
+
],
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsc && node ../../scripts/build-mcp-bundle.mjs",
|
|
59
|
+
"clean": "rm -rf dist data",
|
|
60
|
+
"start": "node dist/index.js",
|
|
61
|
+
"test": "jest"
|
|
62
|
+
}
|
|
63
|
+
}
|