@nifrajs/cli 3.5.0 → 4.0.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.
- package/README.md +42 -3
- package/dist/app-files.d.ts +11 -0
- package/dist/app-files.d.ts.map +1 -0
- package/dist/app-files.js +34 -0
- package/dist/app-files.js.map +1 -0
- package/dist/assure-hydration.d.ts +7 -1
- package/dist/assure-hydration.d.ts.map +1 -1
- package/dist/assure-hydration.js +128 -43
- package/dist/assure-hydration.js.map +1 -1
- package/dist/assure.d.ts.map +1 -1
- package/dist/assure.js +16 -2
- package/dist/assure.js.map +1 -1
- package/dist/capabilities-tool.d.ts +5 -1
- package/dist/capabilities-tool.d.ts.map +1 -1
- package/dist/capabilities-tool.js +32 -10
- package/dist/capabilities-tool.js.map +1 -1
- package/dist/cdn-check.d.ts +41 -0
- package/dist/cdn-check.d.ts.map +1 -0
- package/dist/cdn-check.js +207 -0
- package/dist/cdn-check.js.map +1 -0
- package/dist/check-diagnostics.d.ts +4 -0
- package/dist/check-diagnostics.d.ts.map +1 -1
- package/dist/check-diagnostics.js +13 -0
- package/dist/check-diagnostics.js.map +1 -1
- package/dist/check-scan.d.ts +49 -7
- package/dist/check-scan.d.ts.map +1 -1
- package/dist/check-scan.js +291 -62
- package/dist/check-scan.js.map +1 -1
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +99 -63
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +42 -16
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +262 -82
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.d.ts +62 -5
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +275 -35
- package/dist/command-catalog.js.map +1 -1
- package/dist/config-target.d.ts +8 -0
- package/dist/config-target.d.ts.map +1 -0
- package/dist/config-target.js +45 -0
- package/dist/config-target.js.map +1 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +52 -13
- package/dist/contracts.js.map +1 -1
- package/dist/db-audit.d.ts +37 -0
- package/dist/db-audit.d.ts.map +1 -0
- package/dist/db-audit.js +99 -0
- package/dist/db-audit.js.map +1 -0
- package/dist/db-child.d.ts +64 -0
- package/dist/db-child.d.ts.map +1 -0
- package/dist/db-child.js +213 -0
- package/dist/db-child.js.map +1 -0
- package/dist/db-config.d.ts +60 -0
- package/dist/db-config.d.ts.map +1 -0
- package/dist/db-config.js +176 -0
- package/dist/db-config.js.map +1 -0
- package/dist/db-tool.d.ts +84 -0
- package/dist/db-tool.d.ts.map +1 -0
- package/dist/db-tool.js +537 -0
- package/dist/db-tool.js.map +1 -0
- package/dist/dev-bun-config.d.ts +20 -13
- package/dist/dev-bun-config.d.ts.map +1 -1
- package/dist/dev-bun-config.js +98 -41
- package/dist/dev-bun-config.js.map +1 -1
- package/dist/dev-feed-tool.d.ts +106 -0
- package/dist/dev-feed-tool.d.ts.map +1 -0
- package/dist/dev-feed-tool.js +713 -0
- package/dist/dev-feed-tool.js.map +1 -0
- package/dist/dev-server-client.d.ts +67 -0
- package/dist/dev-server-client.d.ts.map +1 -0
- package/dist/dev-server-client.js +195 -0
- package/dist/dev-server-client.js.map +1 -0
- package/dist/diff-tool.d.ts +3 -3
- package/dist/diff-tool.d.ts.map +1 -1
- package/dist/diff-tool.js +6 -5
- package/dist/diff-tool.js.map +1 -1
- package/dist/docs-search.d.ts.map +1 -1
- package/dist/docs-search.js +12 -4
- package/dist/docs-search.js.map +1 -1
- package/dist/doctor.d.ts +17 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +76 -15
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +15 -0
- package/dist/env-file.d.ts.map +1 -1
- package/dist/env-file.js +73 -1
- package/dist/env-file.js.map +1 -1
- package/dist/fix-recipes.d.ts.map +1 -1
- package/dist/fix-recipes.js +48 -22
- package/dist/fix-recipes.js.map +1 -1
- package/dist/frontend-guidance.js +5 -5
- package/dist/frontend-guidance.js.map +1 -1
- package/dist/i18n-check.d.ts +16 -0
- package/dist/i18n-check.d.ts.map +1 -0
- package/dist/i18n-check.js +154 -0
- package/dist/i18n-check.js.map +1 -0
- package/dist/init-agents.d.ts +49 -13
- package/dist/init-agents.d.ts.map +1 -1
- package/dist/init-agents.js +239 -34
- package/dist/init-agents.js.map +1 -1
- package/dist/internal/code-unit-order.d.ts +4 -0
- package/dist/internal/code-unit-order.d.ts.map +1 -0
- package/dist/internal/code-unit-order.js +6 -0
- package/dist/internal/code-unit-order.js.map +1 -0
- package/dist/internal/script-kind.d.ts +7 -0
- package/dist/internal/script-kind.d.ts.map +1 -0
- package/dist/internal/script-kind.js +12 -0
- package/dist/internal/script-kind.js.map +1 -0
- package/dist/internal/source-facts.d.ts +5 -0
- package/dist/internal/source-facts.d.ts.map +1 -1
- package/dist/internal/source-facts.js +61 -5
- package/dist/internal/source-facts.js.map +1 -1
- package/dist/internal/typescript-import.d.ts +49 -24
- package/dist/internal/typescript-import.d.ts.map +1 -1
- package/dist/internal/typescript-import.js +507 -67
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +5 -1
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +92 -27
- package/dist/introspect.js.map +1 -1
- package/dist/learn.js +3 -3
- package/dist/learn.js.map +1 -1
- package/dist/levels-tool.d.ts +10 -0
- package/dist/levels-tool.d.ts.map +1 -1
- package/dist/levels-tool.js +33 -3
- package/dist/levels-tool.js.map +1 -1
- package/dist/load.d.ts +67 -17
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +78 -18
- package/dist/load.js.map +1 -1
- package/dist/manifest-tool.d.ts.map +1 -1
- package/dist/manifest-tool.js +3 -2
- package/dist/manifest-tool.js.map +1 -1
- package/dist/mcp-app-tool.d.ts.map +1 -1
- package/dist/mcp-app-tool.js +2 -0
- package/dist/mcp-app-tool.js.map +1 -1
- package/dist/mcp-context.js +1 -1
- package/dist/mcp-context.js.map +1 -1
- package/dist/mcp-delegate.d.ts +57 -0
- package/dist/mcp-delegate.d.ts.map +1 -0
- package/dist/mcp-delegate.js +130 -0
- package/dist/mcp-delegate.js.map +1 -0
- package/dist/mcp-docs-tools.d.ts.map +1 -1
- package/dist/mcp-docs-tools.js +23 -5
- package/dist/mcp-docs-tools.js.map +1 -1
- package/dist/mcp-exec.d.ts +2 -0
- package/dist/mcp-exec.d.ts.map +1 -1
- package/dist/mcp-exec.js +132 -108
- package/dist/mcp-exec.js.map +1 -1
- package/dist/mcp-http.d.ts.map +1 -1
- package/dist/mcp-http.js +17 -5
- package/dist/mcp-http.js.map +1 -1
- package/dist/mcp-io.d.ts +14 -0
- package/dist/mcp-io.d.ts.map +1 -1
- package/dist/mcp-io.js +45 -0
- package/dist/mcp-io.js.map +1 -1
- package/dist/mcp-isolate.d.ts +48 -0
- package/dist/mcp-isolate.d.ts.map +1 -0
- package/dist/mcp-isolate.js +222 -0
- package/dist/mcp-isolate.js.map +1 -0
- package/dist/mcp-project-child.d.ts +74 -0
- package/dist/mcp-project-child.d.ts.map +1 -0
- package/dist/mcp-project-child.js +130 -0
- package/dist/mcp-project-child.js.map +1 -0
- package/dist/mcp-render.js +2 -2
- package/dist/mcp-render.js.map +1 -1
- package/dist/mcp-root.d.ts +37 -9
- package/dist/mcp-root.d.ts.map +1 -1
- package/dist/mcp-root.js +110 -23
- package/dist/mcp-root.js.map +1 -1
- package/dist/mcp-run.d.ts +18 -1
- package/dist/mcp-run.d.ts.map +1 -1
- package/dist/mcp-run.js +82 -9
- package/dist/mcp-run.js.map +1 -1
- package/dist/mcp-ws.js +4 -1
- package/dist/mcp-ws.js.map +1 -1
- package/dist/mcp.d.ts +16 -3
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +81 -53
- package/dist/mcp.js.map +1 -1
- package/dist/migrate-layout.d.ts +44 -0
- package/dist/migrate-layout.d.ts.map +1 -0
- package/dist/migrate-layout.js +1155 -0
- package/dist/migrate-layout.js.map +1 -0
- package/dist/openapi-tool.d.ts +2 -2
- package/dist/openapi-tool.d.ts.map +1 -1
- package/dist/openapi-tool.js.map +1 -1
- package/dist/openapi-types.d.ts +2 -1
- package/dist/openapi-types.d.ts.map +1 -1
- package/dist/openapi-types.js +240 -12
- package/dist/openapi-types.js.map +1 -1
- package/dist/pipeline-report.d.ts +3 -2
- package/dist/pipeline-report.d.ts.map +1 -1
- package/dist/pipeline-report.js +19 -16
- package/dist/pipeline-report.js.map +1 -1
- package/dist/port.d.ts +5 -4
- package/dist/port.d.ts.map +1 -1
- package/dist/port.js +46 -29
- package/dist/port.js.map +1 -1
- package/dist/project-facts.d.ts +5 -0
- package/dist/project-facts.d.ts.map +1 -1
- package/dist/project-facts.js.map +1 -1
- package/dist/recipes/4.0.0.d.ts +9 -0
- package/dist/recipes/4.0.0.d.ts.map +1 -0
- package/dist/recipes/4.0.0.js +36 -0
- package/dist/recipes/4.0.0.js.map +1 -0
- package/dist/recipes/index.d.ts.map +1 -1
- package/dist/recipes/index.js +2 -0
- package/dist/recipes/index.js.map +1 -1
- package/dist/release-verification.d.ts +11 -1
- package/dist/release-verification.d.ts.map +1 -1
- package/dist/release-verification.js +47 -4
- package/dist/release-verification.js.map +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +12 -8
- package/dist/review.js.map +1 -1
- package/dist/route-types.d.ts +28 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +106 -0
- package/dist/route-types.js.map +1 -0
- package/dist/rules/codes.d.ts +9 -0
- package/dist/rules/codes.d.ts.map +1 -1
- package/dist/rules/codes.js +9 -0
- package/dist/rules/codes.js.map +1 -1
- package/dist/rules/data-guard.d.ts +12 -0
- package/dist/rules/data-guard.d.ts.map +1 -0
- package/dist/rules/data-guard.js +213 -0
- package/dist/rules/data-guard.js.map +1 -0
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +17 -5
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/islands.d.ts.map +1 -1
- package/dist/rules/islands.js +7 -4
- package/dist/rules/islands.js.map +1 -1
- package/dist/rules/legacy.d.ts.map +1 -1
- package/dist/rules/legacy.js +71 -38
- package/dist/rules/legacy.js.map +1 -1
- package/dist/rules/nano.d.ts.map +1 -1
- package/dist/rules/nano.js +15 -6
- package/dist/rules/nano.js.map +1 -1
- package/dist/rules/pages.d.ts +15 -0
- package/dist/rules/pages.d.ts.map +1 -0
- package/dist/rules/pages.js +88 -0
- package/dist/rules/pages.js.map +1 -0
- package/dist/rules/routes.d.ts +11 -0
- package/dist/rules/routes.d.ts.map +1 -1
- package/dist/rules/routes.js +180 -2
- package/dist/rules/routes.js.map +1 -1
- package/dist/rules/secrets.d.ts +10 -0
- package/dist/rules/secrets.d.ts.map +1 -0
- package/dist/rules/secrets.js +169 -0
- package/dist/rules/secrets.js.map +1 -0
- package/dist/rules/security.d.ts +7 -0
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +171 -65
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/typescript.d.ts +16 -0
- package/dist/rules/typescript.d.ts.map +1 -0
- package/dist/rules/typescript.js +59 -0
- package/dist/rules/typescript.js.map +1 -0
- package/dist/rules/zones.d.ts +17 -0
- package/dist/rules/zones.d.ts.map +1 -0
- package/dist/rules/zones.js +174 -0
- package/dist/rules/zones.js.map +1 -0
- package/dist/scaffold.d.ts +25 -12
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +132 -87
- package/dist/scaffold.js.map +1 -1
- package/dist/sdk.d.ts +17 -3
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +941 -153
- package/dist/sdk.js.map +1 -1
- package/dist/search-terms.d.ts +2 -0
- package/dist/search-terms.d.ts.map +1 -1
- package/dist/search-terms.js +23 -8
- package/dist/search-terms.js.map +1 -1
- package/dist/smoke.d.ts +79 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +494 -0
- package/dist/smoke.js.map +1 -0
- package/dist/sync-manifest.d.ts +10 -2
- package/dist/sync-manifest.d.ts.map +1 -1
- package/dist/sync-manifest.js +44 -19
- package/dist/sync-manifest.js.map +1 -1
- package/dist/sync-routes.d.ts +4 -3
- package/dist/sync-routes.d.ts.map +1 -1
- package/dist/sync-routes.js +4 -3
- package/dist/sync-routes.js.map +1 -1
- package/dist/test-tool.d.ts.map +1 -1
- package/dist/test-tool.js +30 -11
- package/dist/test-tool.js.map +1 -1
- package/dist/types-search.d.ts.map +1 -1
- package/dist/types-search.js +11 -5
- package/dist/types-search.js.map +1 -1
- package/dist/upgrade.d.ts +36 -6
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +167 -29
- package/dist/upgrade.js.map +1 -1
- package/dist/verification-plan.d.ts.map +1 -1
- package/dist/verification-plan.js +4 -0
- package/dist/verification-plan.js.map +1 -1
- package/dist/verification.d.ts.map +1 -1
- package/dist/verification.js +45 -12
- package/dist/verification.js.map +1 -1
- package/dist/web-app-options.d.ts +19 -0
- package/dist/web-app-options.d.ts.map +1 -0
- package/dist/web-app-options.js +49 -0
- package/dist/web-app-options.js.map +1 -0
- package/dist/work-graph.d.ts.map +1 -1
- package/dist/work-graph.js +29 -13
- package/dist/work-graph.js.map +1 -1
- package/docs/examples.json +185 -29
- package/docs/llms-full.txt +3807 -580
- package/docs/types.json +14229 -10939
- package/package.json +19 -12
- package/src/app-files.ts +40 -0
- package/src/assure-hydration.ts +139 -46
- package/src/assure.ts +17 -2
- package/src/capabilities-tool.ts +35 -9
- package/src/cdn-check.ts +268 -0
- package/src/check-diagnostics.ts +17 -0
- package/src/check-scan.ts +358 -63
- package/src/check.ts +97 -62
- package/src/cli.ts +296 -87
- package/src/command-catalog.ts +389 -48
- package/src/config-target.ts +47 -0
- package/src/contracts.ts +54 -12
- package/src/db-audit.ts +128 -0
- package/src/db-child.ts +285 -0
- package/src/db-config.ts +224 -0
- package/src/db-tool.ts +690 -0
- package/src/dev-bun-config.ts +116 -40
- package/src/dev-feed-tool.ts +912 -0
- package/src/dev-server-client.ts +267 -0
- package/src/diff-tool.ts +6 -5
- package/src/docs-search.ts +10 -3
- package/src/doctor.ts +98 -15
- package/src/env-file.ts +78 -1
- package/src/fix-recipes.ts +53 -32
- package/src/frontend-guidance.ts +5 -5
- package/src/i18n-check.ts +179 -0
- package/src/init-agents.ts +301 -38
- package/src/internal/code-unit-order.ts +5 -0
- package/src/internal/script-kind.ts +11 -0
- package/src/internal/source-facts.ts +96 -22
- package/src/internal/typescript-import.ts +663 -68
- package/src/introspect.ts +90 -27
- package/src/learn.ts +3 -3
- package/src/levels-tool.ts +47 -2
- package/src/load.ts +140 -33
- package/src/manifest-tool.ts +3 -2
- package/src/mcp-app-tool.ts +2 -0
- package/src/mcp-context.ts +1 -1
- package/src/mcp-delegate.ts +162 -0
- package/src/mcp-docs-tools.ts +23 -5
- package/src/mcp-exec.ts +160 -132
- package/src/mcp-http.ts +19 -5
- package/src/mcp-io.ts +57 -0
- package/src/mcp-isolate.ts +287 -0
- package/src/mcp-project-child.ts +182 -0
- package/src/mcp-render.ts +2 -2
- package/src/mcp-root.ts +117 -22
- package/src/mcp-run.ts +104 -10
- package/src/mcp-ws.ts +4 -1
- package/src/mcp.ts +106 -64
- package/src/migrate-layout.ts +1338 -0
- package/src/openapi-tool.ts +7 -3
- package/src/openapi-types.ts +315 -13
- package/src/pipeline-report.ts +22 -18
- package/src/port.ts +53 -30
- package/src/project-facts.ts +5 -0
- package/src/recipes/4.0.0.ts +37 -0
- package/src/recipes/index.ts +2 -0
- package/src/release-verification.ts +74 -5
- package/src/review.ts +13 -8
- package/src/route-types.ts +133 -0
- package/src/rules/codes.ts +9 -0
- package/src/rules/data-guard.ts +230 -0
- package/src/rules/index.ts +18 -5
- package/src/rules/islands.ts +12 -4
- package/src/rules/legacy.ts +71 -39
- package/src/rules/nano.ts +18 -6
- package/src/rules/pages.ts +99 -0
- package/src/rules/routes.ts +181 -2
- package/src/rules/secrets.ts +174 -0
- package/src/rules/security.ts +198 -70
- package/src/rules/typescript.ts +77 -0
- package/src/rules/zones.ts +195 -0
- package/src/scaffold.ts +147 -95
- package/src/sdk.ts +1215 -158
- package/src/search-terms.ts +24 -7
- package/src/smoke.ts +607 -0
- package/src/sync-manifest.ts +50 -19
- package/src/sync-routes.ts +4 -3
- package/src/test-tool.ts +32 -11
- package/src/types-search.ts +11 -4
- package/src/upgrade.ts +205 -25
- package/src/verification-plan.ts +13 -0
- package/src/verification.ts +50 -12
- package/src/web-app-options.ts +57 -0
- package/src/work-graph.ts +27 -13
package/src/mcp.ts
CHANGED
|
@@ -20,19 +20,32 @@
|
|
|
20
20
|
* - `nifra_levels` - the cumulative verification ladder (L0 contract → L4 invariants): what the
|
|
21
21
|
* project actually proves, and why each level it misses does not hold.
|
|
22
22
|
* - `nifra_doctor` - package.json dependency drift detector, with safe local-version auto-fix.
|
|
23
|
-
* - `
|
|
23
|
+
* - `nifra_errors` - the running dev server's errors (SSR, loader, API, build, browser, hydration,
|
|
24
|
+
* crash), each a structured diagnostic tagged with its request; `since` cursors, stale flags.
|
|
25
|
+
* - `nifra_logs` - the dev server's console output, server and browser, tagged by request.
|
|
26
|
+
* - `nifra_db_schema` / `nifra_db_query` / `nifra_db_role` - the development database declared as
|
|
27
|
+
* `devDatabase` in nifra.config.ts: its schema, one read-only query (or plan) per call in a fresh
|
|
28
|
+
* subprocess killed at the deadline, and the SQL for a read-only role. Separate tools, so a client
|
|
29
|
+
* can allow reading the schema without allowing queries.
|
|
30
|
+
* - `nifra_explain` - resolve an error (pasted, or the dev server's latest) into a structured
|
|
24
31
|
* diagnostic: stable code, a codeframe in the user's source, and the recognised cause + fix.
|
|
25
32
|
* - `nifra_inspect` - read the running dev server's recent request traces (method/path/status/
|
|
26
|
-
* duration/ISR)
|
|
33
|
+
* duration/ISR/errors): what your requests ACTUALLY did, not a guess.
|
|
27
34
|
*
|
|
28
35
|
* Wire it into a client (e.g. Claude Desktop / Cursor) as: command `nifra`, args `["mcp"]` (or
|
|
29
36
|
* `["mcp", "<dir>"]` to pin the project directory explicitly). The server does NOT silently trust its
|
|
30
37
|
* spawn directory: the root is resolved via `./mcp-root.ts` (marker walk-up, the client's MCP `roots`,
|
|
31
38
|
* fail-closed tools when no nifra project is found) and announced in `initialize` + on every project
|
|
32
|
-
* tool result.
|
|
39
|
+
* tool result. A project that installs its own `@nifrajs/cli` at a different version gets the session
|
|
40
|
+
* handed to that CLI; when that is impossible the version-sensitive tools refuse rather than answer
|
|
41
|
+
* for the wrong release (see `./mcp-delegate.ts`). The protocol is hand-rolled (newline-delimited JSON-RPC 2.0 over stdio), including
|
|
33
42
|
* standard MCP progress notifications and request cancellation - no SDK dependency, the same
|
|
34
43
|
* minimal-surface choice as the rest of nifra. The pure dispatch lives in `./mcp-protocol.ts`; this
|
|
35
44
|
* module is the I/O shell (stdin loop, tool wiring, the run subprocess).
|
|
45
|
+
*
|
|
46
|
+
* This process runs no project code and holds none of the project's `.env`: the config, the backend
|
|
47
|
+
* and everything they import run in a fresh subprocess per call (`./mcp-isolate.ts`), and a session
|
|
48
|
+
* whose process Bun started with `.env` values moves to a copy that never loads them (`./cli.ts`).
|
|
36
49
|
*/
|
|
37
50
|
|
|
38
51
|
import { stat } from "node:fs/promises"
|
|
@@ -40,7 +53,8 @@ import { resolve } from "node:path"
|
|
|
40
53
|
import { loadDocsCorpus } from "./docs-search.ts"
|
|
41
54
|
import { loadExamplesCorpus } from "./examples.ts"
|
|
42
55
|
import type { LoadedApp } from "./load.ts"
|
|
43
|
-
import {
|
|
56
|
+
import { loadMonorepoApps } from "./load.ts"
|
|
57
|
+
import { delegateToProjectCli, refuseVersionSensitive } from "./mcp-delegate.ts"
|
|
44
58
|
import { docsTools } from "./mcp-docs-tools.ts"
|
|
45
59
|
import {
|
|
46
60
|
createMcpProtocolState,
|
|
@@ -56,11 +70,6 @@ import {
|
|
|
56
70
|
type McpTool,
|
|
57
71
|
rpcError,
|
|
58
72
|
} from "./mcp-protocol.ts"
|
|
59
|
-
import {
|
|
60
|
-
extractBackendPrompts,
|
|
61
|
-
extractBackendResources,
|
|
62
|
-
extractBackendTools,
|
|
63
|
-
} from "./mcp-reflect.ts"
|
|
64
73
|
import { loadTypesCorpus } from "./types-search.ts"
|
|
65
74
|
|
|
66
75
|
export {
|
|
@@ -99,7 +108,14 @@ export {
|
|
|
99
108
|
} from "./mcp-io.ts"
|
|
100
109
|
export { clientSupportsRoots, guardTools } from "./mcp-root.ts"
|
|
101
110
|
|
|
102
|
-
import {
|
|
111
|
+
import { projectTools } from "./mcp-exec.ts"
|
|
112
|
+
import {
|
|
113
|
+
createAppSurface,
|
|
114
|
+
detectMonorepoIsolated,
|
|
115
|
+
type IsolatedSurface,
|
|
116
|
+
isolateResources,
|
|
117
|
+
isolateTools,
|
|
118
|
+
} from "./mcp-isolate.ts"
|
|
103
119
|
|
|
104
120
|
export type { CachedAppLoaderOptions } from "./mcp-exec.ts"
|
|
105
121
|
export {
|
|
@@ -115,7 +131,7 @@ export {
|
|
|
115
131
|
wsHandler,
|
|
116
132
|
} from "./mcp-exec.ts"
|
|
117
133
|
|
|
118
|
-
import { namespaceForApp,
|
|
134
|
+
import { namespaceForApp, projectPrompts, projectResources } from "./mcp-context.ts"
|
|
119
135
|
|
|
120
136
|
export type { CommandMcpToolOptions } from "./mcp-context.ts"
|
|
121
137
|
export {
|
|
@@ -127,35 +143,39 @@ export {
|
|
|
127
143
|
resolveProjectDir,
|
|
128
144
|
} from "./mcp-context.ts"
|
|
129
145
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
} catch {
|
|
141
|
-
// Not loadable here (no web config, or the config itself throws). The server still serves.
|
|
142
|
-
}
|
|
143
|
-
return { resources, prompts }
|
|
144
|
-
}
|
|
146
|
+
/**
|
|
147
|
+
* The loader the server builds its tool and resource lists with. It never loads: every handler that
|
|
148
|
+
* reaches the app runs in a project subprocess (`./mcp-isolate.ts`), so one that tried here fails.
|
|
149
|
+
*/
|
|
150
|
+
const noAppInServer = (): Promise<LoadedApp> =>
|
|
151
|
+
Promise.reject(
|
|
152
|
+
new Error("[nifra] the MCP server does not load the app; project code runs in a subprocess"),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
const isolatedToolsByDir = new Map<string, McpTool[]>()
|
|
145
156
|
|
|
146
157
|
/**
|
|
147
|
-
* The
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* so an unloadable project failed `initialize` itself with a `-32603` and the session never opened.
|
|
151
|
-
* An app's own tools are an extension of the built-in set, so their absence must not withdraw the
|
|
152
|
-
* built-ins - a backend-only project still gets docs, examples, types, check, doctor, levels and test.
|
|
158
|
+
* The project's tools, each forwarded to a project subprocess unless it runs no project code. Built
|
|
159
|
+
* once per directory: `nifra_run`/`nifra_render` hold their warm worker in the tool, so a list rebuilt
|
|
160
|
+
* per message started a fresh worker for every `warm: true` call.
|
|
153
161
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
function isolatedProjectTools(cwd: string): McpTool[] {
|
|
163
|
+
let tools = isolatedToolsByDir.get(cwd)
|
|
164
|
+
if (tools === undefined) {
|
|
165
|
+
tools = isolateTools(cwd, projectTools(cwd, noAppInServer))
|
|
166
|
+
isolatedToolsByDir.set(cwd, tools)
|
|
167
|
+
}
|
|
168
|
+
return tools
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** The project's resources and prompts, with the ones the app declares. */
|
|
172
|
+
function appFeatures(cwd: string, surface: IsolatedSurface): McpServerFeatures {
|
|
173
|
+
return {
|
|
174
|
+
resources: [
|
|
175
|
+
...isolateResources(cwd, projectResources(cwd, noAppInServer)),
|
|
176
|
+
...surface.resources,
|
|
177
|
+
],
|
|
178
|
+
prompts: [...projectPrompts(), ...surface.prompts],
|
|
159
179
|
}
|
|
160
180
|
}
|
|
161
181
|
|
|
@@ -163,42 +183,42 @@ const ROOTS_REQUEST_ID = "nifra:roots/list"
|
|
|
163
183
|
const MAX_STDIO_MESSAGE_BYTES = 8 * 1024 * 1024
|
|
164
184
|
const STDIO_ENCODER = new TextEncoder()
|
|
165
185
|
|
|
186
|
+
interface ProjectApp {
|
|
187
|
+
readonly name: string
|
|
188
|
+
readonly cwd: string
|
|
189
|
+
readonly surface: () => Promise<IsolatedSurface>
|
|
190
|
+
}
|
|
191
|
+
|
|
166
192
|
/** Everything derived from the project root - rebuilt wholesale when the root changes (adoption of a
|
|
167
193
|
* client workspace root), so no per-tool state can keep pointing at the old directory. */
|
|
168
194
|
interface ProjectContext {
|
|
169
|
-
|
|
195
|
+
/** A monorepo root's apps; `undefined` when the root is one app. */
|
|
196
|
+
readonly apps: readonly ProjectApp[] | undefined
|
|
170
197
|
readonly features: McpServerFeatures
|
|
171
|
-
readonly
|
|
198
|
+
readonly surface: () => Promise<IsolatedSurface>
|
|
172
199
|
}
|
|
173
200
|
|
|
174
201
|
async function createProjectContext(root: string): Promise<ProjectContext> {
|
|
175
|
-
const monorepo = await
|
|
202
|
+
const monorepo = await detectMonorepoIsolated(root)
|
|
176
203
|
if (monorepo) {
|
|
177
|
-
const
|
|
204
|
+
const apps = (await loadMonorepoApps(root, monorepo)).map(
|
|
205
|
+
({ name, cwd }): ProjectApp => ({ name, cwd, surface: createAppSurface(cwd) }),
|
|
206
|
+
)
|
|
178
207
|
const allResources: McpResource[] = []
|
|
179
208
|
const allPrompts: McpPrompt[] = []
|
|
180
|
-
for (const { name, cwd: appCwd } of
|
|
181
|
-
const
|
|
182
|
-
const ns = namespaceForApp(
|
|
183
|
-
name,
|
|
184
|
-
[],
|
|
185
|
-
await backendFeatures(loader, projectFeatures(appCwd, loader)),
|
|
186
|
-
)
|
|
209
|
+
for (const { name, cwd: appCwd, surface } of apps) {
|
|
210
|
+
const ns = namespaceForApp(name, [], appFeatures(appCwd, await surface()))
|
|
187
211
|
allResources.push(...(ns.features.resources ?? []))
|
|
188
212
|
allPrompts.push(...(ns.features.prompts ?? []))
|
|
189
213
|
}
|
|
190
214
|
return {
|
|
191
|
-
|
|
215
|
+
apps,
|
|
192
216
|
features: { resources: allResources, prompts: allPrompts },
|
|
193
|
-
|
|
217
|
+
surface: createAppSurface(root),
|
|
194
218
|
}
|
|
195
219
|
}
|
|
196
|
-
const
|
|
197
|
-
return {
|
|
198
|
-
monorepo,
|
|
199
|
-
features: await backendFeatures(loadAppCached, projectFeatures(root, loadAppCached)),
|
|
200
|
-
loadAppCached,
|
|
201
|
-
}
|
|
220
|
+
const surface = createAppSurface(root)
|
|
221
|
+
return { apps: undefined, features: appFeatures(root, await surface()), surface }
|
|
202
222
|
}
|
|
203
223
|
|
|
204
224
|
/**
|
|
@@ -217,6 +237,19 @@ export async function runMcpServer(
|
|
|
217
237
|
throw new Error(`nifra mcp: directory not found: ${requested}`)
|
|
218
238
|
}
|
|
219
239
|
let rootState = await resolveRootState(requested, explicitDir !== undefined)
|
|
240
|
+
if (rootState.isProject) {
|
|
241
|
+
// Before anything reads stdin: a hand-off child inherits the descriptor and owns the session.
|
|
242
|
+
const exitCode = await delegateToProjectCli({
|
|
243
|
+
cwd,
|
|
244
|
+
root: rootState.root,
|
|
245
|
+
version,
|
|
246
|
+
args: explicitDir === undefined ? [] : [requested],
|
|
247
|
+
})
|
|
248
|
+
if (exitCode !== undefined) {
|
|
249
|
+
process.exitCode = exitCode
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
}
|
|
220
253
|
let ctx = await createProjectContext(rootState.root)
|
|
221
254
|
let drift: ToolingDrift | undefined = await detectToolingDrift(rootState.root, version)
|
|
222
255
|
const serverInfo = { name: "nifra", version }
|
|
@@ -277,20 +310,27 @@ export async function runMcpServer(
|
|
|
277
310
|
}
|
|
278
311
|
|
|
279
312
|
let activeTools: McpTool[]
|
|
280
|
-
if (ctx.
|
|
281
|
-
const appEntries = await loadMonorepoApps(rootState.root, ctx.monorepo)
|
|
313
|
+
if (ctx.apps) {
|
|
282
314
|
const allTools: McpTool[] = []
|
|
283
|
-
for (const { name, cwd: appCwd } of
|
|
284
|
-
const
|
|
285
|
-
|
|
315
|
+
for (const { name, cwd: appCwd, surface } of ctx.apps) {
|
|
316
|
+
const tools = [
|
|
317
|
+
...refuseVersionSensitive(isolatedProjectTools(appCwd), drift),
|
|
318
|
+
...(await surface()).tools,
|
|
319
|
+
]
|
|
286
320
|
const ns = namespaceForApp(name, tools, { resources: [], prompts: [] })
|
|
287
321
|
allTools.push(...ns.tools)
|
|
288
322
|
}
|
|
289
|
-
activeTools = [
|
|
323
|
+
activeTools = [
|
|
324
|
+
...refuseVersionSensitive(
|
|
325
|
+
docsTools(loadDocsCorpus, loadExamplesCorpus, loadTypesCorpus),
|
|
326
|
+
drift,
|
|
327
|
+
),
|
|
328
|
+
...allTools,
|
|
329
|
+
]
|
|
290
330
|
} else {
|
|
291
331
|
activeTools = [
|
|
292
|
-
...
|
|
293
|
-
...(await
|
|
332
|
+
...refuseVersionSensitive(isolatedProjectTools(rootState.root), drift),
|
|
333
|
+
...(await ctx.surface()).tools,
|
|
294
334
|
]
|
|
295
335
|
}
|
|
296
336
|
const verdict = await rootVerdict(rootState)
|
|
@@ -308,6 +348,8 @@ export async function runMcpServer(
|
|
|
308
348
|
const response = await handleRpc(message, activeTools, serverInfo, features, {
|
|
309
349
|
state,
|
|
310
350
|
sendNotification: send,
|
|
351
|
+
// The stdio caller is the developer's own agent: a failure it cannot read it cannot fix.
|
|
352
|
+
exposeToolErrors: true,
|
|
311
353
|
})
|
|
312
354
|
if (response) send(response)
|
|
313
355
|
// Ask for the client's workspace roots once the handshake completes, and again whenever the
|