@midscene/shared 1.9.8-beta-20260618014851.0 → 1.9.8

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 (75) hide show
  1. package/dist/es/cli/cli-runner.mjs +1 -1
  2. package/dist/es/env/parse-model-config.mjs +1 -1
  3. package/dist/es/env/types.mjs +5 -3
  4. package/dist/es/mcp/base-server.mjs +295 -0
  5. package/dist/es/{agent-tools → mcp}/base-tools.mjs +8 -1
  6. package/dist/es/{agent-tools → mcp}/chrome-path.mjs +3 -14
  7. package/dist/es/{agent-tools → mcp}/index.mjs +3 -0
  8. package/dist/es/mcp/inject-report-html-plugin.mjs +53 -0
  9. package/dist/es/mcp/launcher-helper.mjs +52 -0
  10. package/dist/es/{agent-tools → mcp}/tool-generator.mjs +3 -3
  11. package/dist/es/utils.mjs +6 -2
  12. package/dist/lib/cli/cli-runner.js +1 -1
  13. package/dist/lib/env/parse-model-config.js +1 -1
  14. package/dist/lib/env/types.js +10 -5
  15. package/dist/lib/mcp/base-server.js +345 -0
  16. package/dist/lib/{agent-tools → mcp}/base-tools.js +8 -1
  17. package/dist/lib/{agent-tools → mcp}/chrome-path.js +2 -13
  18. package/dist/lib/{agent-tools → mcp}/index.js +37 -16
  19. package/dist/lib/mcp/inject-report-html-plugin.js +98 -0
  20. package/dist/lib/mcp/launcher-helper.js +86 -0
  21. package/dist/lib/{agent-tools → mcp}/tool-generator.js +3 -3
  22. package/dist/lib/utils.js +15 -8
  23. package/dist/types/cli/cli-args.d.ts +1 -1
  24. package/dist/types/cli/cli-runner.d.ts +2 -2
  25. package/dist/types/env/types.d.ts +6 -8
  26. package/dist/types/key-alias-utils.d.ts +2 -2
  27. package/dist/types/mcp/base-server.d.ts +106 -0
  28. package/dist/types/{agent-tools → mcp}/base-tools.d.ts +13 -7
  29. package/dist/types/{agent-tools → mcp}/index.d.ts +3 -0
  30. package/dist/types/{agent-tools → mcp}/init-arg-utils.d.ts +3 -3
  31. package/dist/types/mcp/inject-report-html-plugin.d.ts +18 -0
  32. package/dist/types/mcp/launcher-helper.d.ts +94 -0
  33. package/dist/types/{agent-tools → mcp}/tool-defaults.d.ts +6 -5
  34. package/dist/types/{agent-tools → mcp}/tool-generator.d.ts +1 -1
  35. package/dist/types/{agent-tools → mcp}/types.d.ts +9 -4
  36. package/dist/types/utils.d.ts +1 -0
  37. package/package.json +8 -15
  38. package/src/cli/cli-args.ts +1 -1
  39. package/src/cli/cli-runner.ts +4 -4
  40. package/src/env/types.ts +5 -5
  41. package/src/key-alias-utils.ts +2 -2
  42. package/src/mcp/base-server.ts +529 -0
  43. package/src/{agent-tools → mcp}/base-tools.ts +33 -8
  44. package/src/{agent-tools → mcp}/chrome-path.ts +3 -20
  45. package/src/{agent-tools → mcp}/index.ts +3 -0
  46. package/src/{agent-tools → mcp}/init-arg-utils.ts +3 -3
  47. package/src/mcp/inject-report-html-plugin.ts +119 -0
  48. package/src/mcp/launcher-helper.ts +200 -0
  49. package/src/{agent-tools → mcp}/tool-defaults.ts +6 -5
  50. package/src/{agent-tools → mcp}/tool-generator.ts +6 -6
  51. package/src/{agent-tools → mcp}/types.ts +9 -4
  52. package/src/utils.ts +10 -1
  53. /package/dist/es/{agent-tools → mcp}/agent-behavior-init-args.mjs +0 -0
  54. /package/dist/es/{agent-tools → mcp}/cli-report-session.mjs +0 -0
  55. /package/dist/es/{agent-tools → mcp}/error-formatter.mjs +0 -0
  56. /package/dist/es/{agent-tools → mcp}/init-arg-utils.mjs +0 -0
  57. /package/dist/es/{agent-tools → mcp}/tool-defaults.mjs +0 -0
  58. /package/dist/es/{agent-tools → mcp}/types.mjs +0 -0
  59. /package/dist/es/{agent-tools → mcp}/user-prompt.mjs +0 -0
  60. /package/dist/lib/{agent-tools → mcp}/agent-behavior-init-args.js +0 -0
  61. /package/dist/lib/{agent-tools → mcp}/cli-report-session.js +0 -0
  62. /package/dist/lib/{agent-tools → mcp}/error-formatter.js +0 -0
  63. /package/dist/lib/{agent-tools → mcp}/init-arg-utils.js +0 -0
  64. /package/dist/lib/{agent-tools → mcp}/tool-defaults.js +0 -0
  65. /package/dist/lib/{agent-tools → mcp}/types.js +0 -0
  66. /package/dist/lib/{agent-tools → mcp}/user-prompt.js +0 -0
  67. /package/dist/types/{agent-tools → mcp}/agent-behavior-init-args.d.ts +0 -0
  68. /package/dist/types/{agent-tools → mcp}/chrome-path.d.ts +0 -0
  69. /package/dist/types/{agent-tools → mcp}/cli-report-session.d.ts +0 -0
  70. /package/dist/types/{agent-tools → mcp}/error-formatter.d.ts +0 -0
  71. /package/dist/types/{agent-tools → mcp}/user-prompt.d.ts +0 -0
  72. /package/src/{agent-tools → mcp}/agent-behavior-init-args.ts +0 -0
  73. /package/src/{agent-tools → mcp}/cli-report-session.ts +0 -0
  74. /package/src/{agent-tools → mcp}/error-formatter.ts +0 -0
  75. /package/src/{agent-tools → mcp}/user-prompt.ts +0 -0
@@ -36,7 +36,6 @@ __webpack_require__.d(__webpack_exports__, {
36
36
  MIDSCENE_ANDROID_IME_STRATEGY: ()=>MIDSCENE_ANDROID_IME_STRATEGY,
37
37
  MIDSCENE_CACHE: ()=>MIDSCENE_CACHE,
38
38
  MIDSCENE_CACHE_MAX_FILENAME_LENGTH: ()=>MIDSCENE_CACHE_MAX_FILENAME_LENGTH,
39
- MIDSCENE_CHROME_PATH: ()=>MIDSCENE_CHROME_PATH,
40
39
  MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG: ()=>MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG,
41
40
  MIDSCENE_DEBUG_MODE: ()=>MIDSCENE_DEBUG_MODE,
42
41
  MIDSCENE_DEBUG_MODEL_PROFILE: ()=>MIDSCENE_DEBUG_MODEL_PROFILE,
@@ -61,7 +60,9 @@ __webpack_require__.d(__webpack_exports__, {
61
60
  MIDSCENE_IOS_SIMULATOR_UDID: ()=>MIDSCENE_IOS_SIMULATOR_UDID,
62
61
  MIDSCENE_LANGFUSE_DEBUG: ()=>MIDSCENE_LANGFUSE_DEBUG,
63
62
  MIDSCENE_LANGSMITH_DEBUG: ()=>MIDSCENE_LANGSMITH_DEBUG,
63
+ MIDSCENE_MCP_ANDROID_MODE: ()=>MIDSCENE_MCP_ANDROID_MODE,
64
64
  MIDSCENE_MCP_CHROME_PATH: ()=>MIDSCENE_MCP_CHROME_PATH,
65
+ MIDSCENE_MCP_USE_PUPPETEER_MODE: ()=>MIDSCENE_MCP_USE_PUPPETEER_MODE,
65
66
  MIDSCENE_MODEL_API_KEY: ()=>MIDSCENE_MODEL_API_KEY,
66
67
  MIDSCENE_MODEL_BASE_URL: ()=>MIDSCENE_MODEL_BASE_URL,
67
68
  MIDSCENE_MODEL_EXTRA_BODY_JSON: ()=>MIDSCENE_MODEL_EXTRA_BODY_JSON,
@@ -122,8 +123,9 @@ const MIDSCENE_DEBUG_MODEL_PROFILE = 'MIDSCENE_DEBUG_MODEL_PROFILE';
122
123
  const MIDSCENE_DEBUG_MODEL_RESPONSE = 'MIDSCENE_DEBUG_MODEL_RESPONSE';
123
124
  const MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG = 'MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG';
124
125
  const MIDSCENE_DEBUG_MODE = 'MIDSCENE_DEBUG_MODE';
125
- const MIDSCENE_CHROME_PATH = 'MIDSCENE_CHROME_PATH';
126
+ const MIDSCENE_MCP_USE_PUPPETEER_MODE = 'MIDSCENE_MCP_USE_PUPPETEER_MODE';
126
127
  const MIDSCENE_MCP_CHROME_PATH = 'MIDSCENE_MCP_CHROME_PATH';
128
+ const MIDSCENE_MCP_ANDROID_MODE = 'MIDSCENE_MCP_ANDROID_MODE';
127
129
  const DOCKER_CONTAINER = 'DOCKER_CONTAINER';
128
130
  const MIDSCENE_LANGSMITH_DEBUG = 'MIDSCENE_LANGSMITH_DEBUG';
129
131
  const MIDSCENE_LANGFUSE_DEBUG = 'MIDSCENE_LANGFUSE_DEBUG';
@@ -206,6 +208,8 @@ const BASIC_ENV_KEYS = [
206
208
  ];
207
209
  const BOOLEAN_ENV_KEYS = [
208
210
  MIDSCENE_CACHE,
211
+ MIDSCENE_MCP_USE_PUPPETEER_MODE,
212
+ MIDSCENE_MCP_ANDROID_MODE,
209
213
  MIDSCENE_LANGSMITH_DEBUG,
210
214
  MIDSCENE_LANGFUSE_DEBUG,
211
215
  MIDSCENE_REPORT_QUIET
@@ -224,7 +228,6 @@ const STRING_ENV_KEYS = [
224
228
  MIDSCENE_REPORT_TAG_NAME,
225
229
  MIDSCENE_PREFERRED_LANGUAGE,
226
230
  MATCH_BY_POSITION,
227
- MIDSCENE_CHROME_PATH,
228
231
  MIDSCENE_MCP_CHROME_PATH,
229
232
  DOCKER_CONTAINER
230
233
  ];
@@ -335,7 +338,6 @@ exports.MIDSCENE_ADB_REMOTE_PORT = __webpack_exports__.MIDSCENE_ADB_REMOTE_PORT;
335
338
  exports.MIDSCENE_ANDROID_IME_STRATEGY = __webpack_exports__.MIDSCENE_ANDROID_IME_STRATEGY;
336
339
  exports.MIDSCENE_CACHE = __webpack_exports__.MIDSCENE_CACHE;
337
340
  exports.MIDSCENE_CACHE_MAX_FILENAME_LENGTH = __webpack_exports__.MIDSCENE_CACHE_MAX_FILENAME_LENGTH;
338
- exports.MIDSCENE_CHROME_PATH = __webpack_exports__.MIDSCENE_CHROME_PATH;
339
341
  exports.MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG = __webpack_exports__.MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG;
340
342
  exports.MIDSCENE_DEBUG_MODE = __webpack_exports__.MIDSCENE_DEBUG_MODE;
341
343
  exports.MIDSCENE_DEBUG_MODEL_PROFILE = __webpack_exports__.MIDSCENE_DEBUG_MODEL_PROFILE;
@@ -360,7 +362,9 @@ exports.MIDSCENE_IOS_DEVICE_UDID = __webpack_exports__.MIDSCENE_IOS_DEVICE_UDID;
360
362
  exports.MIDSCENE_IOS_SIMULATOR_UDID = __webpack_exports__.MIDSCENE_IOS_SIMULATOR_UDID;
361
363
  exports.MIDSCENE_LANGFUSE_DEBUG = __webpack_exports__.MIDSCENE_LANGFUSE_DEBUG;
362
364
  exports.MIDSCENE_LANGSMITH_DEBUG = __webpack_exports__.MIDSCENE_LANGSMITH_DEBUG;
365
+ exports.MIDSCENE_MCP_ANDROID_MODE = __webpack_exports__.MIDSCENE_MCP_ANDROID_MODE;
363
366
  exports.MIDSCENE_MCP_CHROME_PATH = __webpack_exports__.MIDSCENE_MCP_CHROME_PATH;
367
+ exports.MIDSCENE_MCP_USE_PUPPETEER_MODE = __webpack_exports__.MIDSCENE_MCP_USE_PUPPETEER_MODE;
364
368
  exports.MIDSCENE_MODEL_API_KEY = __webpack_exports__.MIDSCENE_MODEL_API_KEY;
365
369
  exports.MIDSCENE_MODEL_BASE_URL = __webpack_exports__.MIDSCENE_MODEL_BASE_URL;
366
370
  exports.MIDSCENE_MODEL_EXTRA_BODY_JSON = __webpack_exports__.MIDSCENE_MODEL_EXTRA_BODY_JSON;
@@ -426,7 +430,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
426
430
  "MIDSCENE_ANDROID_IME_STRATEGY",
427
431
  "MIDSCENE_CACHE",
428
432
  "MIDSCENE_CACHE_MAX_FILENAME_LENGTH",
429
- "MIDSCENE_CHROME_PATH",
430
433
  "MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG",
431
434
  "MIDSCENE_DEBUG_MODE",
432
435
  "MIDSCENE_DEBUG_MODEL_PROFILE",
@@ -451,7 +454,9 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
451
454
  "MIDSCENE_IOS_SIMULATOR_UDID",
452
455
  "MIDSCENE_LANGFUSE_DEBUG",
453
456
  "MIDSCENE_LANGSMITH_DEBUG",
457
+ "MIDSCENE_MCP_ANDROID_MODE",
454
458
  "MIDSCENE_MCP_CHROME_PATH",
459
+ "MIDSCENE_MCP_USE_PUPPETEER_MODE",
455
460
  "MIDSCENE_MODEL_API_KEY",
456
461
  "MIDSCENE_MODEL_BASE_URL",
457
462
  "MIDSCENE_MODEL_EXTRA_BODY_JSON",
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ CLI_ARGS_CONFIG: ()=>CLI_ARGS_CONFIG,
37
+ launchMCPServer: ()=>launchMCPServer,
38
+ BaseMCPServer: ()=>BaseMCPServer
39
+ });
40
+ const external_node_crypto_namespaceObject = require("node:crypto");
41
+ const utils_namespaceObject = require("@midscene/shared/utils");
42
+ const mcp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/mcp.js");
43
+ const stdio_js_namespaceObject = require("@modelcontextprotocol/sdk/server/stdio.js");
44
+ const streamableHttp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
45
+ const external_express_namespaceObject = require("express");
46
+ var external_express_default = /*#__PURE__*/ __webpack_require__.n(external_express_namespaceObject);
47
+ const external_error_formatter_js_namespaceObject = require("./error-formatter.js");
48
+ const external_tool_defaults_js_namespaceObject = require("./tool-defaults.js");
49
+ function _define_property(obj, key, value) {
50
+ if (key in obj) Object.defineProperty(obj, key, {
51
+ value: value,
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true
55
+ });
56
+ else obj[key] = value;
57
+ return obj;
58
+ }
59
+ const CLI_ARGS_CONFIG = {
60
+ mode: {
61
+ type: 'string',
62
+ default: 'stdio'
63
+ },
64
+ port: {
65
+ type: 'string',
66
+ default: '3000'
67
+ },
68
+ host: {
69
+ type: 'string',
70
+ default: 'localhost'
71
+ },
72
+ ...Object.fromEntries(external_tool_defaults_js_namespaceObject.TOOL_BEHAVIOR_FLAGS.map((flag)=>[
73
+ flag.cli,
74
+ {
75
+ type: 'boolean'
76
+ }
77
+ ]))
78
+ };
79
+ function launchMCPServer(server, args) {
80
+ server.setToolDefaults((0, external_tool_defaults_js_namespaceObject.resolveToolDefaults)((cli)=>true === args[cli]));
81
+ if ('http' === args.mode) return server.launchHttp({
82
+ port: Number.parseInt(args.port || '3000', 10),
83
+ host: args.host || 'localhost'
84
+ });
85
+ return server.launch();
86
+ }
87
+ const SESSION_TIMEOUT_MS = 1800000;
88
+ const CLEANUP_INTERVAL_MS = 300000;
89
+ const MAX_SESSIONS = 100;
90
+ class BaseMCPServer {
91
+ setToolDefaults(toolDefaults) {
92
+ this.toolDefaults = (0, external_tool_defaults_js_namespaceObject.mergeToolDefaults)(this.toolDefaults, toolDefaults);
93
+ }
94
+ async initializeToolsManager() {
95
+ (0, utils_namespaceObject.setIsMcp)(true);
96
+ this.toolsManager = this.providedToolsManager || this.createToolsManager();
97
+ this.toolsManager.setToolDefaults?.(this.toolDefaults);
98
+ try {
99
+ await this.toolsManager.initTools();
100
+ } catch (error) {
101
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
102
+ console.error(`Failed to initialize tools: ${message}`);
103
+ console.error('Tools will be initialized on first use');
104
+ }
105
+ this.toolsManager.attachToServer(this.mcpServer);
106
+ }
107
+ async performCleanup() {
108
+ console.error(`${this.config.name} closing...`);
109
+ this.mcpServer.close();
110
+ await this.toolsManager?.destroy?.().catch(console.error);
111
+ }
112
+ async launch() {
113
+ console.log = (...args)=>{
114
+ console.error('[LOG]', ...args);
115
+ };
116
+ console.info = (...args)=>{
117
+ console.error('[INFO]', ...args);
118
+ };
119
+ console.debug = (...args)=>{
120
+ console.error('[DEBUG]', ...args);
121
+ };
122
+ await this.initializeToolsManager();
123
+ const transport = new stdio_js_namespaceObject.StdioServerTransport();
124
+ try {
125
+ await this.mcpServer.connect(transport);
126
+ } catch (error) {
127
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
128
+ console.error(`Failed to connect MCP stdio transport: ${message}`);
129
+ throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
130
+ }
131
+ let isShuttingDown = false;
132
+ const cleanup = ()=>{
133
+ if (isShuttingDown) return;
134
+ isShuttingDown = true;
135
+ console.error(`${this.config.name} shutting down...`);
136
+ this.performCleanup().finally(()=>process.exit(0));
137
+ };
138
+ process.on('uncaughtException', (error)=>{
139
+ if ('EPIPE' === error.code || 'ERR_STREAM_DESTROYED' === error.code) return void cleanup();
140
+ console.error(`[${this.config.name}] Uncaught Exception:`, error);
141
+ console.error('Stack:', error.stack);
142
+ });
143
+ process.on('unhandledRejection', (reason)=>{
144
+ console.error(`[${this.config.name}] Unhandled Rejection:`, reason);
145
+ if (reason instanceof Error) console.error('Stack:', reason.stack);
146
+ });
147
+ process.stdin.on('close', cleanup);
148
+ process.stdin.on('end', cleanup);
149
+ process.stdout.on('error', cleanup);
150
+ process.once('SIGINT', cleanup);
151
+ process.once('SIGTERM', cleanup);
152
+ process.once('SIGHUP', cleanup);
153
+ return {
154
+ close: async ()=>{
155
+ this.performCleanup();
156
+ }
157
+ };
158
+ }
159
+ async launchHttp(options) {
160
+ if (!Number.isInteger(options.port) || options.port < 1 || options.port > 65535) throw new Error(`Invalid port number: ${options.port}. Port must be between 1 and 65535.`);
161
+ await this.initializeToolsManager();
162
+ const app = external_express_default()();
163
+ app.use(external_express_default().json({
164
+ limit: '10mb'
165
+ }));
166
+ const sessions = new Map();
167
+ app.all('/mcp', async (req, res)=>{
168
+ const startTime = Date.now();
169
+ const requestId = (0, external_node_crypto_namespaceObject.randomUUID)().substring(0, 8);
170
+ try {
171
+ const rawSessionId = req.headers['mcp-session-id'];
172
+ const sessionId = Array.isArray(rawSessionId) ? rawSessionId[0] : rawSessionId;
173
+ let session = sessionId ? sessions.get(sessionId) : void 0;
174
+ if (!session && 'POST' === req.method) {
175
+ if (sessions.size >= MAX_SESSIONS) {
176
+ console.error(`[${new Date().toISOString()}] [${requestId}] Session limit reached: ${sessions.size}/${MAX_SESSIONS}`);
177
+ res.status(503).json({
178
+ error: 'Too many active sessions',
179
+ message: 'Server is at maximum capacity. Please try again later.'
180
+ });
181
+ return;
182
+ }
183
+ session = await this.createHttpSession(sessions);
184
+ console.log(`[${new Date().toISOString()}] [${requestId}] New session created: ${session.transport.sessionId}`);
185
+ }
186
+ if (session) {
187
+ session.lastAccessedAt = new Date();
188
+ await session.transport.handleRequest(req, res, req.body);
189
+ const duration = Date.now() - startTime;
190
+ console.log(`[${new Date().toISOString()}] [${requestId}] Request completed in ${duration}ms`);
191
+ } else {
192
+ console.error(`[${new Date().toISOString()}] [${requestId}] Invalid session or GET without session`);
193
+ res.status(400).json({
194
+ error: 'Invalid session or GET without session'
195
+ });
196
+ }
197
+ } catch (error) {
198
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
199
+ const duration = Date.now() - startTime;
200
+ console.error(`[${new Date().toISOString()}] [${requestId}] MCP request error after ${duration}ms: ${message}`);
201
+ if (!res.headersSent) res.status(500).json({
202
+ error: 'Internal server error',
203
+ message: 'Failed to process MCP request'
204
+ });
205
+ }
206
+ });
207
+ const host = options.host || 'localhost';
208
+ const server = app.listen(options.port, host, ()=>{
209
+ console.log(`${this.config.name} HTTP server listening on http://${host}:${options.port}/mcp`);
210
+ }).on('error', (error)=>{
211
+ if ('EADDRINUSE' === error.code) console.error(`ERROR: Port ${options.port} is already in use.\nPlease try a different port: --port=<number>\nExample: --mode=http --port=${options.port + 1}`);
212
+ else if ('EACCES' === error.code) console.error(`ERROR: Permission denied to bind to port ${options.port}.\nPorts below 1024 require root/admin privileges.\nPlease use a port above 1024 or run with elevated privileges.`);
213
+ else console.error(`ERROR: Failed to start HTTP server on ${host}:${options.port}\nReason: ${error.message}\nCode: ${error.code || 'unknown'}`);
214
+ process.exit(1);
215
+ });
216
+ const cleanupInterval = this.startSessionCleanup(sessions);
217
+ this.setupHttpShutdownHandlers(server, sessions, cleanupInterval);
218
+ return {
219
+ port: options.port,
220
+ host,
221
+ close: async ()=>{
222
+ clearInterval(cleanupInterval);
223
+ for (const session of sessions.values())try {
224
+ await session.transport.close();
225
+ } catch (error) {
226
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
227
+ console.error(`Failed to close session ${session.transport.sessionId}: ${message}`);
228
+ }
229
+ sessions.clear();
230
+ return new Promise((resolve)=>{
231
+ server.close(async (err)=>{
232
+ if (err) console.error('Error closing HTTP server:', err);
233
+ await this.performCleanup();
234
+ resolve();
235
+ });
236
+ });
237
+ }
238
+ };
239
+ }
240
+ async createHttpSession(sessions) {
241
+ const transport = new streamableHttp_js_namespaceObject.StreamableHTTPServerTransport({
242
+ sessionIdGenerator: ()=>(0, external_node_crypto_namespaceObject.randomUUID)(),
243
+ onsessioninitialized: (sid)=>{
244
+ sessions.set(sid, {
245
+ transport,
246
+ createdAt: new Date(),
247
+ lastAccessedAt: new Date()
248
+ });
249
+ console.log(`[${new Date().toISOString()}] Session ${sid} initialized (total: ${sessions.size})`);
250
+ }
251
+ });
252
+ transport.onclose = ()=>{
253
+ if (transport.sessionId) {
254
+ sessions.delete(transport.sessionId);
255
+ console.log(`[${new Date().toISOString()}] Session ${transport.sessionId} closed (remaining: ${sessions.size})`);
256
+ }
257
+ };
258
+ try {
259
+ await this.mcpServer.connect(transport);
260
+ } catch (error) {
261
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
262
+ console.error(`[${new Date().toISOString()}] Failed to connect MCP transport: ${message}`);
263
+ if (transport.sessionId) sessions.delete(transport.sessionId);
264
+ throw new Error(`Failed to initialize MCP session: ${message}`);
265
+ }
266
+ return {
267
+ transport,
268
+ createdAt: new Date(),
269
+ lastAccessedAt: new Date()
270
+ };
271
+ }
272
+ startSessionCleanup(sessions) {
273
+ return setInterval(()=>{
274
+ const now = Date.now();
275
+ for (const [sid, session] of sessions)if (now - session.lastAccessedAt.getTime() > SESSION_TIMEOUT_MS) try {
276
+ session.transport.close();
277
+ sessions.delete(sid);
278
+ console.log(`[${new Date().toISOString()}] Session ${sid} cleaned up due to inactivity (remaining: ${sessions.size})`);
279
+ } catch (error) {
280
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
281
+ console.error(`[${new Date().toISOString()}] Failed to close session ${sid} during cleanup: ${message}`);
282
+ sessions.delete(sid);
283
+ }
284
+ }, CLEANUP_INTERVAL_MS);
285
+ }
286
+ setupHttpShutdownHandlers(server, sessions, cleanupInterval) {
287
+ const cleanup = ()=>{
288
+ console.error(`${this.config.name} shutting down...`);
289
+ clearInterval(cleanupInterval);
290
+ for (const session of sessions.values())try {
291
+ session.transport.close();
292
+ } catch (error) {
293
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
294
+ console.error(`Error closing session during shutdown: ${message}`);
295
+ }
296
+ sessions.clear();
297
+ try {
298
+ server.close(()=>{
299
+ this.performCleanup().finally(()=>process.exit(0));
300
+ });
301
+ setTimeout(()=>{
302
+ console.error('Forcefully shutting down after timeout');
303
+ this.performCleanup().finally(()=>process.exit(1));
304
+ }, 5000);
305
+ } catch (error) {
306
+ const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
307
+ console.error(`Error closing HTTP server: ${message}`);
308
+ this.performCleanup().finally(()=>process.exit(1));
309
+ }
310
+ };
311
+ process.once('SIGINT', cleanup);
312
+ process.once('SIGTERM', cleanup);
313
+ }
314
+ getServer() {
315
+ return this.mcpServer;
316
+ }
317
+ getToolsManager() {
318
+ return this.toolsManager;
319
+ }
320
+ constructor(config, toolsManager){
321
+ _define_property(this, "mcpServer", void 0);
322
+ _define_property(this, "toolsManager", void 0);
323
+ _define_property(this, "config", void 0);
324
+ _define_property(this, "providedToolsManager", void 0);
325
+ _define_property(this, "toolDefaults", {});
326
+ this.config = config;
327
+ this.mcpServer = new mcp_js_namespaceObject.McpServer({
328
+ name: config.name,
329
+ version: config.version,
330
+ description: config.description
331
+ });
332
+ this.providedToolsManager = toolsManager;
333
+ }
334
+ }
335
+ exports.BaseMCPServer = __webpack_exports__.BaseMCPServer;
336
+ exports.CLI_ARGS_CONFIG = __webpack_exports__.CLI_ARGS_CONFIG;
337
+ exports.launchMCPServer = __webpack_exports__.launchMCPServer;
338
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
339
+ "BaseMCPServer",
340
+ "CLI_ARGS_CONFIG",
341
+ "launchMCPServer"
342
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
343
+ Object.defineProperty(exports, '__esModule', {
344
+ value: true
345
+ });
@@ -43,7 +43,7 @@ function _define_property(obj, key, value) {
43
43
  else obj[key] = value;
44
44
  return obj;
45
45
  }
46
- const debug = (0, logger_namespaceObject.getDebug)('agent-tools:base-tools');
46
+ const debug = (0, logger_namespaceObject.getDebug)('mcp:base-tools');
47
47
  class BaseMidsceneTools {
48
48
  getInitArgKeys() {
49
49
  return this.initArgSpec ? Object.keys(this.initArgSpec.shape) : [];
@@ -132,6 +132,12 @@ class BaseMidsceneTools {
132
132
  this.toolDefinitions.push(...actionTools, ...commonTools);
133
133
  debug('Total tools prepared:', this.toolDefinitions.length);
134
134
  }
135
+ attachToServer(server) {
136
+ this.mcpServer = server;
137
+ if (0 === this.toolDefinitions.length) debug('Warning: No tools to register. Tools may be initialized lazily.');
138
+ for (const toolDef of this.toolDefinitions)this.mcpServer.tool(toolDef.name, toolDef.description, toolDef.schema, toolDef.handler);
139
+ debug('Registered', this.toolDefinitions.length, 'tools');
140
+ }
135
141
  async destroy() {
136
142
  await this.agent?.destroy?.();
137
143
  }
@@ -177,6 +183,7 @@ class BaseMidsceneTools {
177
183
  };
178
184
  }
179
185
  constructor(){
186
+ _define_property(this, "mcpServer", void 0);
180
187
  _define_property(this, "agent", void 0);
181
188
  _define_property(this, "toolDefinitions", []);
182
189
  _define_property(this, "toolDefaults", {});
@@ -29,11 +29,6 @@ __webpack_require__.d(__webpack_exports__, {
29
29
  });
30
30
  const external_node_fs_namespaceObject = require("node:fs");
31
31
  const index_js_namespaceObject = require("../env/index.js");
32
- const external_logger_js_namespaceObject = require("../logger.js");
33
- const warnChromePath = (0, external_logger_js_namespaceObject.getDebug)('agent-tools:chrome-path', {
34
- console: true
35
- });
36
- let hasWarnedLegacyChromePath = false;
37
32
  function getSystemChromePath() {
38
33
  const platform = process.platform;
39
34
  const chromePaths = {
@@ -60,17 +55,11 @@ function getSystemChromePath() {
60
55
  return paths.find((p)=>(0, external_node_fs_namespaceObject.existsSync)(p));
61
56
  }
62
57
  function resolveChromePath() {
63
- const primaryEnvPath = index_js_namespaceObject.globalConfigManager.getEnvConfigValue(index_js_namespaceObject.MIDSCENE_CHROME_PATH);
64
- const legacyEnvPath = index_js_namespaceObject.globalConfigManager.getEnvConfigValue(index_js_namespaceObject.MIDSCENE_MCP_CHROME_PATH);
65
- const envPath = primaryEnvPath || legacyEnvPath;
66
- if (!primaryEnvPath && legacyEnvPath && !hasWarnedLegacyChromePath) {
67
- warnChromePath('MIDSCENE_MCP_CHROME_PATH is deprecated. Use MIDSCENE_CHROME_PATH instead.');
68
- hasWarnedLegacyChromePath = true;
69
- }
58
+ const envPath = index_js_namespaceObject.globalConfigManager.getEnvConfigValue(index_js_namespaceObject.MIDSCENE_MCP_CHROME_PATH);
70
59
  if (envPath && 'auto' !== envPath && (0, external_node_fs_namespaceObject.existsSync)(envPath)) return envPath;
71
60
  const systemPath = getSystemChromePath();
72
61
  if (systemPath) return systemPath;
73
- throw new Error('Chrome not found. Install Google Chrome or set MIDSCENE_CHROME_PATH environment variable.');
62
+ throw new Error('Chrome not found. Install Google Chrome or set MIDSCENE_MCP_CHROME_PATH environment variable.');
74
63
  }
75
64
  exports.getSystemChromePath = __webpack_exports__.getSystemChromePath;
76
65
  exports.resolveChromePath = __webpack_exports__.resolveChromePath;
@@ -3,6 +3,9 @@ var __webpack_modules__ = {
3
3
  "./agent-behavior-init-args" (module) {
4
4
  module.exports = require("./agent-behavior-init-args.js");
5
5
  },
6
+ "./base-server" (module) {
7
+ module.exports = require("./base-server.js");
8
+ },
6
9
  "./base-tools" (module) {
7
10
  module.exports = require("./base-tools.js");
8
11
  },
@@ -15,6 +18,12 @@ var __webpack_modules__ = {
15
18
  "./init-arg-utils" (module) {
16
19
  module.exports = require("./init-arg-utils.js");
17
20
  },
21
+ "./inject-report-html-plugin" (module) {
22
+ module.exports = require("./inject-report-html-plugin.js");
23
+ },
24
+ "./launcher-helper" (module) {
25
+ module.exports = require("./launcher-helper.js");
26
+ },
18
27
  "./tool-defaults" (module) {
19
28
  module.exports = require("./tool-defaults.js");
20
29
  },
@@ -68,37 +77,49 @@ function __webpack_require__(moduleId) {
68
77
  var __webpack_exports__ = {};
69
78
  (()=>{
70
79
  __webpack_require__.r(__webpack_exports__);
71
- var _base_tools__rspack_import_0 = __webpack_require__("./base-tools");
80
+ var _base_server__rspack_import_0 = __webpack_require__("./base-server");
81
+ var __rspack_reexport = {};
82
+ for(const __rspack_import_key in _base_server__rspack_import_0)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_base_server__rspack_import_0[__rspack_import_key];
83
+ __webpack_require__.d(__webpack_exports__, __rspack_reexport);
84
+ var _base_tools__rspack_import_1 = __webpack_require__("./base-tools");
85
+ var __rspack_reexport = {};
86
+ for(const __rspack_import_key in _base_tools__rspack_import_1)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_base_tools__rspack_import_1[__rspack_import_key];
87
+ __webpack_require__.d(__webpack_exports__, __rspack_reexport);
88
+ var _tool_defaults__rspack_import_2 = __webpack_require__("./tool-defaults");
89
+ var __rspack_reexport = {};
90
+ for(const __rspack_import_key in _tool_defaults__rspack_import_2)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_defaults__rspack_import_2[__rspack_import_key];
91
+ __webpack_require__.d(__webpack_exports__, __rspack_reexport);
92
+ var _agent_behavior_init_args__rspack_import_3 = __webpack_require__("./agent-behavior-init-args");
72
93
  var __rspack_reexport = {};
73
- for(const __rspack_import_key in _base_tools__rspack_import_0)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_base_tools__rspack_import_0[__rspack_import_key];
94
+ for(const __rspack_import_key in _agent_behavior_init_args__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_agent_behavior_init_args__rspack_import_3[__rspack_import_key];
74
95
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
75
- var _tool_defaults__rspack_import_1 = __webpack_require__("./tool-defaults");
96
+ var _init_arg_utils__rspack_import_4 = __webpack_require__("./init-arg-utils");
76
97
  var __rspack_reexport = {};
77
- for(const __rspack_import_key in _tool_defaults__rspack_import_1)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_defaults__rspack_import_1[__rspack_import_key];
98
+ for(const __rspack_import_key in _init_arg_utils__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_init_arg_utils__rspack_import_4[__rspack_import_key];
78
99
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
79
- var _agent_behavior_init_args__rspack_import_2 = __webpack_require__("./agent-behavior-init-args");
100
+ var _error_formatter__rspack_import_5 = __webpack_require__("./error-formatter");
80
101
  var __rspack_reexport = {};
81
- for(const __rspack_import_key in _agent_behavior_init_args__rspack_import_2)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_agent_behavior_init_args__rspack_import_2[__rspack_import_key];
102
+ for(const __rspack_import_key in _error_formatter__rspack_import_5)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_error_formatter__rspack_import_5[__rspack_import_key];
82
103
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
83
- var _init_arg_utils__rspack_import_3 = __webpack_require__("./init-arg-utils");
104
+ var _tool_generator__rspack_import_6 = __webpack_require__("./tool-generator");
84
105
  var __rspack_reexport = {};
85
- for(const __rspack_import_key in _init_arg_utils__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_init_arg_utils__rspack_import_3[__rspack_import_key];
106
+ for(const __rspack_import_key in _tool_generator__rspack_import_6)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_generator__rspack_import_6[__rspack_import_key];
86
107
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
87
- var _error_formatter__rspack_import_4 = __webpack_require__("./error-formatter");
108
+ var _types__rspack_import_7 = __webpack_require__("./types");
88
109
  var __rspack_reexport = {};
89
- for(const __rspack_import_key in _error_formatter__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_error_formatter__rspack_import_4[__rspack_import_key];
110
+ for(const __rspack_import_key in _types__rspack_import_7)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_7[__rspack_import_key];
90
111
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
91
- var _tool_generator__rspack_import_5 = __webpack_require__("./tool-generator");
112
+ var _inject_report_html_plugin__rspack_import_8 = __webpack_require__("./inject-report-html-plugin");
92
113
  var __rspack_reexport = {};
93
- for(const __rspack_import_key in _tool_generator__rspack_import_5)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_generator__rspack_import_5[__rspack_import_key];
114
+ for(const __rspack_import_key in _inject_report_html_plugin__rspack_import_8)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_inject_report_html_plugin__rspack_import_8[__rspack_import_key];
94
115
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
95
- var _types__rspack_import_6 = __webpack_require__("./types");
116
+ var _launcher_helper__rspack_import_9 = __webpack_require__("./launcher-helper");
96
117
  var __rspack_reexport = {};
97
- for(const __rspack_import_key in _types__rspack_import_6)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_6[__rspack_import_key];
118
+ for(const __rspack_import_key in _launcher_helper__rspack_import_9)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_launcher_helper__rspack_import_9[__rspack_import_key];
98
119
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
99
- var _chrome_path__rspack_import_7 = __webpack_require__("./chrome-path");
120
+ var _chrome_path__rspack_import_10 = __webpack_require__("./chrome-path");
100
121
  var __rspack_reexport = {};
101
- for(const __rspack_import_key in _chrome_path__rspack_import_7)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_chrome_path__rspack_import_7[__rspack_import_key];
122
+ for(const __rspack_import_key in _chrome_path__rspack_import_10)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_chrome_path__rspack_import_10[__rspack_import_key];
102
123
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
103
124
  })();
104
125
  for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];