@voltro/mcp 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `@voltro/*` packages are recorded here. The format
4
+ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## Stability contract — read this before you pin a version
7
+
8
+ Voltro is **`0.x` — pre-1.0, and deliberately so.** Under SemVer, `0.y.z` means
9
+ "anything MAY change." We hold to exactly that, stated out loud:
10
+
11
+ - **Pin exact versions.** Depend on `@voltro/runtime@0.4.2`, never `^0.4.2` or
12
+ `~0.4.2`. There is no compatible-range promise below 1.0.
13
+ - **Every MINOR may break.** Breaking changes land on a minor bump (`0.4.x →
14
+ 0.5.0`); patches (`0.4.1 → 0.4.2`) are additive or fixes only. This is the
15
+ standard `0.x` reading of SemVer — the minor slot carries breaking under `0.x`.
16
+ - **Read this changelog before upgrading.** The `⚠ BREAKING` section of each
17
+ release lists every incompatible change with its migration. It is the only
18
+ migration path we provide — there is no deprecation cycle, no compat shim.
19
+ - **All packages release together (lockstep).** One coordinated version across
20
+ the whole framework; the git tag is the source of truth.
21
+
22
+ This is not a placeholder disclaimer — it is the contract. The framework is
23
+ refactored aggressively while it has no external stability obligations, and that
24
+ velocity is the point. A stable-core tier and per-package `1.0` graduation are
25
+ planned, but not yet; until then, treat the whole surface as movable and pin
26
+ exact.
27
+
28
+ The **public API** of each package is its `publishConfig.exports` entry points,
29
+ minus anything marked `@internal` (those are cross-package internals and are
30
+ stripped from the published `.d.ts`). Importing a deep path that isn't an
31
+ exported entry point is unsupported.
32
+
33
+ ---
34
+
35
+ ## [Unreleased]
36
+
37
+ _Changes staged for the next release accumulate here (rolled up from
38
+ `.changes/*.md` at tag time — see `.changes/README.md`)._
39
+
40
+ ---
41
+
42
+ ## [0.1.0]
43
+
44
+ Initial pre-release baseline. This is the starting point the changelog tracks
45
+ from; it is not an exhaustive history of prior development. The framework ships
46
+ as `@voltro/*` packages spanning the runtime, database/query layer, web client
47
+ and router, durable workflows, the CLI, and the plugin ecosystem
48
+ (auth, storage, mail, billing, observability, and more). Not published to a
49
+ public registry yet.
50
+
51
+ Subsequent releases record their deltas from here under dated headings, with
52
+ `⚠ BREAKING` first.
package/LICENSE ADDED
@@ -0,0 +1,57 @@
1
+ Voltro — Proprietary Software License
2
+
3
+ Copyright (c) 2026 Voltro UG. All rights reserved.
4
+
5
+ This software and all associated source code, documentation, and other
6
+ materials (the "Software") are the proprietary property of Voltro UG
7
+ ("Voltro"). This is NOT open-source software.
8
+
9
+ Your access to and use of the Software is governed exclusively by the Voltro
10
+ Terms of Service at:
11
+
12
+ https://voltro.cloud/legal/terms
13
+
14
+ By downloading, installing, or using the Software you agree to those Terms.
15
+ Subject to and conditioned on your continued compliance with them, Voltro
16
+ grants you a limited, non-exclusive, non-transferable, non-sublicensable,
17
+ revocable license to use the Software. All rights not expressly granted in the
18
+ Terms are reserved by Voltro. If you do not agree to the Terms, you have no
19
+ license and may not use the Software.
20
+
21
+ The Terms of Service — including the scope of permitted use, plan
22
+ entitlements, fees, and pricing — may change from time to time. The version in
23
+ force is the one published at the URL above. Commercial terms and pricing are
24
+ NOT part of this notice and are not fixed by, or granted in perpetuity by, the
25
+ version of the Software in which this file appears.
26
+
27
+ Permitted use — your own software. Voltro is a development framework. You may
28
+ use the Software to build, run, and commercially distribute your own
29
+ applications and services, and to charge your own customers for them, without
30
+ owing Voltro any share of that revenue or any further permission beyond the
31
+ Terms. Applications you build with the Software are yours.
32
+
33
+ Prohibited use — reselling Voltro. You may NOT redistribute, resell,
34
+ sublicense, publish, or otherwise provide the Software itself — in whole or in
35
+ part, in source or compiled form — to third parties as a library, framework,
36
+ SDK, template, starter, or development tool for them to build upon, whether
37
+ standalone or repackaged. Shipping the Software as a non-separable, bundled
38
+ dependency inside an application you deliver (for example, compiled into your
39
+ deployed app) is permitted; extracting or re-exposing it as a reusable
40
+ component for others is not.
41
+
42
+ Except as expressly permitted above or by the Terms, you may not copy, modify,
43
+ merge, publish, sublicense, sell, distribute, or create derivative works of the
44
+ Software, in whole or in part.
45
+
46
+ Third-party open-source components distributed alongside the Software are the
47
+ property of their respective owners and are licensed under their own terms; see
48
+ THIRD-PARTY-NOTICES.md where provided. Nothing in this notice limits your
49
+ rights, or extends Voltro's, in those components.
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ VOLTRO BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM,
55
+ OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR ITS USE.
56
+
57
+ For licensing inquiries, contact Voltro UG.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ <div align="center">
2
+
3
+ # @voltro/mcp
4
+
5
+ **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.**
6
+
7
+ [📖 Documentation](https://docs.voltro.dev/docs/cli/mcp) · [Changelog](./CHANGELOG.md) · [voltro.dev](https://voltro.dev) · [Voltro Cloud](https://voltro.cloud)
8
+
9
+ </div>
10
+
11
+ ---
12
+
13
+ ```sh
14
+ npm install @voltro/mcp
15
+ ```
16
+
17
+ > ### [→ Read the documentation for @voltro/mcp](https://docs.voltro.dev/docs/cli/mcp)
18
+
19
+ Installation, guides, the full API reference, and examples all live in the
20
+ **[Voltro documentation](https://docs.voltro.dev/docs/intro/getting-started)** — the single source of truth. This README is
21
+ deliberately short so there is nothing here to drift out of date.
22
+
23
+ ## License
24
+
25
+ Proprietary. © 2026 Voltro UG. Your use is governed by the
26
+ [Terms of Service](https://voltro.cloud/legal/terms). See the bundled `LICENSE`.
package/SECURITY.md ADDED
@@ -0,0 +1,56 @@
1
+ # Security Policy
2
+
3
+ We take the security of Voltro and the applications built on it seriously. This
4
+ document explains how to report a vulnerability and what to expect in return.
5
+
6
+ ## Reporting a vulnerability
7
+
8
+ **Please do not open public issues or discuss suspected vulnerabilities in
9
+ public channels.** Report them privately by email:
10
+
11
+ **security contact: [support@voltro.dev](mailto:support@voltro.dev)**
12
+ (subject line: `SECURITY`).
13
+
14
+ Include, where you can:
15
+
16
+ - the affected package(s) and version(s) (e.g. `@voltro/runtime@x.y.z`);
17
+ - a description of the issue and its impact;
18
+ - a minimal reproduction or proof of concept;
19
+ - any suggested remediation.
20
+
21
+ If you'd like to encrypt your report, ask in a first plain email and we'll
22
+ arrange a key.
23
+
24
+ ## What to expect
25
+
26
+ - **Acknowledgement** of your report within **3 business days**.
27
+ - An initial assessment (severity, affected surface) and a remediation plan as
28
+ soon as we've reproduced the issue.
29
+ - **Coordinated disclosure:** we'll agree a disclosure timeline with you and
30
+ credit you in the release notes if you wish. Please give us reasonable time to
31
+ ship a fix before any public disclosure.
32
+
33
+ We do not currently run a paid bug-bounty program, but we genuinely appreciate
34
+ responsible disclosure and will credit reporters.
35
+
36
+ ## Software Bill of Materials (SBOM)
37
+
38
+ A CycloneDX SBOM of the third-party runtime dependency graph is generated for the
39
+ published packages (`pnpm gen:sbom` → `sbom.cdx.json`). If your procurement or
40
+ security team needs it, request it at
41
+ [support@voltro.dev](mailto:support@voltro.dev).
42
+
43
+ ## Supported versions
44
+
45
+ Voltro is pre-1.0 and ships in lockstep: **only the latest published minor of
46
+ each `@voltro/*` package receives security fixes.** Please upgrade to the latest
47
+ release before reporting, and pin exact versions in production.
48
+
49
+ ## Scope
50
+
51
+ In scope: the published `@voltro/*` packages and the framework's own code.
52
+
53
+ Out of scope: vulnerabilities in third-party dependencies that are already
54
+ tracked upstream (we monitor these via a production-dependency audit gate in
55
+ CI), and issues that require a non-default, explicitly-unsafe configuration. If
56
+ you're unsure, report it anyway — we'd rather hear about it.
@@ -0,0 +1,11 @@
1
+ # Third-Party Notices — @voltro/mcp
2
+
3
+ This package depends on the open-source software listed below. Each is the
4
+ property of its respective copyright holders and is used under the terms of
5
+ its license. This file is provided for attribution; it grants no rights in
6
+ @voltro/mcp itself, which is proprietary (see LICENSE).
7
+
8
+ Generated from the resolved runtime dependency closure (0 packages).
9
+
10
+ ---
11
+
@@ -0,0 +1,103 @@
1
+ import { i as e } from "./mcp-Br4DcrKz.js";
2
+ import { randomUUID as t } from "node:crypto";
3
+ //#region src/http.ts
4
+ var n = "mcp-session-id", r = "application/json", i = "text/event-stream", a = (e) => e.some((e) => e.method === "initialize"), o = (r) => {
5
+ let i = r.newSessionId ?? t;
6
+ if (r.method === "DELETE") return {
7
+ kind: "empty",
8
+ status: 204
9
+ };
10
+ if (r.method === "GET") return r.acceptsSse ? {
11
+ kind: "sse",
12
+ events: [],
13
+ keepOpen: !0
14
+ } : {
15
+ kind: "json",
16
+ status: 405,
17
+ body: c(null, "GET requires Accept: text/event-stream")
18
+ };
19
+ if (r.method !== "POST") return {
20
+ kind: "json",
21
+ status: 405,
22
+ body: c(null, `method ${r.method} not allowed`)
23
+ };
24
+ if (r.body === void 0 || r.body === null) return {
25
+ kind: "json",
26
+ status: 400,
27
+ body: s("empty POST body")
28
+ };
29
+ let o = Array.isArray(r.body) ? r.body : [r.body], l = a(o), u = r.headers[n];
30
+ if (!l && u === void 0) return {
31
+ kind: "json",
32
+ status: 400,
33
+ body: s("missing Mcp-Session-Id header")
34
+ };
35
+ let d = l ? u ?? i() : u, f = o.map((t) => e(r.snapshot, t, r.serverInfo)).filter((e) => e !== null);
36
+ return f.length === 0 ? {
37
+ kind: "empty",
38
+ status: 202
39
+ } : r.acceptsSse ? {
40
+ kind: "sse",
41
+ events: f,
42
+ keepOpen: !1,
43
+ ...d === void 0 ? {} : { sessionId: d }
44
+ } : {
45
+ kind: "json",
46
+ status: 200,
47
+ body: f.length === 1 ? f[0] : f,
48
+ ...d === void 0 ? {} : { sessionId: d }
49
+ };
50
+ }, s = (e) => ({
51
+ jsonrpc: "2.0",
52
+ id: null,
53
+ error: {
54
+ code: -32700,
55
+ message: e
56
+ }
57
+ }), c = (e, t) => ({
58
+ jsonrpc: "2.0",
59
+ id: e,
60
+ error: {
61
+ code: -32601,
62
+ message: t
63
+ }
64
+ }), l = (e) => `event: message\ndata: ${JSON.stringify(e)}\n\n`, u = (e) => e !== void 0 && e.split(",").some((e) => e.trim().startsWith(i)), d = async (e) => {
65
+ let t = "";
66
+ for await (let n of e) t += String(n);
67
+ if (t.trim() !== "") try {
68
+ return JSON.parse(t);
69
+ } catch {
70
+ return;
71
+ }
72
+ }, f = (e) => async (t, a) => {
73
+ let s = t.method ?? "GET", c = s === "POST" ? await d(t) : void 0, f = await e.source.get(), p = {};
74
+ for (let [e, n] of Object.entries(t.headers)) p[e.toLowerCase()] = Array.isArray(n) ? n[0] : n;
75
+ let m = o({
76
+ method: s,
77
+ headers: p,
78
+ body: c,
79
+ snapshot: f,
80
+ serverInfo: e.serverInfo,
81
+ acceptsSse: u(p.accept),
82
+ ...e.newSessionId === void 0 ? {} : { newSessionId: e.newSessionId }
83
+ });
84
+ if (m.kind === "empty") {
85
+ a.writeHead(m.status), a.end();
86
+ return;
87
+ }
88
+ if (m.kind === "json") {
89
+ let e = { "content-type": r };
90
+ m.sessionId !== void 0 && (e[n] = m.sessionId), a.writeHead(m.status, e), a.end(JSON.stringify(m.body));
91
+ return;
92
+ }
93
+ let h = {
94
+ "content-type": i,
95
+ "cache-control": "no-cache",
96
+ connection: "keep-alive"
97
+ };
98
+ m.sessionId !== void 0 && (h[n] = m.sessionId), a.writeHead(200, h);
99
+ for (let e of m.events) a.write(l(e));
100
+ m.keepOpen || a.end();
101
+ };
102
+ //#endregion
103
+ export { o as n, l as r, f as t };
@@ -0,0 +1 @@
1
+ export { }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { v as e } from "./mcp-Br4DcrKz.js";
3
+ import { t } from "./http-DFJ4CBnH.js";
4
+ import { t as n } from "./serve-7hA87wAd.js";
5
+ import { createServer as r } from "node:http";
6
+ //#endregion
7
+ //#region src/httpServer.ts
8
+ (async (i) => {
9
+ let a = i.env.VOLTRO_INSPECT_URL ?? "http://localhost:4000", o = i.env.VOLTRO_INSPECT_TOKEN, s = i.env.VOLTRO_MCP_HTTP_PATH ?? "/mcp", c = Number(i.env.VOLTRO_MCP_HTTP_PORT ?? "4100"), l = t({
10
+ source: e({
11
+ baseUrl: a,
12
+ ...o === void 0 ? {} : { token: o },
13
+ ...i.manifestTtlMs === void 0 ? {} : { ttlMs: i.manifestTtlMs }
14
+ }),
15
+ serverInfo: n(),
16
+ ...i.newSessionId === void 0 ? {} : { newSessionId: i.newSessionId }
17
+ }), u = r((e, t) => {
18
+ let n = (e.url ?? "/").split("?")[0];
19
+ if (n !== s) {
20
+ t.writeHead(404, { "content-type": "application/json" }), t.end(JSON.stringify({ error: `not found: ${n}` }));
21
+ return;
22
+ }
23
+ l(e, t);
24
+ });
25
+ await new Promise((e) => u.listen(c, e));
26
+ let d = u.address();
27
+ return {
28
+ server: u,
29
+ port: typeof d == "object" && d ? d.port : c,
30
+ path: s,
31
+ close: () => new Promise((e, t) => u.close((n) => n ? t(n) : e()))
32
+ };
33
+ })({ env: process.env });
34
+ //#endregion
@@ -0,0 +1,308 @@
1
+ import { IncomingMessage } from 'node:http';
2
+ import { ServerResponse } from 'node:http';
3
+
4
+ /** Pure tool dispatch → the text payload for an MCP `tools/call` result. */
5
+ export declare const callTool: (snapshot: ManifestSnapshot, name: string, args: Record<string, unknown>) => string;
6
+
7
+ export declare interface CapabilityManifest {
8
+ readonly version: number;
9
+ readonly procedures: ReadonlyArray<ManifestProcedure>;
10
+ readonly workflows: ReadonlyArray<{
11
+ readonly name: string;
12
+ }>;
13
+ /** The schema-driven-UI widget kinds — present from manifest v2. */
14
+ readonly widgets?: ReadonlyArray<string>;
15
+ /** USER tables (manifest v2) — graph nodes for tooling/agents. */
16
+ readonly tables?: ReadonlyArray<ManifestTable>;
17
+ }
18
+
19
+ /**
20
+ * A TTL-cached manifest source. The manifest is NOT a boot-time constant —
21
+ * during `voltro dev` procedures appear and disappear as files are saved —
22
+ * so every `tools/*` request reads through this source and picks up changes
23
+ * within `ttlMs`, instead of serving one stale process-lifetime snapshot.
24
+ */
25
+ export declare const createManifestSource: (options: ManifestSourceOptions) => ManifestSource;
26
+
27
+ export declare const EMPTY_MANIFEST: CapabilityManifest;
28
+
29
+ /** Fetch the live capability manifest from a running api. */
30
+ export declare const fetchManifest: (baseUrl: string, token?: string,
31
+ /** Abort the request after this long — a hung api must not hang the agent. */
32
+ timeoutMs?: number) => Promise<CapabilityManifest>;
33
+
34
+ /**
35
+ * Render a prompt against the live manifest. Throws `UnknownPromptError` for
36
+ * an unknown name and `MissingPromptArgumentError` for a missing required
37
+ * argument (the transport maps both to JSON-RPC errors).
38
+ */
39
+ export declare const getPrompt: (snapshot: ManifestSnapshot, name: string, args?: Record<string, unknown>) => McpGetPromptResult;
40
+
41
+ /**
42
+ * Handle one JSON-RPC request against the manifest snapshot. Returns the
43
+ * response, or `null` for a notification (a request with no `id`, e.g.
44
+ * `notifications/initialized`) which must NOT be answered.
45
+ */
46
+ export declare const handleMcpRequest: (snapshot: ManifestSnapshot, request: JsonRpcRequest, serverInfo?: ServerInfo) => JsonRpcResponse | null;
47
+
48
+ /** What `routeHttp` decided the transport should do. */
49
+ export declare type HttpOutcome =
50
+ /** Reply once with a JSON body + status (single JSON-RPC response, or an error). */
51
+ {
52
+ readonly kind: 'json';
53
+ readonly status: number;
54
+ readonly body: unknown;
55
+ readonly sessionId?: string;
56
+ }
57
+ /** Open an SSE stream and emit these JSON-RPC responses as `message` events, then (optionally) close. */
58
+ | {
59
+ readonly kind: 'sse';
60
+ readonly events: ReadonlyArray<JsonRpcResponse>;
61
+ readonly sessionId?: string;
62
+ readonly keepOpen: boolean;
63
+ }
64
+ /** No body (202 Accepted for notification-only POSTs; 204 for a DELETE). */
65
+ | {
66
+ readonly kind: 'empty';
67
+ readonly status: number;
68
+ };
69
+
70
+ export declare interface JsonRpcRequest {
71
+ readonly jsonrpc: '2.0';
72
+ readonly id?: string | number | null;
73
+ readonly method: string;
74
+ readonly params?: Record<string, unknown>;
75
+ }
76
+
77
+ export declare interface JsonRpcResponse {
78
+ readonly jsonrpc: '2.0';
79
+ readonly id: string | number | null;
80
+ readonly result?: unknown;
81
+ readonly error?: {
82
+ readonly code: number;
83
+ readonly message: string;
84
+ };
85
+ }
86
+
87
+ export declare const listPrompts: () => ReadonlyArray<McpPrompt>;
88
+
89
+ /**
90
+ * Every readable resource in the app: the whole manifest, one per rpc
91
+ * procedure, one per user table. Enumerated fresh from the snapshot so a
92
+ * procedure/table added mid-session appears on the next `resources/list`.
93
+ */
94
+ export declare const listResources: (snapshot: ManifestSnapshot) => ReadonlyArray<McpResource>;
95
+
96
+ /** The stable URI for the whole-manifest resource. */
97
+ export declare const MANIFEST_URI = "voltro://manifest";
98
+
99
+ export declare interface ManifestProcedure {
100
+ readonly tag: string;
101
+ readonly kind: string;
102
+ readonly input?: Record<string, unknown>;
103
+ readonly output?: Record<string, unknown>;
104
+ readonly source?: string | ReadonlyArray<string>;
105
+ readonly targets?: ReadonlyArray<{
106
+ readonly table: string;
107
+ readonly op: string;
108
+ }>;
109
+ /** Present when the descriptor is projected to a public REST endpoint. */
110
+ readonly publicApi?: Record<string, unknown>;
111
+ /** Present when the descriptor is exposed as an agent tool. */
112
+ readonly exposeAsTool?: Record<string, unknown>;
113
+ }
114
+
115
+ /**
116
+ * The manifest as the tools see it: the (possibly last-good) manifest data
117
+ * plus the reason the LAST fetch failed, when it did. Carrying the failure
118
+ * into the tool layer lets an agent see "api unreachable: …" instead of a
119
+ * bare `(no procedures)`.
120
+ */
121
+ export declare interface ManifestSnapshot {
122
+ readonly manifest: CapabilityManifest;
123
+ /** Present when the last fetch failed — e.g. `manifest fetch failed: HTTP 401`. */
124
+ readonly error?: string;
125
+ }
126
+
127
+ export declare interface ManifestSource {
128
+ /** The current snapshot — re-fetched when older than `ttlMs`. Never
129
+ * rejects: a failed fetch degrades to the last-good manifest (or the
130
+ * empty one) with `error` set. */
131
+ readonly get: () => Promise<ManifestSnapshot>;
132
+ }
133
+
134
+ export declare interface ManifestSourceOptions {
135
+ readonly baseUrl: string;
136
+ readonly token?: string;
137
+ /** Re-fetch when the cached snapshot is older than this. Default 10s —
138
+ * fresh enough that a procedure added mid-session shows up on the next
139
+ * tool call, cheap enough for a local dev api. */
140
+ readonly ttlMs?: number;
141
+ /** Clock override for tests. */
142
+ readonly now?: () => number;
143
+ }
144
+
145
+ export declare interface ManifestTable {
146
+ readonly name: string;
147
+ readonly columns: ReadonlyArray<{
148
+ readonly name: string;
149
+ readonly type: string;
150
+ readonly nullable: boolean;
151
+ readonly refersTo?: string;
152
+ readonly enum?: ReadonlyArray<string>;
153
+ }>;
154
+ readonly reactive: boolean;
155
+ readonly framework: boolean;
156
+ }
157
+
158
+ /** A `prompts/get` result. */
159
+ export declare interface McpGetPromptResult {
160
+ readonly description: string;
161
+ readonly messages: ReadonlyArray<McpPromptMessage>;
162
+ }
163
+
164
+ /** An entry in a `prompts/list` result. */
165
+ export declare interface McpPrompt {
166
+ readonly name: string;
167
+ readonly description: string;
168
+ readonly arguments: ReadonlyArray<McpPromptArgument>;
169
+ }
170
+
171
+ /** A declared argument of a prompt template. */
172
+ export declare interface McpPromptArgument {
173
+ readonly name: string;
174
+ readonly description: string;
175
+ readonly required: boolean;
176
+ }
177
+
178
+ /** One rendered message in a `prompts/get` result. */
179
+ export declare interface McpPromptMessage {
180
+ readonly role: 'user' | 'assistant';
181
+ readonly content: {
182
+ readonly type: 'text';
183
+ readonly text: string;
184
+ };
185
+ }
186
+
187
+ /** An entry in a `resources/list` result. */
188
+ export declare interface McpResource {
189
+ readonly uri: string;
190
+ readonly name: string;
191
+ readonly description: string;
192
+ readonly mimeType: string;
193
+ }
194
+
195
+ /** One item in a `resources/read` result's `contents` array (text form). */
196
+ export declare interface McpResourceContents {
197
+ readonly uri: string;
198
+ readonly mimeType: string;
199
+ readonly text: string;
200
+ }
201
+
202
+ export declare interface McpTool {
203
+ readonly name: string;
204
+ readonly description: string;
205
+ readonly inputSchema: Record<string, unknown>;
206
+ }
207
+
208
+ /** Raised when a required prompt argument is missing. */
209
+ export declare class MissingPromptArgumentError extends Error {
210
+ readonly promptName: string;
211
+ readonly argument: string;
212
+ readonly _tag = "MissingPromptArgumentError";
213
+ constructor(promptName: string, argument: string);
214
+ }
215
+
216
+ /**
217
+ * MCP version negotiation: echo the client's requested revision when we
218
+ * support it, otherwise answer with our latest (the client then decides
219
+ * whether it can talk to us) — exactly the spec's `initialize` contract.
220
+ */
221
+ export declare const negotiateProtocolVersion: (requested: unknown) => string;
222
+
223
+ /**
224
+ * A `node:http` request handler serving MCP over Streamable HTTP. Refreshes
225
+ * the manifest per request (same freshness contract as the stdio transport)
226
+ * and writes the outcome as JSON, SSE, or an empty status.
227
+ */
228
+ export declare const nodeHttpHandler: (options: NodeHttpHandlerOptions) => (req: IncomingMessage, res: ServerResponse) => Promise<void>;
229
+
230
+ export declare interface NodeHttpHandlerOptions {
231
+ readonly source: ManifestSource;
232
+ readonly serverInfo: ServerInfo;
233
+ readonly newSessionId?: () => string;
234
+ }
235
+
236
+ export declare const PROMPTS: ReadonlyArray<McpPrompt>;
237
+
238
+ /** The latest MCP protocol revision this server speaks. */
239
+ export declare const PROTOCOL_VERSION = "2025-06-18";
240
+
241
+ /**
242
+ * Read one resource by URI → its `contents`. Throws `UnknownResourceError`
243
+ * for an unmatched URI (the transport maps it to a JSON-RPC error), so the
244
+ * `voltro://…` scheme is the single source of truth for what is readable.
245
+ */
246
+ export declare const readResource: (snapshot: ManifestSnapshot, uri: string) => ReadonlyArray<McpResourceContents>;
247
+
248
+ /**
249
+ * The pure protocol core of the Streamable HTTP transport. Given the HTTP
250
+ * method, headers and parsed body, decide the response shape. Reuses the same
251
+ * pure `handleMcpRequest` the stdio transport uses — the two transports share
252
+ * one protocol implementation.
253
+ */
254
+ export declare const routeHttp: (options: RouteHttpOptions) => HttpOutcome;
255
+
256
+ export declare interface RouteHttpOptions {
257
+ readonly method: string;
258
+ readonly headers: Readonly<Record<string, string | undefined>>;
259
+ /** The parsed JSON body for a POST (a single request or a batch array); `undefined` for GET/DELETE. */
260
+ readonly body: unknown;
261
+ /** The manifest snapshot to answer against (already refreshed by the caller). */
262
+ readonly snapshot: Parameters<typeof handleMcpRequest>[0];
263
+ readonly serverInfo: ServerInfo;
264
+ /** Whether the client's `Accept` allows an SSE response. */
265
+ readonly acceptsSse: boolean;
266
+ /** Mint a session id (override for deterministic tests). */
267
+ readonly newSessionId?: () => string;
268
+ }
269
+
270
+ /** Fallback identity. The bin overrides `version` with the value from its own
271
+ * `package.json` at runtime (see `serve.ts`), so the published artifact
272
+ * reports the lockstep-stamped release version, not this dev placeholder. */
273
+ export declare const SERVER_INFO: ServerInfo;
274
+
275
+ export declare interface ServerInfo {
276
+ readonly name: string;
277
+ readonly version: string;
278
+ }
279
+
280
+ /** Format one SSE `message` event carrying a JSON-RPC response. */
281
+ export declare const sseEvent: (response: JsonRpcResponse) => string;
282
+
283
+ /**
284
+ * Every revision this server can serve, newest first. The surface here is
285
+ * tools-only over stdio, which is identical across these revisions (the
286
+ * differences — streamable-http transport, batching, audio content,
287
+ * elicitation — don't touch a tools-only stdio server), so claiming all
288
+ * three is honest.
289
+ */
290
+ export declare const SUPPORTED_PROTOCOL_VERSIONS: ReadonlyArray<string>;
291
+
292
+ export declare const TOOLS: ReadonlyArray<McpTool>;
293
+
294
+ /** Raised when `prompts/get` names no known prompt. */
295
+ export declare class UnknownPromptError extends Error {
296
+ readonly promptName: string;
297
+ readonly _tag = "UnknownPromptError";
298
+ constructor(promptName: string);
299
+ }
300
+
301
+ /** Raised by `readResource` when the URI names no known resource. */
302
+ export declare class UnknownResourceError extends Error {
303
+ readonly uri: string;
304
+ readonly _tag = "UnknownResourceError";
305
+ constructor(uri: string);
306
+ }
307
+
308
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _, y as v } from "./mcp-Br4DcrKz.js";
2
+ import { n as y, r as b, t as x } from "./http-DFJ4CBnH.js";
3
+ export { e as EMPTY_MANIFEST, r as MANIFEST_URI, d as MissingPromptArgumentError, m as PROMPTS, h as PROTOCOL_VERSION, u as SERVER_INFO, p as SUPPORTED_PROTOCOL_VERSIONS, o as TOOLS, n as UnknownPromptError, i as UnknownResourceError, a as callTool, _ as createManifestSource, v as fetchManifest, c as getPrompt, s as handleMcpRequest, g as listPrompts, f as listResources, t as negotiateProtocolVersion, x as nodeHttpHandler, l as readResource, y as routeHttp, b as sseEvent };
@@ -0,0 +1,337 @@
1
+ //#region src/manifest.ts
2
+ var e = {
3
+ version: 2,
4
+ procedures: [],
5
+ workflows: [],
6
+ widgets: [],
7
+ tables: []
8
+ }, t = async (e, t, n = 5e3) => {
9
+ let r = new URL("/_voltro/inspect/manifest", e), i = await fetch(r, {
10
+ headers: t === void 0 ? {} : { authorization: `Bearer ${t}` },
11
+ signal: AbortSignal.timeout(n)
12
+ });
13
+ if (!i.ok) throw Error(`manifest fetch failed: HTTP ${i.status}`);
14
+ return await i.json();
15
+ }, n = (n) => {
16
+ let r = n.ttlMs ?? 1e4, i = n.now ?? Date.now, a, o = -Infinity;
17
+ return { get: async () => {
18
+ if (a !== void 0 && i() - o < r) return a;
19
+ try {
20
+ a = { manifest: await t(n.baseUrl, n.token) };
21
+ } catch (t) {
22
+ a = {
23
+ manifest: a?.manifest ?? e,
24
+ error: String(t)
25
+ };
26
+ }
27
+ return o = i(), a;
28
+ } };
29
+ }, r = {
30
+ type: "object",
31
+ properties: {},
32
+ additionalProperties: !1
33
+ }, i = [
34
+ {
35
+ name: "voltro_list_procedures",
36
+ 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.",
37
+ inputSchema: r
38
+ },
39
+ {
40
+ name: "voltro_get_procedure",
41
+ 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.",
42
+ inputSchema: {
43
+ type: "object",
44
+ properties: { tag: {
45
+ type: "string",
46
+ description: "The rpc tag, e.g. \"todos.create\"."
47
+ } },
48
+ required: ["tag"],
49
+ additionalProperties: !1
50
+ }
51
+ },
52
+ {
53
+ name: "voltro_search_procedures",
54
+ description: "Find procedures whose tag contains the query substring (case-insensitive).",
55
+ inputSchema: {
56
+ type: "object",
57
+ properties: { query: { type: "string" } },
58
+ required: ["query"],
59
+ additionalProperties: !1
60
+ }
61
+ },
62
+ {
63
+ name: "voltro_list_tables",
64
+ 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.",
65
+ inputSchema: r
66
+ },
67
+ {
68
+ name: "voltro_get_table",
69
+ description: "Get one table's full column list (name, type, nullability, foreign-key target, enum values) by table name.",
70
+ inputSchema: {
71
+ type: "object",
72
+ properties: { name: {
73
+ type: "string",
74
+ description: "The table name, e.g. \"todos\"."
75
+ } },
76
+ required: ["name"],
77
+ additionalProperties: !1
78
+ }
79
+ },
80
+ {
81
+ name: "voltro_list_workflows",
82
+ description: "List the durable workflows registered in the app.",
83
+ inputSchema: r
84
+ },
85
+ {
86
+ name: "voltro_list_widgets",
87
+ description: "List the schema-driven-UI widget kinds the app supports — the enumerable set a generated UI binds to.",
88
+ inputSchema: r
89
+ }
90
+ ], a = (e) => {
91
+ let t = [...e.publicApi === void 0 ? [] : [" [public-rest]"], ...e.exposeAsTool === void 0 ? [] : [" [agent-tool]"]].join("");
92
+ return `${e.tag} (${e.kind})${t}`;
93
+ }, o = (e) => `${e.name} (${e.columns.length} column${e.columns.length === 1 ? "" : "s"}${e.reactive ? ", reactive" : ""})`, s = (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?)`, c = (e, t, n) => {
94
+ let r = e.manifest;
95
+ switch (t) {
96
+ case "voltro_list_procedures": return r.procedures.length === 0 ? s("procedures", e) : r.procedures.map(a).join("\n");
97
+ case "voltro_get_procedure": {
98
+ let e = String(n.tag ?? ""), t = r.procedures.find((t) => t.tag === e);
99
+ return t === void 0 ? `No procedure with tag "${e}". Call voltro_list_procedures to see available tags.` : JSON.stringify({
100
+ tag: t.tag,
101
+ kind: t.kind,
102
+ input: t.input,
103
+ output: t.output,
104
+ ...t.source === void 0 ? {} : { source: t.source },
105
+ ...t.targets === void 0 ? {} : { targets: t.targets },
106
+ ...t.publicApi === void 0 ? {} : { publicApi: t.publicApi },
107
+ ...t.exposeAsTool === void 0 ? {} : { exposeAsTool: t.exposeAsTool }
108
+ }, null, 2);
109
+ }
110
+ case "voltro_search_procedures": {
111
+ let e = String(n.query ?? "").toLowerCase(), t = r.procedures.filter((t) => t.tag.toLowerCase().includes(e));
112
+ return t.length === 0 ? `(no procedures matching "${e}")` : t.map(a).join("\n");
113
+ }
114
+ case "voltro_list_tables": {
115
+ let t = r.tables ?? [];
116
+ return t.length === 0 ? s("tables", e) : t.map(o).join("\n");
117
+ }
118
+ case "voltro_get_table": {
119
+ let e = String(n.name ?? ""), t = (r.tables ?? []).find((t) => t.name === e);
120
+ return t === void 0 ? `No table named "${e}". Call voltro_list_tables to see available tables.` : JSON.stringify(t, null, 2);
121
+ }
122
+ case "voltro_list_workflows": return r.workflows.length === 0 ? s("workflows", e) : r.workflows.map((e) => e.name).join("\n");
123
+ case "voltro_list_widgets": {
124
+ let t = r.widgets ?? [];
125
+ return t.length === 0 ? s("widgets", e) : t.join("\n");
126
+ }
127
+ default: throw Error(`unknown tool: ${t}`);
128
+ }
129
+ }, l = "application/json", u = "voltro://manifest", d = (e) => `voltro://procedure/${e}`, f = (e) => `voltro://table/${e}`, p = (e) => {
130
+ let t = e.manifest;
131
+ return [
132
+ {
133
+ uri: u,
134
+ name: "Capability manifest",
135
+ description: "The full app capability manifest: every procedure, table, workflow and widget kind as JSON.",
136
+ mimeType: l
137
+ },
138
+ ...t.procedures.map((e) => ({
139
+ uri: d(e.tag),
140
+ name: e.tag,
141
+ description: `The ${e.kind} "${e.tag}" — its input/output JSON Schema, source, and table targets.`,
142
+ mimeType: l
143
+ })),
144
+ ...(t.tables ?? []).map((e) => ({
145
+ uri: f(e.name),
146
+ name: e.name,
147
+ description: `The "${e.name}" table — its full column list (types, nullability, foreign keys, enums).`,
148
+ mimeType: l
149
+ }))
150
+ ];
151
+ }, m = class extends Error {
152
+ uri;
153
+ _tag = "UnknownResourceError";
154
+ constructor(e) {
155
+ super(`no resource at "${e}"`), this.uri = e, this.name = "UnknownResourceError";
156
+ }
157
+ }, h = (e, t) => {
158
+ let n = e.manifest, r = (e) => [{
159
+ uri: t,
160
+ mimeType: l,
161
+ text: JSON.stringify(e, null, 2)
162
+ }];
163
+ if (t === "voltro://manifest") return r(n);
164
+ let i = t.startsWith("voltro://procedure/") ? t.slice(19) : void 0;
165
+ if (i !== void 0) {
166
+ let e = n.procedures.find((e) => e.tag === i);
167
+ if (e === void 0) throw new m(t);
168
+ return r(e);
169
+ }
170
+ let a = t.startsWith("voltro://table/") ? t.slice(15) : void 0;
171
+ if (a !== void 0) {
172
+ let e = (n.tables ?? []).find((e) => e.name === a);
173
+ if (e === void 0) throw new m(t);
174
+ return r(e);
175
+ }
176
+ throw new m(t);
177
+ }, g = [
178
+ {
179
+ name: "scaffold_procedure",
180
+ 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.",
181
+ arguments: [{
182
+ name: "kind",
183
+ description: "query | mutation | action",
184
+ required: !0
185
+ }, {
186
+ name: "purpose",
187
+ description: "What the procedure should do, in one sentence.",
188
+ required: !0
189
+ }]
190
+ },
191
+ {
192
+ name: "explain_table",
193
+ description: "Explain one table's schema and how the app's procedures read/write it, from the live manifest.",
194
+ arguments: [{
195
+ name: "table",
196
+ description: "The table name, e.g. \"todos\".",
197
+ required: !0
198
+ }]
199
+ },
200
+ {
201
+ name: "wire_ui_for_procedure",
202
+ 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.",
203
+ arguments: [{
204
+ name: "tag",
205
+ description: "The rpc tag, e.g. \"todos.list\".",
206
+ required: !0
207
+ }]
208
+ }
209
+ ], _ = class extends Error {
210
+ promptName;
211
+ _tag = "UnknownPromptError";
212
+ constructor(e) {
213
+ super(`no prompt named "${e}"`), this.promptName = e, this.name = "UnknownPromptError";
214
+ }
215
+ }, v = class extends Error {
216
+ promptName;
217
+ argument;
218
+ _tag = "MissingPromptArgumentError";
219
+ constructor(e, t) {
220
+ super(`prompt "${e}" requires the "${t}" argument`), this.promptName = e, this.argument = t, this.name = "MissingPromptArgumentError";
221
+ }
222
+ }, y = () => g, b = (e) => ({
223
+ role: "user",
224
+ content: {
225
+ type: "text",
226
+ text: e
227
+ }
228
+ }), x = (e, t, n) => {
229
+ let r = t[n];
230
+ if (typeof r != "string" || r === "") throw new v(e, n);
231
+ return r;
232
+ }, S = (e, t, n = {}) => {
233
+ let r = e.manifest;
234
+ switch (t) {
235
+ case "scaffold_procedure": {
236
+ let e = x(t, n, "kind"), i = x(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)";
237
+ return {
238
+ description: `Scaffold a ${e} procedure`,
239
+ messages: [b(`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.`)]
240
+ };
241
+ }
242
+ case "explain_table": {
243
+ let e = x(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);
244
+ return {
245
+ description: `Explain the ${e} table`,
246
+ messages: [b(`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}.`)]
247
+ };
248
+ }
249
+ case "wire_ui_for_procedure": {
250
+ let e = x(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({
251
+ tag: i.tag,
252
+ kind: i.kind,
253
+ input: i.input,
254
+ output: i.output
255
+ }, null, 2);
256
+ return {
257
+ description: `Wire UI for ${e}`,
258
+ messages: [b(`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.`)]
259
+ };
260
+ }
261
+ default: throw new _(t);
262
+ }
263
+ }, C = "2025-06-18", w = [
264
+ C,
265
+ "2025-03-26",
266
+ "2024-11-05"
267
+ ], T = {
268
+ name: "voltro-mcp",
269
+ version: "0.1.0"
270
+ }, E = (e) => typeof e == "string" && w.includes(e) ? e : C, D = (e, t, n = T) => {
271
+ if ((t.id === void 0 || t.id === null) && t.method.startsWith("notifications/")) return null;
272
+ let r = t.id ?? null, a = (e) => ({
273
+ jsonrpc: "2.0",
274
+ id: r,
275
+ result: e
276
+ }), o = (e, t) => ({
277
+ jsonrpc: "2.0",
278
+ id: r,
279
+ error: {
280
+ code: e,
281
+ message: t
282
+ }
283
+ });
284
+ switch (t.method) {
285
+ case "initialize": return a({
286
+ protocolVersion: E(t.params?.protocolVersion),
287
+ capabilities: {
288
+ tools: {},
289
+ resources: {},
290
+ prompts: {}
291
+ },
292
+ serverInfo: n
293
+ });
294
+ case "ping": return a({});
295
+ case "tools/list": return a({ tools: i });
296
+ case "tools/call": {
297
+ let n = t.params ?? {}, r = String(n.name ?? ""), i = n.arguments ?? {};
298
+ try {
299
+ return a({ content: [{
300
+ type: "text",
301
+ text: c(e, r, i)
302
+ }] });
303
+ } catch (e) {
304
+ return a({
305
+ content: [{
306
+ type: "text",
307
+ text: `Error: ${String(e)}`
308
+ }],
309
+ isError: !0
310
+ });
311
+ }
312
+ }
313
+ case "resources/list": return a({ resources: p(e) });
314
+ case "resources/read": {
315
+ let n = String(t.params?.uri ?? "");
316
+ try {
317
+ return a({ contents: h(e, n) });
318
+ } catch (e) {
319
+ if (e instanceof m) return o(-32602, e.message);
320
+ throw e;
321
+ }
322
+ }
323
+ case "prompts/list": return a({ prompts: y() });
324
+ case "prompts/get": {
325
+ let n = String(t.params?.name ?? ""), r = t.params?.arguments ?? {};
326
+ try {
327
+ return a(S(e, n, r));
328
+ } catch (e) {
329
+ if (e instanceof _ || e instanceof v) return o(-32602, e.message);
330
+ throw e;
331
+ }
332
+ }
333
+ default: return t.method.startsWith("notifications/") ? null : o(-32601, `method not found: ${t.method}`);
334
+ }
335
+ };
336
+ //#endregion
337
+ export { e as _, E as a, _ as c, u as d, m as f, c as g, i as h, D as i, S as l, h as m, T as n, v as o, p, w as r, g as s, C as t, y as u, n as v, t as y };
@@ -0,0 +1,47 @@
1
+ import { i as e, n as t, v as n } from "./mcp-Br4DcrKz.js";
2
+ import { createRequire as r } from "node:module";
3
+ //#region src/serve.ts
4
+ var i = () => {
5
+ try {
6
+ let e = r(import.meta.url)("../package.json");
7
+ return {
8
+ name: t.name,
9
+ version: e.version ?? t.version
10
+ };
11
+ } catch {
12
+ return t;
13
+ }
14
+ }, a = async (t) => {
15
+ let r = t.env.VOLTRO_INSPECT_URL ?? "http://localhost:4000", a = t.env.VOLTRO_INSPECT_TOKEN, o = t.serverInfo ?? i(), s = n({
16
+ baseUrl: r,
17
+ ...a === void 0 ? {} : { token: a },
18
+ ...t.manifestTtlMs === void 0 ? {} : { ttlMs: t.manifestTtlMs }
19
+ }), c = await s.get();
20
+ c.error === void 0 ? t.errput.write(`voltro-mcp: loaded ${c.manifest.procedures.length} procedures from ${r}\n`) : t.errput.write(`voltro-mcp: could not fetch manifest from ${r}: ${c.error} — serving empty manifest\n`);
21
+ let l = async (n) => {
22
+ if (n === "") return;
23
+ let r;
24
+ try {
25
+ r = JSON.parse(n);
26
+ } catch {
27
+ return;
28
+ }
29
+ let i = Array.isArray(r) ? r : [r];
30
+ for (let n of i) {
31
+ (n.method === "tools/call" || n.method === "tools/list") && (c = await s.get());
32
+ let r = e(c, n, o);
33
+ r !== null && t.output.write(`${JSON.stringify(r)}\n`);
34
+ }
35
+ }, u = "";
36
+ for await (let e of t.input) {
37
+ u += String(e);
38
+ let t = u.indexOf("\n");
39
+ for (; t !== -1;) {
40
+ let e = u.slice(0, t).trim();
41
+ u = u.slice(t + 1), await l(e), t = u.indexOf("\n");
42
+ }
43
+ }
44
+ await l(u.trim());
45
+ };
46
+ //#endregion
47
+ export { a as n, i as t };
@@ -0,0 +1 @@
1
+ export { }
package/dist/server.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { n as e } from "./serve-7hA87wAd.js";
3
+ //#region src/server.ts
4
+ e({
5
+ input: process.stdin,
6
+ output: process.stdout,
7
+ errput: process.stderr,
8
+ env: process.env
9
+ });
10
+ //#endregion
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@voltro/mcp",
3
+ "version": "0.1.0",
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
+ "keywords": [
6
+ "voltro",
7
+ "typescript",
8
+ "framework"
9
+ ],
10
+ "license": "SEE LICENSE IN LICENSE",
11
+ "homepage": "https://voltro.dev",
12
+ "bugs": {
13
+ "email": "support@voltro.dev"
14
+ },
15
+ "author": {
16
+ "name": "Voltro UG",
17
+ "url": "https://voltro.dev"
18
+ },
19
+ "type": "module",
20
+ "bin": {
21
+ "voltro-mcp": "./dist/server.js",
22
+ "voltro-mcp-http": "./dist/httpServer.js"
23
+ },
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "main": "./dist/index.js",
32
+ "module": "./dist/index.js",
33
+ "types": "./dist/index.d.ts",
34
+ "sideEffects": false,
35
+ "engines": {
36
+ "node": ">=24.0.0"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }