@hcu-lab.me/mcp-device 1.0.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/LICENSE +21 -0
- package/README.md +51 -0
- package/dist/bootstrap.d.ts +1 -0
- package/dist/bootstrap.js +22 -0
- package/dist/command-manager.d.ts +8 -0
- package/dist/command-manager.js +241 -0
- package/dist/config-field-definitions.d.ts +41 -0
- package/dist/config-field-definitions.js +37 -0
- package/dist/config-manager.d.ts +102 -0
- package/dist/config-manager.js +291 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +10 -0
- package/dist/custom-stdio.d.ts +51 -0
- package/dist/custom-stdio.js +358 -0
- package/dist/data/official-app-ca.pem +12 -0
- package/dist/data/onboarding-prompts.json +70 -0
- package/dist/device/device-state.d.ts +13 -0
- package/dist/device/device-state.js +100 -0
- package/dist/device/device-status.d.ts +81 -0
- package/dist/device/device-status.js +156 -0
- package/dist/device/device.d.ts +16 -0
- package/dist/device/device.js +190 -0
- package/dist/device/execution-engine.d.ts +144 -0
- package/dist/device/execution-engine.js +195 -0
- package/dist/device/gateway-channel.d.ts +48 -0
- package/dist/device/gateway-channel.js +384 -0
- package/dist/device/gateway-config.d.ts +40 -0
- package/dist/device/gateway-config.js +207 -0
- package/dist/device/gateway-identity.d.ts +35 -0
- package/dist/device/gateway-identity.js +178 -0
- package/dist/device/gateway-pairing.d.ts +25 -0
- package/dist/device/gateway-pairing.js +105 -0
- package/dist/device/gateway-secure-transport.d.ts +25 -0
- package/dist/device/gateway-secure-transport.js +117 -0
- package/dist/device/gateway-tool-adapter.d.ts +17 -0
- package/dist/device/gateway-tool-adapter.js +284 -0
- package/dist/device/gateway-url-policy.d.ts +3 -0
- package/dist/device/gateway-url-policy.js +43 -0
- package/dist/device/linux-service.d.ts +70 -0
- package/dist/device/linux-service.js +268 -0
- package/dist/device/official-trust.d.ts +7 -0
- package/dist/device/official-trust.js +49 -0
- package/dist/device/project-inspection.d.ts +1 -0
- package/dist/device/project-inspection.js +180 -0
- package/dist/device/runtime-owner.d.ts +41 -0
- package/dist/device/runtime-owner.js +177 -0
- package/dist/device/windows-dpapi.d.ts +11 -0
- package/dist/device/windows-dpapi.js +67 -0
- package/dist/device/windows-service.d.ts +56 -0
- package/dist/device/windows-service.js +238 -0
- package/dist/error-handlers.d.ts +7 -0
- package/dist/error-handlers.js +15 -0
- package/dist/handlers/edit-search-handlers.d.ts +6 -0
- package/dist/handlers/edit-search-handlers.js +6 -0
- package/dist/handlers/filesystem-handlers.d.ts +38 -0
- package/dist/handlers/filesystem-handlers.js +440 -0
- package/dist/handlers/history-handlers.d.ts +12 -0
- package/dist/handlers/history-handlers.js +67 -0
- package/dist/handlers/index.d.ts +6 -0
- package/dist/handlers/index.js +7 -0
- package/dist/handlers/process-handlers.d.ts +9 -0
- package/dist/handlers/process-handlers.js +15 -0
- package/dist/handlers/search-handlers.d.ts +17 -0
- package/dist/handlers/search-handlers.js +224 -0
- package/dist/handlers/terminal-handlers.d.ts +21 -0
- package/dist/handlers/terminal-handlers.js +35 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +138 -0
- package/dist/mcp-device.d.ts +2 -0
- package/dist/mcp-device.js +7 -0
- package/dist/npm-scripts/remote.d.ts +3 -0
- package/dist/npm-scripts/remote.js +314 -0
- package/dist/search-manager.d.ts +147 -0
- package/dist/search-manager.js +828 -0
- package/dist/server.d.ts +46 -0
- package/dist/server.js +1563 -0
- package/dist/terminal-manager.d.ts +104 -0
- package/dist/terminal-manager.js +635 -0
- package/dist/tools/config.d.ts +96 -0
- package/dist/tools/config.js +260 -0
- package/dist/tools/edit.d.ts +38 -0
- package/dist/tools/edit.js +435 -0
- package/dist/tools/feedback.d.ts +8 -0
- package/dist/tools/feedback.js +132 -0
- package/dist/tools/filesystem.d.ts +79 -0
- package/dist/tools/filesystem.js +947 -0
- package/dist/tools/fuzzySearch.d.ts +12 -0
- package/dist/tools/fuzzySearch.js +74 -0
- package/dist/tools/fuzzySearchCore.d.ts +52 -0
- package/dist/tools/fuzzySearchCore.js +125 -0
- package/dist/tools/improved-process-tools.d.ts +24 -0
- package/dist/tools/improved-process-tools.js +627 -0
- package/dist/tools/mime-types.d.ts +3 -0
- package/dist/tools/mime-types.js +28 -0
- package/dist/tools/pdf/extract-images.d.ts +34 -0
- package/dist/tools/pdf/extract-images.js +132 -0
- package/dist/tools/pdf/index.d.ts +6 -0
- package/dist/tools/pdf/index.js +3 -0
- package/dist/tools/pdf/lib/pdf2md.d.ts +36 -0
- package/dist/tools/pdf/lib/pdf2md.js +76 -0
- package/dist/tools/pdf/manipulations.d.ts +13 -0
- package/dist/tools/pdf/manipulations.js +99 -0
- package/dist/tools/pdf/markdown.d.ts +26 -0
- package/dist/tools/pdf/markdown.js +275 -0
- package/dist/tools/pdf/utils.d.ts +12 -0
- package/dist/tools/pdf/utils.js +34 -0
- package/dist/tools/process.d.ts +3 -0
- package/dist/tools/process.js +56 -0
- package/dist/tools/prompts.d.ts +28 -0
- package/dist/tools/prompts.js +259 -0
- package/dist/tools/schemas.d.ts +454 -0
- package/dist/tools/schemas.js +242 -0
- package/dist/tools/usage.d.ts +5 -0
- package/dist/tools/usage.js +24 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +1 -0
- package/dist/ui/config-editor/config-editor-runtime.js +150 -0
- package/dist/ui/config-editor/index.html +13 -0
- package/dist/ui/config-editor/src/app.d.ts +43 -0
- package/dist/ui/config-editor/src/app.js +831 -0
- package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/src/array-modal.js +185 -0
- package/dist/ui/config-editor/src/main.d.ts +1 -0
- package/dist/ui/config-editor/src/main.js +2 -0
- package/dist/ui/config-editor/styles.css +587 -0
- package/dist/ui/contracts.d.ts +14 -0
- package/dist/ui/contracts.js +21 -0
- package/dist/ui/file-preview/index.html +16 -0
- package/dist/ui/file-preview/preview-runtime.js +469 -0
- package/dist/ui/file-preview/shared/preview-file-types.d.ts +5 -0
- package/dist/ui/file-preview/shared/preview-file-types.js +59 -0
- package/dist/ui/file-preview/src/app.d.ts +4 -0
- package/dist/ui/file-preview/src/app.js +680 -0
- package/dist/ui/file-preview/src/components/code-viewer.d.ts +6 -0
- package/dist/ui/file-preview/src/components/code-viewer.js +73 -0
- package/dist/ui/file-preview/src/components/highlighting.d.ts +2 -0
- package/dist/ui/file-preview/src/components/highlighting.js +54 -0
- package/dist/ui/file-preview/src/components/html-renderer.d.ts +5 -0
- package/dist/ui/file-preview/src/components/html-renderer.js +47 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.d.ts +1 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.js +59 -0
- package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
- package/dist/ui/file-preview/src/directory-controller.js +240 -0
- package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
- package/dist/ui/file-preview/src/document-layout.js +109 -0
- package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
- package/dist/ui/file-preview/src/document-outline.js +97 -0
- package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
- package/dist/ui/file-preview/src/document-workspace.js +33 -0
- package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
- package/dist/ui/file-preview/src/file-type-handlers.js +109 -0
- package/dist/ui/file-preview/src/host/external-actions.d.ts +8 -0
- package/dist/ui/file-preview/src/host/external-actions.js +55 -0
- package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
- package/dist/ui/file-preview/src/host/selection-context.js +106 -0
- package/dist/ui/file-preview/src/image-preview.d.ts +3 -0
- package/dist/ui/file-preview/src/image-preview.js +21 -0
- package/dist/ui/file-preview/src/main.d.ts +1 -0
- package/dist/ui/file-preview/src/main.js +5 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
- package/dist/ui/file-preview/src/markdown/controller.d.ts +44 -0
- package/dist/ui/file-preview/src/markdown/controller.js +1043 -0
- package/dist/ui/file-preview/src/markdown/editor.d.ts +131 -0
- package/dist/ui/file-preview/src/markdown/editor.js +1479 -0
- package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
- package/dist/ui/file-preview/src/markdown/linking.js +228 -0
- package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
- package/dist/ui/file-preview/src/markdown/outline.js +16 -0
- package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
- package/dist/ui/file-preview/src/markdown/parser.js +38 -0
- package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/preview.js +20 -0
- package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/utils.js +15 -0
- package/dist/ui/file-preview/src/model.d.ts +35 -0
- package/dist/ui/file-preview/src/model.js +1 -0
- package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
- package/dist/ui/file-preview/src/panel-actions.js +182 -0
- package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
- package/dist/ui/file-preview/src/path-utils.js +64 -0
- package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
- package/dist/ui/file-preview/src/payload-utils.js +119 -0
- package/dist/ui/file-preview/src/types.d.ts +1 -0
- package/dist/ui/file-preview/src/types.js +1 -0
- package/dist/ui/file-preview/styles.css +1631 -0
- package/dist/ui/resources.d.ts +28 -0
- package/dist/ui/resources.js +86 -0
- package/dist/ui/shared/compact-row.d.ts +11 -0
- package/dist/ui/shared/compact-row.js +18 -0
- package/dist/ui/shared/escape-html.d.ts +4 -0
- package/dist/ui/shared/escape-html.js +11 -0
- package/dist/ui/shared/host-context.d.ts +15 -0
- package/dist/ui/shared/host-context.js +51 -0
- package/dist/ui/shared/tool-bridge.d.ts +30 -0
- package/dist/ui/shared/tool-bridge.js +137 -0
- package/dist/ui/shared/tool-shell.d.ts +25 -0
- package/dist/ui/shared/tool-shell.js +107 -0
- package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
- package/dist/ui/shared/ui-event-tracker.js +27 -0
- package/dist/ui/shared/widget-state.d.ts +33 -0
- package/dist/ui/shared/widget-state.js +158 -0
- package/dist/utils/ab-test.d.ts +12 -0
- package/dist/utils/ab-test.js +104 -0
- package/dist/utils/capture.d.ts +35 -0
- package/dist/utils/capture.js +481 -0
- package/dist/utils/dockerPrompt.d.ts +17 -0
- package/dist/utils/dockerPrompt.js +53 -0
- package/dist/utils/feature-flags.d.ts +59 -0
- package/dist/utils/feature-flags.js +215 -0
- package/dist/utils/files/base.d.ts +173 -0
- package/dist/utils/files/base.js +5 -0
- package/dist/utils/files/binary.d.ts +21 -0
- package/dist/utils/files/binary.js +65 -0
- package/dist/utils/files/docx.d.ts +47 -0
- package/dist/utils/files/docx.js +679 -0
- package/dist/utils/files/excel.d.ts +24 -0
- package/dist/utils/files/excel.js +437 -0
- package/dist/utils/files/factory.d.ts +41 -0
- package/dist/utils/files/factory.js +113 -0
- package/dist/utils/files/image.d.ts +21 -0
- package/dist/utils/files/image.js +78 -0
- package/dist/utils/files/index.d.ts +10 -0
- package/dist/utils/files/index.js +13 -0
- package/dist/utils/files/pdf.d.ts +32 -0
- package/dist/utils/files/pdf.js +142 -0
- package/dist/utils/files/text.d.ts +63 -0
- package/dist/utils/files/text.js +370 -0
- package/dist/utils/fuzzySearchLogger.d.ts +30 -0
- package/dist/utils/fuzzySearchLogger.js +126 -0
- package/dist/utils/lineEndingHandler.d.ts +21 -0
- package/dist/utils/lineEndingHandler.js +77 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/mcp-ui-ab-test.d.ts +13 -0
- package/dist/utils/mcp-ui-ab-test.js +62 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.js +42 -0
- package/dist/utils/process-detection.d.ts +23 -0
- package/dist/utils/process-detection.js +150 -0
- package/dist/utils/ripgrep-resolver.d.ts +9 -0
- package/dist/utils/ripgrep-resolver.js +74 -0
- package/dist/utils/system-info.d.ts +71 -0
- package/dist/utils/system-info.js +712 -0
- package/dist/utils/toolHistory.d.ts +86 -0
- package/dist/utils/toolHistory.js +257 -0
- package/dist/utils/trackTools.d.ts +6 -0
- package/dist/utils/trackTools.js +54 -0
- package/dist/utils/unsupportedParams.d.ts +24 -0
- package/dist/utils/unsupportedParams.js +66 -0
- package/dist/utils/usageTracker.d.ts +133 -0
- package/dist/utils/usageTracker.js +477 -0
- package/dist/utils/welcome-onboarding.d.ts +11 -0
- package/dist/utils/welcome-onboarding.js +99 -0
- package/dist/utils/withTimeout.d.ts +28 -0
- package/dist/utils/withTimeout.js +85 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +131 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { searchManager } from '../search-manager.js';
|
|
2
|
+
import { StartSearchArgsSchema, GetMoreSearchResultsArgsSchema, StopSearchArgsSchema } from '../tools/schemas.js';
|
|
3
|
+
import { capture } from '../utils/capture.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handle start_search command
|
|
6
|
+
*/
|
|
7
|
+
export async function handleStartSearch(args) {
|
|
8
|
+
const parsed = StartSearchArgsSchema.safeParse(args);
|
|
9
|
+
if (!parsed.success) {
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: `Invalid arguments for start_search: ${parsed.error}` }],
|
|
12
|
+
isError: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const result = await searchManager.startSearch({
|
|
17
|
+
rootPath: parsed.data.path,
|
|
18
|
+
pattern: parsed.data.pattern,
|
|
19
|
+
searchType: parsed.data.searchType,
|
|
20
|
+
filePattern: parsed.data.filePattern,
|
|
21
|
+
ignoreCase: parsed.data.ignoreCase,
|
|
22
|
+
maxResults: parsed.data.maxResults,
|
|
23
|
+
includeHidden: parsed.data.includeHidden,
|
|
24
|
+
contextLines: parsed.data.contextLines,
|
|
25
|
+
timeout: parsed.data.timeout_ms,
|
|
26
|
+
earlyTermination: parsed.data.earlyTermination,
|
|
27
|
+
literalSearch: parsed.data.literalSearch,
|
|
28
|
+
});
|
|
29
|
+
const searchTypeText = parsed.data.searchType === 'content' ? 'content search' : 'file search';
|
|
30
|
+
let output = `Started ${searchTypeText} session: ${result.sessionId}\n`;
|
|
31
|
+
output += `Pattern: "${parsed.data.pattern}"\n`;
|
|
32
|
+
output += `Path: ${parsed.data.path}\n`;
|
|
33
|
+
output += `Status: ${result.isComplete ? 'COMPLETED' : 'RUNNING'}\n`;
|
|
34
|
+
output += `Runtime: ${Math.round(result.runtime)}ms\n`;
|
|
35
|
+
output += `Total results: ${result.totalResults}\n\n`;
|
|
36
|
+
if (result.results.length > 0) {
|
|
37
|
+
output += "Initial results:\n";
|
|
38
|
+
for (const searchResult of result.results.slice(0, 10)) {
|
|
39
|
+
if (searchResult.type === 'content') {
|
|
40
|
+
output += `📄 ${searchResult.file}:${searchResult.line} - ${searchResult.match?.substring(0, 100)}${searchResult.match && searchResult.match.length > 100 ? '...' : ''}\n`;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
output += `📁 ${searchResult.file}\n`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (result.results.length > 10) {
|
|
47
|
+
output += `... and ${result.results.length - 10} more results\n`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (result.isComplete) {
|
|
51
|
+
output += `\n✅ Search completed.`;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
output += `\n🔄 Search in progress. Use get_more_search_results to get more results.`;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: output }],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
62
|
+
capture('search_session_start_error', { error: errorMessage });
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `Error starting search session: ${errorMessage}` }],
|
|
65
|
+
isError: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Handle get_more_search_results command
|
|
71
|
+
*/
|
|
72
|
+
export async function handleGetMoreSearchResults(args) {
|
|
73
|
+
const parsed = GetMoreSearchResultsArgsSchema.safeParse(args);
|
|
74
|
+
if (!parsed.success) {
|
|
75
|
+
return {
|
|
76
|
+
content: [{ type: "text", text: `Invalid arguments for get_more_search_results: ${parsed.error}` }],
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const results = searchManager.readSearchResults(parsed.data.sessionId, parsed.data.offset, parsed.data.length);
|
|
82
|
+
// Only return error if we have no results AND there's an actual error
|
|
83
|
+
// Permission errors should not block returning found results
|
|
84
|
+
if (results.isError && results.totalResults === 0 && results.error?.trim()) {
|
|
85
|
+
return {
|
|
86
|
+
content: [{
|
|
87
|
+
type: "text",
|
|
88
|
+
text: `Search session ${parsed.data.sessionId} encountered an error: ${results.error}`
|
|
89
|
+
}],
|
|
90
|
+
isError: true,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Format results for display
|
|
94
|
+
let output = `Search session: ${parsed.data.sessionId}\n`;
|
|
95
|
+
output += `Status: ${results.isComplete ? 'COMPLETED' : 'IN PROGRESS'}\n`;
|
|
96
|
+
output += `Runtime: ${Math.round(results.runtime / 1000)}s\n`;
|
|
97
|
+
output += `Total results found: ${results.totalResults} (${results.totalMatches} matches)\n`;
|
|
98
|
+
const offset = parsed.data.offset;
|
|
99
|
+
if (offset < 0) {
|
|
100
|
+
// Negative offset - tail behavior
|
|
101
|
+
output += `Showing last ${results.returnedCount} results\n\n`;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Positive offset - range behavior
|
|
105
|
+
const startPos = offset;
|
|
106
|
+
const endPos = startPos + results.returnedCount - 1;
|
|
107
|
+
output += `Showing results ${startPos}-${endPos}\n\n`;
|
|
108
|
+
}
|
|
109
|
+
if (results.results.length === 0) {
|
|
110
|
+
if (results.isComplete) {
|
|
111
|
+
output += results.totalResults === 0 ? "No matches found." : "No results in this range.";
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
output += "No results yet, search is still running...";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
output += "Results:\n";
|
|
119
|
+
for (const result of results.results) {
|
|
120
|
+
if (result.type === 'content') {
|
|
121
|
+
output += `📄 ${result.file}:${result.line} - ${result.match?.substring(0, 100)}${result.match && result.match.length > 100 ? '...' : ''}\n`;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
output += `📁 ${result.file}\n`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Add pagination hints
|
|
129
|
+
if (offset >= 0 && results.hasMoreResults) {
|
|
130
|
+
const nextOffset = offset + results.returnedCount;
|
|
131
|
+
output += `\n📖 More results available. Use get_more_search_results with offset: ${nextOffset}`;
|
|
132
|
+
}
|
|
133
|
+
if (results.isComplete) {
|
|
134
|
+
output += `\n✅ Search completed.`;
|
|
135
|
+
// Warn users if search was incomplete due to permission issues
|
|
136
|
+
if (results.wasIncomplete) {
|
|
137
|
+
output += `\n⚠️ Warning: Some files were inaccessible due to permissions. Results may be incomplete.`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
content: [{ type: "text", text: output }],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: "text", text: `Error reading search results: ${errorMessage}` }],
|
|
148
|
+
isError: true,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Handle stop_search command
|
|
154
|
+
*/
|
|
155
|
+
export async function handleStopSearch(args) {
|
|
156
|
+
const parsed = StopSearchArgsSchema.safeParse(args);
|
|
157
|
+
if (!parsed.success) {
|
|
158
|
+
return {
|
|
159
|
+
content: [{ type: "text", text: `Invalid arguments for stop_search: ${parsed.error}` }],
|
|
160
|
+
isError: true,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const success = searchManager.terminateSearch(parsed.data.sessionId);
|
|
165
|
+
if (success) {
|
|
166
|
+
return {
|
|
167
|
+
content: [{
|
|
168
|
+
type: "text",
|
|
169
|
+
text: `Search session ${parsed.data.sessionId} terminated successfully.`
|
|
170
|
+
}],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
return {
|
|
175
|
+
content: [{
|
|
176
|
+
type: "text",
|
|
177
|
+
text: `Search session ${parsed.data.sessionId} not found or already completed.`
|
|
178
|
+
}],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
184
|
+
return {
|
|
185
|
+
content: [{ type: "text", text: `Error terminating search session: ${errorMessage}` }],
|
|
186
|
+
isError: true,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Handle list_searches command
|
|
192
|
+
*/
|
|
193
|
+
export async function handleListSearches() {
|
|
194
|
+
try {
|
|
195
|
+
const sessions = searchManager.listSearchSessions();
|
|
196
|
+
if (sessions.length === 0) {
|
|
197
|
+
return {
|
|
198
|
+
content: [{ type: "text", text: "No active searches." }],
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
let output = `Active Searches (${sessions.length}):\n\n`;
|
|
202
|
+
for (const session of sessions) {
|
|
203
|
+
const status = session.isComplete
|
|
204
|
+
? (session.isError ? '❌ ERROR' : '✅ COMPLETED')
|
|
205
|
+
: '🔄 RUNNING';
|
|
206
|
+
output += `Session: ${session.id}\n`;
|
|
207
|
+
output += ` Type: ${session.searchType}\n`;
|
|
208
|
+
output += ` Pattern: "${session.pattern}"\n`;
|
|
209
|
+
output += ` Status: ${status}\n`;
|
|
210
|
+
output += ` Runtime: ${Math.round(session.runtime / 1000)}s\n`;
|
|
211
|
+
output += ` Results: ${session.totalResults}\n\n`;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
content: [{ type: "text", text: output }],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
219
|
+
return {
|
|
220
|
+
content: [{ type: "text", text: `Error listing search sessions: ${errorMessage}` }],
|
|
221
|
+
isError: true,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ServerResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Handle start_process command (improved execute_command)
|
|
4
|
+
*/
|
|
5
|
+
export declare function handleStartProcess(args: unknown): Promise<ServerResult>;
|
|
6
|
+
/**
|
|
7
|
+
* Handle read_process_output command (improved read_output)
|
|
8
|
+
*/
|
|
9
|
+
export declare function handleReadProcessOutput(args: unknown): Promise<ServerResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Handle interact_with_process command (improved send_input)
|
|
12
|
+
*/
|
|
13
|
+
export declare function handleInteractWithProcess(args: unknown): Promise<ServerResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Handle force_terminate command
|
|
16
|
+
*/
|
|
17
|
+
export declare function handleForceTerminate(args: unknown): Promise<ServerResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Handle list_sessions command
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleListSessions(): Promise<ServerResult>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { startProcess, readProcessOutput, interactWithProcess, forceTerminate, listSessions } from '../tools/improved-process-tools.js';
|
|
2
|
+
import { StartProcessArgsSchema, ReadProcessOutputArgsSchema, ForceTerminateArgsSchema } from '../tools/schemas.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handle start_process command (improved execute_command)
|
|
5
|
+
*/
|
|
6
|
+
export async function handleStartProcess(args) {
|
|
7
|
+
const parsed = StartProcessArgsSchema.parse(args);
|
|
8
|
+
return startProcess(parsed);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Handle read_process_output command (improved read_output)
|
|
12
|
+
*/
|
|
13
|
+
export async function handleReadProcessOutput(args) {
|
|
14
|
+
const parsed = ReadProcessOutputArgsSchema.parse(args);
|
|
15
|
+
return readProcessOutput(parsed);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Handle interact_with_process command (improved send_input)
|
|
19
|
+
*/
|
|
20
|
+
export async function handleInteractWithProcess(args) {
|
|
21
|
+
return interactWithProcess(args);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Handle force_terminate command
|
|
25
|
+
*/
|
|
26
|
+
export async function handleForceTerminate(args) {
|
|
27
|
+
const parsed = ForceTerminateArgsSchema.parse(args);
|
|
28
|
+
return forceTerminate(parsed);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Handle list_sessions command
|
|
32
|
+
*/
|
|
33
|
+
export async function handleListSessions() {
|
|
34
|
+
return listSessions();
|
|
35
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// MUST be first: raises the libuv threadpool size before any fs work is
|
|
3
|
+
// submitted. See src/bootstrap.ts for why import order matters.
|
|
4
|
+
import './bootstrap.js';
|
|
5
|
+
import { FilteredStdioServerTransport } from './custom-stdio.js';
|
|
6
|
+
import { server, flushDeferredMessages } from './server.js';
|
|
7
|
+
import { configManager } from './config-manager.js';
|
|
8
|
+
import { featureFlagManager } from './utils/feature-flags.js';
|
|
9
|
+
import { capture } from './utils/capture.js';
|
|
10
|
+
import { logToStderr, logger } from './utils/logger.js';
|
|
11
|
+
import { runRemote } from './npm-scripts/remote.js';
|
|
12
|
+
import { ensureChromeAvailable } from './tools/pdf/markdown.js';
|
|
13
|
+
// Store messages to defer until after initialization
|
|
14
|
+
const deferredMessages = [];
|
|
15
|
+
function deferLog(level, message) {
|
|
16
|
+
deferredMessages.push({ level, message });
|
|
17
|
+
}
|
|
18
|
+
async function runServer() {
|
|
19
|
+
try {
|
|
20
|
+
// Check if first argument is "remote"
|
|
21
|
+
if (process.argv[2] === 'remote') {
|
|
22
|
+
await runRemote();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Parse command line arguments for onboarding control
|
|
26
|
+
const DISABLE_ONBOARDING = process.argv.includes('--no-onboarding');
|
|
27
|
+
if (DISABLE_ONBOARDING) {
|
|
28
|
+
logToStderr('info', 'Onboarding disabled via --no-onboarding flag');
|
|
29
|
+
}
|
|
30
|
+
// Set global flag for onboarding control
|
|
31
|
+
global.disableOnboarding = DISABLE_ONBOARDING;
|
|
32
|
+
// Create transport FIRST so all logging gets properly buffered
|
|
33
|
+
// This must happen before any code that might use logger.*
|
|
34
|
+
const transport = new FilteredStdioServerTransport();
|
|
35
|
+
// Export transport for use throughout the application
|
|
36
|
+
global.mcpTransport = transport;
|
|
37
|
+
try {
|
|
38
|
+
deferLog('info', 'Loading configuration...');
|
|
39
|
+
await configManager.loadConfig();
|
|
40
|
+
deferLog('info', 'Configuration loaded successfully');
|
|
41
|
+
// Initialize feature flags (non-blocking)
|
|
42
|
+
deferLog('info', 'Initializing feature flags...');
|
|
43
|
+
await featureFlagManager.initialize();
|
|
44
|
+
}
|
|
45
|
+
catch (configError) {
|
|
46
|
+
deferLog('error', `Failed to load configuration: ${configError instanceof Error ? configError.message : String(configError)}`);
|
|
47
|
+
if (configError instanceof Error && configError.stack) {
|
|
48
|
+
deferLog('debug', `Stack trace: ${configError.stack}`);
|
|
49
|
+
}
|
|
50
|
+
deferLog('warning', 'Continuing with in-memory configuration only');
|
|
51
|
+
// Continue anyway - we'll use an in-memory config
|
|
52
|
+
}
|
|
53
|
+
// Handle uncaught exceptions
|
|
54
|
+
process.on('uncaughtException', async (error) => {
|
|
55
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
56
|
+
// If this is a JSON parsing error, log it to stderr but don't crash
|
|
57
|
+
if (errorMessage.includes('JSON') && errorMessage.includes('Unexpected token')) {
|
|
58
|
+
logger.error(`JSON parsing error: ${errorMessage}`);
|
|
59
|
+
return; // Don't exit on JSON parsing errors
|
|
60
|
+
}
|
|
61
|
+
capture('run_server_uncaught_exception', {
|
|
62
|
+
error: errorMessage
|
|
63
|
+
});
|
|
64
|
+
logger.error(`Uncaught exception: ${errorMessage}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
// Handle unhandled rejections
|
|
68
|
+
process.on('unhandledRejection', async (reason) => {
|
|
69
|
+
const errorMessage = reason instanceof Error ? reason.message : String(reason);
|
|
70
|
+
// If this is a JSON parsing error, log it to stderr but don't crash
|
|
71
|
+
if (errorMessage.includes('JSON') && errorMessage.includes('Unexpected token')) {
|
|
72
|
+
logger.error(`JSON parsing rejection: ${errorMessage}`);
|
|
73
|
+
return; // Don't exit on JSON parsing errors
|
|
74
|
+
}
|
|
75
|
+
capture('run_server_unhandled_rejection', {
|
|
76
|
+
error: errorMessage
|
|
77
|
+
});
|
|
78
|
+
logger.error(`Unhandled rejection: ${errorMessage}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
|
81
|
+
capture('run_server_start');
|
|
82
|
+
deferLog('info', 'Connecting server...');
|
|
83
|
+
// Set up event-driven initialization completion handler
|
|
84
|
+
server.oninitialized = () => {
|
|
85
|
+
// This callback is triggered after the client sends the "initialized" notification
|
|
86
|
+
// At this point, the MCP protocol handshake is fully complete
|
|
87
|
+
transport.enableNotifications();
|
|
88
|
+
// Flush all deferred messages from both index.ts and server.ts
|
|
89
|
+
while (deferredMessages.length > 0) {
|
|
90
|
+
const msg = deferredMessages.shift();
|
|
91
|
+
transport.sendLog('info', msg.message);
|
|
92
|
+
}
|
|
93
|
+
flushDeferredMessages();
|
|
94
|
+
// Now we can send regular logging messages
|
|
95
|
+
transport.sendLog('info', 'Server connected successfully');
|
|
96
|
+
transport.sendLog('info', 'MCP fully initialized, all startup messages sent');
|
|
97
|
+
// Preemptively check/download Chrome for PDF generation (runs in background)
|
|
98
|
+
ensureChromeAvailable();
|
|
99
|
+
};
|
|
100
|
+
await server.connect(transport);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
104
|
+
logger.error(`FATAL ERROR: ${errorMessage}`);
|
|
105
|
+
if (error instanceof Error && error.stack) {
|
|
106
|
+
logger.debug(error.stack);
|
|
107
|
+
}
|
|
108
|
+
// Send a structured error notification
|
|
109
|
+
const errorNotification = {
|
|
110
|
+
jsonrpc: "2.0",
|
|
111
|
+
method: "notifications/message",
|
|
112
|
+
params: {
|
|
113
|
+
level: "error",
|
|
114
|
+
logger: "mcp-device",
|
|
115
|
+
data: `Failed to start server: ${errorMessage} (${new Date().toISOString()})`
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
process.stdout.write(JSON.stringify(errorNotification) + '\n');
|
|
119
|
+
capture('run_server_failed_start_error', {
|
|
120
|
+
error: errorMessage
|
|
121
|
+
});
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
runServer().catch(async (error) => {
|
|
126
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
127
|
+
console.error(`RUNTIME ERROR: ${errorMessage}`);
|
|
128
|
+
console.error(error instanceof Error && error.stack ? error.stack : 'No stack trace available');
|
|
129
|
+
process.stderr.write(JSON.stringify({
|
|
130
|
+
type: 'error',
|
|
131
|
+
timestamp: new Date().toISOString(),
|
|
132
|
+
message: `Fatal error running server: ${errorMessage}`
|
|
133
|
+
}) + '\n');
|
|
134
|
+
capture('run_server_fatal_error', {
|
|
135
|
+
error: errorMessage
|
|
136
|
+
});
|
|
137
|
+
process.exit(1);
|
|
138
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { GatewayDeviceStatusStore } from '../device/device-status.js';
|
|
2
|
+
export declare function applyServiceCommandStatus(store: GatewayDeviceStatusStore, command: 'install' | 'start' | 'stop' | 'uninstall'): Promise<void>;
|
|
3
|
+
export declare function runRemote(): Promise<void>;
|