agent-web-interface 4.4.0 → 4.5.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 (319) hide show
  1. package/dist/src/browser/browser-session-config.d.ts +33 -0
  2. package/dist/src/browser/browser-session-config.d.ts.map +1 -0
  3. package/dist/src/browser/browser-session-config.js +24 -0
  4. package/dist/src/browser/browser-session-config.js.map +1 -0
  5. package/dist/src/browser/ensure-browser.d.ts +12 -27
  6. package/dist/src/browser/ensure-browser.d.ts.map +1 -1
  7. package/dist/src/browser/ensure-browser.js +104 -37
  8. package/dist/src/browser/ensure-browser.js.map +1 -1
  9. package/dist/src/browser/index.d.ts +2 -1
  10. package/dist/src/browser/index.d.ts.map +1 -1
  11. package/dist/src/browser/index.js +1 -0
  12. package/dist/src/browser/index.js.map +1 -1
  13. package/dist/src/browser/session-manager.d.ts +20 -0
  14. package/dist/src/browser/session-manager.d.ts.map +1 -1
  15. package/dist/src/browser/session-manager.js +122 -17
  16. package/dist/src/browser/session-manager.js.map +1 -1
  17. package/dist/src/browser/session-manager.types.d.ts +14 -2
  18. package/dist/src/browser/session-manager.types.d.ts.map +1 -1
  19. package/dist/src/browser/session-manager.types.js +5 -1
  20. package/dist/src/browser/session-manager.types.js.map +1 -1
  21. package/dist/src/cli/args.d.ts +12 -18
  22. package/dist/src/cli/args.d.ts.map +1 -1
  23. package/dist/src/cli/args.js +35 -40
  24. package/dist/src/cli/args.js.map +1 -1
  25. package/dist/src/form/constraint-extraction.d.ts +5 -0
  26. package/dist/src/form/constraint-extraction.d.ts.map +1 -1
  27. package/dist/src/form/constraint-extraction.js +13 -6
  28. package/dist/src/form/constraint-extraction.js.map +1 -1
  29. package/dist/src/form/field-extractor.d.ts.map +1 -1
  30. package/dist/src/form/field-extractor.js +14 -7
  31. package/dist/src/form/field-extractor.js.map +1 -1
  32. package/dist/src/form/form-state.d.ts.map +1 -1
  33. package/dist/src/form/form-state.js +16 -4
  34. package/dist/src/form/form-state.js.map +1 -1
  35. package/dist/src/gateway/http-gateway.d.ts +56 -0
  36. package/dist/src/gateway/http-gateway.d.ts.map +1 -0
  37. package/dist/src/gateway/http-gateway.js +229 -0
  38. package/dist/src/gateway/http-gateway.js.map +1 -0
  39. package/dist/src/gateway/json-rpc-errors.d.ts +6 -0
  40. package/dist/src/gateway/json-rpc-errors.d.ts.map +1 -0
  41. package/dist/src/gateway/json-rpc-errors.js +11 -0
  42. package/dist/src/gateway/json-rpc-errors.js.map +1 -0
  43. package/dist/src/gateway/session-router.d.ts +80 -0
  44. package/dist/src/gateway/session-router.d.ts.map +1 -0
  45. package/dist/src/gateway/session-router.js +177 -0
  46. package/dist/src/gateway/session-router.js.map +1 -0
  47. package/dist/src/http-entry.d.ts +20 -0
  48. package/dist/src/http-entry.d.ts.map +1 -0
  49. package/dist/src/http-entry.js +112 -0
  50. package/dist/src/http-entry.js.map +1 -0
  51. package/dist/src/index.d.ts +1 -10
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/dist/src/index.js +25 -232
  54. package/dist/src/index.js.map +1 -1
  55. package/dist/src/lib/text-utils.d.ts +0 -24
  56. package/dist/src/lib/text-utils.d.ts.map +1 -1
  57. package/dist/src/lib/text-utils.js +2 -38
  58. package/dist/src/lib/text-utils.js.map +1 -1
  59. package/dist/src/observation/eid-linker.d.ts.map +1 -1
  60. package/dist/src/observation/eid-linker.js +1 -21
  61. package/dist/src/observation/eid-linker.js.map +1 -1
  62. package/dist/src/server/index.d.ts +0 -1
  63. package/dist/src/server/index.d.ts.map +1 -1
  64. package/dist/src/server/index.js +0 -1
  65. package/dist/src/server/index.js.map +1 -1
  66. package/dist/src/server/mcp-server.d.ts +6 -2
  67. package/dist/src/server/mcp-server.d.ts.map +1 -1
  68. package/dist/src/server/mcp-server.js +3 -91
  69. package/dist/src/server/mcp-server.js.map +1 -1
  70. package/dist/src/server/server-config.d.ts +4 -20
  71. package/dist/src/server/server-config.d.ts.map +1 -1
  72. package/dist/src/server/server-config.js +6 -50
  73. package/dist/src/server/server-config.js.map +1 -1
  74. package/dist/src/server/tool-registrar.types.d.ts +25 -0
  75. package/dist/src/server/tool-registrar.types.d.ts.map +1 -0
  76. package/dist/src/server/tool-registrar.types.js +10 -0
  77. package/dist/src/server/tool-registrar.types.js.map +1 -0
  78. package/dist/src/server/tool-result-handler.d.ts +61 -0
  79. package/dist/src/server/tool-result-handler.d.ts.map +1 -0
  80. package/dist/src/server/tool-result-handler.js +137 -0
  81. package/dist/src/server/tool-result-handler.js.map +1 -0
  82. package/dist/src/session/session-controller.d.ts +123 -0
  83. package/dist/src/session/session-controller.d.ts.map +1 -0
  84. package/dist/src/session/session-controller.js +273 -0
  85. package/dist/src/session/session-controller.js.map +1 -0
  86. package/dist/src/shared/services/index.d.ts +0 -2
  87. package/dist/src/shared/services/index.d.ts.map +1 -1
  88. package/dist/src/shared/services/index.js +0 -2
  89. package/dist/src/shared/services/index.js.map +1 -1
  90. package/dist/src/shared/version.d.ts +10 -0
  91. package/dist/src/shared/version.d.ts.map +1 -0
  92. package/dist/src/shared/version.js +32 -0
  93. package/dist/src/shared/version.js.map +1 -0
  94. package/dist/src/snapshot/element-resolver.d.ts +3 -2
  95. package/dist/src/snapshot/element-resolver.d.ts.map +1 -1
  96. package/dist/src/snapshot/element-resolver.js +83 -8
  97. package/dist/src/snapshot/element-resolver.js.map +1 -1
  98. package/dist/src/snapshot/extractors/attribute-extractor.d.ts.map +1 -1
  99. package/dist/src/snapshot/extractors/attribute-extractor.js +4 -0
  100. package/dist/src/snapshot/extractors/attribute-extractor.js.map +1 -1
  101. package/dist/src/snapshot/extractors/layout-extractor.d.ts +9 -7
  102. package/dist/src/snapshot/extractors/layout-extractor.d.ts.map +1 -1
  103. package/dist/src/snapshot/extractors/layout-extractor.js +34 -19
  104. package/dist/src/snapshot/extractors/layout-extractor.js.map +1 -1
  105. package/dist/src/snapshot/extractors/state-extractor.d.ts +2 -2
  106. package/dist/src/snapshot/extractors/state-extractor.d.ts.map +1 -1
  107. package/dist/src/snapshot/extractors/state-extractor.js +22 -2
  108. package/dist/src/snapshot/extractors/state-extractor.js.map +1 -1
  109. package/dist/src/snapshot/extractors/types.d.ts +6 -0
  110. package/dist/src/snapshot/extractors/types.d.ts.map +1 -1
  111. package/dist/src/snapshot/extractors/types.js.map +1 -1
  112. package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -1
  113. package/dist/src/snapshot/snapshot-compiler.js +15 -2
  114. package/dist/src/snapshot/snapshot-compiler.js.map +1 -1
  115. package/dist/src/snapshot/snapshot.types.d.ts +10 -1
  116. package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
  117. package/dist/src/snapshot/snapshot.types.js.map +1 -1
  118. package/dist/src/state/actionables-filter.d.ts.map +1 -1
  119. package/dist/src/state/actionables-filter.js +7 -3
  120. package/dist/src/state/actionables-filter.js.map +1 -1
  121. package/dist/src/state/atoms-extractor.d.ts.map +1 -1
  122. package/dist/src/state/atoms-extractor.js +3 -23
  123. package/dist/src/state/atoms-extractor.js.map +1 -1
  124. package/dist/src/state/diff-engine.d.ts.map +1 -1
  125. package/dist/src/state/diff-engine.js +6 -33
  126. package/dist/src/state/diff-engine.js.map +1 -1
  127. package/dist/src/state/element-identity.d.ts +3 -6
  128. package/dist/src/state/element-identity.d.ts.map +1 -1
  129. package/dist/src/state/element-identity.js +10 -7
  130. package/dist/src/state/element-identity.js.map +1 -1
  131. package/dist/src/state/element-ref.types.d.ts +5 -27
  132. package/dist/src/state/element-ref.types.d.ts.map +1 -1
  133. package/dist/src/state/state-manager.d.ts.map +1 -1
  134. package/dist/src/state/state-manager.js +3 -1
  135. package/dist/src/state/state-manager.js.map +1 -1
  136. package/dist/src/state/state-renderer.d.ts.map +1 -1
  137. package/dist/src/state/state-renderer.js +3 -1
  138. package/dist/src/state/state-renderer.js.map +1 -1
  139. package/dist/src/state/types.d.ts +2 -1
  140. package/dist/src/state/types.d.ts.map +1 -1
  141. package/dist/src/state/url-sanitization.d.ts +1 -1
  142. package/dist/src/state/url-sanitization.d.ts.map +1 -1
  143. package/dist/src/state/url-sanitization.js +29 -13
  144. package/dist/src/state/url-sanitization.js.map +1 -1
  145. package/dist/src/tools/action-context.d.ts +6 -11
  146. package/dist/src/tools/action-context.d.ts.map +1 -1
  147. package/dist/src/tools/action-context.js +10 -19
  148. package/dist/src/tools/action-context.js.map +1 -1
  149. package/dist/src/tools/action-stabilization.d.ts.map +1 -1
  150. package/dist/src/tools/action-stabilization.js +6 -0
  151. package/dist/src/tools/action-stabilization.js.map +1 -1
  152. package/dist/src/tools/browser-tools.d.ts +3 -2
  153. package/dist/src/tools/browser-tools.d.ts.map +1 -1
  154. package/dist/src/tools/browser-tools.js +5 -3
  155. package/dist/src/tools/browser-tools.js.map +1 -1
  156. package/dist/src/tools/canvas-tools.d.ts +2 -1
  157. package/dist/src/tools/canvas-tools.d.ts.map +1 -1
  158. package/dist/src/tools/canvas-tools.js +5 -7
  159. package/dist/src/tools/canvas-tools.js.map +1 -1
  160. package/dist/src/tools/errors.d.ts +2 -34
  161. package/dist/src/tools/errors.d.ts.map +1 -1
  162. package/dist/src/tools/errors.js +1 -44
  163. package/dist/src/tools/errors.js.map +1 -1
  164. package/dist/src/tools/execute-action.d.ts +4 -3
  165. package/dist/src/tools/execute-action.d.ts.map +1 -1
  166. package/dist/src/tools/execute-action.js +32 -23
  167. package/dist/src/tools/execute-action.js.map +1 -1
  168. package/dist/src/tools/form-tools.d.ts +3 -8
  169. package/dist/src/tools/form-tools.d.ts.map +1 -1
  170. package/dist/src/tools/form-tools.js +38 -18
  171. package/dist/src/tools/form-tools.js.map +1 -1
  172. package/dist/src/tools/index.d.ts +6 -6
  173. package/dist/src/tools/index.d.ts.map +1 -1
  174. package/dist/src/tools/index.js +7 -10
  175. package/dist/src/tools/index.js.map +1 -1
  176. package/dist/src/tools/interaction-tools.d.ts +6 -5
  177. package/dist/src/tools/interaction-tools.d.ts.map +1 -1
  178. package/dist/src/tools/interaction-tools.js +29 -32
  179. package/dist/src/tools/interaction-tools.js.map +1 -1
  180. package/dist/src/tools/navigation-tools.d.ts +7 -13
  181. package/dist/src/tools/navigation-tools.d.ts.map +1 -1
  182. package/dist/src/tools/navigation-tools.js +52 -59
  183. package/dist/src/tools/navigation-tools.js.map +1 -1
  184. package/dist/src/tools/observation-tools.d.ts +6 -5
  185. package/dist/src/tools/observation-tools.d.ts.map +1 -1
  186. package/dist/src/tools/observation-tools.js +30 -34
  187. package/dist/src/tools/observation-tools.js.map +1 -1
  188. package/dist/src/tools/readability-tools.d.ts +16 -0
  189. package/dist/src/tools/readability-tools.d.ts.map +1 -0
  190. package/dist/src/tools/readability-tools.js +45 -0
  191. package/dist/src/tools/readability-tools.js.map +1 -0
  192. package/dist/src/tools/response-builder.d.ts +20 -32
  193. package/dist/src/tools/response-builder.d.ts.map +1 -1
  194. package/dist/src/tools/response-builder.js +31 -47
  195. package/dist/src/tools/response-builder.js.map +1 -1
  196. package/dist/src/tools/stale-element-retry.d.ts.map +1 -1
  197. package/dist/src/tools/stale-element-retry.js +37 -2
  198. package/dist/src/tools/stale-element-retry.js.map +1 -1
  199. package/dist/src/tools/tool-context.d.ts +4 -36
  200. package/dist/src/tools/tool-context.d.ts.map +1 -1
  201. package/dist/src/tools/tool-context.js +6 -75
  202. package/dist/src/tools/tool-context.js.map +1 -1
  203. package/dist/src/tools/tool-context.types.d.ts +141 -0
  204. package/dist/src/tools/tool-context.types.d.ts.map +1 -0
  205. package/dist/src/tools/tool-context.types.js +11 -0
  206. package/dist/src/tools/tool-context.types.js.map +1 -0
  207. package/dist/src/tools/tool-registration.d.ts +25 -0
  208. package/dist/src/tools/tool-registration.d.ts.map +1 -0
  209. package/dist/src/tools/tool-registration.js +180 -0
  210. package/dist/src/tools/tool-registration.js.map +1 -0
  211. package/dist/src/tools/tool-schemas.d.ts +88 -1947
  212. package/dist/src/tools/tool-schemas.d.ts.map +1 -1
  213. package/dist/src/tools/tool-schemas.js +21 -302
  214. package/dist/src/tools/tool-schemas.js.map +1 -1
  215. package/dist/src/tools/viewport-tools.d.ts +4 -3
  216. package/dist/src/tools/viewport-tools.d.ts.map +1 -1
  217. package/dist/src/tools/viewport-tools.js +17 -21
  218. package/dist/src/tools/viewport-tools.js.map +1 -1
  219. package/dist/src/worker/chrome-worker-process.d.ts +4 -0
  220. package/dist/src/worker/chrome-worker-process.d.ts.map +1 -1
  221. package/dist/src/worker/chrome-worker-process.js +1 -1
  222. package/dist/src/worker/chrome-worker-process.js.map +1 -1
  223. package/package.json +7 -3
  224. package/dist/src/factpack/action-selector.d.ts +0 -36
  225. package/dist/src/factpack/action-selector.d.ts.map +0 -1
  226. package/dist/src/factpack/action-selector.js +0 -367
  227. package/dist/src/factpack/action-selector.js.map +0 -1
  228. package/dist/src/factpack/dialog-detector.d.ts +0 -19
  229. package/dist/src/factpack/dialog-detector.d.ts.map +0 -1
  230. package/dist/src/factpack/dialog-detector.js +0 -354
  231. package/dist/src/factpack/dialog-detector.js.map +0 -1
  232. package/dist/src/factpack/form-detector.d.ts +0 -28
  233. package/dist/src/factpack/form-detector.d.ts.map +0 -1
  234. package/dist/src/factpack/form-detector.js +0 -555
  235. package/dist/src/factpack/form-detector.js.map +0 -1
  236. package/dist/src/factpack/index.d.ts +0 -32
  237. package/dist/src/factpack/index.d.ts.map +0 -1
  238. package/dist/src/factpack/index.js +0 -73
  239. package/dist/src/factpack/index.js.map +0 -1
  240. package/dist/src/factpack/page-classifier.d.ts +0 -22
  241. package/dist/src/factpack/page-classifier.d.ts.map +0 -1
  242. package/dist/src/factpack/page-classifier.js +0 -526
  243. package/dist/src/factpack/page-classifier.js.map +0 -1
  244. package/dist/src/factpack/types.d.ts +0 -307
  245. package/dist/src/factpack/types.d.ts.map +0 -1
  246. package/dist/src/factpack/types.js +0 -12
  247. package/dist/src/factpack/types.js.map +0 -1
  248. package/dist/src/lib/constants.d.ts +0 -27
  249. package/dist/src/lib/constants.d.ts.map +0 -1
  250. package/dist/src/lib/constants.js +0 -63
  251. package/dist/src/lib/constants.js.map +0 -1
  252. package/dist/src/lib/index.d.ts +0 -12
  253. package/dist/src/lib/index.d.ts.map +0 -1
  254. package/dist/src/lib/index.js +0 -17
  255. package/dist/src/lib/index.js.map +0 -1
  256. package/dist/src/lib/regions.d.ts +0 -29
  257. package/dist/src/lib/regions.d.ts.map +0 -1
  258. package/dist/src/lib/regions.js +0 -93
  259. package/dist/src/lib/regions.js.map +0 -1
  260. package/dist/src/lib/scoring.d.ts +0 -47
  261. package/dist/src/lib/scoring.d.ts.map +0 -1
  262. package/dist/src/lib/scoring.js +0 -79
  263. package/dist/src/lib/scoring.js.map +0 -1
  264. package/dist/src/lib/selectors.d.ts +0 -42
  265. package/dist/src/lib/selectors.d.ts.map +0 -1
  266. package/dist/src/lib/selectors.js +0 -138
  267. package/dist/src/lib/selectors.js.map +0 -1
  268. package/dist/src/renderer/budget-manager.d.ts +0 -46
  269. package/dist/src/renderer/budget-manager.d.ts.map +0 -1
  270. package/dist/src/renderer/budget-manager.js +0 -133
  271. package/dist/src/renderer/budget-manager.js.map +0 -1
  272. package/dist/src/renderer/constants.d.ts +0 -38
  273. package/dist/src/renderer/constants.d.ts.map +0 -1
  274. package/dist/src/renderer/constants.js +0 -29
  275. package/dist/src/renderer/constants.js.map +0 -1
  276. package/dist/src/renderer/index.d.ts +0 -12
  277. package/dist/src/renderer/index.d.ts.map +0 -1
  278. package/dist/src/renderer/index.js +0 -16
  279. package/dist/src/renderer/index.js.map +0 -1
  280. package/dist/src/renderer/section-renderers.d.ts +0 -42
  281. package/dist/src/renderer/section-renderers.d.ts.map +0 -1
  282. package/dist/src/renderer/section-renderers.js +0 -252
  283. package/dist/src/renderer/section-renderers.js.map +0 -1
  284. package/dist/src/renderer/token-counter.d.ts +0 -45
  285. package/dist/src/renderer/token-counter.d.ts.map +0 -1
  286. package/dist/src/renderer/token-counter.js +0 -65
  287. package/dist/src/renderer/token-counter.js.map +0 -1
  288. package/dist/src/renderer/types.d.ts +0 -71
  289. package/dist/src/renderer/types.d.ts.map +0 -1
  290. package/dist/src/renderer/types.js +0 -7
  291. package/dist/src/renderer/types.js.map +0 -1
  292. package/dist/src/renderer/xml-renderer.d.ts +0 -42
  293. package/dist/src/renderer/xml-renderer.d.ts.map +0 -1
  294. package/dist/src/renderer/xml-renderer.js +0 -103
  295. package/dist/src/renderer/xml-renderer.js.map +0 -1
  296. package/dist/src/server/session-store.d.ts +0 -163
  297. package/dist/src/server/session-store.d.ts.map +0 -1
  298. package/dist/src/server/session-store.js +0 -248
  299. package/dist/src/server/session-store.js.map +0 -1
  300. package/dist/src/session/session-worker-binding.d.ts +0 -57
  301. package/dist/src/session/session-worker-binding.d.ts.map +0 -1
  302. package/dist/src/session/session-worker-binding.js +0 -109
  303. package/dist/src/session/session-worker-binding.js.map +0 -1
  304. package/dist/src/shared/services/dom-transformer.service.d.ts +0 -71
  305. package/dist/src/shared/services/dom-transformer.service.d.ts.map +0 -1
  306. package/dist/src/shared/services/dom-transformer.service.js +0 -190
  307. package/dist/src/shared/services/dom-transformer.service.js.map +0 -1
  308. package/dist/src/shared/services/selector-builder.service.d.ts +0 -53
  309. package/dist/src/shared/services/selector-builder.service.d.ts.map +0 -1
  310. package/dist/src/shared/services/selector-builder.service.js +0 -240
  311. package/dist/src/shared/services/selector-builder.service.js.map +0 -1
  312. package/dist/src/state/constants.d.ts +0 -125
  313. package/dist/src/state/constants.d.ts.map +0 -1
  314. package/dist/src/state/constants.js +0 -131
  315. package/dist/src/state/constants.js.map +0 -1
  316. package/dist/src/tools/state-manager-registry.d.ts +0 -26
  317. package/dist/src/tools/state-manager-registry.d.ts.map +0 -1
  318. package/dist/src/tools/state-manager-registry.js +0 -39
  319. package/dist/src/tools/state-manager-registry.js.map +0 -1
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Session Router
3
+ *
4
+ * Maps MCP connections to SessionController instances.
5
+ *
6
+ * - stdio mode: resolve(undefined) returns a single implicit SessionController
7
+ * - HTTP mode: resolve(sessionId) looks up by MCP session ID
8
+ *
9
+ * Each SessionController owns its own browser lifecycle, configured
10
+ * independently via BrowserSessionConfig.
11
+ *
12
+ * @module gateway/session-router
13
+ */
14
+ import { SessionController } from '../session/session-controller.js';
15
+ import { getLogger } from '../shared/services/logging.service.js';
16
+ const logger = getLogger();
17
+ const DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
18
+ const DEFAULT_MAX_SESSIONS = 10;
19
+ /**
20
+ * Maps MCP connections to SessionController instances.
21
+ */
22
+ export class SessionRouter {
23
+ sessions = new Map();
24
+ implicitSession = null;
25
+ idleTimeoutMs;
26
+ maxSessions;
27
+ _onSessionDestroyed;
28
+ idleCheckTimer;
29
+ constructor(options) {
30
+ this.idleTimeoutMs = options?.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
31
+ this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
32
+ this._onSessionDestroyed = options?.onSessionDestroyed;
33
+ }
34
+ /**
35
+ * Resolve an MCP session ID to a ToolContext (SessionController).
36
+ *
37
+ * - If mcpSessionId is undefined (stdio mode), returns the implicit session
38
+ * - If mcpSessionId is provided (HTTP mode), looks up by ID
39
+ */
40
+ resolve(mcpSessionId) {
41
+ if (mcpSessionId === undefined) {
42
+ return this.getOrCreateImplicitSession();
43
+ }
44
+ const session = this.sessions.get(mcpSessionId);
45
+ if (!session) {
46
+ throw new Error(`Session not found: ${mcpSessionId}`);
47
+ }
48
+ session.touch();
49
+ return session;
50
+ }
51
+ /**
52
+ * Create a new session for an MCP connection.
53
+ *
54
+ * @param mcpSessionId - MCP session ID from transport
55
+ * @returns The created SessionController
56
+ */
57
+ // eslint-disable-next-line @typescript-eslint/require-await -- Kept async for API contract with HttpGateway
58
+ async createSession(mcpSessionId) {
59
+ if (this.sessions.has(mcpSessionId)) {
60
+ throw new Error(`Session already exists: ${mcpSessionId}`);
61
+ }
62
+ if (this.sessions.size >= this.maxSessions) {
63
+ throw new Error(`Maximum concurrent sessions (${this.maxSessions}) reached. Close an existing session first.`);
64
+ }
65
+ const options = {
66
+ sessionId: mcpSessionId,
67
+ };
68
+ const controller = new SessionController(options);
69
+ this.sessions.set(mcpSessionId, controller);
70
+ logger.info('Session created', { sessionId: mcpSessionId });
71
+ this.startIdleCheck();
72
+ return controller;
73
+ }
74
+ /**
75
+ * Destroy a session and clean up resources.
76
+ */
77
+ async destroySession(mcpSessionId) {
78
+ const session = this.sessions.get(mcpSessionId);
79
+ if (!session)
80
+ return;
81
+ await session.close();
82
+ this.sessions.delete(mcpSessionId);
83
+ logger.info('Session destroyed', { sessionId: mcpSessionId });
84
+ // Notify the gateway layer so it can clean up transports / MCP servers
85
+ if (this._onSessionDestroyed) {
86
+ try {
87
+ await this._onSessionDestroyed(mcpSessionId);
88
+ }
89
+ catch (err) {
90
+ logger.error('onSessionDestroyed callback failed', err instanceof Error ? err : undefined, {
91
+ sessionId: mcpSessionId,
92
+ });
93
+ }
94
+ }
95
+ if (this.sessions.size === 0) {
96
+ this.stopIdleCheck();
97
+ }
98
+ }
99
+ /**
100
+ * Get or create the implicit session for stdio mode.
101
+ */
102
+ getOrCreateImplicitSession() {
103
+ this.implicitSession ??= new SessionController({
104
+ sessionId: 'stdio',
105
+ });
106
+ this.implicitSession.touch();
107
+ return this.implicitSession;
108
+ }
109
+ /**
110
+ * Get the number of active sessions.
111
+ */
112
+ get sessionCount() {
113
+ return this.sessions.size + (this.implicitSession ? 1 : 0);
114
+ }
115
+ /**
116
+ * Register a callback invoked after a session is destroyed.
117
+ */
118
+ setOnSessionDestroyed(cb) {
119
+ this._onSessionDestroyed = cb;
120
+ }
121
+ /**
122
+ * Shut down all sessions and clean up.
123
+ */
124
+ async shutdown() {
125
+ this.stopIdleCheck();
126
+ const closePromises = [];
127
+ for (const session of this.sessions.values()) {
128
+ closePromises.push(session.close());
129
+ }
130
+ if (this.implicitSession) {
131
+ closePromises.push(this.implicitSession.close());
132
+ this.implicitSession = null;
133
+ }
134
+ await Promise.all(closePromises);
135
+ this.sessions.clear();
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Idle session cleanup
139
+ // ---------------------------------------------------------------------------
140
+ startIdleCheck() {
141
+ if (this.idleCheckTimer)
142
+ return;
143
+ this.idleCheckTimer = setInterval(() => {
144
+ void this.evictIdleSessions();
145
+ }, 60_000); // Check every minute
146
+ this.idleCheckTimer.unref();
147
+ }
148
+ stopIdleCheck() {
149
+ if (this.idleCheckTimer) {
150
+ clearInterval(this.idleCheckTimer);
151
+ this.idleCheckTimer = undefined;
152
+ }
153
+ }
154
+ async evictIdleSessions() {
155
+ const now = Date.now();
156
+ const toEvict = [];
157
+ for (const [id, session] of this.sessions) {
158
+ if (now - session.lastActivity > this.idleTimeoutMs) {
159
+ toEvict.push(id);
160
+ }
161
+ }
162
+ if (toEvict.length === 0)
163
+ return;
164
+ // Evict in parallel — each destroySession operates on a distinct session
165
+ const results = await Promise.allSettled(toEvict.map((id) => {
166
+ logger.info('Evicting idle session', { sessionId: id });
167
+ return this.destroySession(id);
168
+ }));
169
+ for (let i = 0; i < results.length; i++) {
170
+ const result = results[i];
171
+ if (result.status === 'rejected') {
172
+ logger.error('Failed to evict session', result.reason instanceof Error ? result.reason : undefined, { sessionId: toEvict[i] });
173
+ }
174
+ }
175
+ }
176
+ }
177
+ //# sourceMappingURL=session-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-router.js","sourceRoot":"","sources":["../../../src/gateway/session-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HTTP Entry Point
4
+ *
5
+ * Starts the MCP server with Streamable HTTP transport for multi-agent access.
6
+ * Use `--transport http --port 3000` to enable.
7
+ *
8
+ * Each HTTP client connection gets its own McpServer + SessionController pair,
9
+ * providing full session isolation for concurrent AI agents. Each session owns
10
+ * its own browser instance, configured independently via navigate tool params.
11
+ *
12
+ * @module http-entry
13
+ */
14
+ /**
15
+ * HTTP mode main entry point.
16
+ *
17
+ * Called from index.ts when `--transport http` is passed.
18
+ */
19
+ export declare function main(): Promise<void>;
20
+ //# sourceMappingURL=http-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-entry.d.ts","sourceRoot":"","sources":["../../src/http-entry.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG;AAaH;;;;GAIG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA0F1C"}
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HTTP Entry Point
4
+ *
5
+ * Starts the MCP server with Streamable HTTP transport for multi-agent access.
6
+ * Use `--transport http --port 3000` to enable.
7
+ *
8
+ * Each HTTP client connection gets its own McpServer + SessionController pair,
9
+ * providing full session isolation for concurrent AI agents. Each session owns
10
+ * its own browser instance, configured independently via navigate tool params.
11
+ *
12
+ * @module http-entry
13
+ */
14
+ import http from 'node:http';
15
+ import express from 'express';
16
+ import { getServerConfig } from './server/server-config.js';
17
+ import { SessionRouter } from './gateway/session-router.js';
18
+ import { HttpGateway } from './gateway/http-gateway.js';
19
+ import { sendJsonRpcError } from './gateway/json-rpc-errors.js';
20
+ import { getLogger } from './shared/services/logging.service.js';
21
+ import { cleanupTempFiles } from './lib/temp-file.js';
22
+ const logger = getLogger();
23
+ /**
24
+ * HTTP mode main entry point.
25
+ *
26
+ * Called from index.ts when `--transport http` is passed.
27
+ */
28
+ export async function main() {
29
+ const config = getServerConfig();
30
+ const port = config.port;
31
+ const host = process.env.HTTP_HOST ?? '127.0.0.1';
32
+ const router = new SessionRouter();
33
+ const gateway = new HttpGateway({ router });
34
+ const app = express();
35
+ // Allowed origins for DNS rebinding protection (MCP spec MUST requirement).
36
+ const allowedOriginHosts = new Set(['localhost', '127.0.0.1', '[::1]', host]);
37
+ app.use('/mcp', express.json(), (req, res, next) => {
38
+ const origin = req.headers.origin;
39
+ if (origin) {
40
+ try {
41
+ const originUrl = new URL(origin);
42
+ if (!allowedOriginHosts.has(originUrl.hostname)) {
43
+ sendJsonRpcError(res, 403, -32000, 'Forbidden: Origin not allowed');
44
+ return;
45
+ }
46
+ }
47
+ catch {
48
+ sendJsonRpcError(res, 403, -32000, 'Forbidden: Invalid Origin header');
49
+ return;
50
+ }
51
+ }
52
+ next();
53
+ });
54
+ // MCP endpoint
55
+ app.all('/mcp', async (req, res) => {
56
+ try {
57
+ if (req.method === 'POST') {
58
+ await gateway.handlePost(req, res);
59
+ }
60
+ else if (req.method === 'GET') {
61
+ await gateway.handleGet(req, res);
62
+ }
63
+ else if (req.method === 'DELETE') {
64
+ await gateway.handleDelete(req, res);
65
+ }
66
+ else {
67
+ sendJsonRpcError(res, 405, -32000, 'Method not allowed');
68
+ }
69
+ }
70
+ catch (err) {
71
+ logger.error('MCP request error', err instanceof Error ? err : undefined);
72
+ if (!res.headersSent) {
73
+ sendJsonRpcError(res, 500, -32603, 'Internal server error');
74
+ }
75
+ }
76
+ });
77
+ // Health endpoint
78
+ app.get('/health', (_req, res) => {
79
+ res.json({ status: 'ok', sessions: gateway.sessionCount });
80
+ });
81
+ const server = http.createServer(app);
82
+ await new Promise((resolve) => {
83
+ server.listen(port, host, () => {
84
+ logger.info(`HTTP MCP server listening on ${host}:${port}`);
85
+ console.error(`HTTP MCP server listening on http://${host}:${port}/mcp`);
86
+ resolve();
87
+ });
88
+ });
89
+ const shutdown = async (signal) => {
90
+ console.error(`Shutting down... (${signal})`);
91
+ // Hard deadline — if graceful shutdown hangs, force exit
92
+ const deadline = setTimeout(() => {
93
+ console.error('Graceful shutdown timed out after 10s, forcing exit');
94
+ process.exit(1);
95
+ }, 10_000);
96
+ deadline.unref();
97
+ try {
98
+ // Shut down gateway sessions first (closes MCP servers + transports + browsers)
99
+ await gateway.shutdown();
100
+ await cleanupTempFiles();
101
+ server.close();
102
+ process.exit(0);
103
+ }
104
+ catch (err) {
105
+ console.error('Error during shutdown:', err);
106
+ process.exit(1);
107
+ }
108
+ };
109
+ process.on('SIGINT', () => void shutdown('SIGINT'));
110
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
111
+ }
112
+ //# sourceMappingURL=http-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-entry.js","sourceRoot":"","sources":["../../src/http-entry.ts"],"names":[],"mappings":"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"}
@@ -4,14 +4,5 @@
4
4
  *
5
5
  * Main entry point - initializes the MCP server with Puppeteer-based browser automation.
6
6
  */
7
- import { SessionStore } from './server/session-store.js';
8
- import { SessionWorkerBinding } from './session/session-worker-binding.js';
9
- /**
10
- * Get the SessionStore instance for use in tool handlers.
11
- */
12
- export declare function getSessionStore(): SessionStore;
13
- /**
14
- * Get the SessionWorkerBinding instance.
15
- */
16
- export declare function getSessionBinding(): SessionWorkerBinding;
7
+ export {};
17
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAUH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qCAAqC,CAAC;AAgB/F;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,oBAAoB,CAExD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}
package/dist/src/index.js CHANGED
@@ -5,66 +5,11 @@
5
5
  * Main entry point - initializes the MCP server with Puppeteer-based browser automation.
6
6
  */
7
7
  import { BrowserAutomationServer } from './server/mcp-server.js';
8
- import { initServerConfig, getSessionManager, getServerConfig, ensureBrowserForTools, isSessionManagerInitialized, } from './server/server-config.js';
9
- import { SessionStore } from './server/session-store.js';
10
- import { SessionWorkerBinding } from './session/session-worker-binding.js';
11
- import { getLogger } from './shared/services/logging.service.js';
8
+ import { initServerConfig } from './server/server-config.js';
12
9
  import { cleanupTempFiles } from './lib/temp-file.js';
13
- const logger = getLogger();
14
- /** Module-level session store for tenant isolation */
15
- const sessionStore = new SessionStore();
16
- /** Isolation mode from environment (default: 'context') */
17
- const isolationMode = process.env.ISOLATION_MODE === 'process' ? 'process' : 'context';
18
- /** Session-to-worker binding adapter */
19
- const sessionBinding = new SessionWorkerBinding(isolationMode);
20
- /**
21
- * Get the SessionStore instance for use in tool handlers.
22
- */
23
- export function getSessionStore() {
24
- return sessionStore;
25
- }
26
- /**
27
- * Get the SessionWorkerBinding instance.
28
- */
29
- export function getSessionBinding() {
30
- return sessionBinding;
31
- }
32
- import { initializeToolContext,
33
- // Tool handlers
34
- listPages, closePage, closeSession, navigate, goBack, goForward, reload, captureSnapshot, findElements, getNodeDetails, scrollElementIntoView, scrollPage, click, type, press, select, hover, drag, wheel, getFormUnderstanding, getFieldContext, takeScreenshot, inspectCanvas,
35
- // Input schemas only (all outputs are XML strings now)
36
- ListPagesInputSchema, ClosePageInputSchema, CloseSessionInputSchema, NavigateInputSchema, GoBackInputSchema, GoForwardInputSchema, ReloadInputSchema, CaptureSnapshotInputSchema, FindElementsInputSchema, GetNodeDetailsInputSchema, ScrollElementIntoViewInputSchemaBase, ScrollPageInputSchema, ClickInputSchemaBase, TypeInputSchemaBase, PressInputSchema, SelectInputSchemaBase, HoverInputSchemaBase, DragInputSchemaBase, WheelInputSchemaBase, GetFormUnderstandingInputSchema, GetFieldContextInputSchema, TakeScreenshotInputSchemaBase, InspectCanvasInputSchemaBase, } from './tools/index.js';
37
- /**
38
- * Wrap a tool handler with lazy browser initialization.
39
- * Works with both sync and async handlers - sync return values are automatically
40
- * wrapped in a resolved promise by the async function.
41
- * Includes error context logging when browser initialization fails.
42
- */
43
- function withLazyInit(handler, toolName) {
44
- return async (input) => {
45
- try {
46
- await ensureBrowserForTools();
47
- }
48
- catch (error) {
49
- const config = getServerConfig();
50
- const mode = config.autoConnect
51
- ? 'autoConnect'
52
- : config.browserUrl || config.wsEndpoint
53
- ? 'connect'
54
- : 'launch';
55
- logger.error('Browser initialization failed during tool execution', error instanceof Error ? error : undefined, {
56
- tool: toolName,
57
- mode,
58
- headless: config.headless,
59
- autoConnect: config.autoConnect,
60
- browserUrl: config.browserUrl,
61
- wsEndpoint: config.wsEndpoint,
62
- });
63
- throw error;
64
- }
65
- return handler(input);
66
- };
67
- }
10
+ import { VERSION } from './shared/version.js';
11
+ import { SessionRouter } from './gateway/session-router.js';
12
+ import { registerAllTools } from './tools/tool-registration.js';
68
13
  /**
69
14
  * Initialize all services and start the server
70
15
  */
@@ -72,183 +17,35 @@ function initializeServer() {
72
17
  // Parse CLI arguments and initialize server configuration
73
18
  initServerConfig(process.argv.slice(2));
74
19
  // Create MCP server shell
75
- // Note: Don't pass tools/logging capabilities - McpServer registers them automatically
76
- // when tools are registered via .tool() or .registerTool()
77
20
  const server = new BrowserAutomationServer({
78
21
  name: 'agent-web-interface',
79
- version: '3.0.0',
80
- });
81
- // Wire SessionStore to MCP lifecycle events
82
- server.on('session:start', (event) => {
83
- const { clientInfo } = event;
84
- const sessionId = sessionStore.createSession(clientInfo?.name ?? 'unknown', clientInfo);
85
- const session = sessionStore.getSession(sessionId);
86
- // Route session start through the isolation binding.
87
- // Browser init is lazy (first tool call), so context creation may fail here
88
- // if the browser isn't launched yet. That's OK — the tool's withLazyInit
89
- // will ensure the browser is ready before any real work happens.
90
- sessionBinding
91
- .onSessionStart(sessionId, getSessionManager())
92
- .then((result) => {
93
- if (result.browserContext) {
94
- session.browser_context = result.browserContext;
95
- }
96
- })
97
- .catch((err) => {
98
- logger.error('Failed to initialize session isolation', err instanceof Error ? err : undefined, { sessionId, isolationMode });
99
- });
22
+ version: VERSION,
100
23
  });
101
- server.on('session:end', () => {
102
- const session = sessionStore.getDefaultSession();
103
- if (session) {
104
- sessionBinding.onSessionEnd(session.session_id);
105
- void sessionStore.destroySession(session.session_id);
106
- }
107
- });
108
- // Initialize session manager and tools
109
- const session = getSessionManager();
110
- initializeToolContext(session);
111
- // ============================================================================
112
- // SESSION TOOLS
113
- // ============================================================================
114
- server.registerTool('list_pages', {
115
- title: 'List Pages',
116
- description: 'List all open browser pages with their page_id, URL, and title.',
117
- inputSchema: ListPagesInputSchema.shape,
118
- }, withLazyInit(listPages, 'list_pages'));
119
- server.registerTool('close_page', {
120
- title: 'Close Page',
121
- description: 'Close a browser tab. Use list_pages first to get the page_id.',
122
- inputSchema: ClosePageInputSchema.shape,
123
- }, withLazyInit(closePage, 'close_page'));
124
- server.registerTool('close_session', {
125
- title: 'Close Session',
126
- description: 'Close the entire browser and clear all state.',
127
- inputSchema: CloseSessionInputSchema.shape,
128
- }, withLazyInit(closeSession, 'close_session'));
129
- // ============================================================================
130
- // NAVIGATION TOOLS
131
- // ============================================================================
132
- server.registerTool('navigate', {
133
- title: 'Navigate',
134
- description: 'Go to a URL. Returns page snapshot with interactive elements.',
135
- inputSchema: NavigateInputSchema.shape,
136
- }, withLazyInit(navigate, 'navigate'));
137
- server.registerTool('go_back', {
138
- title: 'Go Back',
139
- description: 'Go back one page in browser history.',
140
- inputSchema: GoBackInputSchema.shape,
141
- }, withLazyInit(goBack, 'go_back'));
142
- server.registerTool('go_forward', {
143
- title: 'Go Forward',
144
- description: 'Go forward one page in browser history.',
145
- inputSchema: GoForwardInputSchema.shape,
146
- }, withLazyInit(goForward, 'go_forward'));
147
- server.registerTool('reload', {
148
- title: 'Reload',
149
- description: 'Refresh the current page.',
150
- inputSchema: ReloadInputSchema.shape,
151
- }, withLazyInit(reload, 'reload'));
152
- server.registerTool('snapshot', {
153
- title: 'Snapshot',
154
- description: 'Re-capture the page state without performing any action. Use when the page may have changed on its own (timers, live updates, animations).',
155
- inputSchema: CaptureSnapshotInputSchema.shape,
156
- }, withLazyInit(captureSnapshot, 'snapshot'));
157
- // ============================================================================
158
- // OBSERVATION TOOLS
159
- // ============================================================================
160
- server.registerTool('find', {
161
- title: 'Find',
162
- description: 'Search for interactive elements OR read page text content. Filter by `kind` (button, link, textbox, canvas), `label` (case-insensitive substring match), or `region` (header, main, footer).',
163
- inputSchema: FindElementsInputSchema.shape,
164
- }, withLazyInit(findElements, 'find'));
165
- server.registerTool('get_element', {
166
- title: 'Get Element',
167
- description: 'Get complete details for one element: exact position, size, state, attributes.',
168
- inputSchema: GetNodeDetailsInputSchema.shape,
169
- }, withLazyInit(getNodeDetails, 'get_element'));
170
- server.registerTool('screenshot', {
171
- title: 'Screenshot',
172
- description: 'Capture a screenshot of the current page or a specific element.',
173
- inputSchema: TakeScreenshotInputSchemaBase.shape,
174
- }, withLazyInit(takeScreenshot, 'screenshot'));
175
- // ============================================================================
176
- // INTERACTION TOOLS
177
- // ============================================================================
178
- server.registerTool('scroll_to', {
179
- title: 'Scroll To',
180
- description: 'Scroll until a specific element is visible in the viewport.',
181
- inputSchema: ScrollElementIntoViewInputSchemaBase.shape,
182
- }, withLazyInit(scrollElementIntoView, 'scroll_to'));
183
- server.registerTool('scroll', {
184
- title: 'Scroll',
185
- description: 'Scroll the viewport up or down by pixels.',
186
- inputSchema: ScrollPageInputSchema.shape,
187
- }, withLazyInit(scrollPage, 'scroll'));
188
- server.registerTool('click', {
189
- title: 'Click Element',
190
- description: 'Click an element or at viewport coordinates.',
191
- inputSchema: ClickInputSchemaBase.shape,
192
- }, withLazyInit(click, 'click'));
193
- server.registerTool('type', {
194
- title: 'Type Text',
195
- description: 'Type text into an input field or text area.',
196
- inputSchema: TypeInputSchemaBase.shape,
197
- }, withLazyInit(type, 'type'));
198
- server.registerTool('press', {
199
- title: 'Press Key',
200
- description: 'Press a keyboard key with optional modifiers.',
201
- inputSchema: PressInputSchema.shape,
202
- }, withLazyInit(press, 'press'));
203
- server.registerTool('select', {
204
- title: 'Select Option',
205
- description: 'Choose an option from a dropdown menu by value or visible text.',
206
- inputSchema: SelectInputSchemaBase.shape,
207
- }, withLazyInit(select, 'select'));
208
- server.registerTool('hover', {
209
- title: 'Hover Element',
210
- description: 'Move mouse over an element without clicking. Triggers hover menus and tooltips.',
211
- inputSchema: HoverInputSchemaBase.shape,
212
- }, withLazyInit(hover, 'hover'));
213
- server.registerTool('drag', {
214
- title: 'Drag',
215
- description: 'Drag from one point to another.',
216
- inputSchema: DragInputSchemaBase.shape,
217
- }, withLazyInit(drag, 'drag'));
218
- server.registerTool('wheel', {
219
- title: 'Wheel',
220
- description: 'Dispatch a mouse wheel event at specific coordinates. Use for scroll-to-zoom (with Control modifier) or horizontal scrolling.',
221
- inputSchema: WheelInputSchemaBase.shape,
222
- }, withLazyInit(wheel, 'wheel'));
223
- // ============================================================================
224
- // CANVAS INSPECTION TOOLS
225
- // ============================================================================
226
- server.registerTool('inspect_canvas', {
227
- title: 'Inspect Canvas',
228
- description: 'Analyze a canvas element: auto-detect the rendering library, query its scene graph, and return an annotated screenshot with coordinate grid overlay.',
229
- inputSchema: InspectCanvasInputSchemaBase.shape,
230
- }, withLazyInit(inspectCanvas, 'inspect_canvas'));
231
- // ============================================================================
232
- // FORM UNDERSTANDING TOOLS
233
- // ============================================================================
234
- server.registerTool('get_form', {
235
- title: 'Get Form',
236
- description: 'Analyze all forms on the page: fields, required inputs, validation rules, and field dependencies.',
237
- inputSchema: GetFormUnderstandingInputSchema.shape,
238
- }, withLazyInit(getFormUnderstanding, 'get_form'));
239
- server.registerTool('get_field', {
240
- title: 'Get Field',
241
- description: 'Get detailed info about one form field: purpose, valid input formats, dependencies, and suggested values.',
242
- inputSchema: GetFieldContextInputSchema.shape,
243
- }, withLazyInit(getFieldContext, 'get_field'));
244
- return server;
24
+ // Create session router (stdio mode — implicit single session)
25
+ const router = new SessionRouter();
26
+ // Register all browser automation tools
27
+ // Browser init is session-scoped: each SessionController owns its own
28
+ // SessionManager and lazily launches/connects via ctx.ensureBrowser().
29
+ registerAllTools(server, () => router.resolve());
30
+ return { server, router };
245
31
  }
246
32
  /**
247
33
  * Main entry point
248
34
  */
249
35
  async function main() {
250
36
  try {
251
- const server = initializeServer();
37
+ // Check for HTTP transport mode before initializing the stdio server.
38
+ // We parse early to detect the transport flag, then delegate to http-entry.
39
+ const transportIdx = process.argv.indexOf('--transport');
40
+ const transportArg = transportIdx !== -1 ? process.argv[transportIdx + 1] : undefined;
41
+ const isHttp = transportArg === 'http' || process.env.TRANSPORT === 'http';
42
+ if (isHttp) {
43
+ // Initialize config first so http-entry can read it
44
+ initServerConfig(process.argv.slice(2));
45
+ const { main: httpMain } = await import('./http-entry.js');
46
+ return await httpMain();
47
+ }
48
+ const { server, router } = initializeServer();
252
49
  await server.start();
253
50
  // Handle shutdown gracefully
254
51
  const shutdown = (signal) => {
@@ -256,11 +53,7 @@ async function main() {
256
53
  void (async () => {
257
54
  try {
258
55
  await cleanupTempFiles();
259
- // Shutdown browser session first (only if initialized)
260
- if (isSessionManagerInitialized()) {
261
- const session = getSessionManager();
262
- await session.shutdown();
263
- }
56
+ await router.shutdown();
264
57
  await server.stop();
265
58
  process.exit(0);
266
59
  }