@justanothermldude/mcp-exec 1.7.3 → 1.7.5
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/codegen/wrapper-generator.js +21 -8
- package/dist/index.js +30 -10
- package/dist/tools/tool-catalog.js +12 -2
- package/package.json +1 -1
|
@@ -177,8 +177,14 @@ function generateInterface(name, schema, definitions) {
|
|
|
177
177
|
*/
|
|
178
178
|
function sanitizeJsDoc(text) {
|
|
179
179
|
// Escape */ to prevent premature JSDoc comment closure
|
|
180
|
-
//
|
|
181
|
-
|
|
180
|
+
// (handles glob patterns like "src/**/*.ts" in tool descriptions)
|
|
181
|
+
let sanitized = text.replace(/\*\//g, '* /');
|
|
182
|
+
// Collapse newlines to prevent line-injection into JSDoc blocks
|
|
183
|
+
sanitized = sanitized.replace(/\r?\n/g, ' ');
|
|
184
|
+
// Escape @ at word boundaries to prevent JSDoc tag injection from a
|
|
185
|
+
// malicious tool description (e.g. "@param input.password string").
|
|
186
|
+
sanitized = sanitized.replace(/(?:^|\s)@([a-zA-Z_]\w*)/g, ' \\@$1');
|
|
187
|
+
return sanitized;
|
|
182
188
|
}
|
|
183
189
|
/**
|
|
184
190
|
* Generate a recursive Proxy guard that warns on undefined field access on MCP responses.
|
|
@@ -203,14 +209,18 @@ function __guardFields(obj, label) {
|
|
|
203
209
|
}
|
|
204
210
|
});
|
|
205
211
|
}
|
|
212
|
+
const __safeKeys = new Set(['then', 'toJSON', 'length', 'constructor', 'nodeType', 'valueOf', 'toString', 'inspect']);
|
|
213
|
+
const __dangerousKeys = new Set(['__proto__', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'prototype']);
|
|
206
214
|
return new Proxy(obj, {
|
|
207
215
|
get(target, prop) {
|
|
208
|
-
if (typeof prop === 'symbol'
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
if (typeof prop === 'symbol') return target[prop];
|
|
217
|
+
const propStr = String(prop);
|
|
218
|
+
if (__dangerousKeys.has(propStr)) {
|
|
219
|
+
throw new TypeError('Access to "' + propStr + '" is not allowed on ' + label);
|
|
220
|
+
}
|
|
221
|
+
if (__safeKeys.has(propStr)) {
|
|
211
222
|
return target[prop];
|
|
212
223
|
}
|
|
213
|
-
if (prop === '__proto__' || prop === 'prototype') return undefined;
|
|
214
224
|
if (Object.prototype.hasOwnProperty.call(target, prop)) {
|
|
215
225
|
const val = target[prop];
|
|
216
226
|
if (val && typeof val === 'object') {
|
|
@@ -271,8 +281,11 @@ export function generateFuzzyProxy(targetVarName, contextName, helpString) {
|
|
|
271
281
|
get(target, prop) {
|
|
272
282
|
if (typeof prop !== 'string') return undefined;
|
|
273
283
|
|
|
274
|
-
// Block prototype pollution vectors
|
|
275
|
-
|
|
284
|
+
// Block prototype pollution vectors with a loud error so callers cannot silently
|
|
285
|
+
// probe the proxy for __proto__ or prototype indirection.
|
|
286
|
+
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
|
|
287
|
+
throw new TypeError('Access to "' + prop + '" is not allowed on ${safeContextName}');
|
|
288
|
+
}
|
|
276
289
|
|
|
277
290
|
// Fast-path: exact match — use hasOwnProperty to avoid prototype chain leaks
|
|
278
291
|
if (Object.prototype.hasOwnProperty.call(target, prop)) return target[prop];
|
package/dist/index.js
CHANGED
|
@@ -230,7 +230,12 @@ function compactTypeHint(propSchema) {
|
|
|
230
230
|
const keys = Object.keys(props);
|
|
231
231
|
if (keys.length === 0)
|
|
232
232
|
return "object";
|
|
233
|
-
const
|
|
233
|
+
const PRIM = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean"]);
|
|
234
|
+
const parts = keys.map((k) => {
|
|
235
|
+
const sub = props[k]?.type;
|
|
236
|
+
const sfx = required.includes(k) ? "" : "?";
|
|
237
|
+
return PRIM.has(sub ?? "") ? `${k}${sfx}:${sub}` : `${k}${sfx}`;
|
|
238
|
+
});
|
|
234
239
|
return `{${parts.join(", ")}}`;
|
|
235
240
|
}
|
|
236
241
|
if (type === "object") {
|
|
@@ -242,7 +247,12 @@ function compactTypeHint(propSchema) {
|
|
|
242
247
|
const props = items.properties;
|
|
243
248
|
const required = items.required || [];
|
|
244
249
|
const keys = Object.keys(props);
|
|
245
|
-
const
|
|
250
|
+
const PRIM = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean"]);
|
|
251
|
+
const parts = keys.map((k) => {
|
|
252
|
+
const sub = props[k]?.type;
|
|
253
|
+
const sfx = required.includes(k) ? "" : "?";
|
|
254
|
+
return PRIM.has(sub ?? "") ? `${k}${sfx}:${sub}` : `${k}${sfx}`;
|
|
255
|
+
});
|
|
246
256
|
return `[{${parts.join(", ")}}]`;
|
|
247
257
|
}
|
|
248
258
|
return null;
|
|
@@ -488,7 +498,10 @@ function generateInterface(name, schema, definitions) {
|
|
|
488
498
|
}
|
|
489
499
|
__name(generateInterface, "generateInterface");
|
|
490
500
|
function sanitizeJsDoc(text) {
|
|
491
|
-
|
|
501
|
+
let sanitized = text.replace(/\*\//g, "* /");
|
|
502
|
+
sanitized = sanitized.replace(/\r?\n/g, " ");
|
|
503
|
+
sanitized = sanitized.replace(/(?:^|\s)@([a-zA-Z_]\w*)/g, " \\@$1");
|
|
504
|
+
return sanitized;
|
|
492
505
|
}
|
|
493
506
|
__name(sanitizeJsDoc, "sanitizeJsDoc");
|
|
494
507
|
function generateFieldGuard() {
|
|
@@ -508,14 +521,18 @@ function __guardFields(obj, label) {
|
|
|
508
521
|
}
|
|
509
522
|
});
|
|
510
523
|
}
|
|
524
|
+
const __safeKeys = new Set(['then', 'toJSON', 'length', 'constructor', 'nodeType', 'valueOf', 'toString', 'inspect']);
|
|
525
|
+
const __dangerousKeys = new Set(['__proto__', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'prototype']);
|
|
511
526
|
return new Proxy(obj, {
|
|
512
527
|
get(target, prop) {
|
|
513
|
-
if (typeof prop === 'symbol'
|
|
514
|
-
|
|
515
|
-
|
|
528
|
+
if (typeof prop === 'symbol') return target[prop];
|
|
529
|
+
const propStr = String(prop);
|
|
530
|
+
if (__dangerousKeys.has(propStr)) {
|
|
531
|
+
throw new TypeError('Access to "' + propStr + '" is not allowed on ' + label);
|
|
532
|
+
}
|
|
533
|
+
if (__safeKeys.has(propStr)) {
|
|
516
534
|
return target[prop];
|
|
517
535
|
}
|
|
518
|
-
if (prop === '__proto__' || prop === 'prototype') return undefined;
|
|
519
536
|
if (Object.prototype.hasOwnProperty.call(target, prop)) {
|
|
520
537
|
const val = target[prop];
|
|
521
538
|
if (val && typeof val === 'object') {
|
|
@@ -555,8 +572,11 @@ function generateFuzzyProxy(targetVarName, contextName, helpString) {
|
|
|
555
572
|
get(target, prop) {
|
|
556
573
|
if (typeof prop !== 'string') return undefined;
|
|
557
574
|
|
|
558
|
-
// Block prototype pollution vectors
|
|
559
|
-
|
|
575
|
+
// Block prototype pollution vectors with a loud error so callers cannot silently
|
|
576
|
+
// probe the proxy for __proto__ or prototype indirection.
|
|
577
|
+
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
|
|
578
|
+
throw new TypeError('Access to "' + prop + '" is not allowed on ${safeContextName}');
|
|
579
|
+
}
|
|
560
580
|
|
|
561
581
|
// Fast-path: exact match \u2014 use hasOwnProperty to avoid prototype chain leaks
|
|
562
582
|
if (Object.prototype.hasOwnProperty.call(target, prop)) return target[prop];
|
|
@@ -1981,7 +2001,7 @@ __name(createMcpExecServer, "createMcpExecServer");
|
|
|
1981
2001
|
// dist/index.js
|
|
1982
2002
|
import { ServerPool, createConnection, getServerConfig as getServerConfig2, loadServerManifest as loadServerManifest2, cleanupOrphanedProcesses } from "@justanothermldude/meta-mcp-core";
|
|
1983
2003
|
var APP_NAME = "mcp-exec";
|
|
1984
|
-
var VERSION2 = "1.7.
|
|
2004
|
+
var VERSION2 = "1.7.4";
|
|
1985
2005
|
var defaultExecutor = null;
|
|
1986
2006
|
function getDefaultExecutor() {
|
|
1987
2007
|
if (!defaultExecutor) {
|
|
@@ -44,7 +44,12 @@ function compactTypeHint(propSchema) {
|
|
|
44
44
|
const keys = Object.keys(props);
|
|
45
45
|
if (keys.length === 0)
|
|
46
46
|
return 'object';
|
|
47
|
-
const
|
|
47
|
+
const PRIM = new Set(['string', 'number', 'integer', 'boolean']);
|
|
48
|
+
const parts = keys.map(k => {
|
|
49
|
+
const sub = props[k]?.type;
|
|
50
|
+
const sfx = required.includes(k) ? '' : '?';
|
|
51
|
+
return PRIM.has(sub ?? '') ? `${k}${sfx}:${sub}` : `${k}${sfx}`;
|
|
52
|
+
});
|
|
48
53
|
return `{${parts.join(', ')}}`;
|
|
49
54
|
}
|
|
50
55
|
// Freeform object — AI must call get_mcp_tool_schema before using
|
|
@@ -58,7 +63,12 @@ function compactTypeHint(propSchema) {
|
|
|
58
63
|
const props = items.properties;
|
|
59
64
|
const required = items.required || [];
|
|
60
65
|
const keys = Object.keys(props);
|
|
61
|
-
const
|
|
66
|
+
const PRIM = new Set(['string', 'number', 'integer', 'boolean']);
|
|
67
|
+
const parts = keys.map(k => {
|
|
68
|
+
const sub = props[k]?.type;
|
|
69
|
+
const sfx = required.includes(k) ? '' : '?';
|
|
70
|
+
return PRIM.has(sub ?? '') ? `${k}${sfx}:${sub}` : `${k}${sfx}`;
|
|
71
|
+
});
|
|
62
72
|
return `[{${parts.join(', ')}}]`;
|
|
63
73
|
}
|
|
64
74
|
// Simple typed arrays (string[], number[]) — usually obvious
|