codebase-onboarder 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -46
- package/bin/build-if-source.js +23 -0
- package/cli/commands.d.ts +26 -0
- package/cli/commands.js +836 -811
- package/cli/commands.js.map +1 -0
- package/cli/explorer/advanced.d.ts +14 -0
- package/cli/explorer/advanced.js +321 -329
- package/cli/explorer/advanced.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +384 -313
- package/cli/explorer/app.js.map +1 -0
- package/cli/explorer/assistant.d.ts +9 -0
- package/cli/explorer/assistant.js +58 -0
- package/cli/explorer/assistant.js.map +1 -0
- package/cli/explorer/commands.d.ts +17 -0
- package/cli/explorer/commands.js +368 -302
- package/cli/explorer/commands.js.map +1 -0
- package/cli/explorer/featureViews.d.ts +124 -0
- package/cli/explorer/featureViews.js +179 -0
- package/cli/explorer/featureViews.js.map +1 -0
- package/cli/explorer/github.d.ts +21 -0
- package/cli/explorer/github.js +42 -44
- package/cli/explorer/github.js.map +1 -0
- package/cli/explorer/graphs.d.ts +7 -0
- package/cli/explorer/graphs.js +90 -95
- package/cli/explorer/graphs.js.map +1 -0
- package/cli/explorer/picker.d.ts +22 -0
- package/cli/explorer/picker.js +150 -0
- package/cli/explorer/picker.js.map +1 -0
- package/cli/explorer/report.d.ts +85 -0
- package/cli/explorer/report.js +60 -0
- package/cli/explorer/report.js.map +1 -0
- package/cli/explorer/session.d.ts +449 -0
- package/cli/explorer/session.js +143 -144
- package/cli/explorer/session.js.map +1 -0
- package/cli/explorer/views.d.ts +19 -0
- package/cli/explorer/views.js +465 -482
- package/cli/explorer/views.js.map +1 -0
- package/cli/explorer/wrap.d.ts +1 -0
- package/cli/explorer/wrap.js +28 -44
- package/cli/explorer/wrap.js.map +1 -0
- package/cli/main.d.ts +1 -0
- package/cli/main.js +214 -161
- package/cli/main.js.map +1 -0
- package/cli/prompt.d.ts +5 -0
- package/cli/prompt.js +84 -80
- package/cli/prompt.js.map +1 -0
- package/cli/scanOptions.d.ts +2 -0
- package/cli/scanOptions.js +11 -0
- package/cli/scanOptions.js.map +1 -0
- package/cli/ui.d.ts +33 -0
- package/cli/ui.js +35 -44
- package/cli/ui.js.map +1 -0
- package/cli/wizard.d.ts +187 -0
- package/cli/wizard.js +304 -284
- package/cli/wizard.js.map +1 -0
- package/package.json +15 -4
- package/public/app.d.ts +1 -0
- package/public/app.js +1057 -1009
- package/public/app.js.map +1 -0
- package/public/browser.d.ts +68 -0
- package/public/browser.js +2 -0
- package/public/browser.js.map +1 -0
- package/public/index.html +30 -13
- package/public/js/about.d.ts +6 -0
- package/public/js/about.js +152 -172
- package/public/js/about.js.map +1 -0
- package/public/js/aiDraft.d.ts +3 -0
- package/public/js/aiDraft.js +116 -124
- package/public/js/aiDraft.js.map +1 -0
- package/public/js/analysisPanel.d.ts +7 -0
- package/public/js/analysisPanel.js +166 -166
- package/public/js/analysisPanel.js.map +1 -0
- package/public/js/analysisReport.d.ts +38 -0
- package/public/js/analysisReport.js +105 -110
- package/public/js/analysisReport.js.map +1 -0
- package/public/js/api.d.ts +26 -0
- package/public/js/api.js +176 -167
- package/public/js/api.js.map +1 -0
- package/public/js/atlas.d.ts +6 -0
- package/public/js/atlas.js +50 -58
- package/public/js/atlas.js.map +1 -0
- package/public/js/blameView.d.ts +2 -0
- package/public/js/blameView.js +36 -37
- package/public/js/blameView.js.map +1 -0
- package/public/js/codeTab.d.ts +3 -0
- package/public/js/codeTab.js +175 -180
- package/public/js/codeTab.js.map +1 -0
- package/public/js/codeViewer.d.ts +5 -0
- package/public/js/codeViewer.js +162 -150
- package/public/js/codeViewer.js.map +1 -0
- package/public/js/components/FileChip.d.ts +9 -0
- package/public/js/components/FileChip.js +45 -49
- package/public/js/components/FileChip.js.map +1 -0
- package/public/js/components/MetricSparkline.d.ts +7 -0
- package/public/js/components/MetricSparkline.js +35 -44
- package/public/js/components/MetricSparkline.js.map +1 -0
- package/public/js/components/RiskBadge.d.ts +9 -0
- package/public/js/components/RiskBadge.js +55 -63
- package/public/js/components/RiskBadge.js.map +1 -0
- package/public/js/deepAnalysisView.d.ts +99 -0
- package/public/js/deepAnalysisView.js +282 -302
- package/public/js/deepAnalysisView.js.map +1 -0
- package/public/js/diagramPane.d.ts +8 -0
- package/public/js/diagramPane.js +133 -135
- package/public/js/diagramPane.js.map +1 -0
- package/public/js/diffView.d.ts +6 -0
- package/public/js/diffView.js +222 -209
- package/public/js/diffView.js.map +1 -0
- package/public/js/docsView.d.ts +2 -0
- package/public/js/docsView.js +441 -442
- package/public/js/docsView.js.map +1 -0
- package/public/js/dom.d.ts +189 -0
- package/public/js/dom.js +5 -0
- package/public/js/dom.js.map +1 -0
- package/public/js/fileSourceBrowser.d.ts +5 -0
- package/public/js/fileSourceBrowser.js +33 -41
- package/public/js/fileSourceBrowser.js.map +1 -0
- package/public/js/flameGraph.d.ts +5 -0
- package/public/js/flameGraph.js +62 -72
- package/public/js/flameGraph.js.map +1 -0
- package/public/js/forceGraph.d.ts +10 -0
- package/public/js/forceGraph.js +581 -556
- package/public/js/forceGraph.js.map +1 -0
- package/public/js/heatmap.d.ts +4 -0
- package/public/js/heatmap.js +142 -164
- package/public/js/heatmap.js.map +1 -0
- package/public/js/highlight.d.ts +2 -0
- package/public/js/highlight.js +116 -107
- package/public/js/highlight.js.map +1 -0
- package/public/js/html.d.ts +2 -0
- package/public/js/html.js +14 -44
- package/public/js/html.js.map +1 -0
- package/public/js/insightsView.d.ts +5 -0
- package/public/js/insightsView.js +93 -111
- package/public/js/insightsView.js.map +1 -0
- package/public/js/inspector.d.ts +37 -0
- package/public/js/inspector.js +416 -445
- package/public/js/inspector.js.map +1 -0
- package/public/js/llm.d.ts +113 -0
- package/public/js/llm.js +233 -272
- package/public/js/llm.js.map +1 -0
- package/public/js/mapView.d.ts +3 -0
- package/public/js/mapView.js +121 -120
- package/public/js/mapView.js.map +1 -0
- package/public/js/markdown.d.ts +3 -0
- package/public/js/markdown.js +84 -91
- package/public/js/markdown.js.map +1 -0
- package/public/js/mindmap.d.ts +32 -0
- package/public/js/mindmap.js +244 -259
- package/public/js/mindmap.js.map +1 -0
- package/public/js/mobilePanels.d.ts +5 -0
- package/public/js/mobilePanels.js +50 -0
- package/public/js/mobilePanels.js.map +1 -0
- package/public/js/repoFiles.d.ts +12 -0
- package/public/js/repoFiles.js +28 -27
- package/public/js/repoFiles.js.map +1 -0
- package/public/js/reviewView.d.ts +28 -0
- package/public/js/reviewView.js +256 -0
- package/public/js/reviewView.js.map +1 -0
- package/public/js/sbomView.d.ts +3 -0
- package/public/js/sbomView.js +59 -67
- package/public/js/sbomView.js.map +1 -0
- package/public/js/scanCache.d.ts +16 -0
- package/public/js/scanCache.js +67 -65
- package/public/js/scanCache.js.map +1 -0
- package/public/js/search.d.ts +7 -0
- package/public/js/search.js +868 -800
- package/public/js/search.js.map +1 -0
- package/public/js/searchLocal.d.ts +42 -0
- package/public/js/searchLocal.js +87 -0
- package/public/js/searchLocal.js.map +1 -0
- package/public/js/serverSettings.d.ts +5 -0
- package/public/js/serverSettings.js +153 -164
- package/public/js/serverSettings.js.map +1 -0
- package/public/js/state.d.ts +798 -0
- package/public/js/state.js +114 -122
- package/public/js/state.js.map +1 -0
- package/public/js/tour.d.ts +6 -0
- package/public/js/tour.js +5 -7
- package/public/js/tour.js.map +1 -0
- package/public/js/transitions.d.ts +2 -0
- package/public/js/transitions.js +9 -10
- package/public/js/transitions.js.map +1 -0
- package/public/js/tree.d.ts +12 -0
- package/public/js/tree.js +157 -154
- package/public/js/tree.js.map +1 -0
- package/public/js/workflowsView.d.ts +3 -0
- package/public/js/workflowsView.js +15 -22
- package/public/js/workflowsView.js.map +1 -0
- package/public/search.css +495 -0
- package/public/styles.css +163 -346
- package/public/workbench.css +166 -0
- package/server/apiAuth.d.ts +3 -0
- package/server/apiAuth.js +18 -20
- package/server/apiAuth.js.map +1 -0
- package/server/apiDiff.d.ts +2 -0
- package/server/apiDiff.js +20 -18
- package/server/apiDiff.js.map +1 -0
- package/server/apiDocs.d.ts +2 -0
- package/server/apiDocs.js +38 -40
- package/server/apiDocs.js.map +1 -0
- package/server/apiFile.d.ts +1 -0
- package/server/apiFile.js +14 -17
- package/server/apiFile.js.map +1 -0
- package/server/apiGitBlame.d.ts +2 -0
- package/server/apiGitBlame.js +50 -51
- package/server/apiGitBlame.js.map +1 -0
- package/server/apiMcp.d.ts +4 -0
- package/server/apiMcp.js +64 -66
- package/server/apiMcp.js.map +1 -0
- package/server/apiReview.d.ts +2 -0
- package/server/apiReview.js +45 -0
- package/server/apiReview.js.map +1 -0
- package/server/apiScan.d.ts +5 -0
- package/server/apiScan.js +90 -71
- package/server/apiScan.js.map +1 -0
- package/server/apiSearch.d.ts +33 -0
- package/server/apiSearch.js +184 -200
- package/server/apiSearch.js.map +1 -0
- package/server/apiSettings.d.ts +4 -0
- package/server/apiSettings.js +84 -85
- package/server/apiSettings.js.map +1 -0
- package/server/apiTools.d.ts +3 -0
- package/server/apiTools.js +55 -56
- package/server/apiTools.js.map +1 -0
- package/server/auth.d.ts +5 -0
- package/server/auth.js +54 -51
- package/server/auth.js.map +1 -0
- package/server/config.d.ts +42 -0
- package/server/config.js +189 -194
- package/server/config.js.map +1 -0
- package/server/daemon.d.ts +12 -0
- package/server/daemon.js +124 -114
- package/server/daemon.js.map +1 -0
- package/server/fileSourceNode.d.ts +2 -0
- package/server/fileSourceNode.js +34 -36
- package/server/fileSourceNode.js.map +1 -0
- package/server/gitClone.d.ts +9 -0
- package/server/gitClone.js +59 -61
- package/server/gitClone.js.map +1 -0
- package/server/gitDiff.d.ts +36 -0
- package/server/gitDiff.js +271 -169
- package/server/gitDiff.js.map +1 -0
- package/server/gitHistory.d.ts +12 -0
- package/server/gitHistory.js +80 -80
- package/server/gitHistory.js.map +1 -0
- package/server/gitRemote.d.ts +12 -0
- package/server/gitRemote.js +37 -38
- package/server/gitRemote.js.map +1 -0
- package/server/htmlText.d.ts +4 -0
- package/server/htmlText.js +16 -23
- package/server/htmlText.js.map +1 -0
- package/server/http.d.ts +5 -0
- package/server/http.js +27 -30
- package/server/http.js.map +1 -0
- package/server/httpGuards.d.ts +2 -0
- package/server/httpGuards.js +47 -43
- package/server/httpGuards.js.map +1 -0
- package/server/https.d.ts +34 -0
- package/server/https.js +121 -111
- package/server/https.js.map +1 -0
- package/server/index.d.ts +40 -0
- package/server/index.js +139 -147
- package/server/index.js.map +1 -0
- package/server/layout.d.ts +26 -0
- package/server/layout.js +59 -64
- package/server/layout.js.map +1 -0
- package/server/llmProxy.d.ts +3 -0
- package/server/llmProxy.js +137 -135
- package/server/llmProxy.js.map +1 -0
- package/server/logger.d.ts +38 -0
- package/server/logger.js +198 -211
- package/server/logger.js.map +1 -0
- package/server/mcp/analysis.d.ts +29 -0
- package/server/mcp/analysis.js +99 -120
- package/server/mcp/analysis.js.map +1 -0
- package/server/mcp/http.d.ts +9 -0
- package/server/mcp/http.js +128 -137
- package/server/mcp/http.js.map +1 -0
- package/server/mcp/runner.d.ts +68 -0
- package/server/mcp/runner.js +208 -218
- package/server/mcp/runner.js.map +1 -0
- package/server/mcp/server.d.ts +29 -0
- package/server/mcp/server.js +166 -179
- package/server/mcp/server.js.map +1 -0
- package/server/mcp/standalone.d.ts +1 -0
- package/server/mcp/standalone.js +8 -10
- package/server/mcp/standalone.js.map +1 -0
- package/server/mcp/tools.d.ts +2020 -0
- package/server/mcp/tools.js +523 -574
- package/server/mcp/tools.js.map +1 -0
- package/server/paths.d.ts +3 -0
- package/server/paths.js +17 -15
- package/server/paths.js.map +1 -0
- package/server/pidfile.d.ts +9 -0
- package/server/pidfile.js +43 -45
- package/server/pidfile.js.map +1 -0
- package/server/review.d.ts +5 -0
- package/server/review.js +35 -0
- package/server/review.js.map +1 -0
- package/server/router.d.ts +33 -0
- package/server/router.js +191 -197
- package/server/router.js.map +1 -0
- package/server/scanRequest.d.ts +3 -0
- package/server/scanRequest.js +36 -0
- package/server/scanRequest.js.map +1 -0
- package/server/searchIndex.d.ts +17 -0
- package/server/searchIndex.js +83 -80
- package/server/searchIndex.js.map +1 -0
- package/server/sessions.d.ts +14 -0
- package/server/sessions.js +62 -70
- package/server/sessions.js.map +1 -0
- package/server/startup.d.ts +118 -0
- package/server/startup.js +143 -148
- package/server/startup.js.map +1 -0
- package/server/static.d.ts +6 -0
- package/server/static.js +28 -31
- package/server/static.js.map +1 -0
- package/server/tools/install.d.ts +4 -0
- package/server/tools/install.js +176 -185
- package/server/tools/install.js.map +1 -0
- package/server/tools/parse.d.ts +8 -0
- package/server/tools/parse.js +112 -114
- package/server/tools/parse.js.map +1 -0
- package/server/tools/platform.d.ts +9 -0
- package/server/tools/platform.js +49 -47
- package/server/tools/platform.js.map +1 -0
- package/server/tools/registry.d.ts +137 -0
- package/server/tools/registry.js +173 -172
- package/server/tools/registry.js.map +1 -0
- package/server/tools/scan.d.ts +34 -0
- package/server/tools/scan.js +89 -98
- package/server/tools/scan.js.map +1 -0
- package/server/tools.d.ts +34 -0
- package/server/tools.js +94 -107
- package/server/tools.js.map +1 -0
- package/server/tunnel.d.ts +29 -0
- package/server/tunnel.js +61 -66
- package/server/tunnel.js.map +1 -0
- package/shared/analyzer/docs.d.ts +16 -0
- package/shared/analyzer/docs.js +99 -93
- package/shared/analyzer/docs.js.map +1 -0
- package/shared/analyzer/explainLocal.d.ts +4 -0
- package/shared/analyzer/explainLocal.js +122 -142
- package/shared/analyzer/explainLocal.js.map +1 -0
- package/shared/analyzer/github.d.ts +37 -0
- package/shared/analyzer/github.js +41 -43
- package/shared/analyzer/github.js.map +1 -0
- package/shared/analyzer/graph.d.ts +41 -0
- package/shared/analyzer/graph.js +393 -400
- package/shared/analyzer/graph.js.map +1 -0
- package/shared/analyzer/health.d.ts +33 -0
- package/shared/analyzer/health.js +197 -193
- package/shared/analyzer/health.js.map +1 -0
- package/shared/analyzer/history.d.ts +29 -0
- package/shared/analyzer/history.js +110 -111
- package/shared/analyzer/history.js.map +1 -0
- package/shared/analyzer/jsonConfig.d.ts +2 -0
- package/shared/analyzer/jsonConfig.js +61 -0
- package/shared/analyzer/jsonConfig.js.map +1 -0
- package/shared/analyzer/languages/csharp.d.ts +26 -0
- package/shared/analyzer/languages/csharp.js +83 -88
- package/shared/analyzer/languages/csharp.js.map +1 -0
- package/shared/analyzer/languages/generic.d.ts +23 -0
- package/shared/analyzer/languages/generic.js +94 -105
- package/shared/analyzer/languages/generic.js.map +1 -0
- package/shared/analyzer/languages/go.d.ts +24 -0
- package/shared/analyzer/languages/go.js +45 -54
- package/shared/analyzer/languages/go.js.map +1 -0
- package/shared/analyzer/languages/index.d.ts +6 -0
- package/shared/analyzer/languages/index.js +19 -20
- package/shared/analyzer/languages/index.js.map +1 -0
- package/shared/analyzer/languages/java.d.ts +20 -0
- package/shared/analyzer/languages/java.js +73 -78
- package/shared/analyzer/languages/java.js.map +1 -0
- package/shared/analyzer/languages/javascript.d.ts +12 -0
- package/shared/analyzer/languages/javascript.js +258 -209
- package/shared/analyzer/languages/javascript.js.map +1 -0
- package/shared/analyzer/languages/python.d.ts +23 -0
- package/shared/analyzer/languages/python.js +92 -100
- package/shared/analyzer/languages/python.js.map +1 -0
- package/shared/analyzer/languages/rust.d.ts +17 -0
- package/shared/analyzer/languages/rust.js +96 -98
- package/shared/analyzer/languages/rust.js.map +1 -0
- package/shared/analyzer/languages/typescript.d.ts +11 -0
- package/shared/analyzer/languages/typescript.js +117 -116
- package/shared/analyzer/languages/typescript.js.map +1 -0
- package/shared/analyzer/licenses.d.ts +18 -0
- package/shared/analyzer/licenses.js +130 -133
- package/shared/analyzer/licenses.js.map +1 -0
- package/shared/analyzer/metrics.d.ts +20 -0
- package/shared/analyzer/metrics.js +112 -104
- package/shared/analyzer/metrics.js.map +1 -0
- package/shared/analyzer/pathUtil.d.ts +10 -0
- package/shared/analyzer/pathUtil.js +29 -35
- package/shared/analyzer/pathUtil.js.map +1 -0
- package/shared/analyzer/patterns.d.ts +11 -0
- package/shared/analyzer/patterns.js +231 -253
- package/shared/analyzer/patterns.js.map +1 -0
- package/shared/analyzer/scan.d.ts +62 -0
- package/shared/analyzer/scan.js +451 -442
- package/shared/analyzer/scan.js.map +1 -0
- package/shared/analyzer/scanControl.d.ts +11 -0
- package/shared/analyzer/scanControl.js +62 -0
- package/shared/analyzer/scanControl.js.map +1 -0
- package/shared/analyzer/security.d.ts +18 -0
- package/shared/analyzer/security.js +159 -159
- package/shared/analyzer/security.js.map +1 -0
- package/shared/analyzer/services.d.ts +5 -0
- package/shared/analyzer/services.js +141 -138
- package/shared/analyzer/services.js.map +1 -0
- package/shared/analyzer/stack.d.ts +6 -0
- package/shared/analyzer/stack.js +134 -141
- package/shared/analyzer/stack.js.map +1 -0
- package/shared/analyzer/tour.d.ts +2 -0
- package/shared/analyzer/tour.js +45 -53
- package/shared/analyzer/tour.js.map +1 -0
- package/shared/analyzer/util.d.ts +8 -0
- package/shared/analyzer/util.js +130 -76
- package/shared/analyzer/util.js.map +1 -0
- package/shared/analyzer/workflows.d.ts +8 -0
- package/shared/analyzer/workflows.js +139 -134
- package/shared/analyzer/workflows.js.map +1 -0
- package/shared/contracts.d.ts +250 -0
- package/shared/contracts.js +2 -0
- package/shared/contracts.js.map +1 -0
- package/shared/diagram/aiFacts.d.ts +35 -0
- package/shared/diagram/aiFacts.js +102 -105
- package/shared/diagram/aiFacts.js.map +1 -0
- package/shared/diagram/aiMermaid.d.ts +5 -0
- package/shared/diagram/aiMermaid.js +46 -45
- package/shared/diagram/aiMermaid.js.map +1 -0
- package/shared/diagram/atlas.d.ts +16 -0
- package/shared/diagram/atlas.js +51 -60
- package/shared/diagram/atlas.js.map +1 -0
- package/shared/diagram/mermaid.d.ts +43 -0
- package/shared/diagram/mermaid.js +348 -370
- package/shared/diagram/mermaid.js.map +1 -0
- package/shared/review/contracts.d.ts +95 -0
- package/shared/review/contracts.js +2 -0
- package/shared/review/contracts.js.map +1 -0
- package/shared/review/review.d.ts +10 -0
- package/shared/review/review.js +184 -0
- package/shared/review/review.js.map +1 -0
- package/shared/search/query.d.ts +32 -0
- package/shared/search/query.js +395 -388
- package/shared/search/query.js.map +1 -0
package/server/mcp/runner.js
CHANGED
|
@@ -11,32 +11,26 @@
|
|
|
11
11
|
// shell, no user-supplied arguments — the one thing this runner executes is a
|
|
12
12
|
// path built from this repository's own directory, so there is no injection
|
|
13
13
|
// surface here even though the tool server can read any folder it is pointed at.
|
|
14
|
-
|
|
15
14
|
import { spawn } from 'node:child_process';
|
|
16
15
|
import path from 'node:path';
|
|
17
16
|
import { fileURLToPath } from 'node:url';
|
|
18
|
-
|
|
19
17
|
import { mcpStatus } from './tools.js';
|
|
20
|
-
|
|
21
18
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
22
19
|
// server/mcp/ -> server/ -> repository root
|
|
23
20
|
export const REPO_ROOT = path.resolve(here, '..', '..');
|
|
24
21
|
export const ENTRY = path.join(here, 'standalone.js');
|
|
25
|
-
|
|
26
22
|
// How long to wait for a graceful stop before killing. SIGTERM lets Node finish
|
|
27
23
|
// what it is doing; a hard kill would be an acceptable fallback, but only after
|
|
28
24
|
// this long, because a scan in progress deserves the chance to finish.
|
|
29
25
|
const STOP_GRACE_MS = 1500;
|
|
30
|
-
|
|
31
26
|
// The command a client is configured with, and the only one this file will ever
|
|
32
27
|
// run. It is a function rather than a constant string in a template because a
|
|
33
28
|
// client config is a promise about what is actually happening: the path in the
|
|
34
29
|
// README, the path in the copy box, and the argv the runner builds all have to be
|
|
35
30
|
// the same string, and this is the one place it is written.
|
|
36
31
|
export function mcpCommand() {
|
|
37
|
-
|
|
32
|
+
return path.relative(REPO_ROOT, ENTRY);
|
|
38
33
|
}
|
|
39
|
-
|
|
40
34
|
// The absolute form, for anything a client will execute.
|
|
41
35
|
//
|
|
42
36
|
// The runner can launch `server/mcp/standalone.js` relative to `cwd` because it
|
|
@@ -45,234 +39,230 @@ export function mcpCommand() {
|
|
|
45
39
|
// that fails only after it has been pasted somewhere real. The copy box and the
|
|
46
40
|
// README therefore both use this, and only the runner gets the relative one.
|
|
47
41
|
export function mcpEntryPoint() {
|
|
48
|
-
|
|
42
|
+
return ENTRY;
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
//
|
|
52
45
|
// `override` exists so a test can substitute a command — one that exits at once,
|
|
53
46
|
// one that answers the handshake wrong — without the production path growing a
|
|
54
47
|
// test-only branch. It is the whole argument or nothing: a half-overridden config
|
|
55
48
|
// would spawn something that is neither the real server nor the fake.
|
|
56
|
-
|
|
57
49
|
export function mcpConfig(override) {
|
|
58
|
-
|
|
50
|
+
if (override) {
|
|
51
|
+
return {
|
|
52
|
+
command: override.command,
|
|
53
|
+
args: override.args || [],
|
|
54
|
+
cwd: override.cwd || REPO_ROOT,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
59
57
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
command: process.execPath,
|
|
59
|
+
args: [ENTRY],
|
|
60
|
+
cwd: REPO_ROOT,
|
|
63
61
|
};
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
command: process.execPath,
|
|
67
|
-
args: [ENTRY],
|
|
68
|
-
cwd: REPO_ROOT,
|
|
69
|
-
};
|
|
70
62
|
}
|
|
71
|
-
|
|
72
63
|
export class McpRunner {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.log = [];
|
|
104
|
-
this.onLog = onLog || (() => {});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async start() {
|
|
108
|
-
if (this.running) return this.status();
|
|
109
|
-
this.state = 'starting';
|
|
110
|
-
this.lastError = null;
|
|
111
|
-
this.log = [];
|
|
112
|
-
|
|
113
|
-
// Built from the same function the config box shows. If those could differ,
|
|
114
|
-
// the button would be reporting on a different server than the one a client
|
|
115
|
-
// launches — which is worse than having no button.
|
|
116
|
-
const cfg = mcpConfig(this.commandOverride);
|
|
117
|
-
const child = spawn(cfg.command, cfg.args, {
|
|
118
|
-
cwd: cfg.cwd,
|
|
119
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
120
|
-
env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },
|
|
121
|
-
// No shell: the command is a fixed argv, and a shell would only add a way
|
|
122
|
-
// for something to be interpreted.
|
|
123
|
-
shell: false,
|
|
124
|
-
});
|
|
125
|
-
this.child = child;
|
|
126
|
-
|
|
127
|
-
child.stdout.setEncoding('utf8');
|
|
128
|
-
child.stderr.setEncoding('utf8');
|
|
129
|
-
// Only stderr is a log. stdout is the MCP protocol stream: logging it would
|
|
130
|
-
// fill the panel with JSON-RPC frames, and the one that matters — the
|
|
131
|
-
// handshake reply — is consumed by `handshake` below. The stream is drained
|
|
132
|
-
// regardless, because a pipe nobody reads eventually blocks the writer.
|
|
133
|
-
child.stdout.on('data', () => {});
|
|
134
|
-
child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));
|
|
135
|
-
|
|
136
|
-
const exited = new Promise((resolve) => {
|
|
137
|
-
child.once('exit', (code, signal) => {
|
|
138
|
-
const wasStopping = this.state === 'stopping';
|
|
64
|
+
commandOverride;
|
|
65
|
+
child;
|
|
66
|
+
state;
|
|
67
|
+
startedAt;
|
|
68
|
+
lastError;
|
|
69
|
+
log;
|
|
70
|
+
onLog;
|
|
71
|
+
get running() {
|
|
72
|
+
return this.state === 'running' || this.state === 'starting';
|
|
73
|
+
}
|
|
74
|
+
note(line) {
|
|
75
|
+
if (!line)
|
|
76
|
+
return;
|
|
77
|
+
const entry = { at: Date.now(), line };
|
|
78
|
+
this.log.push(entry);
|
|
79
|
+
// Bounded, because this is a status panel, not a log file.
|
|
80
|
+
if (this.log.length > 100)
|
|
81
|
+
this.log.shift();
|
|
82
|
+
this.onLog(entry);
|
|
83
|
+
}
|
|
84
|
+
// `command`/`args`/`cwd` are the whole argv override, handed straight to
|
|
85
|
+
// `mcpConfig`. Accepting them flat rather than as one nested object is what
|
|
86
|
+
// every caller naturally reaches for — `new McpRunner({ command, args })` — and
|
|
87
|
+
// the tests need it to point the runner at a fake child. The runner itself has
|
|
88
|
+
// no idea what it is launching: a runner that knew would be a second place
|
|
89
|
+
// where the entry point is written down, and the two could drift.
|
|
90
|
+
constructor({ onLog, command, args, cwd } = {}) {
|
|
91
|
+
this.commandOverride = command
|
|
92
|
+
? { command, args: args || [], ...(cwd ? { cwd } : {}) }
|
|
93
|
+
: null;
|
|
139
94
|
this.child = null;
|
|
140
|
-
this.state = 'stopped';
|
|
95
|
+
this.state = 'stopped'; // stopped | starting | running | stopping
|
|
141
96
|
this.startedAt = null;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
97
|
+
this.lastError = null;
|
|
98
|
+
// The tail of the child's output, kept for the UI. An MCP child that dies
|
|
99
|
+
// usually says why just before it goes, and "it stopped" with no reason is
|
|
100
|
+
// the single most annoying thing a status panel can tell you.
|
|
101
|
+
this.log = [];
|
|
102
|
+
this.onLog = onLog || ((..._args) => { });
|
|
103
|
+
}
|
|
104
|
+
async start() {
|
|
105
|
+
if (this.running)
|
|
106
|
+
return this.status();
|
|
107
|
+
this.state = 'starting';
|
|
108
|
+
this.lastError = null;
|
|
109
|
+
this.log = [];
|
|
110
|
+
// Built from the same function the config box shows. If those could differ,
|
|
111
|
+
// the button would be reporting on a different server than the one a client
|
|
112
|
+
// launches — which is worse than having no button.
|
|
113
|
+
const cfg = mcpConfig(this.commandOverride);
|
|
114
|
+
const child = spawn(cfg.command, cfg.args, {
|
|
115
|
+
cwd: cfg.cwd,
|
|
116
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
117
|
+
env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },
|
|
118
|
+
// No shell: the command is a fixed argv, and a shell would only add a way
|
|
119
|
+
// for something to be interpreted.
|
|
120
|
+
shell: false,
|
|
121
|
+
});
|
|
122
|
+
this.child = child;
|
|
123
|
+
child.stdout.setEncoding('utf8');
|
|
124
|
+
child.stderr.setEncoding('utf8');
|
|
125
|
+
// Only stderr is a log. stdout is the MCP protocol stream: logging it would
|
|
126
|
+
// fill the panel with JSON-RPC frames, and the one that matters — the
|
|
127
|
+
// handshake reply — is consumed by `handshake` below. The stream is drained
|
|
128
|
+
// regardless, because a pipe nobody reads eventually blocks the writer.
|
|
129
|
+
child.stdout.on('data', (..._args) => { });
|
|
130
|
+
child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));
|
|
131
|
+
const exited = new Promise((resolve) => {
|
|
132
|
+
child.once('exit', (code, signal) => {
|
|
133
|
+
const wasStopping = this.state === 'stopping';
|
|
134
|
+
this.child = null;
|
|
135
|
+
this.state = 'stopped';
|
|
136
|
+
this.startedAt = null;
|
|
137
|
+
if (!wasStopping) {
|
|
138
|
+
this.lastError = signal
|
|
139
|
+
? `Stopped unexpectedly (${signal}).`
|
|
140
|
+
: `Stopped unexpectedly (exit code ${code}).`;
|
|
141
|
+
this.note(this.lastError);
|
|
142
|
+
}
|
|
143
|
+
resolve({ code, signal });
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
child.once('error', (err) => {
|
|
147
|
+
this.lastError = `Could not start: ${err.message}`;
|
|
148
|
+
this.state = 'stopped';
|
|
149
|
+
this.child = null;
|
|
150
|
+
this.note(this.lastError);
|
|
151
|
+
});
|
|
152
|
+
// A handshake proves the server is not merely spawned but actually answering
|
|
153
|
+
// MCP. "running" that means the process exists is how a broken server ends up
|
|
154
|
+
// looking healthy in the UI.
|
|
155
|
+
const ok = await this.handshake(exited);
|
|
156
|
+
if (ok) {
|
|
157
|
+
this.state = 'running';
|
|
158
|
+
this.startedAt = Date.now();
|
|
159
|
+
this.note('MCP server ready on stdio.');
|
|
160
|
+
}
|
|
161
|
+
else if (this.child) {
|
|
162
|
+
await this.stop();
|
|
147
163
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
child.once('error', (err) => {
|
|
153
|
-
this.lastError = `Could not start: ${err.message}`;
|
|
154
|
-
this.state = 'stopped';
|
|
155
|
-
this.child = null;
|
|
156
|
-
this.note(this.lastError);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// A handshake proves the server is not merely spawned but actually answering
|
|
160
|
-
// MCP. "running" that means the process exists is how a broken server ends up
|
|
161
|
-
// looking healthy in the UI.
|
|
162
|
-
const ok = await this.handshake(exited);
|
|
163
|
-
if (ok) {
|
|
164
|
-
this.state = 'running';
|
|
165
|
-
this.startedAt = Date.now();
|
|
166
|
-
this.note('MCP server ready on stdio.');
|
|
167
|
-
} else if (this.child) {
|
|
168
|
-
await this.stop();
|
|
169
|
-
} else {
|
|
170
|
-
this.state = 'stopped';
|
|
164
|
+
else {
|
|
165
|
+
this.state = 'stopped';
|
|
166
|
+
}
|
|
167
|
+
return this.status();
|
|
171
168
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
169
|
+
// The MCP handshake, spoken to our own child: initialize, then the
|
|
170
|
+
// `notifications/initialized` the spec requires before ordinary traffic.
|
|
171
|
+
async handshake(exited) {
|
|
172
|
+
const child = this.child;
|
|
173
|
+
if (!child)
|
|
174
|
+
return false;
|
|
175
|
+
return new Promise((resolve) => {
|
|
176
|
+
let buffer = '';
|
|
177
|
+
let settled = false;
|
|
178
|
+
const finish = (ok) => {
|
|
179
|
+
if (settled)
|
|
180
|
+
return;
|
|
181
|
+
settled = true;
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
child.stdout.off('data', onData);
|
|
184
|
+
// Resolve now, not on exit. The child is *supposed* to stay running, so
|
|
185
|
+
// waiting for it to exit would mean this promise only ever settled when
|
|
186
|
+
// something had already gone wrong.
|
|
187
|
+
resolve(ok && this.child !== null);
|
|
188
|
+
};
|
|
189
|
+
const onData = (chunk) => {
|
|
190
|
+
buffer += chunk;
|
|
191
|
+
let nl;
|
|
192
|
+
while ((nl = buffer.indexOf('\n')) !== -1) {
|
|
193
|
+
const line = buffer.slice(0, nl).trim();
|
|
194
|
+
buffer = buffer.slice(nl + 1);
|
|
195
|
+
if (!line)
|
|
196
|
+
continue;
|
|
197
|
+
try {
|
|
198
|
+
const msg = JSON.parse(line);
|
|
199
|
+
if (msg?.id === 'onboarder-probe' && msg.result?.serverInfo?.name === 'onboarder') {
|
|
200
|
+
child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\n');
|
|
201
|
+
finish(true);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// A line that is not JSON during the handshake is a bug elsewhere —
|
|
207
|
+
// something wrote to stdout that should not have. Keep reading: the
|
|
208
|
+
// real initialize reply may still arrive.
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
const timer = setTimeout(() => {
|
|
213
|
+
this.lastError = 'The MCP server did not answer its handshake within 5s.';
|
|
214
|
+
this.note(this.lastError);
|
|
215
|
+
finish(false);
|
|
216
|
+
}, 5000);
|
|
217
|
+
child.stdout.on('data', onData);
|
|
218
|
+
// If the child dies first, do not wait out the full timeout.
|
|
219
|
+
exited.then(() => finish(false));
|
|
220
|
+
child.stdin.write(JSON.stringify({
|
|
221
|
+
jsonrpc: '2.0',
|
|
222
|
+
id: 'onboarder-probe',
|
|
223
|
+
method: 'initialize',
|
|
224
|
+
params: {
|
|
225
|
+
protocolVersion: '2025-06-18',
|
|
226
|
+
capabilities: {},
|
|
227
|
+
clientInfo: { name: 'onboarder-ui', version: '1.0.0' },
|
|
228
|
+
},
|
|
229
|
+
}) + '\n');
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async stop() {
|
|
233
|
+
const child = this.child;
|
|
234
|
+
if (!child) {
|
|
235
|
+
this.state = 'stopped';
|
|
236
|
+
return this.status();
|
|
213
237
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
async stop() {
|
|
240
|
-
const child = this.child;
|
|
241
|
-
if (!child) {
|
|
242
|
-
this.state = 'stopped';
|
|
243
|
-
return this.status();
|
|
238
|
+
this.state = 'stopping';
|
|
239
|
+
// Closing stdin is the polite shutdown: `serveMcp` drains what is queued and
|
|
240
|
+
// lets the loop empty, so a request in flight gets its answer.
|
|
241
|
+
const exited = new Promise((resolve) => child.once('exit', resolve));
|
|
242
|
+
child.stdin.end();
|
|
243
|
+
const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);
|
|
244
|
+
await exited;
|
|
245
|
+
clearTimeout(timer);
|
|
246
|
+
this.child = null;
|
|
247
|
+
this.state = 'stopped';
|
|
248
|
+
this.startedAt = null;
|
|
249
|
+
this.note('MCP server stopped.');
|
|
250
|
+
return this.status();
|
|
251
|
+
}
|
|
252
|
+
status() {
|
|
253
|
+
return {
|
|
254
|
+
...mcpStatus(),
|
|
255
|
+
state: this.state,
|
|
256
|
+
running: this.running,
|
|
257
|
+
pid: this.child?.pid ?? null,
|
|
258
|
+
startedAt: this.startedAt,
|
|
259
|
+
uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,
|
|
260
|
+
lastError: this.lastError,
|
|
261
|
+
log: this.log.slice(-20),
|
|
262
|
+
};
|
|
244
263
|
}
|
|
245
|
-
this.state = 'stopping';
|
|
246
|
-
|
|
247
|
-
// Closing stdin is the polite shutdown: `serveMcp` drains what is queued and
|
|
248
|
-
// lets the loop empty, so a request in flight gets its answer.
|
|
249
|
-
const exited = new Promise((resolve) => child.once('exit', resolve));
|
|
250
|
-
child.stdin.end();
|
|
251
|
-
const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);
|
|
252
|
-
|
|
253
|
-
await exited;
|
|
254
|
-
clearTimeout(timer);
|
|
255
|
-
this.child = null;
|
|
256
|
-
this.state = 'stopped';
|
|
257
|
-
this.startedAt = null;
|
|
258
|
-
this.note('MCP server stopped.');
|
|
259
|
-
return this.status();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
status() {
|
|
263
|
-
return {
|
|
264
|
-
...mcpStatus(),
|
|
265
|
-
state: this.state,
|
|
266
|
-
running: this.running,
|
|
267
|
-
pid: this.child?.pid ?? null,
|
|
268
|
-
startedAt: this.startedAt,
|
|
269
|
-
uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,
|
|
270
|
-
lastError: this.lastError,
|
|
271
|
-
log: this.log.slice(-20),
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
264
|
}
|
|
275
|
-
|
|
276
265
|
export function createMcpRunner(opts) {
|
|
277
|
-
|
|
266
|
+
return new McpRunner(opts);
|
|
278
267
|
}
|
|
268
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/server/mcp/runner.ts"],"names":[],"mappings":"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","sourcesContent":["// The process runner. The HTTP server owns one of these; the topbar button calls\n// `start` and `stop` on it.\n//\n// Why a child process rather than an HTTP endpoint: the MCP stdio transport *is*\n// the contract. A client config points at a command and speaks JSON-RPC to its\n// stdin/stdout. There is no port to connect to, and nothing to authenticate,\n// which is why this transport is the right one for a local-first tool and why it\n// must stay local if it is ever exposed at all.\n//\n// The child is deliberately plain: `node server/mcp/standalone.js`. No `npx`, no\n// shell, no user-supplied arguments — the one thing this runner executes is a\n// path built from this repository's own directory, so there is no injection\n// surface here even though the tool server can read any folder it is pointed at.\n\nimport { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { mcpStatus } from './tools.js';\n\nconst here = path.dirname(fileURLToPath(import.meta.url));\n// server/mcp/ -> server/ -> repository root\nexport const REPO_ROOT = path.resolve(here, '..', '..');\nexport const ENTRY = path.join(here, 'standalone.js');\n\n// How long to wait for a graceful stop before killing. SIGTERM lets Node finish\n// what it is doing; a hard kill would be an acceptable fallback, but only after\n// this long, because a scan in progress deserves the chance to finish.\nconst STOP_GRACE_MS = 1500;\n\n// The command a client is configured with, and the only one this file will ever\n// run. It is a function rather than a constant string in a template because a\n// client config is a promise about what is actually happening: the path in the\n// README, the path in the copy box, and the argv the runner builds all have to be\n// the same string, and this is the one place it is written.\nexport function mcpCommand() {\n return path.relative(REPO_ROOT, ENTRY);\n}\n\n// The absolute form, for anything a client will execute.\n//\n// The runner can launch `server/mcp/standalone.js` relative to `cwd` because it\n// sets `cwd` itself. A client cannot: it spawns the command wherever the user's\n// harness happens to live, so a relative path in a copied config is a command\n// that fails only after it has been pasted somewhere real. The copy box and the\n// README therefore both use this, and only the runner gets the relative one.\nexport function mcpEntryPoint() {\n return ENTRY;\n}\n\n//\n// `override` exists so a test can substitute a command — one that exits at once,\n// one that answers the handshake wrong — without the production path growing a\n// test-only branch. It is the whole argument or nothing: a half-overridden config\n// would spawn something that is neither the real server nor the fake.\n\nexport function mcpConfig(override) {\n if (override) {\n return {\n command: override.command,\n args: override.args || [],\n cwd: override.cwd || REPO_ROOT,\n };\n }\n return {\n command: process.execPath,\n args: [ENTRY],\n cwd: REPO_ROOT,\n };\n}\n\nexport class McpRunner {\n commandOverride: any;\n child: any;\n state: string;\n startedAt: any;\n lastError: string;\n log: any[];\n onLog: any;\n\n get running() {\n return this.state === 'running' || this.state === 'starting';\n }\n\n note(line) {\n if (!line) return;\n const entry = { at: Date.now(), line };\n this.log.push(entry);\n // Bounded, because this is a status panel, not a log file.\n if (this.log.length > 100) this.log.shift();\n this.onLog(entry);\n }\n\n // `command`/`args`/`cwd` are the whole argv override, handed straight to\n // `mcpConfig`. Accepting them flat rather than as one nested object is what\n // every caller naturally reaches for — `new McpRunner({ command, args })` — and\n // the tests need it to point the runner at a fake child. The runner itself has\n // no idea what it is launching: a runner that knew would be a second place\n // where the entry point is written down, and the two could drift.\n constructor({ onLog, command, args, cwd }: Record<string, any> = {}) {\n this.commandOverride = command\n ? { command, args: args || [], ...(cwd ? { cwd } : {}) }\n : null;\n this.child = null;\n this.state = 'stopped'; // stopped | starting | running | stopping\n this.startedAt = null;\n this.lastError = null;\n // The tail of the child's output, kept for the UI. An MCP child that dies\n // usually says why just before it goes, and \"it stopped\" with no reason is\n // the single most annoying thing a status panel can tell you.\n this.log = [];\n this.onLog = onLog || ((..._args: unknown[]) => {});\n }\n\n async start() {\n if (this.running) return this.status();\n this.state = 'starting';\n this.lastError = null;\n this.log = [];\n\n // Built from the same function the config box shows. If those could differ,\n // the button would be reporting on a different server than the one a client\n // launches — which is worse than having no button.\n const cfg = mcpConfig(this.commandOverride);\n const child = spawn(cfg.command, cfg.args, {\n cwd: cfg.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },\n // No shell: the command is a fixed argv, and a shell would only add a way\n // for something to be interpreted.\n shell: false,\n });\n this.child = child;\n\n child.stdout.setEncoding('utf8');\n child.stderr.setEncoding('utf8');\n // Only stderr is a log. stdout is the MCP protocol stream: logging it would\n // fill the panel with JSON-RPC frames, and the one that matters — the\n // handshake reply — is consumed by `handshake` below. The stream is drained\n // regardless, because a pipe nobody reads eventually blocks the writer.\n child.stdout.on('data', (..._args: unknown[]) => {});\n child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));\n\n const exited = new Promise((resolve) => {\n child.once('exit', (code, signal) => {\n const wasStopping = this.state === 'stopping';\n this.child = null;\n this.state = 'stopped';\n this.startedAt = null;\n if (!wasStopping) {\n this.lastError = signal\n ? `Stopped unexpectedly (${signal}).`\n : `Stopped unexpectedly (exit code ${code}).`;\n this.note(this.lastError);\n }\n resolve({ code, signal });\n });\n });\n\n child.once('error', (err) => {\n this.lastError = `Could not start: ${err.message}`;\n this.state = 'stopped';\n this.child = null;\n this.note(this.lastError);\n });\n\n // A handshake proves the server is not merely spawned but actually answering\n // MCP. \"running\" that means the process exists is how a broken server ends up\n // looking healthy in the UI.\n const ok = await this.handshake(exited);\n if (ok) {\n this.state = 'running';\n this.startedAt = Date.now();\n this.note('MCP server ready on stdio.');\n } else if (this.child) {\n await this.stop();\n } else {\n this.state = 'stopped';\n }\n return this.status();\n }\n\n // The MCP handshake, spoken to our own child: initialize, then the\n // `notifications/initialized` the spec requires before ordinary traffic.\n async handshake(exited) {\n const child = this.child;\n if (!child) return false;\n\n return new Promise((resolve) => {\n let buffer = '';\n let settled = false;\n const finish = (ok) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n child.stdout.off('data', onData);\n // Resolve now, not on exit. The child is *supposed* to stay running, so\n // waiting for it to exit would mean this promise only ever settled when\n // something had already gone wrong.\n resolve(ok && this.child !== null);\n };\n const onData = (chunk) => {\n buffer += chunk;\n let nl;\n while ((nl = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (!line) continue;\n try {\n const msg = JSON.parse(line);\n if (msg?.id === 'onboarder-probe' && msg.result?.serverInfo?.name === 'onboarder') {\n child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\\n');\n finish(true);\n return;\n }\n } catch {\n // A line that is not JSON during the handshake is a bug elsewhere —\n // something wrote to stdout that should not have. Keep reading: the\n // real initialize reply may still arrive.\n }\n }\n };\n\n const timer = setTimeout(() => {\n this.lastError = 'The MCP server did not answer its handshake within 5s.';\n this.note(this.lastError);\n finish(false);\n }, 5000);\n\n child.stdout.on('data', onData);\n // If the child dies first, do not wait out the full timeout.\n exited.then(() => finish(false));\n\n child.stdin.write(JSON.stringify({\n jsonrpc: '2.0',\n id: 'onboarder-probe',\n method: 'initialize',\n params: {\n protocolVersion: '2025-06-18',\n capabilities: {},\n clientInfo: { name: 'onboarder-ui', version: '1.0.0' },\n },\n }) + '\\n');\n });\n }\n\n async stop() {\n const child = this.child;\n if (!child) {\n this.state = 'stopped';\n return this.status();\n }\n this.state = 'stopping';\n\n // Closing stdin is the polite shutdown: `serveMcp` drains what is queued and\n // lets the loop empty, so a request in flight gets its answer.\n const exited = new Promise((resolve) => child.once('exit', resolve));\n child.stdin.end();\n const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);\n\n await exited;\n clearTimeout(timer);\n this.child = null;\n this.state = 'stopped';\n this.startedAt = null;\n this.note('MCP server stopped.');\n return this.status();\n }\n\n status() {\n return {\n ...mcpStatus(),\n state: this.state,\n running: this.running,\n pid: this.child?.pid ?? null,\n startedAt: this.startedAt,\n uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,\n lastError: this.lastError,\n log: this.log.slice(-20),\n };\n }\n}\n\nexport function createMcpRunner(opts) {\n return new McpRunner(opts);\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const PROTOCOL_VERSION = "2025-06-18";
|
|
2
|
+
export declare const SERVER_INFO: {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
title: string;
|
|
6
|
+
instructions: string;
|
|
7
|
+
};
|
|
8
|
+
export { handle };
|
|
9
|
+
declare function handle(msg: any): Promise<{
|
|
10
|
+
jsonrpc: string;
|
|
11
|
+
id: any;
|
|
12
|
+
result: any;
|
|
13
|
+
} | {
|
|
14
|
+
jsonrpc: string;
|
|
15
|
+
id: any;
|
|
16
|
+
error: {
|
|
17
|
+
code: number;
|
|
18
|
+
message: string;
|
|
19
|
+
data?: unknown;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Run the server until stdin closes. `input` and `output` are parameters so tests
|
|
24
|
+
* can drive a whole session through in-memory streams.
|
|
25
|
+
*/
|
|
26
|
+
export declare function serveMcp({ input, output }?: Record<string, any>): {
|
|
27
|
+
stop(): void;
|
|
28
|
+
settled(): Promise<void>;
|
|
29
|
+
};
|