@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.
Files changed (33) hide show
  1. package/bin/binaries/probe-v0.6.0-rc209-aarch64-apple-darwin.tar.gz +0 -0
  2. package/bin/binaries/probe-v0.6.0-rc209-aarch64-unknown-linux-musl.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc209-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc209-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc209-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.d.ts +4 -2
  7. package/build/agent/ProbeAgent.js +2 -1
  8. package/build/agent/bashPermissions.js +88 -7
  9. package/build/agent/index.js +342 -24
  10. package/build/agent/mcp/client.js +236 -5
  11. package/build/agent/mcp/config.js +87 -0
  12. package/build/agent/mcp/xmlBridge.js +15 -5
  13. package/build/agent/simpleTelemetry.js +26 -0
  14. package/build/tools/bash.js +5 -3
  15. package/cjs/agent/ProbeAgent.cjs +314 -18
  16. package/cjs/agent/simpleTelemetry.cjs +22 -0
  17. package/cjs/index.cjs +336 -18
  18. package/index.d.ts +4 -2
  19. package/package.json +1 -1
  20. package/src/agent/ProbeAgent.d.ts +4 -2
  21. package/src/agent/ProbeAgent.js +2 -1
  22. package/src/agent/bashPermissions.js +88 -7
  23. package/src/agent/index.js +5 -5
  24. package/src/agent/mcp/client.js +236 -5
  25. package/src/agent/mcp/config.js +87 -0
  26. package/src/agent/mcp/xmlBridge.js +15 -5
  27. package/src/agent/simpleTelemetry.js +26 -0
  28. package/src/tools/bash.js +5 -3
  29. package/bin/binaries/probe-v0.6.0-rc207-aarch64-apple-darwin.tar.gz +0 -0
  30. package/bin/binaries/probe-v0.6.0-rc207-aarch64-unknown-linux-musl.tar.gz +0 -0
  31. package/bin/binaries/probe-v0.6.0-rc207-x86_64-apple-darwin.tar.gz +0 -0
  32. package/bin/binaries/probe-v0.6.0-rc207-x86_64-pc-windows-msvc.zip +0 -0
  33. package/bin/binaries/probe-v0.6.0-rc207-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -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 all XML tool definitions for inclusion in system prompt
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
- return Object.values(this.xmlDefinitions).join('\n\n');
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