@nifrajs/cli 0.1.0-alpha.1

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/dist/check.d.ts +100 -0
  4. package/dist/check.d.ts.map +1 -0
  5. package/dist/check.js +690 -0
  6. package/dist/check.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +208 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/docs-search.d.ts +30 -0
  12. package/dist/docs-search.d.ts.map +1 -0
  13. package/dist/docs-search.js +94 -0
  14. package/dist/docs-search.js.map +1 -0
  15. package/dist/doctor.d.ts +52 -0
  16. package/dist/doctor.d.ts.map +1 -0
  17. package/dist/doctor.js +291 -0
  18. package/dist/doctor.js.map +1 -0
  19. package/dist/examples.d.ts +30 -0
  20. package/dist/examples.d.ts.map +1 -0
  21. package/dist/examples.js +70 -0
  22. package/dist/examples.js.map +1 -0
  23. package/dist/introspect.d.ts +64 -0
  24. package/dist/introspect.d.ts.map +1 -0
  25. package/dist/introspect.js +243 -0
  26. package/dist/introspect.js.map +1 -0
  27. package/dist/load.d.ts +51 -0
  28. package/dist/load.d.ts.map +1 -0
  29. package/dist/load.js +70 -0
  30. package/dist/load.js.map +1 -0
  31. package/dist/mcp-docs-tools.d.ts +13 -0
  32. package/dist/mcp-docs-tools.d.ts.map +1 -0
  33. package/dist/mcp-docs-tools.js +63 -0
  34. package/dist/mcp-docs-tools.js.map +1 -0
  35. package/dist/mcp-http.d.ts +43 -0
  36. package/dist/mcp-http.d.ts.map +1 -0
  37. package/dist/mcp-http.js +136 -0
  38. package/dist/mcp-http.js.map +1 -0
  39. package/dist/mcp-protocol.d.ts +97 -0
  40. package/dist/mcp-protocol.d.ts.map +1 -0
  41. package/dist/mcp-protocol.js +248 -0
  42. package/dist/mcp-protocol.js.map +1 -0
  43. package/dist/mcp-render.d.ts +17 -0
  44. package/dist/mcp-render.d.ts.map +1 -0
  45. package/dist/mcp-render.js +73 -0
  46. package/dist/mcp-render.js.map +1 -0
  47. package/dist/mcp-run.d.ts +24 -0
  48. package/dist/mcp-run.d.ts.map +1 -0
  49. package/dist/mcp-run.js +142 -0
  50. package/dist/mcp-run.js.map +1 -0
  51. package/dist/mcp-ws.d.ts +26 -0
  52. package/dist/mcp-ws.d.ts.map +1 -0
  53. package/dist/mcp-ws.js +258 -0
  54. package/dist/mcp-ws.js.map +1 -0
  55. package/dist/mcp.d.ts +42 -0
  56. package/dist/mcp.d.ts.map +1 -0
  57. package/dist/mcp.js +712 -0
  58. package/dist/mcp.js.map +1 -0
  59. package/dist/openapi-tool.d.ts +6 -0
  60. package/dist/openapi-tool.d.ts.map +1 -0
  61. package/dist/openapi-tool.js +48 -0
  62. package/dist/openapi-tool.js.map +1 -0
  63. package/dist/scaffold.d.ts +35 -0
  64. package/dist/scaffold.d.ts.map +1 -0
  65. package/dist/scaffold.js +140 -0
  66. package/dist/scaffold.js.map +1 -0
  67. package/dist/search-terms.d.ts +17 -0
  68. package/dist/search-terms.d.ts.map +1 -0
  69. package/dist/search-terms.js +82 -0
  70. package/dist/search-terms.js.map +1 -0
  71. package/dist/test-tool.d.ts +29 -0
  72. package/dist/test-tool.d.ts.map +1 -0
  73. package/dist/test-tool.js +150 -0
  74. package/dist/test-tool.js.map +1 -0
  75. package/docs/examples.json +314 -0
  76. package/docs/llms-full.txt +4325 -0
  77. package/package.json +58 -0
  78. package/src/check.ts +790 -0
  79. package/src/cli.ts +237 -0
  80. package/src/docs-search.ts +111 -0
  81. package/src/doctor.ts +349 -0
  82. package/src/examples.ts +89 -0
  83. package/src/introspect.ts +284 -0
  84. package/src/load.ts +129 -0
  85. package/src/mcp-docs-tools.ts +72 -0
  86. package/src/mcp-http.ts +155 -0
  87. package/src/mcp-protocol.ts +326 -0
  88. package/src/mcp-render.ts +78 -0
  89. package/src/mcp-run.ts +153 -0
  90. package/src/mcp-ws.ts +328 -0
  91. package/src/mcp.ts +863 -0
  92. package/src/openapi-tool.ts +51 -0
  93. package/src/scaffold.ts +164 -0
  94. package/src/search-terms.ts +89 -0
  95. package/src/test-tool.ts +181 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The `nifra_run` engine + its child-process entry. The MCP server spawns this file fresh on every
3
+ * `nifra_run` call (`bun mcp-run.ts <cwd>`) so the project's CURRENT backend code is loaded — picking
4
+ * up the agent's latest edits. {@link runBackend} is the pure-ish core (resolve entry → import → run),
5
+ * exported so it's unit-testable in-process; the entry below wires it to stdin/stdout.
6
+ */
7
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
8
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
9
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
10
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
11
+ });
12
+ }
13
+ return path;
14
+ };
15
+ import { existsSync } from "node:fs";
16
+ import { resolve } from "node:path";
17
+ import { pathToFileURL } from "node:url";
18
+ import { runApp } from "@nifrajs/runner";
19
+ const ENTRY_CANDIDATES = ["backend.ts", "app.ts", "src/backend.ts", "src/app.ts"];
20
+ const errString = (err) => err instanceof Error ? `${err.name}: ${err.message}` : String(err);
21
+ export async function loadBackend(cwd, entry) {
22
+ const candidates = entry && entry.length > 0 ? [entry] : ENTRY_CANDIDATES;
23
+ const found = candidates.map((c) => resolve(cwd, c)).find((p) => existsSync(p));
24
+ if (!found) {
25
+ return { error: `no backend entry found in ${cwd} (looked for ${candidates.join(", ")})` };
26
+ }
27
+ let mod;
28
+ try {
29
+ mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(found).href)));
30
+ }
31
+ catch (err) {
32
+ return { error: errString(err) };
33
+ }
34
+ const app = (mod.app ?? mod.backend ?? mod.default);
35
+ if (!app || typeof app.fetch !== "function") {
36
+ return {
37
+ error: `${found} does not export a nifra app (expected \`app\`, \`backend\`, or default).`,
38
+ };
39
+ }
40
+ return { app };
41
+ }
42
+ /**
43
+ * Resolve the backend entry under `cwd`, import it, and run `requests` through its exported app. Never
44
+ * throws — every failure (missing/invalid entry, import/compile/runtime error) becomes `{ error }`, so
45
+ * the caller (and the agent) always gets actionable output. An import error here IS the failure the
46
+ * agent needs to see and fix.
47
+ */
48
+ export async function runBackend(cwd, requests, entry) {
49
+ if (!Array.isArray(requests))
50
+ return { error: "expected { requests: [...] }" };
51
+ const loaded = await loadBackend(cwd, entry);
52
+ if ("error" in loaded)
53
+ return loaded;
54
+ try {
55
+ return { results: await runApp(loaded.app, requests) };
56
+ }
57
+ catch (err) {
58
+ return { error: errString(err) };
59
+ }
60
+ }
61
+ function redirectConsoleToStderr() {
62
+ const write = (level, args) => {
63
+ Bun.stderr.write(`[${level}] ${args.map((arg) => String(arg)).join(" ")}\n`);
64
+ };
65
+ console.debug = (...args) => write("debug", args);
66
+ console.info = (...args) => write("info", args);
67
+ console.log = (...args) => write("log", args);
68
+ console.warn = (...args) => write("warn", args);
69
+ console.error = (...args) => write("error", args);
70
+ }
71
+ async function runWorker(cwd) {
72
+ redirectConsoleToStderr();
73
+ const apps = new Map();
74
+ const decoder = new TextDecoder();
75
+ let buffer = "";
76
+ const send = (id, output) => {
77
+ process.stdout.write(`${JSON.stringify({ id, output })}\n`);
78
+ };
79
+ for await (const chunk of Bun.stdin.stream()) {
80
+ buffer += decoder.decode(chunk, { stream: true });
81
+ let nl = buffer.indexOf("\n");
82
+ while (nl !== -1) {
83
+ const line = buffer.slice(0, nl).trim();
84
+ buffer = buffer.slice(nl + 1);
85
+ nl = buffer.indexOf("\n");
86
+ if (line === "")
87
+ continue;
88
+ let message;
89
+ try {
90
+ message = JSON.parse(line);
91
+ }
92
+ catch {
93
+ send(null, { error: "invalid worker input: expected JSON line" });
94
+ continue;
95
+ }
96
+ const requests = message.input?.requests;
97
+ const entry = message.input?.entry;
98
+ if (!Array.isArray(requests)) {
99
+ send(message.id, { error: "expected { requests: [...] }" });
100
+ continue;
101
+ }
102
+ const key = entry ?? "";
103
+ let loaded = apps.get(key);
104
+ if (loaded === undefined) {
105
+ loaded = loadBackend(cwd, entry);
106
+ apps.set(key, loaded);
107
+ }
108
+ const app = await loaded;
109
+ if ("error" in app) {
110
+ send(message.id, app);
111
+ continue;
112
+ }
113
+ try {
114
+ send(message.id, {
115
+ results: await runApp(app.app, requests),
116
+ });
117
+ }
118
+ catch (err) {
119
+ send(message.id, { error: errString(err) });
120
+ }
121
+ }
122
+ }
123
+ }
124
+ // Child-process entry: read `{ requests, entry? }` from stdin, run, print JSON to stdout. Guarded so
125
+ // this only executes when run directly (not when imported by a test).
126
+ if (import.meta.main) {
127
+ const cwd = process.argv[2] ?? process.cwd();
128
+ if (process.argv.includes("--worker")) {
129
+ await runWorker(cwd);
130
+ process.exit(0);
131
+ }
132
+ let output;
133
+ try {
134
+ const { requests, entry } = JSON.parse(await Bun.stdin.text());
135
+ output = await runBackend(cwd, requests, entry);
136
+ }
137
+ catch {
138
+ output = { error: "invalid input: expected JSON { requests: [...] }" };
139
+ }
140
+ process.stdout.write(JSON.stringify(output, null, 2));
141
+ }
142
+ //# sourceMappingURL=mcp-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-run.js","sourceRoot":"","sources":["../src/mcp-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The `nifra_ws` engine + child-process entry. The MCP server spawns this file fresh on every
3
+ * WebSocket verification so the project's current backend code loads, then this module starts the
4
+ * app on an ephemeral localhost port, connects with Bun's WebSocket client, and returns structured
5
+ * evidence. It intentionally only targets the current app; this is a verification tool, not a
6
+ * general-purpose network client.
7
+ */
8
+ interface CloseInfo {
9
+ readonly code: number;
10
+ readonly reason: string;
11
+ readonly wasClean: boolean;
12
+ }
13
+ export interface WebSocketVerificationResult {
14
+ readonly ok: boolean;
15
+ readonly opened: boolean;
16
+ readonly path: string;
17
+ readonly sent: readonly string[];
18
+ readonly received: readonly string[];
19
+ readonly durationMs: number;
20
+ readonly url?: string;
21
+ readonly close?: CloseInfo;
22
+ readonly error?: string;
23
+ }
24
+ export declare function runWebSocket(cwd: string, args: unknown): Promise<WebSocketVerificationResult>;
25
+ export {};
26
+ //# sourceMappingURL=mcp-ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-ws.d.ts","sourceRoot":"","sources":["../src/mcp-ws.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4BH,UAAU,SAAS;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAsID,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,2BAA2B,CAAC,CAqHtC"}
package/dist/mcp-ws.js ADDED
@@ -0,0 +1,258 @@
1
+ /**
2
+ * The `nifra_ws` engine + child-process entry. The MCP server spawns this file fresh on every
3
+ * WebSocket verification so the project's current backend code loads, then this module starts the
4
+ * app on an ephemeral localhost port, connects with Bun's WebSocket client, and returns structured
5
+ * evidence. It intentionally only targets the current app; this is a verification tool, not a
6
+ * general-purpose network client.
7
+ */
8
+ import { loadBackend } from "./mcp-run.js";
9
+ const DEFAULT_TIMEOUT_MS = 3_000;
10
+ const MAX_TIMEOUT_MS = 30_000;
11
+ const MAX_MESSAGES = 50;
12
+ const MAX_MESSAGE_BYTES = 64 * 1024;
13
+ const MAX_PATH_LENGTH = 2_048;
14
+ const ENCODER = new TextEncoder();
15
+ const errString = (err) => err instanceof Error ? `${err.name}: ${err.message}` : String(err);
16
+ function hasControlCharacter(value) {
17
+ for (let i = 0; i < value.length; i++) {
18
+ const code = value.charCodeAt(i);
19
+ if (code < 0x20 || code === 0x7f)
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ function fail(path, sent, startedAt, error, extra = {}) {
25
+ return {
26
+ ok: false,
27
+ opened: extra.opened ?? false,
28
+ path,
29
+ sent,
30
+ received: extra.received ?? [],
31
+ durationMs: Math.round(performance.now() - startedAt),
32
+ error,
33
+ ...(extra.url === undefined ? {} : { url: extra.url }),
34
+ ...(extra.close === undefined ? {} : { close: extra.close }),
35
+ };
36
+ }
37
+ function normalizeInput(args) {
38
+ if (args === null || typeof args !== "object") {
39
+ return { error: 'expected JSON { "path": "/..." }', path: "" };
40
+ }
41
+ const input = args;
42
+ const path = input.path;
43
+ if (typeof path !== "string" || path.length === 0) {
44
+ return { error: 'expected "path" to be a non-empty string starting with "/"', path: "" };
45
+ }
46
+ if (!path.startsWith("/") || path.startsWith("//")) {
47
+ return { error: 'expected "path" to be an app-local path such as "/ws"', path };
48
+ }
49
+ if (path.length > MAX_PATH_LENGTH) {
50
+ return { error: `"path" is too long (max ${MAX_PATH_LENGTH} characters)`, path };
51
+ }
52
+ if (hasControlCharacter(path)) {
53
+ return { error: '"path" must not contain control characters', path };
54
+ }
55
+ if (path.includes("#"))
56
+ return { error: '"path" must not include a fragment', path };
57
+ const messagesValue = input.messages;
58
+ const messages = messagesValue === undefined ? [] : Array.isArray(messagesValue) ? messagesValue : undefined;
59
+ if (messages === undefined)
60
+ return { error: '"messages" must be an array of strings', path };
61
+ if (messages.length > MAX_MESSAGES) {
62
+ return { error: `"messages" can include at most ${MAX_MESSAGES} frames`, path };
63
+ }
64
+ const strings = [];
65
+ for (const [index, message] of messages.entries()) {
66
+ if (typeof message !== "string") {
67
+ return { error: `"messages[${index}]" must be a string`, path };
68
+ }
69
+ if (ENCODER.encode(message).byteLength > MAX_MESSAGE_BYTES) {
70
+ return { error: `"messages[${index}]" is too large (max ${MAX_MESSAGE_BYTES} bytes)`, path };
71
+ }
72
+ strings.push(message);
73
+ }
74
+ const expectRaw = input.expectMessages;
75
+ const expectMessages = expectRaw === undefined
76
+ ? strings.length > 0
77
+ ? strings.length
78
+ : 1
79
+ : typeof expectRaw === "number" && Number.isInteger(expectRaw)
80
+ ? expectRaw
81
+ : undefined;
82
+ if (expectMessages === undefined || expectMessages < 0 || expectMessages > MAX_MESSAGES) {
83
+ return { error: `"expectMessages" must be an integer from 0 to ${MAX_MESSAGES}`, path };
84
+ }
85
+ const timeoutRaw = input.timeoutMs;
86
+ const timeoutMs = timeoutRaw === undefined
87
+ ? DEFAULT_TIMEOUT_MS
88
+ : typeof timeoutRaw === "number" && Number.isFinite(timeoutRaw)
89
+ ? Math.trunc(timeoutRaw)
90
+ : undefined;
91
+ if (timeoutMs === undefined || timeoutMs <= 0) {
92
+ return { error: '"timeoutMs" must be a positive number', path };
93
+ }
94
+ const entry = input.entry;
95
+ if (entry !== undefined && typeof entry !== "string") {
96
+ return { error: '"entry" must be a string when provided', path };
97
+ }
98
+ return {
99
+ path,
100
+ messages: strings,
101
+ expectMessages,
102
+ timeoutMs: Math.min(Math.max(timeoutMs, 250), MAX_TIMEOUT_MS),
103
+ ...(entry === undefined || entry.length === 0 ? {} : { entry }),
104
+ };
105
+ }
106
+ async function dataToString(data) {
107
+ if (typeof data === "string")
108
+ return data;
109
+ if (data instanceof ArrayBuffer)
110
+ return new TextDecoder().decode(data);
111
+ if (ArrayBuffer.isView(data)) {
112
+ return new TextDecoder().decode(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
113
+ }
114
+ if (typeof Blob !== "undefined" && data instanceof Blob)
115
+ return data.text();
116
+ return String(data);
117
+ }
118
+ function closeInfo(event) {
119
+ return { code: event.code, reason: event.reason, wasClean: event.wasClean };
120
+ }
121
+ function redirectConsoleToStderr() {
122
+ const write = (level, args) => {
123
+ Bun.stderr.write(`[${level}] ${args.map((arg) => String(arg)).join(" ")}\n`);
124
+ };
125
+ console.debug = (...args) => write("debug", args);
126
+ console.info = (...args) => write("info", args);
127
+ console.log = (...args) => write("log", args);
128
+ console.warn = (...args) => write("warn", args);
129
+ console.error = (...args) => write("error", args);
130
+ }
131
+ export async function runWebSocket(cwd, args) {
132
+ const startedAt = performance.now();
133
+ const normalized = normalizeInput(args);
134
+ if ("error" in normalized)
135
+ return fail(normalized.path, [], startedAt, normalized.error);
136
+ const loaded = await loadBackend(cwd, normalized.entry);
137
+ if ("error" in loaded)
138
+ return fail(normalized.path, [], startedAt, loaded.error);
139
+ const app = loaded.app;
140
+ if (typeof app.listen !== "function") {
141
+ return fail(normalized.path, [], startedAt, "backend app does not expose listen(); WebSocket verification requires a Bun-listenable nifra app.");
142
+ }
143
+ let running;
144
+ let socket;
145
+ try {
146
+ running = app.listen(0);
147
+ const url = `ws://127.0.0.1:${running.port}${normalized.path}`;
148
+ socket = new WebSocket(url);
149
+ socket.binaryType = "arraybuffer";
150
+ return await new Promise((resolve) => {
151
+ const received = [];
152
+ const sent = [];
153
+ let opened = false;
154
+ let close;
155
+ let settled = false;
156
+ let timer;
157
+ const settle = (ok, error, extra = {}) => {
158
+ if (settled)
159
+ return;
160
+ settled = true;
161
+ clearTimeout(timer);
162
+ if (extra.close !== undefined)
163
+ close = extra.close;
164
+ resolve({
165
+ ok,
166
+ opened,
167
+ path: normalized.path,
168
+ url,
169
+ sent,
170
+ received,
171
+ durationMs: Math.round(performance.now() - startedAt),
172
+ ...(close === undefined ? {} : { close }),
173
+ ...(error === undefined ? {} : { error }),
174
+ });
175
+ };
176
+ timer = setTimeout(() => {
177
+ settle(false, `timed out after ${normalized.timeoutMs}ms waiting for ${normalized.expectMessages} message(s); received ${received.length}`, close === undefined ? {} : { close });
178
+ }, normalized.timeoutMs);
179
+ socket?.addEventListener("open", () => {
180
+ opened = true;
181
+ try {
182
+ for (const message of normalized.messages) {
183
+ socket?.send(message);
184
+ sent.push(message);
185
+ }
186
+ }
187
+ catch (err) {
188
+ settle(false, errString(err));
189
+ return;
190
+ }
191
+ if (normalized.expectMessages === 0)
192
+ settle(true);
193
+ });
194
+ socket?.addEventListener("message", (event) => {
195
+ void dataToString(event.data)
196
+ .then((text) => {
197
+ received.push(text);
198
+ if (received.length >= normalized.expectMessages)
199
+ settle(true);
200
+ })
201
+ .catch((err) => settle(false, errString(err)));
202
+ });
203
+ socket?.addEventListener("error", () => {
204
+ settle(false, opened ? "websocket error" : "websocket failed before open");
205
+ });
206
+ socket?.addEventListener("close", (event) => {
207
+ close = closeInfo(event);
208
+ if (!settled && received.length < normalized.expectMessages) {
209
+ settle(false, opened
210
+ ? `websocket closed before ${normalized.expectMessages} message(s); received ${received.length}`
211
+ : "websocket closed before open", { close });
212
+ }
213
+ });
214
+ });
215
+ }
216
+ catch (err) {
217
+ return fail(normalized.path, [], startedAt, errString(err));
218
+ }
219
+ finally {
220
+ try {
221
+ if (socket !== undefined && socket.readyState < WebSocket.CLOSING)
222
+ socket.close();
223
+ }
224
+ catch {
225
+ // Cleanup is best effort; the structured verification result above is the important signal.
226
+ }
227
+ try {
228
+ running?.stop(true);
229
+ }
230
+ catch {
231
+ // Same as socket.close(): do not mask the verification result with teardown noise.
232
+ }
233
+ }
234
+ }
235
+ // Child-process entry: read `{ path, messages?, expectMessages?, timeoutMs?, entry? }` from stdin,
236
+ // verify, and print JSON to stdout. Console output from the project is redirected so agents receive
237
+ // parseable JSON even when the app logs during import or request handling.
238
+ if (import.meta.main) {
239
+ redirectConsoleToStderr();
240
+ const cwd = process.argv[2] ?? process.cwd();
241
+ let output;
242
+ try {
243
+ output = await runWebSocket(cwd, JSON.parse(await Bun.stdin.text()));
244
+ }
245
+ catch {
246
+ output = {
247
+ ok: false,
248
+ opened: false,
249
+ path: "",
250
+ sent: [],
251
+ received: [],
252
+ durationMs: 0,
253
+ error: 'invalid input: expected JSON { "path": "/..." }',
254
+ };
255
+ }
256
+ process.stdout.write(JSON.stringify(output, null, 2));
257
+ }
258
+ //# sourceMappingURL=mcp-ws.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-ws.js","sourceRoot":"","sources":["../src/mcp-ws.ts"],"names":[],"mappings":"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"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `nifra mcp` — a Model Context Protocol server (stdio) that lets a coding agent (Claude, Cursor, …)
3
+ * act on a nifra project, not just read about it:
4
+ *
5
+ * - `nifra_context` — this project's API routes + page routes + conventions (see {@link describeProject}).
6
+ * - `nifra_run` — run HTTP requests through the project's backend and return structured results
7
+ * (status, body, errors). The write → run → see-the-failure → fix loop, powered by `@nifrajs/runner`.
8
+ * Each call runs the backend in a FRESH subprocess, so it reflects the agent's latest edits.
9
+ * - `nifra_render` — SSR a page route through the project's web app; returns the rendered HTML (the
10
+ * page half of `nifra_run`). Fresh subprocess per call; no build needed.
11
+ * - `nifra_ws` — verify a WebSocket route with a real Bun WebSocket round-trip.
12
+ * - `nifra_docs` — keyword-search the framework docs; returns only the matching sections.
13
+ * - `nifra_example` — a verified, copy-pasteable snippet for a task (typechecked against the live API,
14
+ * so it can't hallucinate a drifted nifra API).
15
+ * - `nifra_scaffold`— map a URL path to the correct `routes/` file + a contract-correct page stub.
16
+ * - `nifra_check` — the drift gate (typecheck + lints, each with a structured fix), for an agent to fix against.
17
+ * - `nifra_doctor` — package.json dependency drift detector, with safe local-version auto-fix.
18
+ *
19
+ * Wire it into a client (e.g. Claude Desktop / Cursor) as: command `nifra`, args `["mcp"]`, run in the
20
+ * project root. The protocol is hand-rolled (newline-delimited JSON-RPC 2.0 over stdio), including
21
+ * standard MCP progress notifications and request cancellation — no SDK dependency, the same
22
+ * minimal-surface choice as the rest of nifra. The pure dispatch lives in `./mcp-protocol.ts`; this
23
+ * module is the I/O shell (stdin loop, tool wiring, the run subprocess).
24
+ */
25
+ import type { LoadAppOptions, LoadedApp } from "./load.js";
26
+ import { type McpPrompt, type McpResource, type McpServerFeatures, type McpTool } from "./mcp-protocol.js";
27
+ type LoadAppForCache = (cwd: string, outDirName?: string, options?: LoadAppOptions) => Promise<LoadedApp>;
28
+ export interface CachedAppLoaderOptions {
29
+ readonly loadApp?: LoadAppForCache;
30
+ readonly fingerprint?: (cwd: string) => Promise<string>;
31
+ }
32
+ /** Cache LoadedApp inside one MCP server process, invalidating when config/backend mtimes change. */
33
+ export declare function createCachedAppLoader(cwd: string, options?: CachedAppLoaderOptions): (outDirName?: string) => Promise<LoadedApp>;
34
+ export declare function projectResources(cwd: string, loadAppCached?: (outDirName?: string) => Promise<LoadedApp>): McpResource[];
35
+ export declare function projectPrompts(): McpPrompt[];
36
+ export declare function projectFeatures(cwd: string, loadAppCached?: (outDirName?: string) => Promise<LoadedApp>): McpServerFeatures;
37
+ /** Build the project-scoped tools for `cwd`. */
38
+ export declare function projectTools(cwd: string, loadAppCached?: (outDirName?: string) => Promise<LoadedApp>): McpTool[];
39
+ /** Run the stdio MCP server: read newline-delimited JSON-RPC from stdin, write responses to stdout. */
40
+ export declare function runMcpServer(cwd: string, version: string): Promise<void>;
41
+ export {};
42
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE1D,OAAO,EAML,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,OAAO,EAGb,MAAM,mBAAmB,CAAA;AAgQ1B,KAAK,eAAe,GAAG,CACrB,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,cAAc,KACrB,OAAO,CAAC,SAAS,CAAC,CAAA;AAEvB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAA;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACxD;AAmCD,qGAAqG;AACrG,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,sBAA2B,GACnC,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CA+B7C;AAyCD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,aAAa,GAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAA8B,GACtF,WAAW,EAAE,CAmCf;AAED,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAkE5C;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,aAAa,GAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAA8B,GACtF,iBAAiB,CAEnB;AAED,gDAAgD;AAChD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,aAAa,GAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAA8B,GACtF,OAAO,EAAE,CAsRX;AAED,uGAAuG;AACvG,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC9E"}