@nimblebrain/synapse 0.1.0 → 0.1.2

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.
Files changed (39) hide show
  1. package/dist/chunk-42N5BB5O.cjs +118 -0
  2. package/dist/chunk-42N5BB5O.cjs.map +1 -0
  3. package/dist/{chunk-AW3YIXLE.cjs → chunk-HLT5UBJF.cjs} +2 -116
  4. package/dist/chunk-HLT5UBJF.cjs.map +1 -0
  5. package/dist/{chunk-M4I222LB.js → chunk-JKHGWDZI.js} +3 -114
  6. package/dist/chunk-JKHGWDZI.js.map +1 -0
  7. package/dist/chunk-YWX3D24J.js +114 -0
  8. package/dist/chunk-YWX3D24J.js.map +1 -0
  9. package/dist/codegen/cli.cjs +58 -47
  10. package/dist/codegen/cli.cjs.map +1 -1
  11. package/dist/codegen/cli.js +58 -47
  12. package/dist/codegen/cli.js.map +1 -1
  13. package/dist/codegen/index.cjs +9 -8
  14. package/dist/codegen/index.js +2 -1
  15. package/dist/schema-reader-776246MJ.js +3 -0
  16. package/dist/schema-reader-776246MJ.js.map +1 -0
  17. package/dist/schema-reader-B6LTGBMJ.cjs +20 -0
  18. package/dist/schema-reader-B6LTGBMJ.cjs.map +1 -0
  19. package/dist/server-RUCX2TIB.js +204 -0
  20. package/dist/server-RUCX2TIB.js.map +1 -0
  21. package/dist/server-SEI7XI3B.cjs +206 -0
  22. package/dist/server-SEI7XI3B.cjs.map +1 -0
  23. package/dist/type-generator-MZ4X4DE5.js +3 -0
  24. package/dist/type-generator-MZ4X4DE5.js.map +1 -0
  25. package/dist/type-generator-UA3L4OIA.cjs +12 -0
  26. package/dist/type-generator-UA3L4OIA.cjs.map +1 -0
  27. package/dist/vite/index.cjs +248 -18
  28. package/dist/vite/index.cjs.map +1 -1
  29. package/dist/vite/index.d.cts +26 -12
  30. package/dist/vite/index.d.ts +26 -12
  31. package/dist/vite/index.js +248 -18
  32. package/dist/vite/index.js.map +1 -1
  33. package/dist/writer-NDK4U6C5.cjs +14 -0
  34. package/dist/writer-NDK4U6C5.cjs.map +1 -0
  35. package/dist/writer-ZNBXYUYC.js +12 -0
  36. package/dist/writer-ZNBXYUYC.js.map +1 -0
  37. package/package.json +13 -10
  38. package/dist/chunk-AW3YIXLE.cjs.map +0 -1
  39. package/dist/chunk-M4I222LB.js.map +0 -1
@@ -1,46 +1,276 @@
1
+ import { spawn } from 'child_process';
2
+ import { existsSync, readFileSync } from 'fs';
3
+ import { resolve, join } from 'path';
4
+
1
5
  // src/vite/plugin.ts
2
- function synapseVite(options) {
3
- const { appName, platformUrl = "http://localhost:4321", injectBridge = true } = options;
6
+ function synapseVite(options = {}) {
7
+ const enablePreview = options.preview !== false;
8
+ let manifest = null;
9
+ let appName = options.appName ?? "app";
10
+ let serverProcess = null;
11
+ let pendingRequests = /* @__PURE__ */ new Map();
12
+ let serverBuffer = "";
13
+ function loadManifest(root) {
14
+ const manifestPath = options.manifest ? resolve(options.manifest) : resolve(root, "..", "manifest.json");
15
+ if (!existsSync(manifestPath)) return null;
16
+ try {
17
+ return JSON.parse(readFileSync(manifestPath, "utf-8"));
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+ function deriveServerCmd(m, root) {
23
+ if (options.serverCmd) return options.serverCmd;
24
+ const cfg = m.server?.mcp_config;
25
+ if (!cfg?.command) return null;
26
+ const serverDir = resolve(root, "..");
27
+ let cmd = cfg.command;
28
+ const args = cfg.args ?? [];
29
+ if (cmd === "python" && existsSync(join(serverDir, "pyproject.toml"))) {
30
+ cmd = "uv run python";
31
+ }
32
+ return `cd ${JSON.stringify(serverDir)} && ${cmd} ${args.join(" ")}`;
33
+ }
34
+ function startServer(cmd) {
35
+ serverProcess = spawn(cmd, {
36
+ shell: true,
37
+ stdio: ["pipe", "pipe", "pipe"]
38
+ });
39
+ serverProcess.stderr?.on("data", (d) => {
40
+ process.stderr.write(` [mcp] ${d}`);
41
+ });
42
+ serverProcess.stdout?.on("data", (d) => {
43
+ serverBuffer += d.toString();
44
+ const lines = serverBuffer.split("\n");
45
+ serverBuffer = lines.pop();
46
+ for (const line of lines) {
47
+ if (!line.trim()) continue;
48
+ try {
49
+ const msg = JSON.parse(line);
50
+ if (msg.id && pendingRequests.has(msg.id)) {
51
+ const p = pendingRequests.get(msg.id);
52
+ pendingRequests.delete(msg.id);
53
+ p.resolve(msg);
54
+ }
55
+ } catch {
56
+ process.stderr.write(` [mcp] ${line}
57
+ `);
58
+ }
59
+ }
60
+ });
61
+ serverProcess.on("exit", (code) => {
62
+ if (code !== null && code !== 0) {
63
+ console.error(` [mcp] Server exited with code ${code}`);
64
+ }
65
+ serverProcess = null;
66
+ });
67
+ sendToServer({
68
+ jsonrpc: "2.0",
69
+ id: "init-1",
70
+ method: "initialize",
71
+ params: {
72
+ protocolVersion: "2024-11-05",
73
+ capabilities: {},
74
+ clientInfo: { name: "synapse-preview", version: "0.1.0" }
75
+ }
76
+ });
77
+ }
78
+ function sendToServer(msg) {
79
+ if (!serverProcess?.stdin?.writable) return;
80
+ serverProcess.stdin.write(JSON.stringify(msg) + "\n");
81
+ }
82
+ function callServerTool(name, args) {
83
+ return new Promise((resolve2, reject) => {
84
+ const id = `preview-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
85
+ pendingRequests.set(id, { resolve: resolve2, reject });
86
+ sendToServer({
87
+ jsonrpc: "2.0",
88
+ id,
89
+ method: "tools/call",
90
+ params: { name, arguments: args }
91
+ });
92
+ setTimeout(() => {
93
+ if (pendingRequests.has(id)) {
94
+ pendingRequests.delete(id);
95
+ reject(new Error("Tool call timed out (10s)"));
96
+ }
97
+ }, 1e4);
98
+ });
99
+ }
4
100
  return {
5
101
  name: "synapse",
6
- config() {
102
+ config(_, { command }) {
7
103
  return {
8
104
  define: {
9
- "import.meta.env.SYNAPSE_PLATFORM_URL": JSON.stringify(platformUrl),
10
105
  "import.meta.env.SYNAPSE_APP_NAME": JSON.stringify(appName)
11
106
  },
12
107
  server: {
13
108
  hmr: {
14
- // Required for HMR inside sandboxed iframe
15
109
  protocol: "ws",
16
110
  host: "localhost"
17
111
  }
18
112
  }
19
113
  };
20
114
  },
115
+ configResolved(config) {
116
+ manifest = loadManifest(config.root);
117
+ if (manifest?.name) {
118
+ appName = options.appName ?? manifest.name;
119
+ }
120
+ },
21
121
  configureServer(server) {
22
- server.middlewares.use((_req, res, next) => {
122
+ if (enablePreview && manifest) {
123
+ const cmd = deriveServerCmd(manifest, server.config.root);
124
+ if (cmd) {
125
+ console.log(`
126
+ [synapse] Starting MCP server: ${cmd}
127
+ `);
128
+ startServer(cmd);
129
+ }
130
+ }
131
+ server.middlewares.use((req, res, next) => {
23
132
  res.setHeader("Access-Control-Allow-Origin", "*");
24
133
  res.setHeader("Access-Control-Allow-Methods", "*");
25
134
  res.setHeader("Access-Control-Allow-Headers", "*");
135
+ if (req.url === "/__preview" || req.url === "/__preview/") {
136
+ const port = server.config.server.port ?? 5173;
137
+ res.writeHead(200, { "Content-Type": "text/html" });
138
+ res.end(previewHostHtml(appName, port));
139
+ return;
140
+ }
141
+ if (req.method === "POST" && req.url === "/__mcp") {
142
+ let body = "";
143
+ req.on("data", (chunk) => {
144
+ body += chunk.toString();
145
+ });
146
+ req.on("end", async () => {
147
+ try {
148
+ const msg = JSON.parse(body);
149
+ const result = await callServerTool(msg.params.name, msg.params.arguments || {});
150
+ res.writeHead(200, { "Content-Type": "application/json" });
151
+ res.end(JSON.stringify(result));
152
+ } catch (err) {
153
+ res.writeHead(200, { "Content-Type": "application/json" });
154
+ res.end(JSON.stringify({
155
+ jsonrpc: "2.0",
156
+ id: JSON.parse(body).id,
157
+ error: { code: -32e3, message: err.message }
158
+ }));
159
+ }
160
+ });
161
+ return;
162
+ }
26
163
  next();
27
164
  });
28
165
  },
29
- transformIndexHtml(html) {
30
- if (!injectBridge) return html;
31
- const bridgeScript = `
32
- <script type="module">
33
- import { createSynapse } from "@nimblebrain/synapse";
34
- window.__synapse = createSynapse({
35
- name: ${JSON.stringify(appName)},
36
- version: "0.0.0-dev",
37
- });
38
- </script>`;
39
- return html.replace("</head>", `${bridgeScript}
40
- </head>`);
166
+ buildEnd() {
167
+ if (serverProcess) {
168
+ serverProcess.kill("SIGTERM");
169
+ serverProcess = null;
170
+ }
41
171
  }
42
172
  };
43
173
  }
174
+ function previewHostHtml(appName, port) {
175
+ return `<!DOCTYPE html>
176
+ <html>
177
+ <head>
178
+ <meta charset="utf-8" />
179
+ <title>${appName} \u2014 Synapse Preview</title>
180
+ <style>
181
+ * { margin: 0; padding: 0; box-sizing: border-box; }
182
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #0f172a; color: #e2e8f0; }
183
+ header { padding: 10px 16px; background: #1e293b; border-bottom: 1px solid #334155; display: flex; align-items: center; gap: 10px; font-size: 13px; }
184
+ header .dot { width: 8px; height: 8px; border-radius: 50%; background: #22c55e; }
185
+ header .name { font-weight: 600; }
186
+ header .spacer { flex: 1; }
187
+ header button { background: #334155; border: none; color: #e2e8f0; padding: 3px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; }
188
+ header .url { color: #64748b; font-size: 11px; font-family: monospace; }
189
+ iframe { width: 100%; height: calc(100vh - 41px); border: none; }
190
+ </style>
191
+ </head>
192
+ <body>
193
+ <header>
194
+ <span class="dot"></span>
195
+ <span class="name">${appName}</span>
196
+ <span class="spacer"></span>
197
+ <button id="toggle">Toggle Theme</button>
198
+ <span class="url">localhost:${port}/__preview</span>
199
+ </header>
200
+ <iframe id="app" src="http://localhost:${port}/"></iframe>
201
+
202
+ <script>
203
+ var iframe = document.getElementById("app");
204
+ var dark = true;
205
+
206
+ function getTokens(d) {
207
+ return d ? {
208
+ "--nb-background":"#0f172a","--nb-foreground":"#e2e8f0",
209
+ "--nb-card":"#1e293b","--nb-card-foreground":"#e2e8f0",
210
+ "--nb-primary":"#6366f1","--nb-primary-foreground":"#fff",
211
+ "--nb-muted-foreground":"#94a3b8","--nb-border":"#334155",
212
+ "--nb-ring":"#6366f1","--nb-destructive":"#ef4444",
213
+ "--nb-radius":"0.5rem","--nb-font-sans":"-apple-system,BlinkMacSystemFont,sans-serif"
214
+ } : {
215
+ "--nb-background":"#ffffff","--nb-foreground":"#0f172a",
216
+ "--nb-card":"#f8fafc","--nb-card-foreground":"#0f172a",
217
+ "--nb-primary":"#6366f1","--nb-primary-foreground":"#fff",
218
+ "--nb-muted-foreground":"#64748b","--nb-border":"#e2e8f0",
219
+ "--nb-ring":"#6366f1","--nb-destructive":"#ef4444",
220
+ "--nb-radius":"0.5rem","--nb-font-sans":"-apple-system,BlinkMacSystemFont,sans-serif"
221
+ };
222
+ }
223
+
224
+ function post(msg) { iframe.contentWindow.postMessage(msg, "*"); }
225
+
226
+ window.addEventListener("message", async function(e) {
227
+ if (e.source !== iframe.contentWindow) return;
228
+ var msg = e.data;
229
+ if (!msg || typeof msg !== "object") return;
230
+
231
+ // ext-apps handshake
232
+ if (msg.method === "ui/initialize" && msg.id) {
233
+ post({ jsonrpc:"2.0", id:msg.id, result: {
234
+ protocolVersion:"2026-01-26",
235
+ serverInfo:{name:"nimblebrain",version:"preview"},
236
+ capabilities:{openLinks:{},serverTools:{}},
237
+ hostContext:{theme:dark?"dark":"light",primaryColor:"#6366f1",tokens:getTokens(dark)}
238
+ }});
239
+ return;
240
+ }
241
+ if (msg.method === "ui/notifications/initialized") return;
242
+
243
+ // Tool calls \u2014 proxy via Vite middleware
244
+ if (msg.method === "tools/call" && msg.id) {
245
+ try {
246
+ var r = await fetch("/__mcp", {
247
+ method:"POST", headers:{"Content-Type":"application/json"},
248
+ body: JSON.stringify({jsonrpc:"2.0",id:msg.id,method:"tools/call",params:{name:msg.params.name,arguments:msg.params.arguments||{}}})
249
+ });
250
+ post(await r.json());
251
+ } catch(err) {
252
+ post({jsonrpc:"2.0",id:msg.id,error:{code:-32000,message:err.message}});
253
+ }
254
+ return;
255
+ }
256
+
257
+ // Log other messages
258
+ if (msg.method === "ui/chat") console.log("[chat]", msg.params?.message);
259
+ else if (msg.method === "ui/action") console.log("[action]", msg.params?.action, msg.params);
260
+ else if (msg.method === "ui/stateChanged") { console.log("[state]", msg.params?.state); post({jsonrpc:"2.0",method:"ui/stateAcknowledged",params:{truncated:false}}); }
261
+ else if (msg.method === "ui/keydown") { /* ignore */ }
262
+ else if (msg.method) console.log("[bridge]", msg.method, msg);
263
+ });
264
+
265
+ document.getElementById("toggle").onclick = function() {
266
+ dark = !dark;
267
+ document.body.style.background = dark ? "#0f172a" : "#f1f5f9";
268
+ post({jsonrpc:"2.0",method:"ui/themeChanged",params:{mode:dark?"dark":"light",tokens:getTokens(dark)}});
269
+ };
270
+ </script>
271
+ </body>
272
+ </html>`;
273
+ }
44
274
 
45
275
  export { synapseVite };
46
276
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vite/plugin.ts"],"names":[],"mappings":";AAmBO,SAAS,YAAY,OAAA,EAA2C;AACrE,EAAA,MAAM,EAAE,OAAA,EAAS,WAAA,GAAc,uBAAA,EAAyB,YAAA,GAAe,MAAK,GAAI,OAAA;AAEhF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IAEN,MAAA,GAAS;AACP,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN,sCAAA,EAAwC,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAAA,UAClE,kCAAA,EAAoC,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,SAC5D;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,GAAA,EAAK;AAAA;AAAA,YAEH,QAAA,EAAU,IAAA;AAAA,YACV,IAAA,EAAM;AAAA;AACR;AACF,OACF;AAAA,IACF,CAAA;AAAA,IAEA,gBAAgB,MAAA,EAAuB;AAErC,MAAA,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,EAAM,KAAK,IAAA,KAAS;AAC1C,QAAA,GAAA,CAAI,SAAA,CAAU,+BAA+B,GAAG,CAAA;AAChD,QAAA,GAAA,CAAI,SAAA,CAAU,gCAAgC,GAAG,CAAA;AACjD,QAAA,GAAA,CAAI,SAAA,CAAU,gCAAgC,GAAG,CAAA;AACjD,QAAA,IAAA,EAAK;AAAA,MACP,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,mBAAmB,IAAA,EAAc;AAC/B,MAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAE1B,MAAA,MAAM,YAAA,GAAe;AAAA;AAAA;AAAA;AAAA,UAAA,EAIf,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAM7B,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,CAAA,EAAG,YAAY;AAAA,OAAA,CAAW,CAAA;AAAA,IAC3D;AAAA,GACF;AACF","file":"index.js","sourcesContent":["import type { Plugin, ViteDevServer } from \"vite\";\n\nexport interface SynapseVitePluginOptions {\n /** App name (must match manifest) */\n appName: string;\n /** Platform API URL (default: http://localhost:4321) */\n platformUrl?: string;\n /** Auto-inject bridge runtime into HTML entry (default: true) */\n injectBridge?: boolean;\n}\n\n/**\n * Vite plugin for Synapse app development.\n *\n * - Configures CORS for cross-origin iframe communication\n * - Injects ext-apps bridge runtime if `injectBridge` is true\n * - Sets up HMR WebSocket to work inside iframe sandbox\n * - Exposes platform URL as `import.meta.env.SYNAPSE_PLATFORM_URL`\n */\nexport function synapseVite(options: SynapseVitePluginOptions): Plugin {\n const { appName, platformUrl = \"http://localhost:4321\", injectBridge = true } = options;\n\n return {\n name: \"synapse\",\n\n config() {\n return {\n define: {\n \"import.meta.env.SYNAPSE_PLATFORM_URL\": JSON.stringify(platformUrl),\n \"import.meta.env.SYNAPSE_APP_NAME\": JSON.stringify(appName),\n },\n server: {\n hmr: {\n // Required for HMR inside sandboxed iframe\n protocol: \"ws\",\n host: \"localhost\",\n },\n },\n };\n },\n\n configureServer(server: ViteDevServer) {\n // Add CORS headers for cross-origin iframe communication\n server.middlewares.use((_req, res, next) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"*\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n next();\n });\n },\n\n transformIndexHtml(html: string) {\n if (!injectBridge) return html;\n\n const bridgeScript = `\n<script type=\"module\">\n import { createSynapse } from \"@nimblebrain/synapse\";\n window.__synapse = createSynapse({\n name: ${JSON.stringify(appName)},\n version: \"0.0.0-dev\",\n });\n</script>`;\n\n // Inject before closing </head> tag\n return html.replace(\"</head>\", `${bridgeScript}\\n</head>`);\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/vite/plugin.ts"],"names":["resolve"],"mappings":"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","file":"index.js","sourcesContent":["import type { Plugin, ViteDevServer } from \"vite\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\n\nexport interface SynapseVitePluginOptions {\n /** App name. If omitted, reads from ../manifest.json */\n appName?: string;\n /** Path to manifest.json. Default: ../manifest.json (relative to ui/) */\n manifest?: string;\n /**\n * Shell command to start the MCP server. If omitted, derived from manifest.\n * The server runs in stdio mode — stdin/stdout JSON-RPC.\n */\n serverCmd?: string;\n /** Set to false to disable the preview host page at /__preview */\n preview?: boolean;\n}\n\ninterface Manifest {\n name: string;\n version?: string;\n server?: {\n type?: string;\n entry_point?: string;\n mcp_config?: {\n command?: string;\n args?: string[];\n };\n };\n}\n\n/**\n * Synapse Vite plugin — full local dev experience for MCP apps.\n *\n * What it does:\n * - Reads ../manifest.json to get app name and server config\n * - Spawns the MCP server as a child process (stdio mode)\n * - Serves a preview host page at /__preview that iframes your app\n * - Proxies tool calls from the iframe through POST /__mcp to the server\n * - Handles the ext-apps handshake so Synapse hooks work\n * - HMR works inside the iframe — edit .tsx, see changes instantly\n *\n * Usage in vite.config.ts:\n * import { synapseVite } from \"@nimblebrain/synapse/vite\";\n * export default { plugins: [react(), viteSingleFile(), synapseVite()] };\n *\n * Then: cd ui && npm run dev && open http://localhost:5173/__preview\n */\nexport function synapseVite(options: SynapseVitePluginOptions = {}): Plugin {\n const enablePreview = options.preview !== false;\n let manifest: Manifest | null = null;\n let appName = options.appName ?? \"app\";\n let serverProcess: ChildProcess | null = null;\n let pendingRequests = new Map<string, { resolve: (v: unknown) => void; reject: (e: Error) => void }>();\n let serverBuffer = \"\";\n\n function loadManifest(root: string): Manifest | null {\n const manifestPath = options.manifest\n ? resolve(options.manifest)\n : resolve(root, \"..\", \"manifest.json\");\n\n if (!existsSync(manifestPath)) return null;\n try {\n return JSON.parse(readFileSync(manifestPath, \"utf-8\"));\n } catch {\n return null;\n }\n }\n\n function deriveServerCmd(m: Manifest, root: string): string | null {\n if (options.serverCmd) return options.serverCmd;\n const cfg = m.server?.mcp_config;\n if (!cfg?.command) return null;\n\n const serverDir = resolve(root, \"..\");\n let cmd = cfg.command;\n const args = cfg.args ?? [];\n\n // Python projects: use `uv run` if pyproject.toml exists\n if (cmd === \"python\" && existsSync(join(serverDir, \"pyproject.toml\"))) {\n cmd = \"uv run python\";\n }\n\n return `cd ${JSON.stringify(serverDir)} && ${cmd} ${args.join(\" \")}`;\n }\n\n function startServer(cmd: string): void {\n serverProcess = spawn(cmd, {\n shell: true,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n serverProcess.stderr?.on(\"data\", (d: Buffer) => {\n process.stderr.write(` [mcp] ${d}`);\n });\n\n serverProcess.stdout?.on(\"data\", (d: Buffer) => {\n serverBuffer += d.toString();\n // Parse line-delimited JSON-RPC responses\n const lines = serverBuffer.split(\"\\n\");\n serverBuffer = lines.pop()!; // keep incomplete line\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line);\n if (msg.id && pendingRequests.has(msg.id)) {\n const p = pendingRequests.get(msg.id)!;\n pendingRequests.delete(msg.id);\n p.resolve(msg);\n }\n } catch {\n // Not JSON — log it\n process.stderr.write(` [mcp] ${line}\\n`);\n }\n }\n });\n\n serverProcess.on(\"exit\", (code) => {\n if (code !== null && code !== 0) {\n console.error(` [mcp] Server exited with code ${code}`);\n }\n serverProcess = null;\n });\n\n // Send initialize\n sendToServer({\n jsonrpc: \"2.0\",\n id: \"init-1\",\n method: \"initialize\",\n params: {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"synapse-preview\", version: \"0.1.0\" },\n },\n });\n }\n\n function sendToServer(msg: Record<string, unknown>): void {\n if (!serverProcess?.stdin?.writable) return;\n serverProcess.stdin.write(JSON.stringify(msg) + \"\\n\");\n }\n\n function callServerTool(name: string, args: Record<string, unknown>): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const id = `preview-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n pendingRequests.set(id, { resolve, reject });\n sendToServer({\n jsonrpc: \"2.0\",\n id,\n method: \"tools/call\",\n params: { name, arguments: args },\n });\n setTimeout(() => {\n if (pendingRequests.has(id)) {\n pendingRequests.delete(id);\n reject(new Error(\"Tool call timed out (10s)\"));\n }\n }, 10000);\n });\n }\n\n return {\n name: \"synapse\",\n\n config(_, { command }) {\n return {\n define: {\n \"import.meta.env.SYNAPSE_APP_NAME\": JSON.stringify(appName),\n },\n server: {\n hmr: {\n protocol: \"ws\",\n host: \"localhost\",\n },\n },\n };\n },\n\n configResolved(config) {\n manifest = loadManifest(config.root);\n if (manifest?.name) {\n appName = options.appName ?? manifest.name;\n }\n },\n\n configureServer(server: ViteDevServer) {\n // Start MCP server\n if (enablePreview && manifest) {\n const cmd = deriveServerCmd(manifest, server.config.root);\n if (cmd) {\n console.log(`\\n [synapse] Starting MCP server: ${cmd}\\n`);\n startServer(cmd);\n }\n }\n\n server.middlewares.use((req, res, next) => {\n // CORS for iframe communication\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"*\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n\n // /__preview — bridge host page\n if (req.url === \"/__preview\" || req.url === \"/__preview/\") {\n const port = server.config.server.port ?? 5173;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(previewHostHtml(appName, port));\n return;\n }\n\n // POST /__mcp — tool call proxy\n if (req.method === \"POST\" && req.url === \"/__mcp\") {\n let body = \"\";\n req.on(\"data\", (chunk: Buffer) => { body += chunk.toString(); });\n req.on(\"end\", async () => {\n try {\n const msg = JSON.parse(body);\n const result = await callServerTool(msg.params.name, msg.params.arguments || {});\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result));\n } catch (err) {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({\n jsonrpc: \"2.0\",\n id: JSON.parse(body).id,\n error: { code: -32000, message: (err as Error).message },\n }));\n }\n });\n return;\n }\n\n next();\n });\n },\n\n buildEnd() {\n // Kill server on build end (for production builds)\n if (serverProcess) {\n serverProcess.kill(\"SIGTERM\");\n serverProcess = null;\n }\n },\n };\n}\n\nfunction previewHostHtml(appName: string, port: number): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <title>${appName} — Synapse Preview</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: #0f172a; color: #e2e8f0; }\n header { padding: 10px 16px; background: #1e293b; border-bottom: 1px solid #334155; display: flex; align-items: center; gap: 10px; font-size: 13px; }\n header .dot { width: 8px; height: 8px; border-radius: 50%; background: #22c55e; }\n header .name { font-weight: 600; }\n header .spacer { flex: 1; }\n header button { background: #334155; border: none; color: #e2e8f0; padding: 3px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; }\n header .url { color: #64748b; font-size: 11px; font-family: monospace; }\n iframe { width: 100%; height: calc(100vh - 41px); border: none; }\n </style>\n</head>\n<body>\n <header>\n <span class=\"dot\"></span>\n <span class=\"name\">${appName}</span>\n <span class=\"spacer\"></span>\n <button id=\"toggle\">Toggle Theme</button>\n <span class=\"url\">localhost:${port}/__preview</span>\n </header>\n <iframe id=\"app\" src=\"http://localhost:${port}/\"></iframe>\n\n <script>\n var iframe = document.getElementById(\"app\");\n var dark = true;\n\n function getTokens(d) {\n return d ? {\n \"--nb-background\":\"#0f172a\",\"--nb-foreground\":\"#e2e8f0\",\n \"--nb-card\":\"#1e293b\",\"--nb-card-foreground\":\"#e2e8f0\",\n \"--nb-primary\":\"#6366f1\",\"--nb-primary-foreground\":\"#fff\",\n \"--nb-muted-foreground\":\"#94a3b8\",\"--nb-border\":\"#334155\",\n \"--nb-ring\":\"#6366f1\",\"--nb-destructive\":\"#ef4444\",\n \"--nb-radius\":\"0.5rem\",\"--nb-font-sans\":\"-apple-system,BlinkMacSystemFont,sans-serif\"\n } : {\n \"--nb-background\":\"#ffffff\",\"--nb-foreground\":\"#0f172a\",\n \"--nb-card\":\"#f8fafc\",\"--nb-card-foreground\":\"#0f172a\",\n \"--nb-primary\":\"#6366f1\",\"--nb-primary-foreground\":\"#fff\",\n \"--nb-muted-foreground\":\"#64748b\",\"--nb-border\":\"#e2e8f0\",\n \"--nb-ring\":\"#6366f1\",\"--nb-destructive\":\"#ef4444\",\n \"--nb-radius\":\"0.5rem\",\"--nb-font-sans\":\"-apple-system,BlinkMacSystemFont,sans-serif\"\n };\n }\n\n function post(msg) { iframe.contentWindow.postMessage(msg, \"*\"); }\n\n window.addEventListener(\"message\", async function(e) {\n if (e.source !== iframe.contentWindow) return;\n var msg = e.data;\n if (!msg || typeof msg !== \"object\") return;\n\n // ext-apps handshake\n if (msg.method === \"ui/initialize\" && msg.id) {\n post({ jsonrpc:\"2.0\", id:msg.id, result: {\n protocolVersion:\"2026-01-26\",\n serverInfo:{name:\"nimblebrain\",version:\"preview\"},\n capabilities:{openLinks:{},serverTools:{}},\n hostContext:{theme:dark?\"dark\":\"light\",primaryColor:\"#6366f1\",tokens:getTokens(dark)}\n }});\n return;\n }\n if (msg.method === \"ui/notifications/initialized\") return;\n\n // Tool calls — proxy via Vite middleware\n if (msg.method === \"tools/call\" && msg.id) {\n try {\n var r = await fetch(\"/__mcp\", {\n method:\"POST\", headers:{\"Content-Type\":\"application/json\"},\n body: JSON.stringify({jsonrpc:\"2.0\",id:msg.id,method:\"tools/call\",params:{name:msg.params.name,arguments:msg.params.arguments||{}}})\n });\n post(await r.json());\n } catch(err) {\n post({jsonrpc:\"2.0\",id:msg.id,error:{code:-32000,message:err.message}});\n }\n return;\n }\n\n // Log other messages\n if (msg.method === \"ui/chat\") console.log(\"[chat]\", msg.params?.message);\n else if (msg.method === \"ui/action\") console.log(\"[action]\", msg.params?.action, msg.params);\n else if (msg.method === \"ui/stateChanged\") { console.log(\"[state]\", msg.params?.state); post({jsonrpc:\"2.0\",method:\"ui/stateAcknowledged\",params:{truncated:false}}); }\n else if (msg.method === \"ui/keydown\") { /* ignore */ }\n else if (msg.method) console.log(\"[bridge]\", msg.method, msg);\n });\n\n document.getElementById(\"toggle\").onclick = function() {\n dark = !dark;\n document.body.style.background = dark ? \"#0f172a\" : \"#f1f5f9\";\n post({jsonrpc:\"2.0\",method:\"ui/themeChanged\",params:{mode:dark?\"dark\":\"light\",tokens:getTokens(dark)}});\n };\n </script>\n</body>\n</html>`;\n}\n"]}
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+
6
+ // src/codegen/writer.ts
7
+ function writeOutput(content, outputPath) {
8
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
9
+ fs.writeFileSync(outputPath, content, "utf-8");
10
+ }
11
+
12
+ exports.writeOutput = writeOutput;
13
+ //# sourceMappingURL=writer-NDK4U6C5.cjs.map
14
+ //# sourceMappingURL=writer-NDK4U6C5.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codegen/writer.ts"],"names":["mkdirSync","dirname","writeFileSync"],"mappings":";;;;;;AAMO,SAAS,WAAA,CAAY,SAAiB,UAAA,EAA0B;AACrE,EAAAA,YAAA,CAAUC,aAAQ,UAAU,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAClD,EAAAC,gBAAA,CAAc,UAAA,EAAY,SAAS,OAAO,CAAA;AAC5C","file":"writer-NDK4U6C5.cjs","sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n/**\n * Write generated TypeScript to a file, creating parent directories as needed.\n */\nexport function writeOutput(content: string, outputPath: string): void {\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, content, \"utf-8\");\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { mkdirSync, writeFileSync } from 'fs';
2
+ import { dirname } from 'path';
3
+
4
+ // src/codegen/writer.ts
5
+ function writeOutput(content, outputPath) {
6
+ mkdirSync(dirname(outputPath), { recursive: true });
7
+ writeFileSync(outputPath, content, "utf-8");
8
+ }
9
+
10
+ export { writeOutput };
11
+ //# sourceMappingURL=writer-ZNBXYUYC.js.map
12
+ //# sourceMappingURL=writer-ZNBXYUYC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codegen/writer.ts"],"names":[],"mappings":";;;;AAMO,SAAS,WAAA,CAAY,SAAiB,UAAA,EAA0B;AACrE,EAAA,SAAA,CAAU,QAAQ,UAAU,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAClD,EAAA,aAAA,CAAc,UAAA,EAAY,SAAS,OAAO,CAAA;AAC5C","file":"writer-ZNBXYUYC.js","sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n/**\n * Write generated TypeScript to a file, creating parent directories as needed.\n */\nexport function writeOutput(content: string, outputPath: string): void {\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, content, \"utf-8\");\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimblebrain/synapse",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Agent-aware app SDK for the NimbleBrain platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -63,15 +63,18 @@
63
63
  "devDependencies": {
64
64
  "@biomejs/biome": "^2.4.9",
65
65
  "@modelcontextprotocol/ext-apps": "^1.3.1",
66
- "@testing-library/react": "^16.0.0",
67
- "@types/node": "^22.19.15",
68
- "@types/react": "^19.0.0",
69
- "happy-dom": "^15.0.0",
70
- "react": "^19.0.0",
71
- "tsup": "^8.0.0",
72
- "typescript": "^5.7.0",
73
- "vite": "^6.0.0",
74
- "vitest": "^3.0.0"
66
+ "@testing-library/react": "^16.3.2",
67
+ "@types/node": "^25.5.0",
68
+ "@types/react": "^19.2.14",
69
+ "happy-dom": "^20.8.8",
70
+ "react": "^19.2.4",
71
+ "tsup": "^8.5.1",
72
+ "typescript": "^5.8.3",
73
+ "vite": "^8.0.3",
74
+ "vitest": "^4.1.2"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
75
78
  },
76
79
  "license": "MIT",
77
80
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/codegen/schema-reader.ts","../src/codegen/type-generator.ts"],"names":["existsSync","readFileSync","readdirSync","join","basename"],"mappings":"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","file":"chunk-AW3YIXLE.cjs","sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { ToolDefinition } from \"../types.js\";\n\n/**\n * Read tool definitions from a manifest.json file.\n * Extracts tools from the MCP standard `tools` array.\n */\nexport function readFromManifest(manifestPath: string): ToolDefinition[] {\n if (!existsSync(manifestPath)) {\n throw new Error(`Manifest not found: ${manifestPath}`);\n }\n\n const raw = JSON.parse(readFileSync(manifestPath, \"utf-8\"));\n const tools = raw.tools ?? [];\n\n if (!Array.isArray(tools)) {\n return [];\n }\n\n return tools.map((t: any) => ({\n name: t.name as string,\n description: t.description as string | undefined,\n inputSchema: (t.inputSchema ?? {}) as Record<string, unknown>,\n outputSchema: t.outputSchema as Record<string, unknown> | undefined,\n }));\n}\n\n/**\n * Read tool definitions from a running MCP server via tools/list.\n * Connects to the server's HTTP endpoint and calls the JSON-RPC method.\n */\nexport async function readFromServer(url: string): Promise<ToolDefinition[]> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"tools/list\",\n id: \"codegen-1\",\n params: {},\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Server responded with ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n if (result.error) {\n throw new Error(`Server error: ${result.error.message}`);\n }\n\n const tools = result.result?.tools ?? [];\n return tools.map((t: any) => ({\n name: t.name as string,\n description: t.description as string | undefined,\n inputSchema: (t.inputSchema ?? {}) as Record<string, unknown>,\n outputSchema: t.outputSchema as Record<string, unknown> | undefined,\n }));\n}\n\n/**\n * Read entity schemas from a directory and generate CRUD tool definitions.\n * Each .schema.json file becomes create/read/update/delete/list tools.\n */\nexport function readFromSchemaDir(dirPath: string): ToolDefinition[] {\n if (!existsSync(dirPath)) {\n throw new Error(`Schema directory not found: ${dirPath}`);\n }\n\n const files = readdirSync(dirPath).filter((f: string) => f.endsWith(\".schema.json\"));\n const tools: ToolDefinition[] = [];\n\n for (const file of files) {\n const schema = JSON.parse(readFileSync(join(dirPath, file), \"utf-8\"));\n const entityName = basename(file, \".schema.json\");\n\n tools.push(\n {\n name: `create_${entityName}`,\n description: `Create a new ${entityName}`,\n inputSchema: schema,\n outputSchema: schema,\n },\n {\n name: `read_${entityName}`,\n description: `Read a ${entityName} by ID`,\n inputSchema: {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n required: [\"id\"],\n },\n outputSchema: schema,\n },\n {\n name: `update_${entityName}`,\n description: `Update an existing ${entityName}`,\n inputSchema: schema,\n outputSchema: schema,\n },\n {\n name: `delete_${entityName}`,\n description: `Delete a ${entityName} by ID`,\n inputSchema: {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n required: [\"id\"],\n },\n },\n {\n name: `list_${entityName}s`,\n description: `List all ${entityName}s`,\n inputSchema: {\n type: \"object\",\n properties: {\n filter: { type: \"string\" },\n limit: { type: \"number\" },\n },\n },\n outputSchema: {\n type: \"object\",\n properties: {\n items: { type: \"array\", items: schema },\n total: { type: \"number\" },\n },\n required: [\"items\", \"total\"],\n },\n },\n );\n }\n\n return tools;\n}\n","import type { ToolDefinition } from \"../types.js\";\n\n/**\n * Generate TypeScript interfaces from tool definitions.\n */\nexport function generateTypes(tools: ToolDefinition[], appName: string): string {\n const lines: string[] = [];\n const mapName = `${toPascalCase(appName)}ToolMap`;\n\n lines.push(\"/**\");\n lines.push(` * Auto-generated by @nimblebrain/synapse codegen`);\n lines.push(` * Source: ${appName}`);\n lines.push(` *`);\n lines.push(\n ` * DO NOT EDIT — regenerate with: npx synapse codegen --from-manifest ./manifest.json`,\n );\n lines.push(` */`);\n lines.push(\"\");\n\n const mapEntries: string[] = [];\n\n for (const tool of tools) {\n const baseName = toPascalCase(tool.name);\n\n // Input type\n const inputName = `${baseName}Input`;\n lines.push(schemaToInterface(inputName, tool.inputSchema));\n lines.push(\"\");\n\n // Output type\n let outputName = \"unknown\";\n if (tool.outputSchema) {\n outputName = `${baseName}Output`;\n lines.push(schemaToInterface(outputName, tool.outputSchema));\n lines.push(\"\");\n }\n\n mapEntries.push(` ${tool.name}: { input: ${inputName}; output: ${outputName} };`);\n }\n\n // Tool map\n lines.push(`/** Tool type map for typed useCallTool */`);\n lines.push(`export interface ${mapName} {`);\n for (const entry of mapEntries) {\n lines.push(entry);\n }\n lines.push(`}`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// JSON Schema -> TypeScript conversion\n// ---------------------------------------------------------------------------\n\nfunction schemaToInterface(name: string, schema: Record<string, unknown>): string {\n const type = schemaToType(schema, name);\n\n // If the schema is an object, generate a named interface\n if (schema.type === \"object\" || schema.properties) {\n return generateInterface(name, schema);\n }\n\n // Otherwise, generate a type alias\n return `export type ${name} = ${type};`;\n}\n\nfunction generateInterface(name: string, schema: Record<string, unknown>): string {\n const lines: string[] = [];\n lines.push(`export interface ${name} {`);\n\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required ?? []) as string[]);\n\n for (const [key, propSchema] of Object.entries(props)) {\n const isRequired = required.has(key);\n const type = schemaToType(propSchema, name + toPascalCase(key));\n const desc = propSchema.description;\n if (desc) {\n lines.push(` /** ${desc} */`);\n }\n lines.push(` ${key}${isRequired ? \"\" : \"?\"}: ${type};`);\n }\n\n lines.push(`}`);\n return lines.join(\"\\n\");\n}\n\nfunction schemaToType(schema: Record<string, unknown>, context: string): string {\n // Handle enum\n if (schema.enum && Array.isArray(schema.enum)) {\n return (schema.enum as unknown[])\n .map((v) => (typeof v === \"string\" ? `\"${v}\"` : String(v)))\n .join(\" | \");\n }\n\n // Handle oneOf / anyOf\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n return (schema.oneOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Option${i}`))\n .join(\" | \");\n }\n if (schema.anyOf && Array.isArray(schema.anyOf)) {\n return (schema.anyOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Option${i}`))\n .join(\" | \");\n }\n\n // Handle allOf (intersection)\n if (schema.allOf && Array.isArray(schema.allOf)) {\n return (schema.allOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Part${i}`))\n .join(\" & \");\n }\n\n // Handle type-based conversion\n const type = schema.type as string | string[] | undefined;\n\n if (Array.isArray(type)) {\n // Multi-type (e.g., [\"string\", \"null\"])\n return type.map((t) => primitiveType(t)).join(\" | \");\n }\n\n switch (type) {\n case \"string\":\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n case \"array\": {\n const items = schema.items as Record<string, unknown> | undefined;\n if (items) {\n return `${schemaToType(items, `${context}Item`)}[]`;\n }\n return \"unknown[]\";\n }\n case \"object\": {\n if (schema.properties) {\n // Inline object — generate property types\n const props = schema.properties as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required ?? []) as string[]);\n const fields = Object.entries(props)\n .map(([key, propSchema]) => {\n const t = schemaToType(propSchema, context + toPascalCase(key));\n return `${key}${required.has(key) ? \"\" : \"?\"}: ${t}`;\n })\n .join(\"; \");\n return `{ ${fields} }`;\n }\n return \"Record<string, unknown>\";\n }\n default:\n return \"unknown\";\n }\n}\n\nfunction primitiveType(t: string): string {\n switch (t) {\n case \"string\":\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n default:\n return \"unknown\";\n }\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_@/]/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/codegen/schema-reader.ts","../src/codegen/type-generator.ts"],"names":[],"mappings":"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","file":"chunk-M4I222LB.js","sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { ToolDefinition } from \"../types.js\";\n\n/**\n * Read tool definitions from a manifest.json file.\n * Extracts tools from the MCP standard `tools` array.\n */\nexport function readFromManifest(manifestPath: string): ToolDefinition[] {\n if (!existsSync(manifestPath)) {\n throw new Error(`Manifest not found: ${manifestPath}`);\n }\n\n const raw = JSON.parse(readFileSync(manifestPath, \"utf-8\"));\n const tools = raw.tools ?? [];\n\n if (!Array.isArray(tools)) {\n return [];\n }\n\n return tools.map((t: any) => ({\n name: t.name as string,\n description: t.description as string | undefined,\n inputSchema: (t.inputSchema ?? {}) as Record<string, unknown>,\n outputSchema: t.outputSchema as Record<string, unknown> | undefined,\n }));\n}\n\n/**\n * Read tool definitions from a running MCP server via tools/list.\n * Connects to the server's HTTP endpoint and calls the JSON-RPC method.\n */\nexport async function readFromServer(url: string): Promise<ToolDefinition[]> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"tools/list\",\n id: \"codegen-1\",\n params: {},\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Server responded with ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n if (result.error) {\n throw new Error(`Server error: ${result.error.message}`);\n }\n\n const tools = result.result?.tools ?? [];\n return tools.map((t: any) => ({\n name: t.name as string,\n description: t.description as string | undefined,\n inputSchema: (t.inputSchema ?? {}) as Record<string, unknown>,\n outputSchema: t.outputSchema as Record<string, unknown> | undefined,\n }));\n}\n\n/**\n * Read entity schemas from a directory and generate CRUD tool definitions.\n * Each .schema.json file becomes create/read/update/delete/list tools.\n */\nexport function readFromSchemaDir(dirPath: string): ToolDefinition[] {\n if (!existsSync(dirPath)) {\n throw new Error(`Schema directory not found: ${dirPath}`);\n }\n\n const files = readdirSync(dirPath).filter((f: string) => f.endsWith(\".schema.json\"));\n const tools: ToolDefinition[] = [];\n\n for (const file of files) {\n const schema = JSON.parse(readFileSync(join(dirPath, file), \"utf-8\"));\n const entityName = basename(file, \".schema.json\");\n\n tools.push(\n {\n name: `create_${entityName}`,\n description: `Create a new ${entityName}`,\n inputSchema: schema,\n outputSchema: schema,\n },\n {\n name: `read_${entityName}`,\n description: `Read a ${entityName} by ID`,\n inputSchema: {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n required: [\"id\"],\n },\n outputSchema: schema,\n },\n {\n name: `update_${entityName}`,\n description: `Update an existing ${entityName}`,\n inputSchema: schema,\n outputSchema: schema,\n },\n {\n name: `delete_${entityName}`,\n description: `Delete a ${entityName} by ID`,\n inputSchema: {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n required: [\"id\"],\n },\n },\n {\n name: `list_${entityName}s`,\n description: `List all ${entityName}s`,\n inputSchema: {\n type: \"object\",\n properties: {\n filter: { type: \"string\" },\n limit: { type: \"number\" },\n },\n },\n outputSchema: {\n type: \"object\",\n properties: {\n items: { type: \"array\", items: schema },\n total: { type: \"number\" },\n },\n required: [\"items\", \"total\"],\n },\n },\n );\n }\n\n return tools;\n}\n","import type { ToolDefinition } from \"../types.js\";\n\n/**\n * Generate TypeScript interfaces from tool definitions.\n */\nexport function generateTypes(tools: ToolDefinition[], appName: string): string {\n const lines: string[] = [];\n const mapName = `${toPascalCase(appName)}ToolMap`;\n\n lines.push(\"/**\");\n lines.push(` * Auto-generated by @nimblebrain/synapse codegen`);\n lines.push(` * Source: ${appName}`);\n lines.push(` *`);\n lines.push(\n ` * DO NOT EDIT — regenerate with: npx synapse codegen --from-manifest ./manifest.json`,\n );\n lines.push(` */`);\n lines.push(\"\");\n\n const mapEntries: string[] = [];\n\n for (const tool of tools) {\n const baseName = toPascalCase(tool.name);\n\n // Input type\n const inputName = `${baseName}Input`;\n lines.push(schemaToInterface(inputName, tool.inputSchema));\n lines.push(\"\");\n\n // Output type\n let outputName = \"unknown\";\n if (tool.outputSchema) {\n outputName = `${baseName}Output`;\n lines.push(schemaToInterface(outputName, tool.outputSchema));\n lines.push(\"\");\n }\n\n mapEntries.push(` ${tool.name}: { input: ${inputName}; output: ${outputName} };`);\n }\n\n // Tool map\n lines.push(`/** Tool type map for typed useCallTool */`);\n lines.push(`export interface ${mapName} {`);\n for (const entry of mapEntries) {\n lines.push(entry);\n }\n lines.push(`}`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// JSON Schema -> TypeScript conversion\n// ---------------------------------------------------------------------------\n\nfunction schemaToInterface(name: string, schema: Record<string, unknown>): string {\n const type = schemaToType(schema, name);\n\n // If the schema is an object, generate a named interface\n if (schema.type === \"object\" || schema.properties) {\n return generateInterface(name, schema);\n }\n\n // Otherwise, generate a type alias\n return `export type ${name} = ${type};`;\n}\n\nfunction generateInterface(name: string, schema: Record<string, unknown>): string {\n const lines: string[] = [];\n lines.push(`export interface ${name} {`);\n\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required ?? []) as string[]);\n\n for (const [key, propSchema] of Object.entries(props)) {\n const isRequired = required.has(key);\n const type = schemaToType(propSchema, name + toPascalCase(key));\n const desc = propSchema.description;\n if (desc) {\n lines.push(` /** ${desc} */`);\n }\n lines.push(` ${key}${isRequired ? \"\" : \"?\"}: ${type};`);\n }\n\n lines.push(`}`);\n return lines.join(\"\\n\");\n}\n\nfunction schemaToType(schema: Record<string, unknown>, context: string): string {\n // Handle enum\n if (schema.enum && Array.isArray(schema.enum)) {\n return (schema.enum as unknown[])\n .map((v) => (typeof v === \"string\" ? `\"${v}\"` : String(v)))\n .join(\" | \");\n }\n\n // Handle oneOf / anyOf\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n return (schema.oneOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Option${i}`))\n .join(\" | \");\n }\n if (schema.anyOf && Array.isArray(schema.anyOf)) {\n return (schema.anyOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Option${i}`))\n .join(\" | \");\n }\n\n // Handle allOf (intersection)\n if (schema.allOf && Array.isArray(schema.allOf)) {\n return (schema.allOf as Record<string, unknown>[])\n .map((s, i) => schemaToType(s, `${context}Part${i}`))\n .join(\" & \");\n }\n\n // Handle type-based conversion\n const type = schema.type as string | string[] | undefined;\n\n if (Array.isArray(type)) {\n // Multi-type (e.g., [\"string\", \"null\"])\n return type.map((t) => primitiveType(t)).join(\" | \");\n }\n\n switch (type) {\n case \"string\":\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n case \"array\": {\n const items = schema.items as Record<string, unknown> | undefined;\n if (items) {\n return `${schemaToType(items, `${context}Item`)}[]`;\n }\n return \"unknown[]\";\n }\n case \"object\": {\n if (schema.properties) {\n // Inline object — generate property types\n const props = schema.properties as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required ?? []) as string[]);\n const fields = Object.entries(props)\n .map(([key, propSchema]) => {\n const t = schemaToType(propSchema, context + toPascalCase(key));\n return `${key}${required.has(key) ? \"\" : \"?\"}: ${t}`;\n })\n .join(\"; \");\n return `{ ${fields} }`;\n }\n return \"Record<string, unknown>\";\n }\n default:\n return \"unknown\";\n }\n}\n\nfunction primitiveType(t: string): string {\n switch (t) {\n case \"string\":\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n default:\n return \"unknown\";\n }\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_@/]/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n}\n"]}