@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/resources.js
CHANGED
|
@@ -1,7 +1,215 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.extractSection = extractSection;
|
|
37
|
+
exports.resourceMimeType = resourceMimeType;
|
|
3
38
|
exports.handleResourceRead = handleResourceRead;
|
|
4
39
|
exports.listResources = listResources;
|
|
40
|
+
const template_catalog_js_1 = require("./template-catalog.js");
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
function findRepoRoot() {
|
|
44
|
+
let dir = path.resolve(__dirname);
|
|
45
|
+
while (dir !== path.dirname(dir)) {
|
|
46
|
+
if (fs.existsSync(path.join(dir, 'pnpm-workspace.yaml')))
|
|
47
|
+
return dir;
|
|
48
|
+
dir = path.dirname(dir);
|
|
49
|
+
}
|
|
50
|
+
return dir;
|
|
51
|
+
}
|
|
52
|
+
const REPO_ROOT = findRepoRoot();
|
|
53
|
+
const PAPERS = [
|
|
54
|
+
{
|
|
55
|
+
uri: 'totemsdk://papers/yellow',
|
|
56
|
+
name: 'Core Yellow Paper',
|
|
57
|
+
description: 'WOTS+ signatures, TreeKey hierarchy, MMR proofs, byte-exact serialization, lease/watermark coordination, Rust/WASM engine',
|
|
58
|
+
file: 'TOTEM_CORE_YELLOW_PAPER.md',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
uri: 'totemsdk://papers/red',
|
|
62
|
+
name: 'Connect Red Paper',
|
|
63
|
+
description: 'dApp-wallet wire protocol specification — every method, parameter, response shape, error code and the security model',
|
|
64
|
+
file: 'TOTEM_CONNECT_RED_PAPER.md',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
uri: 'totemsdk://papers/blue',
|
|
68
|
+
name: 'Omnia Blue Paper',
|
|
69
|
+
description: 'P2P payment channels, eltoo state machine, multi-hop routing, channel factories, VTXO accounting, statechain prepaid passes, lending/borrowing, off-chain tokens, privacy by design, scaling to billions of devices',
|
|
70
|
+
file: 'TOTEM_OMNIA_BLUE_PAPER.md',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
uri: 'totemsdk://papers/green',
|
|
74
|
+
name: 'Governance Green Paper',
|
|
75
|
+
description: 'Authority mandates, delegation chains, recursive MAST 7-layer policy trees, quadratic voting, liquid democracy, QVAC agent policy, modular governance patterns',
|
|
76
|
+
file: 'TOTEM_GOVERNANCE_GREEN_PAPER.md',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
uri: 'totemsdk://papers/grey',
|
|
80
|
+
name: 'Edge Grey Paper',
|
|
81
|
+
description: 'Port-injected transport-agnostic edge runtime, 11 protocol adapters, MachinePay credit gating, offline operation, industrial action, sensor-to-settlement bridge',
|
|
82
|
+
file: 'TOTEM_EDGE_GREY_PAPER.md',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
uri: 'totemsdk://papers/gold',
|
|
86
|
+
name: 'Network Economics Gold Paper',
|
|
87
|
+
description: 'Progressive decentralisation; MINIMA as settlement/native collateral where appropriate; $TOTEM as a potential network coordination and service-assurance asset (provider bonding, DAO stewardship, community-heavy genesis); no token assumed — network must earn the right to need one',
|
|
88
|
+
file: 'TOTEM_NETWORK_ECONOMICS_GOLD_PAPER.md',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
uri: 'totemsdk://papers/purple',
|
|
92
|
+
name: 'Intelligence & Decision Purple Paper',
|
|
93
|
+
description: 'Bounded intelligence for autonomous systems — Intelligence vs Decision separation, bounded candidate spaces, the deterministic shell around probabilistic models, effective authority, governed Edge runtime, receipts and the Physical AI trust stack',
|
|
94
|
+
file: 'TOTEM_INTELLIGENCE_DECISION_PURPLE_PAPER.md',
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
/** Derive a name/description for a doc from its first heading + first paragraph. */
|
|
98
|
+
function docMeta(file, fallbackName) {
|
|
99
|
+
const content = readRepoFile(file) ?? '';
|
|
100
|
+
const lines = content.split('\n');
|
|
101
|
+
const titleIdx = lines.findIndex(l => l.startsWith('# '));
|
|
102
|
+
const name = titleIdx >= 0 ? lines[titleIdx].replace(/^#\s+/, '').trim() : fallbackName;
|
|
103
|
+
let description = '';
|
|
104
|
+
for (let i = titleIdx + 1; i < lines.length; i++) {
|
|
105
|
+
const t = lines[i].trim();
|
|
106
|
+
if (!t || t.startsWith('#') || t.startsWith('**Status') || t.startsWith('---') || t.startsWith('>'))
|
|
107
|
+
continue;
|
|
108
|
+
description = t.replace(/[*_`]/g, '').trim();
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return { name: name || fallbackName, description: description || name || fallbackName };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* RFCs and audits are discovered from disk, so a new `docs/rfc/RFC-*.md` or
|
|
115
|
+
* `docs/audits/*.md` is exposed automatically — there is no hand-maintained
|
|
116
|
+
* list to forget.
|
|
117
|
+
*/
|
|
118
|
+
function discoverDocs() {
|
|
119
|
+
const docs = [];
|
|
120
|
+
const rfcDir = path.join(REPO_ROOT, 'docs', 'rfc');
|
|
121
|
+
if (fs.existsSync(rfcDir)) {
|
|
122
|
+
for (const f of fs.readdirSync(rfcDir).sort()) {
|
|
123
|
+
const m = f.match(/^RFC-(\d+)-(.+)\.md$/);
|
|
124
|
+
if (!m)
|
|
125
|
+
continue;
|
|
126
|
+
const file = path.join('docs', 'rfc', f);
|
|
127
|
+
const meta = docMeta(file, `RFC-${m[1]}`);
|
|
128
|
+
docs.push({ uri: `totemsdk://rfc/${m[1]}`, ...meta, file });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const auditDir = path.join(REPO_ROOT, 'docs', 'audits');
|
|
132
|
+
if (fs.existsSync(auditDir)) {
|
|
133
|
+
for (const f of fs.readdirSync(auditDir).sort()) {
|
|
134
|
+
if (!f.endsWith('.md'))
|
|
135
|
+
continue;
|
|
136
|
+
const base = f.replace(/\.md$/, '');
|
|
137
|
+
const slug = base.replace(/-\d{4}-\d{2}$/, '');
|
|
138
|
+
const file = path.join('docs', 'audits', f);
|
|
139
|
+
const meta = docMeta(file, base);
|
|
140
|
+
docs.push({ uri: `totemsdk://audit/${slug}`, ...meta, file });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return docs;
|
|
144
|
+
}
|
|
145
|
+
const DOCS = discoverDocs();
|
|
146
|
+
/** Generated structured catalogs (parsed from source, not stored). */
|
|
147
|
+
const CATALOGS = [
|
|
148
|
+
{ uri: 'totemsdk://connect/methods', name: 'Connect Methods', description: 'The dApp-wallet wire protocol method catalog (@totemsdk/connect)' },
|
|
149
|
+
{ uri: 'totemsdk://edge/capabilities', name: 'Edge Capabilities', description: 'Canonical EdgeCapability strings (@totemsdk/edge)' },
|
|
150
|
+
{ uri: 'totemsdk://rfc', name: 'RFC Index', description: 'Index of SDK RFCs' },
|
|
151
|
+
];
|
|
152
|
+
function readRepoFile(rel) {
|
|
153
|
+
const p = path.join(REPO_ROOT, rel);
|
|
154
|
+
return fs.existsSync(p) ? fs.readFileSync(p, 'utf-8') : null;
|
|
155
|
+
}
|
|
156
|
+
function slugify(s) {
|
|
157
|
+
return s.toLowerCase().replace(/[`*_]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
158
|
+
}
|
|
159
|
+
/** Extract a markdown section by heading slug/text (for `totemsdk://rfc/014#6-design`). */
|
|
160
|
+
function extractSection(markdown, anchor) {
|
|
161
|
+
const lines = markdown.split('\n');
|
|
162
|
+
const decoded = anchor.replace(/%20/g, ' ').toLowerCase();
|
|
163
|
+
let start = -1;
|
|
164
|
+
let level = 0;
|
|
165
|
+
for (let i = 0; i < lines.length; i++) {
|
|
166
|
+
const m = lines[i].match(/^(#{1,6})\s+(.*)$/);
|
|
167
|
+
if (!m)
|
|
168
|
+
continue;
|
|
169
|
+
const text = m[2].trim();
|
|
170
|
+
if (slugify(text) === slugify(anchor) || text.toLowerCase().includes(decoded)) {
|
|
171
|
+
start = i;
|
|
172
|
+
level = m[1].length;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (start < 0)
|
|
177
|
+
return null;
|
|
178
|
+
let end = lines.length;
|
|
179
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
180
|
+
const m = lines[i].match(/^(#{1,6})\s+/);
|
|
181
|
+
if (m && m[1].length <= level) {
|
|
182
|
+
end = i;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return lines.slice(start, end).join('\n').trim();
|
|
187
|
+
}
|
|
188
|
+
function connectMethods() {
|
|
189
|
+
const src = readRepoFile(path.join('packages', 'connect', 'src', 'index.ts'));
|
|
190
|
+
if (!src)
|
|
191
|
+
return [];
|
|
192
|
+
return [...new Set([...src.matchAll(/method:\s*'([A-Za-z_]+)'/g)].map(m => m[1]))].sort();
|
|
193
|
+
}
|
|
194
|
+
function edgeCapabilities() {
|
|
195
|
+
const src = readRepoFile(path.join('packages', 'edge', 'src', 'capabilities.ts'));
|
|
196
|
+
if (!src)
|
|
197
|
+
return [];
|
|
198
|
+
return [...new Set([...src.matchAll(/'([a-z][a-z0-9-]*:[a-z0-9-]+)'/g)].map(m => m[1]))].sort();
|
|
199
|
+
}
|
|
200
|
+
/** MIME type for a resource URI. */
|
|
201
|
+
function resourceMimeType(uri) {
|
|
202
|
+
const base = uri.split('#')[0];
|
|
203
|
+
if (base === 'totemsdk://conventions' || base === 'totemsdk://templates')
|
|
204
|
+
return 'text/markdown';
|
|
205
|
+
if (/^totemsdk:\/\/(papers|rfc|audit)\/[^/]+$/.test(base))
|
|
206
|
+
return 'text/markdown';
|
|
207
|
+
if (base === 'totemsdk://packages' || base === 'totemsdk://domain-map' || base === 'totemsdk://rfc')
|
|
208
|
+
return 'application/json';
|
|
209
|
+
if (/^totemsdk:\/\/(packages|symbol|connect|edge)(\/|$)/.test(base))
|
|
210
|
+
return 'application/json';
|
|
211
|
+
return 'text/plain';
|
|
212
|
+
}
|
|
5
213
|
const CONVENTIONS = `# Totem SDK Conventions
|
|
6
214
|
|
|
7
215
|
## Package Structure
|
|
@@ -19,11 +227,11 @@ const CONVENTIONS = `# Totem SDK Conventions
|
|
|
19
227
|
## Canonical JSON
|
|
20
228
|
- Recursive deterministic JSON with sorted object keys
|
|
21
229
|
- Used as input to all hashing and signing operations
|
|
22
|
-
-
|
|
230
|
+
- Shared: import { canonicalJson, hashCanonical, toHex, sha3_256 } from '@totemsdk/core'
|
|
23
231
|
|
|
24
232
|
## Hashing
|
|
25
233
|
- SHA3-256 via @totemsdk/core
|
|
26
|
-
- Domain-
|
|
234
|
+
- Domain-separated: hashCanonical('<DOMAIN>_V1', data) == sha3-256(domain + canonicalJson(data))
|
|
27
235
|
- Domain constants like 'TOTEM_GOVERNANCE_PROPOSAL_V1'
|
|
28
236
|
|
|
29
237
|
## Signing
|
|
@@ -46,6 +254,27 @@ const CONVENTIONS = `# Totem SDK Conventions
|
|
|
46
254
|
- Promise<T> everywhere, typed event emitters, no Observables
|
|
47
255
|
- Action lifecycle: propose -> reserve -> execute -> confirm/fail/unknown`;
|
|
48
256
|
function handleResourceRead(uri, index) {
|
|
257
|
+
if (uri === 'totemsdk://connect/methods')
|
|
258
|
+
return JSON.stringify(connectMethods(), null, 2);
|
|
259
|
+
if (uri === 'totemsdk://edge/capabilities')
|
|
260
|
+
return JSON.stringify(edgeCapabilities(), null, 2);
|
|
261
|
+
if (uri === 'totemsdk://rfc') {
|
|
262
|
+
return JSON.stringify(DOCS.filter(d => d.uri.startsWith('totemsdk://rfc/')).map(d => ({ uri: d.uri, name: d.name, description: d.description })), null, 2);
|
|
263
|
+
}
|
|
264
|
+
const base = uri.split('#')[0];
|
|
265
|
+
const readable = [...PAPERS, ...DOCS].find(d => d.uri === base);
|
|
266
|
+
if (readable) {
|
|
267
|
+
const filePath = path.join(REPO_ROOT, readable.file);
|
|
268
|
+
if (!fs.existsSync(filePath))
|
|
269
|
+
return `Document not found: ${readable.file}`;
|
|
270
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
271
|
+
const hash = uri.indexOf('#');
|
|
272
|
+
if (hash >= 0) {
|
|
273
|
+
const section = extractSection(content, uri.slice(hash + 1));
|
|
274
|
+
return section ?? `Section not found: ${uri.slice(hash + 1)}`;
|
|
275
|
+
}
|
|
276
|
+
return content;
|
|
277
|
+
}
|
|
49
278
|
if (uri === 'totemsdk://packages') {
|
|
50
279
|
return JSON.stringify(Object.values(index.packages).map(p => ({
|
|
51
280
|
name: p.name,
|
|
@@ -59,6 +288,19 @@ function handleResourceRead(uri, index) {
|
|
|
59
288
|
}
|
|
60
289
|
if (uri === 'totemsdk://conventions')
|
|
61
290
|
return CONVENTIONS;
|
|
291
|
+
if (uri === 'totemsdk://templates') {
|
|
292
|
+
const all = (0, template_catalog_js_1.getAllTemplates)();
|
|
293
|
+
return all.map(t => {
|
|
294
|
+
const pkgs = Array.isArray(t.package) ? t.package : t.package ? [t.package] : [];
|
|
295
|
+
return {
|
|
296
|
+
template: t.template,
|
|
297
|
+
functions: t.functions,
|
|
298
|
+
configTypes: t.configTypes,
|
|
299
|
+
package: pkgs.length > 0 ? pkgs.map(p => `@totemsdk/${p}`) : ['@totemsdk/kissvm'],
|
|
300
|
+
description: t.description,
|
|
301
|
+
};
|
|
302
|
+
}).map(t => `## ${t.template}\n\n${t.description}\n\n**Package:** ${t.package.join(', ')}\n\n**Functions:**\n${t.functions.map(f => ` - \`import { ${f} } from '@totemsdk/kissvm'\``).join('\n')}\n`).join('\n---\n');
|
|
303
|
+
}
|
|
62
304
|
if (uri === 'totemsdk://domain-map') {
|
|
63
305
|
return JSON.stringify(index.domainMap, null, 2);
|
|
64
306
|
}
|
|
@@ -93,9 +335,13 @@ function handleResourceRead(uri, index) {
|
|
|
93
335
|
}
|
|
94
336
|
function listResources(index) {
|
|
95
337
|
const resources = [
|
|
96
|
-
{ uri: 'totemsdk://packages', name: 'All Packages', description:
|
|
338
|
+
{ uri: 'totemsdk://packages', name: 'All Packages', description: `List of all ${Object.keys(index.packages).length} SDK packages with metadata` },
|
|
339
|
+
{ uri: 'totemsdk://templates', name: 'All KISSVM Templates', description: `All ${(0, template_catalog_js_1.getAllTemplates)().length} KISSVM script templates with import paths and descriptions` },
|
|
97
340
|
{ uri: 'totemsdk://conventions', name: 'Coding Conventions', description: 'Totem SDK coding conventions and patterns' },
|
|
98
341
|
{ uri: 'totemsdk://domain-map', name: 'Domain Map', description: 'Packages grouped by domain layer' },
|
|
342
|
+
...PAPERS.map(p => ({ uri: p.uri, name: p.name, description: p.description })),
|
|
343
|
+
...DOCS.map(d => ({ uri: d.uri, name: d.name, description: d.description })),
|
|
344
|
+
...CATALOGS,
|
|
99
345
|
];
|
|
100
346
|
for (const [domain, pkgs] of Object.entries(index.domainMap)) {
|
|
101
347
|
resources.push({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface TemplateEntry {
|
|
2
|
+
template: string;
|
|
3
|
+
functions: string[];
|
|
4
|
+
configTypes: string[];
|
|
5
|
+
package: string | string[] | null;
|
|
6
|
+
keywords: string[];
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const TEMPLATE_CATALOG: TemplateEntry[];
|
|
10
|
+
export declare function getTemplatesForPackage(pkgName: string): TemplateEntry[];
|
|
11
|
+
export declare function searchTemplates(query: string): TemplateEntry[];
|
|
12
|
+
export declare function getAllTemplates(): TemplateEntry[];
|