@voltro/mcp 0.33.0 → 0.35.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.
@@ -0,0 +1,542 @@
1
+ //#region src/manifest.ts
2
+ var e = {
3
+ version: 2,
4
+ procedures: [],
5
+ workflows: [],
6
+ widgets: [],
7
+ tables: [],
8
+ scopes: []
9
+ }, t = async (e, t, n = 5e3) => {
10
+ let r = new URL("/_voltro/inspect/manifest", e), i = await fetch(r, {
11
+ headers: t === void 0 ? {} : { authorization: `Bearer ${t}` },
12
+ signal: AbortSignal.timeout(n)
13
+ });
14
+ if (!i.ok) throw Error(`manifest fetch failed: HTTP ${i.status}`);
15
+ return await i.json();
16
+ }, n = (n) => {
17
+ let r = n.ttlMs ?? 1e4, i = n.now ?? Date.now, a, o = -Infinity;
18
+ return { get: async () => {
19
+ if (a !== void 0 && i() - o < r) return a;
20
+ try {
21
+ a = { manifest: await t(n.baseUrl, n.token) };
22
+ } catch (t) {
23
+ a = {
24
+ manifest: a?.manifest ?? e,
25
+ error: String(t)
26
+ };
27
+ }
28
+ return o = i(), a;
29
+ } };
30
+ }, r = {
31
+ maxTools: 64,
32
+ maxDescriptionChars: 1024,
33
+ maxResultBytes: 256 * 1024,
34
+ requestTimeoutMs: 3e4
35
+ }, i = (e, t) => {
36
+ let n = Number(e);
37
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : t;
38
+ }, a = (e, t) => ({
39
+ maxTools: t?.maxTools ?? i(e.VOLTRO_MCP_MAX_APP_TOOLS, r.maxTools),
40
+ maxDescriptionChars: t?.maxDescriptionChars ?? i(e.VOLTRO_MCP_MAX_DESCRIPTION_CHARS, r.maxDescriptionChars),
41
+ maxResultBytes: t?.maxResultBytes ?? i(e.VOLTRO_MCP_MAX_RESULT_BYTES, r.maxResultBytes),
42
+ requestTimeoutMs: t?.requestTimeoutMs ?? i(e.VOLTRO_MCP_TIMEOUT_MS, r.requestTimeoutMs)
43
+ }), o = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF\u{E0000}-\u{E007F}]/gu, s = (e, t) => {
44
+ let n = (typeof e == "string" ? e : e == null ? "" : String(e)).replace(o, "").replace(/\n{3,}/g, "\n\n").trim();
45
+ return n.length <= t ? n : `${n.slice(0, t)}… [truncated by Voltro]`;
46
+ }, c = "app_", l = (e) => `${c}${e.replace(/[^A-Za-z0-9_-]/g, "_")}`, u = (e) => e.startsWith(c), d = {
47
+ type: "object",
48
+ properties: {},
49
+ additionalProperties: !0
50
+ }, f = (e, t) => {
51
+ let n = [...e.dropped], r = [], i = /* @__PURE__ */ new Set(), a = [...e.tools].sort((e, t) => e.tag.localeCompare(t.tag));
52
+ for (let e of a) {
53
+ let a = l(e.tag);
54
+ if (i.has(a)) {
55
+ n.push({
56
+ name: e.tag,
57
+ reason: `its MCP tool name "${a}" collides with another tag`
58
+ });
59
+ continue;
60
+ }
61
+ if (r.length >= t.maxTools) {
62
+ n.push({
63
+ name: e.tag,
64
+ reason: `over maxTools (${t.maxTools})`
65
+ });
66
+ continue;
67
+ }
68
+ i.add(a);
69
+ let o = e.input;
70
+ r.push({
71
+ tag: e.tag,
72
+ tool: {
73
+ name: a,
74
+ description: `[${e.write ? "WRITE" : "read"}] ${e.tag} — ` + s(e.description, t.maxDescriptionChars),
75
+ inputSchema: o !== void 0 && o.type === "object" ? o : d
76
+ }
77
+ });
78
+ }
79
+ return {
80
+ mounted: r,
81
+ dropped: n
82
+ };
83
+ }, p = (e, t) => {
84
+ let n = e.VOLTRO_INSPECT_TOKEN, r = e.VOLTRO_INSPECT_WRITE_TOKEN, i = e.VOLTRO_AGENT_TOKEN;
85
+ return {
86
+ baseUrl: e.VOLTRO_INSPECT_URL ?? "http://localhost:4000",
87
+ ...n === void 0 ? {} : { inspectToken: n },
88
+ ...r === void 0 ? {} : { inspectWriteToken: r },
89
+ ...i === void 0 ? {} : { agentToken: i },
90
+ bounds: a(e, t)
91
+ };
92
+ }, m = async (e, t) => {
93
+ let n = e.body;
94
+ if (n === null || typeof n.getReader != "function") {
95
+ let n = await e.text();
96
+ return n.length > t ? n.slice(0, t) : n;
97
+ }
98
+ let r = n.getReader(), i = new TextDecoder(), a = "", o = 0;
99
+ try {
100
+ for (;;) {
101
+ let { done: e, value: n } = await r.read();
102
+ if (e) break;
103
+ if (n !== void 0) {
104
+ if (o += n.byteLength, o > t) return `${a}\n… [truncated by Voltro: over ${t} bytes]`;
105
+ a += i.decode(n, { stream: !0 });
106
+ }
107
+ }
108
+ } finally {
109
+ await r.cancel().catch(() => void 0);
110
+ }
111
+ return a + i.decode();
112
+ }, h = async (e, t, n) => {
113
+ let r = e.fetchImpl ?? ((...e) => fetch(...e)), i = new URL(t, e.baseUrl), a = {
114
+ accept: "application/json",
115
+ ...n.extraHeaders ?? {}
116
+ };
117
+ e.inspectToken !== void 0 && (a.authorization = `Bearer ${e.inspectToken}`), n.body !== void 0 && (a["content-type"] = "application/json");
118
+ let o = await r(i, {
119
+ method: n.method,
120
+ headers: a,
121
+ ...n.body === void 0 ? {} : { body: n.body },
122
+ signal: AbortSignal.timeout(e.bounds.requestTimeoutMs)
123
+ });
124
+ return {
125
+ status: o.status,
126
+ text: await m(o, e.bounds.maxResultBytes)
127
+ };
128
+ }, g = async (e) => {
129
+ try {
130
+ let { status: t, text: n } = await h(e, "/_voltro/inspect/agent/tools", { method: "GET" });
131
+ if (t !== 200) return {
132
+ enabled: !1,
133
+ reason: `the app answered HTTP ${t} for /_voltro/inspect/agent/tools` + (t === 401 ? " — is VOLTRO_INSPECT_TOKEN set, and does it match the app?" : ""),
134
+ tools: [],
135
+ dropped: []
136
+ };
137
+ let r = JSON.parse(n);
138
+ return {
139
+ enabled: r.enabled === !0,
140
+ ...r.reason === void 0 ? {} : { reason: r.reason },
141
+ tools: Array.isArray(r.tools) ? r.tools : [],
142
+ dropped: Array.isArray(r.dropped) ? r.dropped : []
143
+ };
144
+ } catch (t) {
145
+ return {
146
+ enabled: !1,
147
+ reason: `could not reach ${e.baseUrl}: ${String(t)}`,
148
+ tools: [],
149
+ dropped: []
150
+ };
151
+ }
152
+ }, _ = async (e, t, n) => {
153
+ if (e.agentToken === void 0 || e.agentToken.trim() === "") return "Error: no VOLTRO_AGENT_TOKEN is configured for this MCP server, so there is no app identity to execute as. The inspect token authorises the transport only. Set VOLTRO_AGENT_TOKEN to an app credential (e.g. an API key) scoped to what this agent may do. Nothing was sent to the app.";
154
+ if (e.inspectWriteToken === void 0 || e.inspectWriteToken.trim() === "") return "Error: no VOLTRO_INSPECT_WRITE_TOKEN is configured. Executing an app tool is a non-GET inspect call and needs the write credential in addition to the read token. Nothing was sent to the app.";
155
+ try {
156
+ let { status: r, text: i } = await h(e, "/_voltro/inspect/agent/call", {
157
+ method: "POST",
158
+ body: JSON.stringify({
159
+ tool: t,
160
+ input: n
161
+ }),
162
+ extraHeaders: {
163
+ "x-voltro-inspect-write": e.inspectWriteToken,
164
+ "x-voltro-agent-authorization": `Bearer ${e.agentToken}`
165
+ }
166
+ });
167
+ if (r !== 200) return `Error: the app refused the call with HTTP ${r}: ${i}`;
168
+ let a = JSON.parse(i);
169
+ return a.ok === !0 ? typeof a.result == "string" ? a.result : JSON.stringify(a.result ?? null, null, 2) : `Error: ${JSON.stringify(a.error ?? "the call failed with no error payload")}`;
170
+ } catch (t) {
171
+ return `Error: could not reach the app at ${e.baseUrl}: ${String(t)}`;
172
+ }
173
+ }, v = async (e) => {
174
+ try {
175
+ let { status: t, text: n } = await h(e, "/_voltro/inspect/checks", { method: "GET" });
176
+ return t === 200 ? n : `Error: the app answered HTTP ${t} for /_voltro/inspect/checks` + (t === 401 ? " — is VOLTRO_INSPECT_TOKEN set, and does it match the app?" : "");
177
+ } catch (t) {
178
+ return `Error: could not reach the app at ${e.baseUrl}: ${String(t)}`;
179
+ }
180
+ }, y = (e, t = {}) => {
181
+ let n = t.ttlMs ?? 1e4, r = t.now ?? Date.now, i = -Infinity, a, o = async () => {
182
+ if (a !== void 0 && r() - i < n) return a;
183
+ let t = await g(e), o = f(t, e.bounds);
184
+ return a = {
185
+ mounted: o.mounted,
186
+ dropped: t.enabled ? [...o.dropped] : [...o.dropped, {
187
+ name: "(all)",
188
+ reason: t.reason ?? "the app exposes no agent tools"
189
+ }]
190
+ }, i = r(), a;
191
+ };
192
+ return {
193
+ appTools: o,
194
+ callAppTool: async (t, n) => {
195
+ let { mounted: r } = await o();
196
+ return r.some((e) => e.tag === t) ? _(e, t, n) : `Error: '${t}' is not an executable agent tool on this app right now. Call tools/list again — the set is refreshed from the app, and a tool can be withdrawn by policy.`;
197
+ },
198
+ invariantChecks: () => v(e)
199
+ };
200
+ }, b = {
201
+ type: "object",
202
+ properties: {},
203
+ additionalProperties: !1
204
+ }, x = [
205
+ {
206
+ name: "voltro_list_procedures",
207
+ description: "List every rpc procedure (queries, mutations, actions, streams) in the app with its kind. Markers: [public-rest] = also served as a public REST endpoint, [agent-tool] = exposed as an in-app agent tool. Use this to discover what the backend exposes before writing UI or agent code.",
208
+ inputSchema: b
209
+ },
210
+ {
211
+ name: "voltro_get_procedure",
212
+ description: "Get one procedure's full metadata by its tag (e.g. 'todos.create'): kind, input/output JSON Schema, source file(s), the tables it reads/writes (targets), and its public-REST / agent-tool projection when present. Use the input schema to drive a form / a tool call; the output schema to type the result.",
213
+ inputSchema: {
214
+ type: "object",
215
+ properties: { tag: {
216
+ type: "string",
217
+ description: "The rpc tag, e.g. \"todos.create\"."
218
+ } },
219
+ required: ["tag"],
220
+ additionalProperties: !1
221
+ }
222
+ },
223
+ {
224
+ name: "voltro_search_procedures",
225
+ description: "Find procedures whose tag contains the query substring (case-insensitive).",
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: { query: { type: "string" } },
229
+ required: ["query"],
230
+ additionalProperties: !1
231
+ }
232
+ },
233
+ {
234
+ name: "voltro_list_tables",
235
+ description: "List the app's USER tables (framework-internal tables excluded) with column count and reactivity. Use voltro_get_table for the full column list of one table.",
236
+ inputSchema: b
237
+ },
238
+ {
239
+ name: "voltro_get_table",
240
+ description: "Get one table's full column list (name, type, nullability, foreign-key target, enum values) by table name.",
241
+ inputSchema: {
242
+ type: "object",
243
+ properties: { name: {
244
+ type: "string",
245
+ description: "The table name, e.g. \"todos\"."
246
+ } },
247
+ required: ["name"],
248
+ additionalProperties: !1
249
+ }
250
+ },
251
+ {
252
+ name: "voltro_list_workflows",
253
+ description: "List the durable workflows registered in the app.",
254
+ inputSchema: b
255
+ },
256
+ {
257
+ name: "voltro_list_widgets",
258
+ description: "List the schema-driven-UI widget kinds the app supports — the enumerable set a generated UI binds to.",
259
+ inputSchema: b
260
+ },
261
+ {
262
+ name: "voltro_check_invariants",
263
+ description: "Verify your own work: run the framework's invariant checks against the RUNNING app and get a machine-readable verdict. Checks: browser-safety (does the generated rpcGroup transitively import a server-only module — returns the exact import chain), procedure-access (does every wire-exposed procedure declare `guards:` or `openAccess:`), schema-convergence (has the live schema drifted, are operations pending), server-only-exposure (does a query output a `.serverOnly()` column). Each check answers pass | fail | unavailable; `unavailable` means THIS process cannot answer it (a deployed `voltro serve` has no source tree to walk) and is never a pass. Call this after editing schema, descriptors or shared lib/ files.",
264
+ inputSchema: b
265
+ }
266
+ ], S = (e) => {
267
+ let t = [...e.publicApi === void 0 ? [] : [" [public-rest]"], ...e.exposeAsTool === void 0 ? [] : [" [agent-tool]"]].join("");
268
+ return `${e.tag} (${e.kind})${t}`;
269
+ }, C = (e) => `${e.name} (${e.columns.length} column${e.columns.length === 1 ? "" : "s"}${e.reactive ? ", reactive" : ""})`, w = (e, t) => t.error === void 0 ? `(no ${e})` : `(no ${e} — manifest unavailable: ${t.error}. Is the api running at VOLTRO_INSPECT_URL, and is VOLTRO_INSPECT_TOKEN set if the inspect surface is gated?)`, T = (e, t, n) => {
270
+ let r = e.manifest;
271
+ switch (t) {
272
+ case "voltro_list_procedures": return r.procedures.length === 0 ? w("procedures", e) : r.procedures.map(S).join("\n");
273
+ case "voltro_get_procedure": {
274
+ let e = String(n.tag ?? ""), t = r.procedures.find((t) => t.tag === e);
275
+ return t === void 0 ? `No procedure with tag "${e}". Call voltro_list_procedures to see available tags.` : JSON.stringify({
276
+ tag: t.tag,
277
+ kind: t.kind,
278
+ input: t.input,
279
+ output: t.output,
280
+ ...t.source === void 0 ? {} : { source: t.source },
281
+ ...t.targets === void 0 ? {} : { targets: t.targets },
282
+ ...t.publicApi === void 0 ? {} : { publicApi: t.publicApi },
283
+ ...t.exposeAsTool === void 0 ? {} : { exposeAsTool: t.exposeAsTool }
284
+ }, null, 2);
285
+ }
286
+ case "voltro_search_procedures": {
287
+ let e = String(n.query ?? "").toLowerCase(), t = r.procedures.filter((t) => t.tag.toLowerCase().includes(e));
288
+ return t.length === 0 ? `(no procedures matching "${e}")` : t.map(S).join("\n");
289
+ }
290
+ case "voltro_list_tables": {
291
+ let t = r.tables ?? [];
292
+ return t.length === 0 ? w("tables", e) : t.map(C).join("\n");
293
+ }
294
+ case "voltro_get_table": {
295
+ let e = String(n.name ?? ""), t = (r.tables ?? []).find((t) => t.name === e);
296
+ return t === void 0 ? `No table named "${e}". Call voltro_list_tables to see available tables.` : JSON.stringify(t, null, 2);
297
+ }
298
+ case "voltro_list_workflows": return r.workflows.length === 0 ? w("workflows", e) : r.workflows.map((e) => e.name).join("\n");
299
+ case "voltro_list_widgets": {
300
+ let t = r.widgets ?? [];
301
+ return t.length === 0 ? w("widgets", e) : t.join("\n");
302
+ }
303
+ case "voltro_check_invariants": throw Error(`'${t}' needs a live connection to the app and must be dispatched through handleMcpRequestAsync; this transport routed it to the pure handler.`);
304
+ default: throw Error(`unknown tool: ${t}`);
305
+ }
306
+ }, E = "application/json", D = "voltro://manifest", O = (e) => `voltro://procedure/${e}`, k = (e) => `voltro://table/${e}`, A = (e) => {
307
+ let t = e.manifest;
308
+ return [
309
+ {
310
+ uri: D,
311
+ name: "Capability manifest",
312
+ description: "The full app capability manifest: every procedure, table, workflow and widget kind as JSON.",
313
+ mimeType: E
314
+ },
315
+ ...t.procedures.map((e) => ({
316
+ uri: O(e.tag),
317
+ name: e.tag,
318
+ description: `The ${e.kind} "${e.tag}" — its input/output JSON Schema, source, and table targets.`,
319
+ mimeType: E
320
+ })),
321
+ ...(t.tables ?? []).map((e) => ({
322
+ uri: k(e.name),
323
+ name: e.name,
324
+ description: `The "${e.name}" table — its full column list (types, nullability, foreign keys, enums).`,
325
+ mimeType: E
326
+ }))
327
+ ];
328
+ }, j = class extends Error {
329
+ uri;
330
+ _tag = "UnknownResourceError";
331
+ constructor(e) {
332
+ super(`no resource at "${e}"`), this.uri = e, this.name = "UnknownResourceError";
333
+ }
334
+ }, M = (e, t) => {
335
+ let n = e.manifest, r = (e) => [{
336
+ uri: t,
337
+ mimeType: E,
338
+ text: JSON.stringify(e, null, 2)
339
+ }];
340
+ if (t === "voltro://manifest") return r(n);
341
+ let i = t.startsWith("voltro://procedure/") ? t.slice(19) : void 0;
342
+ if (i !== void 0) {
343
+ let e = n.procedures.find((e) => e.tag === i);
344
+ if (e === void 0) throw new j(t);
345
+ return r(e);
346
+ }
347
+ let a = t.startsWith("voltro://table/") ? t.slice(15) : void 0;
348
+ if (a !== void 0) {
349
+ let e = (n.tables ?? []).find((e) => e.name === a);
350
+ if (e === void 0) throw new j(t);
351
+ return r(e);
352
+ }
353
+ throw new j(t);
354
+ }, N = [
355
+ {
356
+ name: "scaffold_procedure",
357
+ description: "Draft a new Voltro rpc procedure (query/mutation/action) following the app's existing conventions, grounded in the current manifest so it references real tables and matches the shape of siblings.",
358
+ arguments: [{
359
+ name: "kind",
360
+ description: "query | mutation | action",
361
+ required: !0
362
+ }, {
363
+ name: "purpose",
364
+ description: "What the procedure should do, in one sentence.",
365
+ required: !0
366
+ }]
367
+ },
368
+ {
369
+ name: "explain_table",
370
+ description: "Explain one table's schema and how the app's procedures read/write it, from the live manifest.",
371
+ arguments: [{
372
+ name: "table",
373
+ description: "The table name, e.g. \"todos\".",
374
+ required: !0
375
+ }]
376
+ },
377
+ {
378
+ name: "wire_ui_for_procedure",
379
+ description: "Generate the client code to call one procedure and render its result, using the procedure's real input/output JSON Schema from the manifest.",
380
+ arguments: [{
381
+ name: "tag",
382
+ description: "The rpc tag, e.g. \"todos.list\".",
383
+ required: !0
384
+ }]
385
+ }
386
+ ], P = class extends Error {
387
+ promptName;
388
+ _tag = "UnknownPromptError";
389
+ constructor(e) {
390
+ super(`no prompt named "${e}"`), this.promptName = e, this.name = "UnknownPromptError";
391
+ }
392
+ }, F = class extends Error {
393
+ promptName;
394
+ argument;
395
+ _tag = "MissingPromptArgumentError";
396
+ constructor(e, t) {
397
+ super(`prompt "${e}" requires the "${t}" argument`), this.promptName = e, this.argument = t, this.name = "MissingPromptArgumentError";
398
+ }
399
+ }, I = () => N, L = (e) => ({
400
+ role: "user",
401
+ content: {
402
+ type: "text",
403
+ text: e
404
+ }
405
+ }), R = (e, t, n) => {
406
+ let r = t[n];
407
+ if (typeof r != "string" || r === "") throw new F(e, n);
408
+ return r;
409
+ }, z = (e, t, n = {}) => {
410
+ let r = e.manifest;
411
+ switch (t) {
412
+ case "scaffold_procedure": {
413
+ let e = R(t, n, "kind"), i = R(t, n, "purpose"), a = (r.tables ?? []).map((e) => e.name).join(", ") || "(none discovered)", o = r.procedures.filter((t) => t.kind === e).map((e) => e.tag).slice(0, 10).join(", ") || "(none yet)";
414
+ return {
415
+ description: `Scaffold a ${e} procedure`,
416
+ messages: [L(`Write a new Voltro ${e} procedure that: ${i}.\n\nThe app's tables are: ${a}.\nExisting ${e} procedures (match their file-convention and shape): ${o}.\n\nFollow the Voltro file conventions for a ${e} descriptor + its server handler, define the input/output with the schema DSL, and only reference tables that exist above.`)]
417
+ };
418
+ }
419
+ case "explain_table": {
420
+ let e = R(t, n, "table"), i = (r.tables ?? []).find((t) => t.name === e), a = r.procedures.filter((t) => (t.targets ?? []).some((t) => t.table === e)).map((t) => `${t.tag} (${(t.targets ?? []).filter((t) => t.table === e).map((e) => e.op).join("/")})`).join(", ") || "(none)", o = i === void 0 ? `(no table named "${e}" in the manifest)` : JSON.stringify(i, null, 2);
421
+ return {
422
+ description: `Explain the ${e} table`,
423
+ messages: [L(`Explain the "${e}" table of this Voltro app: its columns and their meaning, and how the app uses it.\n\nSchema:\n${o}\n\nProcedures touching it: ${a}.`)]
424
+ };
425
+ }
426
+ case "wire_ui_for_procedure": {
427
+ let e = R(t, n, "tag"), i = r.procedures.find((t) => t.tag === e), a = i === void 0 ? `(no procedure with tag "${e}" in the manifest)` : JSON.stringify({
428
+ tag: i.tag,
429
+ kind: i.kind,
430
+ input: i.input,
431
+ output: i.output
432
+ }, null, 2);
433
+ return {
434
+ description: `Wire UI for ${e}`,
435
+ messages: [L(`Write the Voltro client code to call the "${e}" procedure and render its result.\n\nProcedure:\n${a}\n\nUse the correct Voltro hook for this procedure kind, type the call from the input/output schema above, and render a minimal but complete UI for the result.`)]
436
+ };
437
+ }
438
+ default: throw new P(t);
439
+ }
440
+ }, B = "2025-06-18", V = [
441
+ B,
442
+ "2025-03-26",
443
+ "2024-11-05"
444
+ ], H = {
445
+ name: "voltro-mcp",
446
+ version: "0.1.0"
447
+ }, U = (e) => typeof e == "string" && V.includes(e) ? e : B, W = (e, t, n = H) => {
448
+ if ((t.id === void 0 || t.id === null) && t.method.startsWith("notifications/")) return null;
449
+ let r = t.id ?? null, i = (e) => ({
450
+ jsonrpc: "2.0",
451
+ id: r,
452
+ result: e
453
+ }), a = (e, t) => ({
454
+ jsonrpc: "2.0",
455
+ id: r,
456
+ error: {
457
+ code: e,
458
+ message: t
459
+ }
460
+ });
461
+ switch (t.method) {
462
+ case "initialize": return i({
463
+ protocolVersion: U(t.params?.protocolVersion),
464
+ capabilities: {
465
+ tools: {},
466
+ resources: {},
467
+ prompts: {}
468
+ },
469
+ serverInfo: n
470
+ });
471
+ case "ping": return i({});
472
+ case "tools/list": return i({ tools: x });
473
+ case "tools/call": {
474
+ let n = t.params ?? {}, r = String(n.name ?? ""), a = n.arguments ?? {};
475
+ try {
476
+ return i({ content: [{
477
+ type: "text",
478
+ text: T(e, r, a)
479
+ }] });
480
+ } catch (e) {
481
+ return i({
482
+ content: [{
483
+ type: "text",
484
+ text: `Error: ${String(e)}`
485
+ }],
486
+ isError: !0
487
+ });
488
+ }
489
+ }
490
+ case "resources/list": return i({ resources: A(e) });
491
+ case "resources/read": {
492
+ let n = String(t.params?.uri ?? "");
493
+ try {
494
+ return i({ contents: M(e, n) });
495
+ } catch (e) {
496
+ if (e instanceof j) return a(-32602, e.message);
497
+ throw e;
498
+ }
499
+ }
500
+ case "prompts/list": return i({ prompts: I() });
501
+ case "prompts/get": {
502
+ let n = String(t.params?.name ?? ""), r = t.params?.arguments ?? {};
503
+ try {
504
+ return i(z(e, n, r));
505
+ } catch (e) {
506
+ if (e instanceof P || e instanceof F) return a(-32602, e.message);
507
+ throw e;
508
+ }
509
+ }
510
+ default: return t.method.startsWith("notifications/") ? null : a(-32601, `method not found: ${t.method}`);
511
+ }
512
+ }, G = async (e, t, n = H, r) => {
513
+ let i = t.id ?? null, a = (e) => ({
514
+ jsonrpc: "2.0",
515
+ id: i,
516
+ result: e
517
+ }), o = (e, t = !1) => a({
518
+ content: [{
519
+ type: "text",
520
+ text: e
521
+ }],
522
+ ...t ? { isError: !0 } : {}
523
+ });
524
+ if (t.method === "tools/list") {
525
+ let i = W(e, t, n);
526
+ if (r === void 0 || i === null) return i;
527
+ let { mounted: o } = await r.appTools(), s = i.result;
528
+ return a({ tools: [...s.tools, ...o.map((e) => e.tool)] });
529
+ }
530
+ if (t.method === "tools/call") {
531
+ let e = t.params ?? {}, n = String(e.name ?? ""), i = e.arguments ?? {};
532
+ if (u(n)) {
533
+ if (r === void 0) return o(`Error: '${n}' is an app tool and this server has no live connection configured. Set VOLTRO_INSPECT_URL / VOLTRO_INSPECT_TOKEN.`, !0);
534
+ let { mounted: e } = await r.appTools(), t = e.find((e) => e.tool.name === n);
535
+ return t === void 0 ? o(`Error: no app tool named '${n}'. The set is refreshed from the running app — call tools/list again.`, !0) : o(await r.callAppTool(t.tag, i));
536
+ }
537
+ if (n === "voltro_check_invariants") return r === void 0 ? o("Error: the invariant checks need a live connection to the app. Set VOLTRO_INSPECT_URL / VOLTRO_INSPECT_TOKEN and reconnect.", !0) : o(await r.invariantChecks());
538
+ }
539
+ return W(e, t, n);
540
+ };
541
+ //#endregion
542
+ export { e as A, g as C, y as D, p as E, t as M, f as O, _ as S, u as T, T as _, G as a, l as b, N as c, I as d, D as f, x as g, M as h, W as i, n as j, a as k, P as l, A as m, H as n, U as o, j as p, V as r, F as s, B as t, z as u, c as v, v as w, s as x, r as y };
@@ -0,0 +1,47 @@
1
+ import { D as e, E as t, a as n, j as r, n as i } from "./mcp-CZJe2Frv.js";
2
+ import { createRequire as a } from "node:module";
3
+ //#region src/serve.ts
4
+ var o = () => {
5
+ try {
6
+ let e = a(import.meta.url)("../package.json");
7
+ return {
8
+ name: i.name,
9
+ version: e.version ?? i.version
10
+ };
11
+ } catch {
12
+ return i;
13
+ }
14
+ }, s = async (i) => {
15
+ let a = i.env.VOLTRO_INSPECT_URL ?? "http://localhost:4000", s = i.env.VOLTRO_INSPECT_TOKEN, c = i.serverInfo ?? o(), l = r({
16
+ baseUrl: a,
17
+ ...s === void 0 ? {} : { token: s },
18
+ ...i.manifestTtlMs === void 0 ? {} : { ttlMs: i.manifestTtlMs }
19
+ }), u = i.live ?? e(t(i.env), ...i.manifestTtlMs === void 0 ? [] : [{ ttlMs: i.manifestTtlMs }]), d = await l.get();
20
+ d.error === void 0 ? i.errput.write(`voltro-mcp: loaded ${d.manifest.procedures.length} procedures from ${a}\n`) : i.errput.write(`voltro-mcp: could not fetch manifest from ${a}: ${d.error} — serving empty manifest\n`);
21
+ let f = async (e) => {
22
+ if (e === "") return;
23
+ let t;
24
+ try {
25
+ t = JSON.parse(e);
26
+ } catch {
27
+ return;
28
+ }
29
+ let r = Array.isArray(t) ? t : [t];
30
+ for (let e of r) {
31
+ (e.method === "tools/call" || e.method === "tools/list") && (d = await l.get());
32
+ let t = await n(d, e, c, u);
33
+ t !== null && i.output.write(`${JSON.stringify(t)}\n`);
34
+ }
35
+ }, p = "";
36
+ for await (let e of i.input) {
37
+ p += String(e);
38
+ let t = p.indexOf("\n");
39
+ for (; t !== -1;) {
40
+ let e = p.slice(0, t).trim();
41
+ p = p.slice(t + 1), await f(e), t = p.indexOf("\n");
42
+ }
43
+ }
44
+ await f(p.trim());
45
+ };
46
+ //#endregion
47
+ export { s as n, o as t };
package/dist/server.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as e } from "./serve-CRW_Na4H.js";
2
+ import { n as e } from "./serve-ZSmqUcRM.js";
3
3
  //#region src/server.ts
4
4
  e({
5
5
  input: process.stdin,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/mcp",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "MCP server for coding agents over a running Voltro api — exposes the app's procedures, tables, workflows and their JSON Schemas as MCP tools, resources and prompts, over stdio (voltro-mcp) or Streamable HTTP (voltro-mcp-http). Zero dependencies.",
5
5
  "keywords": [
6
6
  "voltro",