@midscene/shared 1.7.4 → 1.7.5-beta-20260420031652.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/mcp/base-server.mjs +9 -8
- package/dist/es/mcp/error-formatter.mjs +19 -0
- package/dist/es/mcp/index.mjs +1 -0
- package/dist/es/mcp/tool-generator.mjs +1 -3
- package/dist/lib/mcp/base-server.js +9 -8
- package/dist/lib/mcp/error-formatter.js +53 -0
- package/dist/lib/mcp/index.js +17 -10
- package/dist/lib/mcp/tool-generator.js +7 -9
- package/dist/types/mcp/error-formatter.d.ts +12 -0
- package/dist/types/mcp/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/mcp/base-server.ts +9 -11
- package/src/mcp/error-formatter.ts +52 -0
- package/src/mcp/index.ts +1 -0
- package/src/mcp/tool-generator.ts +1 -7
|
@@ -4,6 +4,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
6
|
import express from "express";
|
|
7
|
+
import { getErrorMessage } from "./error-formatter.mjs";
|
|
7
8
|
function _define_property(obj, key, value) {
|
|
8
9
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
9
10
|
value: value,
|
|
@@ -45,7 +46,7 @@ class BaseMCPServer {
|
|
|
45
46
|
try {
|
|
46
47
|
await this.toolsManager.initTools();
|
|
47
48
|
} catch (error) {
|
|
48
|
-
const message =
|
|
49
|
+
const message = getErrorMessage(error);
|
|
49
50
|
console.error(`Failed to initialize tools: ${message}`);
|
|
50
51
|
console.error('Tools will be initialized on first use');
|
|
51
52
|
}
|
|
@@ -71,7 +72,7 @@ class BaseMCPServer {
|
|
|
71
72
|
try {
|
|
72
73
|
await this.mcpServer.connect(transport);
|
|
73
74
|
} catch (error) {
|
|
74
|
-
const message =
|
|
75
|
+
const message = getErrorMessage(error);
|
|
75
76
|
console.error(`Failed to connect MCP stdio transport: ${message}`);
|
|
76
77
|
throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
|
|
77
78
|
}
|
|
@@ -142,7 +143,7 @@ class BaseMCPServer {
|
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
} catch (error) {
|
|
145
|
-
const message =
|
|
146
|
+
const message = getErrorMessage(error);
|
|
146
147
|
const duration = Date.now() - startTime;
|
|
147
148
|
console.error(`[${new Date().toISOString()}] [${requestId}] MCP request error after ${duration}ms: ${message}`);
|
|
148
149
|
if (!res.headersSent) res.status(500).json({
|
|
@@ -170,7 +171,7 @@ class BaseMCPServer {
|
|
|
170
171
|
for (const session of sessions.values())try {
|
|
171
172
|
await session.transport.close();
|
|
172
173
|
} catch (error) {
|
|
173
|
-
const message =
|
|
174
|
+
const message = getErrorMessage(error);
|
|
174
175
|
console.error(`Failed to close session ${session.transport.sessionId}: ${message}`);
|
|
175
176
|
}
|
|
176
177
|
sessions.clear();
|
|
@@ -205,7 +206,7 @@ class BaseMCPServer {
|
|
|
205
206
|
try {
|
|
206
207
|
await this.mcpServer.connect(transport);
|
|
207
208
|
} catch (error) {
|
|
208
|
-
const message =
|
|
209
|
+
const message = getErrorMessage(error);
|
|
209
210
|
console.error(`[${new Date().toISOString()}] Failed to connect MCP transport: ${message}`);
|
|
210
211
|
if (transport.sessionId) sessions.delete(transport.sessionId);
|
|
211
212
|
throw new Error(`Failed to initialize MCP session: ${message}`);
|
|
@@ -224,7 +225,7 @@ class BaseMCPServer {
|
|
|
224
225
|
sessions.delete(sid);
|
|
225
226
|
console.log(`[${new Date().toISOString()}] Session ${sid} cleaned up due to inactivity (remaining: ${sessions.size})`);
|
|
226
227
|
} catch (error) {
|
|
227
|
-
const message =
|
|
228
|
+
const message = getErrorMessage(error);
|
|
228
229
|
console.error(`[${new Date().toISOString()}] Failed to close session ${sid} during cleanup: ${message}`);
|
|
229
230
|
sessions.delete(sid);
|
|
230
231
|
}
|
|
@@ -237,7 +238,7 @@ class BaseMCPServer {
|
|
|
237
238
|
for (const session of sessions.values())try {
|
|
238
239
|
session.transport.close();
|
|
239
240
|
} catch (error) {
|
|
240
|
-
const message =
|
|
241
|
+
const message = getErrorMessage(error);
|
|
241
242
|
console.error(`Error closing session during shutdown: ${message}`);
|
|
242
243
|
}
|
|
243
244
|
sessions.clear();
|
|
@@ -250,7 +251,7 @@ class BaseMCPServer {
|
|
|
250
251
|
this.performCleanup().finally(()=>process.exit(1));
|
|
251
252
|
}, 5000);
|
|
252
253
|
} catch (error) {
|
|
253
|
-
const message =
|
|
254
|
+
const message = getErrorMessage(error);
|
|
254
255
|
console.error(`Error closing HTTP server: ${message}`);
|
|
255
256
|
this.performCleanup().finally(()=>process.exit(1));
|
|
256
257
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function getErrorMessage(error) {
|
|
2
|
+
if (error instanceof Error) return error.message;
|
|
3
|
+
if (null == error) return String(error);
|
|
4
|
+
if ('object' != typeof error) return String(error);
|
|
5
|
+
const candidate = extractStringMessage(error);
|
|
6
|
+
if (candidate) return candidate;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(error);
|
|
9
|
+
} catch {
|
|
10
|
+
return Object.prototype.toString.call(error);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function extractStringMessage(error) {
|
|
14
|
+
const anyError = error;
|
|
15
|
+
if ('string' == typeof anyError.message && anyError.message) return anyError.message;
|
|
16
|
+
if (anyError.error && 'string' == typeof anyError.error.message && anyError.error.message) return anyError.error.message;
|
|
17
|
+
if (anyError.cause && 'string' == typeof anyError.cause.message && anyError.cause.message) return anyError.cause.message;
|
|
18
|
+
}
|
|
19
|
+
export { getErrorMessage };
|
package/dist/es/mcp/index.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { parseBase64 } from "@midscene/shared/img";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { getZodDescription, getZodTypeName, isMidsceneLocatorField, unwrapZodField } from "../zod-schema-utils.mjs";
|
|
4
|
-
|
|
5
|
-
return error instanceof Error ? error.message : String(error);
|
|
6
|
-
}
|
|
4
|
+
import { getErrorMessage } from "./error-formatter.mjs";
|
|
7
5
|
function describeActionForMCP(action) {
|
|
8
6
|
const actionDesc = action.description || `Execute ${action.name} action`;
|
|
9
7
|
if (!action.paramSchema) return `${action.name} action, ${actionDesc}`;
|
|
@@ -44,6 +44,7 @@ const stdio_js_namespaceObject = require("@modelcontextprotocol/sdk/server/stdio
|
|
|
44
44
|
const streamableHttp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
45
45
|
const external_express_namespaceObject = require("express");
|
|
46
46
|
var external_express_default = /*#__PURE__*/ __webpack_require__.n(external_express_namespaceObject);
|
|
47
|
+
const external_error_formatter_js_namespaceObject = require("./error-formatter.js");
|
|
47
48
|
function _define_property(obj, key, value) {
|
|
48
49
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
49
50
|
value: value,
|
|
@@ -85,7 +86,7 @@ class BaseMCPServer {
|
|
|
85
86
|
try {
|
|
86
87
|
await this.toolsManager.initTools();
|
|
87
88
|
} catch (error) {
|
|
88
|
-
const message =
|
|
89
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
89
90
|
console.error(`Failed to initialize tools: ${message}`);
|
|
90
91
|
console.error('Tools will be initialized on first use');
|
|
91
92
|
}
|
|
@@ -111,7 +112,7 @@ class BaseMCPServer {
|
|
|
111
112
|
try {
|
|
112
113
|
await this.mcpServer.connect(transport);
|
|
113
114
|
} catch (error) {
|
|
114
|
-
const message =
|
|
115
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
115
116
|
console.error(`Failed to connect MCP stdio transport: ${message}`);
|
|
116
117
|
throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
|
|
117
118
|
}
|
|
@@ -182,7 +183,7 @@ class BaseMCPServer {
|
|
|
182
183
|
});
|
|
183
184
|
}
|
|
184
185
|
} catch (error) {
|
|
185
|
-
const message =
|
|
186
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
186
187
|
const duration = Date.now() - startTime;
|
|
187
188
|
console.error(`[${new Date().toISOString()}] [${requestId}] MCP request error after ${duration}ms: ${message}`);
|
|
188
189
|
if (!res.headersSent) res.status(500).json({
|
|
@@ -210,7 +211,7 @@ class BaseMCPServer {
|
|
|
210
211
|
for (const session of sessions.values())try {
|
|
211
212
|
await session.transport.close();
|
|
212
213
|
} catch (error) {
|
|
213
|
-
const message =
|
|
214
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
214
215
|
console.error(`Failed to close session ${session.transport.sessionId}: ${message}`);
|
|
215
216
|
}
|
|
216
217
|
sessions.clear();
|
|
@@ -245,7 +246,7 @@ class BaseMCPServer {
|
|
|
245
246
|
try {
|
|
246
247
|
await this.mcpServer.connect(transport);
|
|
247
248
|
} catch (error) {
|
|
248
|
-
const message =
|
|
249
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
249
250
|
console.error(`[${new Date().toISOString()}] Failed to connect MCP transport: ${message}`);
|
|
250
251
|
if (transport.sessionId) sessions.delete(transport.sessionId);
|
|
251
252
|
throw new Error(`Failed to initialize MCP session: ${message}`);
|
|
@@ -264,7 +265,7 @@ class BaseMCPServer {
|
|
|
264
265
|
sessions.delete(sid);
|
|
265
266
|
console.log(`[${new Date().toISOString()}] Session ${sid} cleaned up due to inactivity (remaining: ${sessions.size})`);
|
|
266
267
|
} catch (error) {
|
|
267
|
-
const message =
|
|
268
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
268
269
|
console.error(`[${new Date().toISOString()}] Failed to close session ${sid} during cleanup: ${message}`);
|
|
269
270
|
sessions.delete(sid);
|
|
270
271
|
}
|
|
@@ -277,7 +278,7 @@ class BaseMCPServer {
|
|
|
277
278
|
for (const session of sessions.values())try {
|
|
278
279
|
session.transport.close();
|
|
279
280
|
} catch (error) {
|
|
280
|
-
const message =
|
|
281
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
281
282
|
console.error(`Error closing session during shutdown: ${message}`);
|
|
282
283
|
}
|
|
283
284
|
sessions.clear();
|
|
@@ -290,7 +291,7 @@ class BaseMCPServer {
|
|
|
290
291
|
this.performCleanup().finally(()=>process.exit(1));
|
|
291
292
|
}, 5000);
|
|
292
293
|
} catch (error) {
|
|
293
|
-
const message =
|
|
294
|
+
const message = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
294
295
|
console.error(`Error closing HTTP server: ${message}`);
|
|
295
296
|
this.performCleanup().finally(()=>process.exit(1));
|
|
296
297
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
getErrorMessage: ()=>getErrorMessage
|
|
28
|
+
});
|
|
29
|
+
function getErrorMessage(error) {
|
|
30
|
+
if (error instanceof Error) return error.message;
|
|
31
|
+
if (null == error) return String(error);
|
|
32
|
+
if ('object' != typeof error) return String(error);
|
|
33
|
+
const candidate = extractStringMessage(error);
|
|
34
|
+
if (candidate) return candidate;
|
|
35
|
+
try {
|
|
36
|
+
return JSON.stringify(error);
|
|
37
|
+
} catch {
|
|
38
|
+
return Object.prototype.toString.call(error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function extractStringMessage(error) {
|
|
42
|
+
const anyError = error;
|
|
43
|
+
if ('string' == typeof anyError.message && anyError.message) return anyError.message;
|
|
44
|
+
if (anyError.error && 'string' == typeof anyError.error.message && anyError.error.message) return anyError.error.message;
|
|
45
|
+
if (anyError.cause && 'string' == typeof anyError.cause.message && anyError.cause.message) return anyError.cause.message;
|
|
46
|
+
}
|
|
47
|
+
exports.getErrorMessage = __webpack_exports__.getErrorMessage;
|
|
48
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
49
|
+
"getErrorMessage"
|
|
50
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
51
|
+
Object.defineProperty(exports, '__esModule', {
|
|
52
|
+
value: true
|
|
53
|
+
});
|
package/dist/lib/mcp/index.js
CHANGED
|
@@ -9,6 +9,9 @@ var __webpack_modules__ = {
|
|
|
9
9
|
"./chrome-path" (module) {
|
|
10
10
|
module.exports = require("./chrome-path.js");
|
|
11
11
|
},
|
|
12
|
+
"./error-formatter" (module) {
|
|
13
|
+
module.exports = require("./error-formatter.js");
|
|
14
|
+
},
|
|
12
15
|
"./inject-report-html-plugin" (module) {
|
|
13
16
|
module.exports = require("./inject-report-html-plugin.js");
|
|
14
17
|
},
|
|
@@ -73,25 +76,29 @@ var __webpack_exports__ = {};
|
|
|
73
76
|
var __rspack_reexport = {};
|
|
74
77
|
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];
|
|
75
78
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
76
|
-
var
|
|
79
|
+
var _error_formatter__rspack_import_2 = __webpack_require__("./error-formatter");
|
|
80
|
+
var __rspack_reexport = {};
|
|
81
|
+
for(const __rspack_import_key in _error_formatter__rspack_import_2)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_error_formatter__rspack_import_2[__rspack_import_key];
|
|
82
|
+
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
83
|
+
var _tool_generator__rspack_import_3 = __webpack_require__("./tool-generator");
|
|
77
84
|
var __rspack_reexport = {};
|
|
78
|
-
for(const __rspack_import_key in
|
|
85
|
+
for(const __rspack_import_key in _tool_generator__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_generator__rspack_import_3[__rspack_import_key];
|
|
79
86
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
80
|
-
var
|
|
87
|
+
var _types__rspack_import_4 = __webpack_require__("./types");
|
|
81
88
|
var __rspack_reexport = {};
|
|
82
|
-
for(const __rspack_import_key in
|
|
89
|
+
for(const __rspack_import_key in _types__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_4[__rspack_import_key];
|
|
83
90
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
84
|
-
var
|
|
91
|
+
var _inject_report_html_plugin__rspack_import_5 = __webpack_require__("./inject-report-html-plugin");
|
|
85
92
|
var __rspack_reexport = {};
|
|
86
|
-
for(const __rspack_import_key in
|
|
93
|
+
for(const __rspack_import_key in _inject_report_html_plugin__rspack_import_5)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_inject_report_html_plugin__rspack_import_5[__rspack_import_key];
|
|
87
94
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
88
|
-
var
|
|
95
|
+
var _launcher_helper__rspack_import_6 = __webpack_require__("./launcher-helper");
|
|
89
96
|
var __rspack_reexport = {};
|
|
90
|
-
for(const __rspack_import_key in
|
|
97
|
+
for(const __rspack_import_key in _launcher_helper__rspack_import_6)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_launcher_helper__rspack_import_6[__rspack_import_key];
|
|
91
98
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
92
|
-
var
|
|
99
|
+
var _chrome_path__rspack_import_7 = __webpack_require__("./chrome-path");
|
|
93
100
|
var __rspack_reexport = {};
|
|
94
|
-
for(const __rspack_import_key in
|
|
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];
|
|
95
102
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
96
103
|
})();
|
|
97
104
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
@@ -30,9 +30,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
30
30
|
const img_namespaceObject = require("@midscene/shared/img");
|
|
31
31
|
const external_zod_namespaceObject = require("zod");
|
|
32
32
|
const external_zod_schema_utils_js_namespaceObject = require("../zod-schema-utils.js");
|
|
33
|
-
|
|
34
|
-
return error instanceof Error ? error.message : String(error);
|
|
35
|
-
}
|
|
33
|
+
const external_error_formatter_js_namespaceObject = require("./error-formatter.js");
|
|
36
34
|
function describeActionForMCP(action) {
|
|
37
35
|
const actionDesc = action.description || `Execute ${action.name} action`;
|
|
38
36
|
if (!action.paramSchema) return `${action.name} action, ${actionDesc}`;
|
|
@@ -173,7 +171,7 @@ function serializeArgsToDescription(args) {
|
|
|
173
171
|
return `${key}: "${value}"`;
|
|
174
172
|
}).join(', ');
|
|
175
173
|
} catch (error) {
|
|
176
|
-
const errorMessage = getErrorMessage(error);
|
|
174
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
177
175
|
console.error('Error serializing args:', errorMessage);
|
|
178
176
|
return `[args serialization failed: ${errorMessage}]`;
|
|
179
177
|
}
|
|
@@ -241,7 +239,7 @@ async function captureScreenshotResult(agent, actionName, actionResult) {
|
|
|
241
239
|
content
|
|
242
240
|
};
|
|
243
241
|
} catch (error) {
|
|
244
|
-
const errorMessage = getErrorMessage(error);
|
|
242
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
245
243
|
console.error('Error capturing screenshot:', errorMessage);
|
|
246
244
|
content[0] = {
|
|
247
245
|
type: 'text',
|
|
@@ -323,13 +321,13 @@ function generateToolsFromActionSpace(actionSpace, getAgent) {
|
|
|
323
321
|
try {
|
|
324
322
|
actionResult = await executeAction(agent, action.name, normalizedArgs);
|
|
325
323
|
} catch (error) {
|
|
326
|
-
const errorMessage = getErrorMessage(error);
|
|
324
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
327
325
|
console.error(`Error executing action "${action.name}":`, errorMessage);
|
|
328
326
|
return await captureFailureResult(agent, action.name, errorMessage);
|
|
329
327
|
}
|
|
330
328
|
return await captureScreenshotResult(agent, action.name, actionResult);
|
|
331
329
|
} catch (error) {
|
|
332
|
-
const errorMessage = getErrorMessage(error);
|
|
330
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
333
331
|
console.error(`Error in handler for "${action.name}":`, errorMessage);
|
|
334
332
|
return createErrorResult(`Failed to get agent or execute action "${action.name}": ${errorMessage}`);
|
|
335
333
|
}
|
|
@@ -359,7 +357,7 @@ function generateCommonTools(getAgent) {
|
|
|
359
357
|
]
|
|
360
358
|
};
|
|
361
359
|
} catch (error) {
|
|
362
|
-
const errorMessage = getErrorMessage(error);
|
|
360
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
363
361
|
console.error('Error taking screenshot:', errorMessage);
|
|
364
362
|
return createErrorResult(`Failed to capture screenshot: ${errorMessage}`);
|
|
365
363
|
}
|
|
@@ -389,7 +387,7 @@ function generateCommonTools(getAgent) {
|
|
|
389
387
|
}
|
|
390
388
|
return screenshotResult;
|
|
391
389
|
} catch (error) {
|
|
392
|
-
const errorMessage = getErrorMessage(error);
|
|
390
|
+
const errorMessage = (0, external_error_formatter_js_namespaceObject.getErrorMessage)(error);
|
|
393
391
|
console.error('Error executing act:', errorMessage);
|
|
394
392
|
return createErrorResult(`Failed to execute act: ${errorMessage}`);
|
|
395
393
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a human-readable message from an unknown thrown value.
|
|
3
|
+
*
|
|
4
|
+
* Many SDK/transport layers reject with structured objects (e.g.
|
|
5
|
+
* `{ code, message }`, `{ error: { message } }`, `{ cause: { message } }`)
|
|
6
|
+
* rather than `Error` instances. `String(obj)` collapses those to
|
|
7
|
+
* `"[object Object]"`, which is useless for diagnostics. This helper walks
|
|
8
|
+
* the common shapes, falls back to `JSON.stringify`, and finally to
|
|
9
|
+
* `Object.prototype.toString.call` so that callers always get something
|
|
10
|
+
* actionable in logs and surfaced tool results.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getErrorMessage(error: unknown): string;
|
package/package.json
CHANGED
package/src/mcp/base-server.ts
CHANGED
|
@@ -9,6 +9,7 @@ import express, {
|
|
|
9
9
|
type Request,
|
|
10
10
|
type Response,
|
|
11
11
|
} from 'express';
|
|
12
|
+
import { getErrorMessage } from './error-formatter';
|
|
12
13
|
import type { IMidsceneTools } from './types';
|
|
13
14
|
|
|
14
15
|
export interface BaseMCPServerConfig {
|
|
@@ -119,7 +120,7 @@ export abstract class BaseMCPServer {
|
|
|
119
120
|
try {
|
|
120
121
|
await this.toolsManager.initTools();
|
|
121
122
|
} catch (error: unknown) {
|
|
122
|
-
const message =
|
|
123
|
+
const message = getErrorMessage(error);
|
|
123
124
|
console.error(`Failed to initialize tools: ${message}`);
|
|
124
125
|
console.error('Tools will be initialized on first use');
|
|
125
126
|
}
|
|
@@ -160,7 +161,7 @@ export abstract class BaseMCPServer {
|
|
|
160
161
|
try {
|
|
161
162
|
await this.mcpServer.connect(transport);
|
|
162
163
|
} catch (error: unknown) {
|
|
163
|
-
const message =
|
|
164
|
+
const message = getErrorMessage(error);
|
|
164
165
|
console.error(`Failed to connect MCP stdio transport: ${message}`);
|
|
165
166
|
throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
|
|
166
167
|
}
|
|
@@ -282,7 +283,7 @@ export abstract class BaseMCPServer {
|
|
|
282
283
|
.json({ error: 'Invalid session or GET without session' });
|
|
283
284
|
}
|
|
284
285
|
} catch (error: unknown) {
|
|
285
|
-
const message =
|
|
286
|
+
const message = getErrorMessage(error);
|
|
286
287
|
const duration = Date.now() - startTime;
|
|
287
288
|
console.error(
|
|
288
289
|
`[${new Date().toISOString()}] [${requestId}] MCP request error after ${duration}ms: ${message}`,
|
|
@@ -336,8 +337,7 @@ export abstract class BaseMCPServer {
|
|
|
336
337
|
try {
|
|
337
338
|
await session.transport.close();
|
|
338
339
|
} catch (error: unknown) {
|
|
339
|
-
const message =
|
|
340
|
-
error instanceof Error ? error.message : String(error);
|
|
340
|
+
const message = getErrorMessage(error);
|
|
341
341
|
console.error(
|
|
342
342
|
`Failed to close session ${session.transport.sessionId}: ${message}`,
|
|
343
343
|
);
|
|
@@ -390,7 +390,7 @@ export abstract class BaseMCPServer {
|
|
|
390
390
|
try {
|
|
391
391
|
await this.mcpServer.connect(transport);
|
|
392
392
|
} catch (error: unknown) {
|
|
393
|
-
const message =
|
|
393
|
+
const message = getErrorMessage(error);
|
|
394
394
|
console.error(
|
|
395
395
|
`[${new Date().toISOString()}] Failed to connect MCP transport: ${message}`,
|
|
396
396
|
);
|
|
@@ -425,8 +425,7 @@ export abstract class BaseMCPServer {
|
|
|
425
425
|
`[${new Date().toISOString()}] Session ${sid} cleaned up due to inactivity (remaining: ${sessions.size})`,
|
|
426
426
|
);
|
|
427
427
|
} catch (error: unknown) {
|
|
428
|
-
const message =
|
|
429
|
-
error instanceof Error ? error.message : String(error);
|
|
428
|
+
const message = getErrorMessage(error);
|
|
430
429
|
console.error(
|
|
431
430
|
`[${new Date().toISOString()}] Failed to close session ${sid} during cleanup: ${message}`,
|
|
432
431
|
);
|
|
@@ -455,8 +454,7 @@ export abstract class BaseMCPServer {
|
|
|
455
454
|
try {
|
|
456
455
|
session.transport.close();
|
|
457
456
|
} catch (error: unknown) {
|
|
458
|
-
const message =
|
|
459
|
-
error instanceof Error ? error.message : String(error);
|
|
457
|
+
const message = getErrorMessage(error);
|
|
460
458
|
console.error(`Error closing session during shutdown: ${message}`);
|
|
461
459
|
}
|
|
462
460
|
}
|
|
@@ -475,7 +473,7 @@ export abstract class BaseMCPServer {
|
|
|
475
473
|
this.performCleanup().finally(() => process.exit(1));
|
|
476
474
|
}, 5000);
|
|
477
475
|
} catch (error: unknown) {
|
|
478
|
-
const message =
|
|
476
|
+
const message = getErrorMessage(error);
|
|
479
477
|
console.error(`Error closing HTTP server: ${message}`);
|
|
480
478
|
this.performCleanup().finally(() => process.exit(1));
|
|
481
479
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a human-readable message from an unknown thrown value.
|
|
3
|
+
*
|
|
4
|
+
* Many SDK/transport layers reject with structured objects (e.g.
|
|
5
|
+
* `{ code, message }`, `{ error: { message } }`, `{ cause: { message } }`)
|
|
6
|
+
* rather than `Error` instances. `String(obj)` collapses those to
|
|
7
|
+
* `"[object Object]"`, which is useless for diagnostics. This helper walks
|
|
8
|
+
* the common shapes, falls back to `JSON.stringify`, and finally to
|
|
9
|
+
* `Object.prototype.toString.call` so that callers always get something
|
|
10
|
+
* actionable in logs and surfaced tool results.
|
|
11
|
+
*/
|
|
12
|
+
export function getErrorMessage(error: unknown): string {
|
|
13
|
+
if (error instanceof Error) return error.message;
|
|
14
|
+
if (error === null || error === undefined) return String(error);
|
|
15
|
+
if (typeof error !== 'object') return String(error);
|
|
16
|
+
|
|
17
|
+
const candidate = extractStringMessage(error);
|
|
18
|
+
if (candidate) return candidate;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
return JSON.stringify(error);
|
|
22
|
+
} catch {
|
|
23
|
+
return Object.prototype.toString.call(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function extractStringMessage(error: object): string | undefined {
|
|
28
|
+
const anyError = error as {
|
|
29
|
+
message?: unknown;
|
|
30
|
+
error?: { message?: unknown };
|
|
31
|
+
cause?: { message?: unknown };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (typeof anyError.message === 'string' && anyError.message) {
|
|
35
|
+
return anyError.message;
|
|
36
|
+
}
|
|
37
|
+
if (
|
|
38
|
+
anyError.error &&
|
|
39
|
+
typeof anyError.error.message === 'string' &&
|
|
40
|
+
anyError.error.message
|
|
41
|
+
) {
|
|
42
|
+
return anyError.error.message;
|
|
43
|
+
}
|
|
44
|
+
if (
|
|
45
|
+
anyError.cause &&
|
|
46
|
+
typeof anyError.cause.message === 'string' &&
|
|
47
|
+
anyError.cause.message
|
|
48
|
+
) {
|
|
49
|
+
return anyError.cause.message;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
package/src/mcp/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
isMidsceneLocatorField,
|
|
7
7
|
unwrapZodField,
|
|
8
8
|
} from '../zod-schema-utils';
|
|
9
|
+
import { getErrorMessage } from './error-formatter';
|
|
9
10
|
import type {
|
|
10
11
|
ActionSpaceItem,
|
|
11
12
|
BaseAgent,
|
|
@@ -13,13 +14,6 @@ import type {
|
|
|
13
14
|
ToolResult,
|
|
14
15
|
} from './types';
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
* Extract error message from unknown error type
|
|
18
|
-
*/
|
|
19
|
-
function getErrorMessage(error: unknown): string {
|
|
20
|
-
return error instanceof Error ? error.message : String(error);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
17
|
/**
|
|
24
18
|
* Generate MCP tool description from ActionSpaceItem
|
|
25
19
|
* Format: "actionName action, description. Parameters: param1 (type) - desc; param2 (type) - desc"
|