@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.
Files changed (261) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -0
  3. package/dist/bootstrap.d.ts +1 -0
  4. package/dist/bootstrap.js +22 -0
  5. package/dist/command-manager.d.ts +8 -0
  6. package/dist/command-manager.js +241 -0
  7. package/dist/config-field-definitions.d.ts +41 -0
  8. package/dist/config-field-definitions.js +37 -0
  9. package/dist/config-manager.d.ts +102 -0
  10. package/dist/config-manager.js +291 -0
  11. package/dist/config.d.ts +6 -0
  12. package/dist/config.js +10 -0
  13. package/dist/custom-stdio.d.ts +51 -0
  14. package/dist/custom-stdio.js +358 -0
  15. package/dist/data/official-app-ca.pem +12 -0
  16. package/dist/data/onboarding-prompts.json +70 -0
  17. package/dist/device/device-state.d.ts +13 -0
  18. package/dist/device/device-state.js +100 -0
  19. package/dist/device/device-status.d.ts +81 -0
  20. package/dist/device/device-status.js +156 -0
  21. package/dist/device/device.d.ts +16 -0
  22. package/dist/device/device.js +190 -0
  23. package/dist/device/execution-engine.d.ts +144 -0
  24. package/dist/device/execution-engine.js +195 -0
  25. package/dist/device/gateway-channel.d.ts +48 -0
  26. package/dist/device/gateway-channel.js +384 -0
  27. package/dist/device/gateway-config.d.ts +40 -0
  28. package/dist/device/gateway-config.js +207 -0
  29. package/dist/device/gateway-identity.d.ts +35 -0
  30. package/dist/device/gateway-identity.js +178 -0
  31. package/dist/device/gateway-pairing.d.ts +25 -0
  32. package/dist/device/gateway-pairing.js +105 -0
  33. package/dist/device/gateway-secure-transport.d.ts +25 -0
  34. package/dist/device/gateway-secure-transport.js +117 -0
  35. package/dist/device/gateway-tool-adapter.d.ts +17 -0
  36. package/dist/device/gateway-tool-adapter.js +284 -0
  37. package/dist/device/gateway-url-policy.d.ts +3 -0
  38. package/dist/device/gateway-url-policy.js +43 -0
  39. package/dist/device/linux-service.d.ts +70 -0
  40. package/dist/device/linux-service.js +268 -0
  41. package/dist/device/official-trust.d.ts +7 -0
  42. package/dist/device/official-trust.js +49 -0
  43. package/dist/device/project-inspection.d.ts +1 -0
  44. package/dist/device/project-inspection.js +180 -0
  45. package/dist/device/runtime-owner.d.ts +41 -0
  46. package/dist/device/runtime-owner.js +177 -0
  47. package/dist/device/windows-dpapi.d.ts +11 -0
  48. package/dist/device/windows-dpapi.js +67 -0
  49. package/dist/device/windows-service.d.ts +56 -0
  50. package/dist/device/windows-service.js +238 -0
  51. package/dist/error-handlers.d.ts +7 -0
  52. package/dist/error-handlers.js +15 -0
  53. package/dist/handlers/edit-search-handlers.d.ts +6 -0
  54. package/dist/handlers/edit-search-handlers.js +6 -0
  55. package/dist/handlers/filesystem-handlers.d.ts +38 -0
  56. package/dist/handlers/filesystem-handlers.js +440 -0
  57. package/dist/handlers/history-handlers.d.ts +12 -0
  58. package/dist/handlers/history-handlers.js +67 -0
  59. package/dist/handlers/index.d.ts +6 -0
  60. package/dist/handlers/index.js +7 -0
  61. package/dist/handlers/process-handlers.d.ts +9 -0
  62. package/dist/handlers/process-handlers.js +15 -0
  63. package/dist/handlers/search-handlers.d.ts +17 -0
  64. package/dist/handlers/search-handlers.js +224 -0
  65. package/dist/handlers/terminal-handlers.d.ts +21 -0
  66. package/dist/handlers/terminal-handlers.js +35 -0
  67. package/dist/index.d.ts +2 -0
  68. package/dist/index.js +138 -0
  69. package/dist/mcp-device.d.ts +2 -0
  70. package/dist/mcp-device.js +7 -0
  71. package/dist/npm-scripts/remote.d.ts +3 -0
  72. package/dist/npm-scripts/remote.js +314 -0
  73. package/dist/search-manager.d.ts +147 -0
  74. package/dist/search-manager.js +828 -0
  75. package/dist/server.d.ts +46 -0
  76. package/dist/server.js +1563 -0
  77. package/dist/terminal-manager.d.ts +104 -0
  78. package/dist/terminal-manager.js +635 -0
  79. package/dist/tools/config.d.ts +96 -0
  80. package/dist/tools/config.js +260 -0
  81. package/dist/tools/edit.d.ts +38 -0
  82. package/dist/tools/edit.js +435 -0
  83. package/dist/tools/feedback.d.ts +8 -0
  84. package/dist/tools/feedback.js +132 -0
  85. package/dist/tools/filesystem.d.ts +79 -0
  86. package/dist/tools/filesystem.js +947 -0
  87. package/dist/tools/fuzzySearch.d.ts +12 -0
  88. package/dist/tools/fuzzySearch.js +74 -0
  89. package/dist/tools/fuzzySearchCore.d.ts +52 -0
  90. package/dist/tools/fuzzySearchCore.js +125 -0
  91. package/dist/tools/improved-process-tools.d.ts +24 -0
  92. package/dist/tools/improved-process-tools.js +627 -0
  93. package/dist/tools/mime-types.d.ts +3 -0
  94. package/dist/tools/mime-types.js +28 -0
  95. package/dist/tools/pdf/extract-images.d.ts +34 -0
  96. package/dist/tools/pdf/extract-images.js +132 -0
  97. package/dist/tools/pdf/index.d.ts +6 -0
  98. package/dist/tools/pdf/index.js +3 -0
  99. package/dist/tools/pdf/lib/pdf2md.d.ts +36 -0
  100. package/dist/tools/pdf/lib/pdf2md.js +76 -0
  101. package/dist/tools/pdf/manipulations.d.ts +13 -0
  102. package/dist/tools/pdf/manipulations.js +99 -0
  103. package/dist/tools/pdf/markdown.d.ts +26 -0
  104. package/dist/tools/pdf/markdown.js +275 -0
  105. package/dist/tools/pdf/utils.d.ts +12 -0
  106. package/dist/tools/pdf/utils.js +34 -0
  107. package/dist/tools/process.d.ts +3 -0
  108. package/dist/tools/process.js +56 -0
  109. package/dist/tools/prompts.d.ts +28 -0
  110. package/dist/tools/prompts.js +259 -0
  111. package/dist/tools/schemas.d.ts +454 -0
  112. package/dist/tools/schemas.js +242 -0
  113. package/dist/tools/usage.d.ts +5 -0
  114. package/dist/tools/usage.js +24 -0
  115. package/dist/types.d.ts +83 -0
  116. package/dist/types.js +1 -0
  117. package/dist/ui/config-editor/config-editor-runtime.js +150 -0
  118. package/dist/ui/config-editor/index.html +13 -0
  119. package/dist/ui/config-editor/src/app.d.ts +43 -0
  120. package/dist/ui/config-editor/src/app.js +831 -0
  121. package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
  122. package/dist/ui/config-editor/src/array-modal.js +185 -0
  123. package/dist/ui/config-editor/src/main.d.ts +1 -0
  124. package/dist/ui/config-editor/src/main.js +2 -0
  125. package/dist/ui/config-editor/styles.css +587 -0
  126. package/dist/ui/contracts.d.ts +14 -0
  127. package/dist/ui/contracts.js +21 -0
  128. package/dist/ui/file-preview/index.html +16 -0
  129. package/dist/ui/file-preview/preview-runtime.js +469 -0
  130. package/dist/ui/file-preview/shared/preview-file-types.d.ts +5 -0
  131. package/dist/ui/file-preview/shared/preview-file-types.js +59 -0
  132. package/dist/ui/file-preview/src/app.d.ts +4 -0
  133. package/dist/ui/file-preview/src/app.js +680 -0
  134. package/dist/ui/file-preview/src/components/code-viewer.d.ts +6 -0
  135. package/dist/ui/file-preview/src/components/code-viewer.js +73 -0
  136. package/dist/ui/file-preview/src/components/highlighting.d.ts +2 -0
  137. package/dist/ui/file-preview/src/components/highlighting.js +54 -0
  138. package/dist/ui/file-preview/src/components/html-renderer.d.ts +5 -0
  139. package/dist/ui/file-preview/src/components/html-renderer.js +47 -0
  140. package/dist/ui/file-preview/src/components/markdown-renderer.d.ts +1 -0
  141. package/dist/ui/file-preview/src/components/markdown-renderer.js +59 -0
  142. package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
  143. package/dist/ui/file-preview/src/directory-controller.js +240 -0
  144. package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
  145. package/dist/ui/file-preview/src/document-layout.js +109 -0
  146. package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
  147. package/dist/ui/file-preview/src/document-outline.js +97 -0
  148. package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
  149. package/dist/ui/file-preview/src/document-workspace.js +33 -0
  150. package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
  151. package/dist/ui/file-preview/src/file-type-handlers.js +109 -0
  152. package/dist/ui/file-preview/src/host/external-actions.d.ts +8 -0
  153. package/dist/ui/file-preview/src/host/external-actions.js +55 -0
  154. package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
  155. package/dist/ui/file-preview/src/host/selection-context.js +106 -0
  156. package/dist/ui/file-preview/src/image-preview.d.ts +3 -0
  157. package/dist/ui/file-preview/src/image-preview.js +21 -0
  158. package/dist/ui/file-preview/src/main.d.ts +1 -0
  159. package/dist/ui/file-preview/src/main.js +5 -0
  160. package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
  161. package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
  162. package/dist/ui/file-preview/src/markdown/controller.d.ts +44 -0
  163. package/dist/ui/file-preview/src/markdown/controller.js +1043 -0
  164. package/dist/ui/file-preview/src/markdown/editor.d.ts +131 -0
  165. package/dist/ui/file-preview/src/markdown/editor.js +1479 -0
  166. package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
  167. package/dist/ui/file-preview/src/markdown/linking.js +228 -0
  168. package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
  169. package/dist/ui/file-preview/src/markdown/outline.js +16 -0
  170. package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
  171. package/dist/ui/file-preview/src/markdown/parser.js +38 -0
  172. package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
  173. package/dist/ui/file-preview/src/markdown/preview.js +20 -0
  174. package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
  175. package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
  176. package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
  177. package/dist/ui/file-preview/src/markdown/utils.js +15 -0
  178. package/dist/ui/file-preview/src/model.d.ts +35 -0
  179. package/dist/ui/file-preview/src/model.js +1 -0
  180. package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
  181. package/dist/ui/file-preview/src/panel-actions.js +182 -0
  182. package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
  183. package/dist/ui/file-preview/src/path-utils.js +64 -0
  184. package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
  185. package/dist/ui/file-preview/src/payload-utils.js +119 -0
  186. package/dist/ui/file-preview/src/types.d.ts +1 -0
  187. package/dist/ui/file-preview/src/types.js +1 -0
  188. package/dist/ui/file-preview/styles.css +1631 -0
  189. package/dist/ui/resources.d.ts +28 -0
  190. package/dist/ui/resources.js +86 -0
  191. package/dist/ui/shared/compact-row.d.ts +11 -0
  192. package/dist/ui/shared/compact-row.js +18 -0
  193. package/dist/ui/shared/escape-html.d.ts +4 -0
  194. package/dist/ui/shared/escape-html.js +11 -0
  195. package/dist/ui/shared/host-context.d.ts +15 -0
  196. package/dist/ui/shared/host-context.js +51 -0
  197. package/dist/ui/shared/tool-bridge.d.ts +30 -0
  198. package/dist/ui/shared/tool-bridge.js +137 -0
  199. package/dist/ui/shared/tool-shell.d.ts +25 -0
  200. package/dist/ui/shared/tool-shell.js +107 -0
  201. package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
  202. package/dist/ui/shared/ui-event-tracker.js +27 -0
  203. package/dist/ui/shared/widget-state.d.ts +33 -0
  204. package/dist/ui/shared/widget-state.js +158 -0
  205. package/dist/utils/ab-test.d.ts +12 -0
  206. package/dist/utils/ab-test.js +104 -0
  207. package/dist/utils/capture.d.ts +35 -0
  208. package/dist/utils/capture.js +481 -0
  209. package/dist/utils/dockerPrompt.d.ts +17 -0
  210. package/dist/utils/dockerPrompt.js +53 -0
  211. package/dist/utils/feature-flags.d.ts +59 -0
  212. package/dist/utils/feature-flags.js +215 -0
  213. package/dist/utils/files/base.d.ts +173 -0
  214. package/dist/utils/files/base.js +5 -0
  215. package/dist/utils/files/binary.d.ts +21 -0
  216. package/dist/utils/files/binary.js +65 -0
  217. package/dist/utils/files/docx.d.ts +47 -0
  218. package/dist/utils/files/docx.js +679 -0
  219. package/dist/utils/files/excel.d.ts +24 -0
  220. package/dist/utils/files/excel.js +437 -0
  221. package/dist/utils/files/factory.d.ts +41 -0
  222. package/dist/utils/files/factory.js +113 -0
  223. package/dist/utils/files/image.d.ts +21 -0
  224. package/dist/utils/files/image.js +78 -0
  225. package/dist/utils/files/index.d.ts +10 -0
  226. package/dist/utils/files/index.js +13 -0
  227. package/dist/utils/files/pdf.d.ts +32 -0
  228. package/dist/utils/files/pdf.js +142 -0
  229. package/dist/utils/files/text.d.ts +63 -0
  230. package/dist/utils/files/text.js +370 -0
  231. package/dist/utils/fuzzySearchLogger.d.ts +30 -0
  232. package/dist/utils/fuzzySearchLogger.js +126 -0
  233. package/dist/utils/lineEndingHandler.d.ts +21 -0
  234. package/dist/utils/lineEndingHandler.js +77 -0
  235. package/dist/utils/logger.d.ts +32 -0
  236. package/dist/utils/logger.js +72 -0
  237. package/dist/utils/mcp-ui-ab-test.d.ts +13 -0
  238. package/dist/utils/mcp-ui-ab-test.js +62 -0
  239. package/dist/utils/open-browser.d.ts +9 -0
  240. package/dist/utils/open-browser.js +42 -0
  241. package/dist/utils/process-detection.d.ts +23 -0
  242. package/dist/utils/process-detection.js +150 -0
  243. package/dist/utils/ripgrep-resolver.d.ts +9 -0
  244. package/dist/utils/ripgrep-resolver.js +74 -0
  245. package/dist/utils/system-info.d.ts +71 -0
  246. package/dist/utils/system-info.js +712 -0
  247. package/dist/utils/toolHistory.d.ts +86 -0
  248. package/dist/utils/toolHistory.js +257 -0
  249. package/dist/utils/trackTools.d.ts +6 -0
  250. package/dist/utils/trackTools.js +54 -0
  251. package/dist/utils/unsupportedParams.d.ts +24 -0
  252. package/dist/utils/unsupportedParams.js +66 -0
  253. package/dist/utils/usageTracker.d.ts +133 -0
  254. package/dist/utils/usageTracker.js +477 -0
  255. package/dist/utils/welcome-onboarding.d.ts +11 -0
  256. package/dist/utils/welcome-onboarding.js +99 -0
  257. package/dist/utils/withTimeout.d.ts +28 -0
  258. package/dist/utils/withTimeout.js +85 -0
  259. package/dist/version.d.ts +1 -0
  260. package/dist/version.js +1 -0
  261. 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
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import './bootstrap.js';
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,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ // MCP Device publishes only the authenticated device runtime surface.
3
+ if (process.argv[2] !== 'remote')
4
+ process.argv.splice(2, 0, 'remote');
5
+ const { runRemote } = await import('./npm-scripts/remote.js');
6
+ await runRemote();
7
+ export {};
@@ -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>;