@probelabs/probe 0.6.0-rc207 → 0.6.0-rc209
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/bin/binaries/probe-v0.6.0-rc209-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc209-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc209-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc209-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc209-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.d.ts +4 -2
- package/build/agent/ProbeAgent.js +2 -1
- package/build/agent/bashPermissions.js +88 -7
- package/build/agent/index.js +342 -24
- package/build/agent/mcp/client.js +236 -5
- package/build/agent/mcp/config.js +87 -0
- package/build/agent/mcp/xmlBridge.js +15 -5
- package/build/agent/simpleTelemetry.js +26 -0
- package/build/tools/bash.js +5 -3
- package/cjs/agent/ProbeAgent.cjs +314 -18
- package/cjs/agent/simpleTelemetry.cjs +22 -0
- package/cjs/index.cjs +336 -18
- package/index.d.ts +4 -2
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +4 -2
- package/src/agent/ProbeAgent.js +2 -1
- package/src/agent/bashPermissions.js +88 -7
- package/src/agent/index.js +5 -5
- package/src/agent/mcp/client.js +236 -5
- package/src/agent/mcp/config.js +87 -0
- package/src/agent/mcp/xmlBridge.js +15 -5
- package/src/agent/simpleTelemetry.js +26 -0
- package/src/tools/bash.js +5 -3
- package/bin/binaries/probe-v0.6.0-rc207-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc207-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc207-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc207-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc207-x86_64-unknown-linux-musl.tar.gz +0 -0
package/src/agent/mcp/config.js
CHANGED
|
@@ -29,6 +29,61 @@ export function validateTimeout(value) {
|
|
|
29
29
|
return Math.min(num, MAX_TIMEOUT); // Cap at max timeout
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Validate and normalize method filter configuration
|
|
34
|
+
* @param {Object} serverConfig - Server configuration
|
|
35
|
+
* @param {string} serverName - Server name for logging
|
|
36
|
+
* @returns {Object} Object with allowedMethods and blockedMethods (null if not configured)
|
|
37
|
+
*/
|
|
38
|
+
export function validateMethodFilter(serverConfig, serverName = 'unknown') {
|
|
39
|
+
const result = { allowedMethods: null, blockedMethods: null };
|
|
40
|
+
const debug = process.env.DEBUG === '1' || process.env.DEBUG_MCP === '1';
|
|
41
|
+
|
|
42
|
+
// Check if both are specified - allowedMethods takes precedence
|
|
43
|
+
if (serverConfig.allowedMethods && serverConfig.blockedMethods) {
|
|
44
|
+
console.error(`[MCP WARN] Server '${serverName}' has both allowedMethods and blockedMethods - using allowedMethods only`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Process allowedMethods
|
|
48
|
+
if (serverConfig.allowedMethods) {
|
|
49
|
+
if (!Array.isArray(serverConfig.allowedMethods)) {
|
|
50
|
+
console.error(`[MCP WARN] Server '${serverName}' allowedMethods must be an array, ignoring`);
|
|
51
|
+
} else {
|
|
52
|
+
const validMethods = serverConfig.allowedMethods.filter(m => typeof m === 'string' && m.length > 0);
|
|
53
|
+
if (validMethods.length !== serverConfig.allowedMethods.length) {
|
|
54
|
+
console.error(`[MCP WARN] Server '${serverName}' allowedMethods contains non-string values, skipping those`);
|
|
55
|
+
}
|
|
56
|
+
if (validMethods.length > 0) {
|
|
57
|
+
result.allowedMethods = validMethods;
|
|
58
|
+
if (debug) {
|
|
59
|
+
console.error(`[MCP DEBUG] Server '${serverName}' allowedMethods: ${validMethods.join(', ')}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result; // If allowedMethods is specified (even if invalid), don't process blockedMethods
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Process blockedMethods (only if allowedMethods not specified)
|
|
67
|
+
if (serverConfig.blockedMethods) {
|
|
68
|
+
if (!Array.isArray(serverConfig.blockedMethods)) {
|
|
69
|
+
console.error(`[MCP WARN] Server '${serverName}' blockedMethods must be an array, ignoring`);
|
|
70
|
+
} else {
|
|
71
|
+
const validMethods = serverConfig.blockedMethods.filter(m => typeof m === 'string' && m.length > 0);
|
|
72
|
+
if (validMethods.length !== serverConfig.blockedMethods.length) {
|
|
73
|
+
console.error(`[MCP WARN] Server '${serverName}' blockedMethods contains non-string values, skipping those`);
|
|
74
|
+
}
|
|
75
|
+
if (validMethods.length > 0) {
|
|
76
|
+
result.blockedMethods = validMethods;
|
|
77
|
+
if (debug) {
|
|
78
|
+
console.error(`[MCP DEBUG] Server '${serverName}' blockedMethods: ${validMethods.join(', ')}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
32
87
|
/**
|
|
33
88
|
* Default MCP configuration structure
|
|
34
89
|
*/
|
|
@@ -187,6 +242,16 @@ function mergeWithEnvironment(config) {
|
|
|
187
242
|
console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
|
|
188
243
|
}
|
|
189
244
|
break;
|
|
245
|
+
case 'ALLOWLIST':
|
|
246
|
+
// Comma-separated list of allowed method names (supports wildcards)
|
|
247
|
+
// e.g., MCP_SERVERS_MYSERVER_ALLOWLIST=method1,method2,prefix_*
|
|
248
|
+
config.mcpServers[normalizedName].allowedMethods = value.split(',').map(m => m.trim()).filter(Boolean);
|
|
249
|
+
break;
|
|
250
|
+
case 'BLOCKLIST':
|
|
251
|
+
// Comma-separated list of blocked method names (supports wildcards)
|
|
252
|
+
// e.g., MCP_SERVERS_MYSERVER_BLOCKLIST=dangerous_*,risky_method
|
|
253
|
+
config.mcpServers[normalizedName].blockedMethods = value.split(',').map(m => m.trim()).filter(Boolean);
|
|
254
|
+
break;
|
|
190
255
|
}
|
|
191
256
|
}
|
|
192
257
|
}
|
|
@@ -256,6 +321,11 @@ export function parseEnabledServers(config) {
|
|
|
256
321
|
server.timeout = validatedTimeout;
|
|
257
322
|
}
|
|
258
323
|
|
|
324
|
+
// Validate and normalize method filter configuration
|
|
325
|
+
const methodFilter = validateMethodFilter(serverConfig, name);
|
|
326
|
+
server.allowedMethods = methodFilter.allowedMethods;
|
|
327
|
+
server.blockedMethods = methodFilter.blockedMethods;
|
|
328
|
+
|
|
259
329
|
servers.push(server);
|
|
260
330
|
}
|
|
261
331
|
|
|
@@ -321,6 +391,22 @@ export function createSampleConfig() {
|
|
|
321
391
|
enabled: false,
|
|
322
392
|
timeout: 120000,
|
|
323
393
|
description: 'Example server with custom 2-minute timeout (overrides global setting)'
|
|
394
|
+
},
|
|
395
|
+
'filtered-server-example': {
|
|
396
|
+
command: 'npx',
|
|
397
|
+
args: ['-y', '@example/mcp-server'],
|
|
398
|
+
transport: 'stdio',
|
|
399
|
+
enabled: false,
|
|
400
|
+
allowedMethods: ['safe_read', 'safe_query'],
|
|
401
|
+
description: 'Example server with method allowlist - only safe_read and safe_query are available'
|
|
402
|
+
},
|
|
403
|
+
'blocklist-server-example': {
|
|
404
|
+
command: 'npx',
|
|
405
|
+
args: ['-y', '@example/mcp-server'],
|
|
406
|
+
transport: 'stdio',
|
|
407
|
+
enabled: false,
|
|
408
|
+
blockedMethods: ['dangerous_delete', 'dangerous_*'],
|
|
409
|
+
description: 'Example server with method blocklist - all methods except dangerous ones (supports wildcards)'
|
|
324
410
|
}
|
|
325
411
|
},
|
|
326
412
|
// Global settings (apply to all servers unless overridden per-server)
|
|
@@ -356,6 +442,7 @@ export default {
|
|
|
356
442
|
createSampleConfig,
|
|
357
443
|
saveConfig,
|
|
358
444
|
validateTimeout,
|
|
445
|
+
validateMethodFilter,
|
|
359
446
|
DEFAULT_TIMEOUT,
|
|
360
447
|
MAX_TIMEOUT
|
|
361
448
|
};
|
|
@@ -127,6 +127,7 @@ export function parseXmlMcpToolCall(xmlString, mcpToolNames = []) {
|
|
|
127
127
|
export class MCPXmlBridge {
|
|
128
128
|
constructor(options = {}) {
|
|
129
129
|
this.debug = options.debug || false;
|
|
130
|
+
this.tracer = options.tracer || null;
|
|
130
131
|
this.mcpTools = {};
|
|
131
132
|
this.mcpManager = null;
|
|
132
133
|
this.xmlDefinitions = {};
|
|
@@ -179,8 +180,8 @@ export class MCPXmlBridge {
|
|
|
179
180
|
console.error('[MCP DEBUG] Initializing MCP client manager...');
|
|
180
181
|
}
|
|
181
182
|
|
|
182
|
-
// Initialize the MCP client manager
|
|
183
|
-
this.mcpManager = new MCPClientManager({ debug: this.debug });
|
|
183
|
+
// Initialize the MCP client manager with tracer support
|
|
184
|
+
this.mcpManager = new MCPClientManager({ debug: this.debug, tracer: this.tracer });
|
|
184
185
|
const result = await this.mcpManager.initialize(mcpConfigs);
|
|
185
186
|
|
|
186
187
|
// Get tools from the manager
|
|
@@ -211,11 +212,20 @@ export class MCPXmlBridge {
|
|
|
211
212
|
}
|
|
212
213
|
|
|
213
214
|
/**
|
|
214
|
-
* Get
|
|
215
|
+
* Get XML tool definitions for inclusion in system prompt
|
|
216
|
+
* @param {Array<string>|null} filterToolNames - Optional list of tool names to include (if null, include all)
|
|
215
217
|
* @returns {string} Combined XML tool definitions
|
|
216
218
|
*/
|
|
217
|
-
getXmlToolDefinitions() {
|
|
218
|
-
|
|
219
|
+
getXmlToolDefinitions(filterToolNames = null) {
|
|
220
|
+
if (filterToolNames === null) {
|
|
221
|
+
return Object.values(this.xmlDefinitions).join('\n\n');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Filter definitions based on provided tool names
|
|
225
|
+
return Object.entries(this.xmlDefinitions)
|
|
226
|
+
.filter(([name]) => filterToolNames.includes(name))
|
|
227
|
+
.map(([, def]) => def)
|
|
228
|
+
.join('\n\n');
|
|
219
229
|
}
|
|
220
230
|
|
|
221
231
|
/**
|
|
@@ -231,6 +231,32 @@ export class SimpleAppTracer {
|
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Record MCP (Model Context Protocol) events
|
|
236
|
+
* Tracks server connections, tool discovery, method filtering, and tool execution
|
|
237
|
+
*/
|
|
238
|
+
recordMcpEvent(eventType, data = {}) {
|
|
239
|
+
if (!this.isEnabled()) return;
|
|
240
|
+
|
|
241
|
+
this.addEvent(`mcp.${eventType}`, {
|
|
242
|
+
'session.id': this.sessionId,
|
|
243
|
+
...data
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Record bash tool events
|
|
249
|
+
* Tracks command permission checks, allowed/denied commands, and execution
|
|
250
|
+
*/
|
|
251
|
+
recordBashEvent(eventType, data = {}) {
|
|
252
|
+
if (!this.isEnabled()) return;
|
|
253
|
+
|
|
254
|
+
this.addEvent(`bash.${eventType}`, {
|
|
255
|
+
'session.id': this.sessionId,
|
|
256
|
+
...data
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
234
260
|
setAttributes(attributes) {
|
|
235
261
|
// For simplicity, just log attributes when no active span
|
|
236
262
|
if (this.telemetry && this.telemetry.enableConsole) {
|
package/src/tools/bash.js
CHANGED
|
@@ -31,16 +31,18 @@ export const bashTool = (options = {}) => {
|
|
|
31
31
|
bashConfig = {},
|
|
32
32
|
debug = false,
|
|
33
33
|
cwd,
|
|
34
|
-
allowedFolders = []
|
|
34
|
+
allowedFolders = [],
|
|
35
|
+
tracer = null
|
|
35
36
|
} = options;
|
|
36
37
|
|
|
37
|
-
// Create permission checker
|
|
38
|
+
// Create permission checker with tracer for telemetry
|
|
38
39
|
const permissionChecker = new BashPermissionChecker({
|
|
39
40
|
allow: bashConfig.allow,
|
|
40
41
|
deny: bashConfig.deny,
|
|
41
42
|
disableDefaultAllow: bashConfig.disableDefaultAllow,
|
|
42
43
|
disableDefaultDeny: bashConfig.disableDefaultDeny,
|
|
43
|
-
debug
|
|
44
|
+
debug,
|
|
45
|
+
tracer
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
// Determine default working directory
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|