@totemsdk/mcp-server 0.3.0 → 0.4.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/data/sdk-index.json +1 -1
- package/dist/indexer.js +17 -3
- package/dist/resources.js +38 -7
- package/package.json +1 -1
package/dist/indexer.js
CHANGED
|
@@ -310,10 +310,24 @@ function collectExports(file, symbols, visited) {
|
|
|
310
310
|
const braceMatch = block.match(/\{([^}]+)\}/);
|
|
311
311
|
if (braceMatch) {
|
|
312
312
|
for (const part of braceMatch[1].split(',')) {
|
|
313
|
-
|
|
314
|
-
if (!
|
|
313
|
+
let clause = part.trim();
|
|
314
|
+
if (!clause)
|
|
315
315
|
continue;
|
|
316
|
-
|
|
316
|
+
// Inline type modifiers: `export { type Foo }` / `export { type Foo as Bar }`.
|
|
317
|
+
// Strip the leading `type` keyword before resolving the exposed name,
|
|
318
|
+
// otherwise the symbol is recorded literally as "type Foo".
|
|
319
|
+
let inlineType = false;
|
|
320
|
+
const typeKw = clause.match(/^type\s+([\s\S]+)$/);
|
|
321
|
+
if (typeKw) {
|
|
322
|
+
inlineType = true;
|
|
323
|
+
clause = typeKw[1].trim();
|
|
324
|
+
}
|
|
325
|
+
const name = clause.split(/\s+as\s+/).pop()?.trim() || '';
|
|
326
|
+
// Reject anything that isn't a plain identifier (guards against
|
|
327
|
+
// malformed fragments leaking in as fake symbols).
|
|
328
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(name))
|
|
329
|
+
continue;
|
|
330
|
+
const kind = isType || inlineType || /^[A-Z]/.test(name) ? 'type' : 'function';
|
|
317
331
|
setSymbol(symbols, name, { kind });
|
|
318
332
|
}
|
|
319
333
|
}
|
package/dist/resources.js
CHANGED
|
@@ -108,7 +108,12 @@ function docMeta(file, fallbackName) {
|
|
|
108
108
|
description = t.replace(/[*_`]/g, '').trim();
|
|
109
109
|
break;
|
|
110
110
|
}
|
|
111
|
-
|
|
111
|
+
const clean = description || name || fallbackName;
|
|
112
|
+
// Cap at the first sentence / ~160 chars. Discovery must stay cheap: an
|
|
113
|
+
// unbounded first paragraph bloats every client's resource list.
|
|
114
|
+
const firstSentence = clean.split(/(?<=\.)\s/)[0];
|
|
115
|
+
const bounded = (firstSentence.length <= 160 ? firstSentence : clean.slice(0, 160)).trim();
|
|
116
|
+
return { name: name || fallbackName, description: bounded.length > 0 ? bounded : name || fallbackName };
|
|
112
117
|
}
|
|
113
118
|
/**
|
|
114
119
|
* RFCs and audits are discovered from disk, so a new `docs/rfc/RFC-*.md` or
|
|
@@ -125,7 +130,14 @@ function discoverDocs() {
|
|
|
125
130
|
continue;
|
|
126
131
|
const file = path.join('docs', 'rfc', f);
|
|
127
132
|
const meta = docMeta(file, `RFC-${m[1]}`);
|
|
128
|
-
|
|
133
|
+
// Amendments share an RFC number with the original; give them a distinct
|
|
134
|
+
// URI (`totemsdk://rfc/007/amendment-a`) so a reader never retrieves an
|
|
135
|
+
// amendment when they asked for the base specification.
|
|
136
|
+
const amend = m[2].match(/^AMENDMENT-([A-Z])/i);
|
|
137
|
+
const uri = amend
|
|
138
|
+
? `totemsdk://rfc/${m[1]}/amendment-${amend[1].toLowerCase()}`
|
|
139
|
+
: `totemsdk://rfc/${m[1]}`;
|
|
140
|
+
docs.push({ uri, ...meta, file });
|
|
129
141
|
}
|
|
130
142
|
}
|
|
131
143
|
const auditDir = path.join(REPO_ROOT, 'docs', 'audits');
|
|
@@ -140,6 +152,19 @@ function discoverDocs() {
|
|
|
140
152
|
docs.push({ uri: `totemsdk://audit/${slug}`, ...meta, file });
|
|
141
153
|
}
|
|
142
154
|
}
|
|
155
|
+
// Worked, runnable end-to-end scenarios (usually backed by a test under
|
|
156
|
+
// packages/sdk-tests). Discovered from disk like RFCs/audits.
|
|
157
|
+
const exampleDir = path.join(REPO_ROOT, 'docs', 'examples');
|
|
158
|
+
if (fs.existsSync(exampleDir)) {
|
|
159
|
+
for (const f of fs.readdirSync(exampleDir).sort()) {
|
|
160
|
+
if (!f.endsWith('.md'))
|
|
161
|
+
continue;
|
|
162
|
+
const slug = f.replace(/\.md$/, '');
|
|
163
|
+
const file = path.join('docs', 'examples', f);
|
|
164
|
+
const meta = docMeta(file, slug);
|
|
165
|
+
docs.push({ uri: `totemsdk://example/${slug}`, ...meta, file });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
143
168
|
return docs;
|
|
144
169
|
}
|
|
145
170
|
const DOCS = discoverDocs();
|
|
@@ -202,7 +227,7 @@ function resourceMimeType(uri) {
|
|
|
202
227
|
const base = uri.split('#')[0];
|
|
203
228
|
if (base === 'totemsdk://conventions' || base === 'totemsdk://templates')
|
|
204
229
|
return 'text/markdown';
|
|
205
|
-
if (/^totemsdk:\/\/(papers|rfc|audit)\/[^/]
|
|
230
|
+
if (/^totemsdk:\/\/(papers|rfc|audit|example)\/[^/]+(\/[^/]+)?$/.test(base))
|
|
206
231
|
return 'text/markdown';
|
|
207
232
|
if (base === 'totemsdk://packages' || base === 'totemsdk://domain-map' || base === 'totemsdk://rfc')
|
|
208
233
|
return 'application/json';
|
|
@@ -367,10 +392,16 @@ function listResources(index) {
|
|
|
367
392
|
description: `Dependencies of ${name}`,
|
|
368
393
|
});
|
|
369
394
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
395
|
+
// Symbol lookups are served by the `search-symbol` tool (query-driven), which
|
|
396
|
+
// is far cheaper than enumerating ~3.7k symbols as resources. Only surface a
|
|
397
|
+
// small set of the most unambiguous symbols (exported by exactly one package)
|
|
398
|
+
// so `totemsdk://symbol/{name}` remains discoverable without bloating
|
|
399
|
+
// discovery to hundreds of entries.
|
|
400
|
+
const uniqueSymbols = Object.entries(index.symbolIndex)
|
|
401
|
+
.filter(([_, v]) => v.length === 1)
|
|
402
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
403
|
+
.slice(0, 50);
|
|
404
|
+
for (const [symbol, entries] of uniqueSymbols) {
|
|
374
405
|
resources.push({
|
|
375
406
|
uri: `totemsdk://symbol/${symbol}`,
|
|
376
407
|
name: `Symbol: ${symbol}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totemsdk/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
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",
|