@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
@@ -10601,9 +10601,11 @@ var init_bashPermissions = __esm({
10601
10601
  * @param {boolean} [config.disableDefaultAllow] - Disable default allow list
10602
10602
  * @param {boolean} [config.disableDefaultDeny] - Disable default deny list
10603
10603
  * @param {boolean} [config.debug] - Enable debug logging
10604
+ * @param {Object} [config.tracer] - Optional tracer for telemetry
10604
10605
  */
10605
10606
  constructor(config = {}) {
10606
10607
  this.debug = config.debug || false;
10608
+ this.tracer = config.tracer || null;
10607
10609
  this.allowPatterns = [];
10608
10610
  if (!config.disableDefaultAllow) {
10609
10611
  this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
@@ -10633,6 +10635,24 @@ var init_bashPermissions = __esm({
10633
10635
  if (this.debug) {
10634
10636
  console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
10635
10637
  }
10638
+ this.recordBashEvent("permissions.initialized", {
10639
+ allowPatternCount: this.allowPatterns.length,
10640
+ denyPatternCount: this.denyPatterns.length,
10641
+ hasCustomAllowPatterns: !!(config.allow && config.allow.length > 0),
10642
+ hasCustomDenyPatterns: !!(config.deny && config.deny.length > 0),
10643
+ disableDefaultAllow: !!config.disableDefaultAllow,
10644
+ disableDefaultDeny: !!config.disableDefaultDeny
10645
+ });
10646
+ }
10647
+ /**
10648
+ * Record a bash telemetry event if tracer is available
10649
+ * @param {string} eventType - Event type (e.g., 'permission.checked', 'permission.denied')
10650
+ * @param {Object} data - Event data
10651
+ */
10652
+ recordBashEvent(eventType, data = {}) {
10653
+ if (this.tracer && typeof this.tracer.recordBashEvent === "function") {
10654
+ this.tracer.recordBashEvent(eventType, data);
10655
+ }
10636
10656
  }
10637
10657
  /**
10638
10658
  * Check if a simple command is allowed (complex commands allowed if they match patterns)
@@ -10641,11 +10661,17 @@ var init_bashPermissions = __esm({
10641
10661
  */
10642
10662
  check(command) {
10643
10663
  if (!command || typeof command !== "string") {
10644
- return {
10664
+ const result2 = {
10645
10665
  allowed: false,
10646
10666
  reason: "Invalid or empty command",
10647
10667
  command
10648
10668
  };
10669
+ this.recordBashEvent("permission.denied", {
10670
+ command: String(command),
10671
+ reason: result2.reason,
10672
+ isComplex: false
10673
+ });
10674
+ return result2;
10649
10675
  }
10650
10676
  const commandIsComplex = isComplexCommand(command);
10651
10677
  if (commandIsComplex) {
@@ -10653,18 +10679,31 @@ var init_bashPermissions = __esm({
10653
10679
  }
10654
10680
  const parsed = parseCommand(command);
10655
10681
  if (parsed.error) {
10656
- return {
10682
+ const result2 = {
10657
10683
  allowed: false,
10658
10684
  reason: parsed.error,
10659
10685
  command
10660
10686
  };
10687
+ this.recordBashEvent("permission.denied", {
10688
+ command,
10689
+ reason: result2.reason,
10690
+ isComplex: false,
10691
+ parseError: true
10692
+ });
10693
+ return result2;
10661
10694
  }
10662
10695
  if (!parsed.command) {
10663
- return {
10696
+ const result2 = {
10664
10697
  allowed: false,
10665
10698
  reason: "No valid command found",
10666
10699
  command
10667
10700
  };
10701
+ this.recordBashEvent("permission.denied", {
10702
+ command,
10703
+ reason: result2.reason,
10704
+ isComplex: false
10705
+ });
10706
+ return result2;
10668
10707
  }
10669
10708
  if (this.debug) {
10670
10709
  console.log(`[BashPermissions] Checking simple command: "${command}"`);
@@ -10672,22 +10711,37 @@ var init_bashPermissions = __esm({
10672
10711
  }
10673
10712
  if (matchesAnyPattern(parsed, this.denyPatterns)) {
10674
10713
  const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
10675
- return {
10714
+ const result2 = {
10676
10715
  allowed: false,
10677
10716
  reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
10678
10717
  command,
10679
10718
  parsed,
10680
10719
  matchedPatterns
10681
10720
  };
10721
+ this.recordBashEvent("permission.denied", {
10722
+ command,
10723
+ parsedCommand: parsed.command,
10724
+ reason: "matches_deny_pattern",
10725
+ matchedPattern: matchedPatterns[0],
10726
+ isComplex: false
10727
+ });
10728
+ return result2;
10682
10729
  }
10683
10730
  if (this.allowPatterns.length > 0) {
10684
10731
  if (!matchesAnyPattern(parsed, this.allowPatterns)) {
10685
- return {
10732
+ const result2 = {
10686
10733
  allowed: false,
10687
10734
  reason: "Command not in allow list",
10688
10735
  command,
10689
10736
  parsed
10690
10737
  };
10738
+ this.recordBashEvent("permission.denied", {
10739
+ command,
10740
+ parsedCommand: parsed.command,
10741
+ reason: "not_in_allow_list",
10742
+ isComplex: false
10743
+ });
10744
+ return result2;
10691
10745
  }
10692
10746
  }
10693
10747
  const result = {
@@ -10699,6 +10753,11 @@ var init_bashPermissions = __esm({
10699
10753
  if (this.debug) {
10700
10754
  console.log(`[BashPermissions] ALLOWED - command passed all checks`);
10701
10755
  }
10756
+ this.recordBashEvent("permission.allowed", {
10757
+ command,
10758
+ parsedCommand: parsed.command,
10759
+ isComplex: false
10760
+ });
10702
10761
  return result;
10703
10762
  }
10704
10763
  /**
@@ -10722,13 +10781,20 @@ var init_bashPermissions = __esm({
10722
10781
  if (this.debug) {
10723
10782
  console.log(`[BashPermissions] DENIED - matches complex deny pattern: ${pattern}`);
10724
10783
  }
10725
- return {
10784
+ const result = {
10726
10785
  allowed: false,
10727
10786
  reason: `Command matches deny pattern: ${pattern}`,
10728
10787
  command,
10729
10788
  isComplex: true,
10730
10789
  matchedPatterns: [pattern]
10731
10790
  };
10791
+ this.recordBashEvent("permission.denied", {
10792
+ command,
10793
+ reason: "matches_deny_pattern",
10794
+ matchedPattern: pattern,
10795
+ isComplex: true
10796
+ });
10797
+ return result;
10732
10798
  }
10733
10799
  }
10734
10800
  for (const pattern of complexAllowPatterns) {
@@ -10736,17 +10802,28 @@ var init_bashPermissions = __esm({
10736
10802
  if (this.debug) {
10737
10803
  console.log(`[BashPermissions] ALLOWED - matches complex allow pattern: ${pattern}`);
10738
10804
  }
10739
- return {
10805
+ const result = {
10740
10806
  allowed: true,
10741
10807
  command,
10742
10808
  isComplex: true,
10743
10809
  matchedPattern: pattern
10744
10810
  };
10811
+ this.recordBashEvent("permission.allowed", {
10812
+ command,
10813
+ matchedPattern: pattern,
10814
+ isComplex: true
10815
+ });
10816
+ return result;
10745
10817
  }
10746
10818
  }
10747
10819
  if (this.debug) {
10748
10820
  console.log(`[BashPermissions] DENIED - no matching complex pattern found`);
10749
10821
  }
10822
+ this.recordBashEvent("permission.denied", {
10823
+ command,
10824
+ reason: "no_matching_complex_pattern",
10825
+ isComplex: true
10826
+ });
10750
10827
  return {
10751
10828
  allowed: false,
10752
10829
  reason: 'Complex shell commands require explicit allow patterns (e.g., "cd * && git *")',
@@ -11044,14 +11121,16 @@ var init_bash = __esm({
11044
11121
  bashConfig = {},
11045
11122
  debug = false,
11046
11123
  cwd,
11047
- allowedFolders = []
11124
+ allowedFolders = [],
11125
+ tracer = null
11048
11126
  } = options;
11049
11127
  const permissionChecker = new BashPermissionChecker({
11050
11128
  allow: bashConfig.allow,
11051
11129
  deny: bashConfig.deny,
11052
11130
  disableDefaultAllow: bashConfig.disableDefaultAllow,
11053
11131
  disableDefaultDeny: bashConfig.disableDefaultDeny,
11054
- debug
11132
+ debug,
11133
+ tracer
11055
11134
  });
11056
11135
  const getDefaultWorkingDirectory = () => {
11057
11136
  if (bashConfig.workingDirectory) {
@@ -11681,6 +11760,28 @@ var init_simpleTelemetry = __esm({
11681
11760
  ...data
11682
11761
  });
11683
11762
  }
11763
+ /**
11764
+ * Record MCP (Model Context Protocol) events
11765
+ * Tracks server connections, tool discovery, method filtering, and tool execution
11766
+ */
11767
+ recordMcpEvent(eventType, data = {}) {
11768
+ if (!this.isEnabled()) return;
11769
+ this.addEvent(`mcp.${eventType}`, {
11770
+ "session.id": this.sessionId,
11771
+ ...data
11772
+ });
11773
+ }
11774
+ /**
11775
+ * Record bash tool events
11776
+ * Tracks command permission checks, allowed/denied commands, and execution
11777
+ */
11778
+ recordBashEvent(eventType, data = {}) {
11779
+ if (!this.isEnabled()) return;
11780
+ this.addEvent(`bash.${eventType}`, {
11781
+ "session.id": this.sessionId,
11782
+ ...data
11783
+ });
11784
+ }
11684
11785
  setAttributes(attributes) {
11685
11786
  if (this.telemetry && this.telemetry.enableConsole) {
11686
11787
  console.log("[Attributes]", attributes);
@@ -57907,6 +58008,47 @@ function validateTimeout(value) {
57907
58008
  if (!Number.isFinite(num) || num < 0) return void 0;
57908
58009
  return Math.min(num, MAX_TIMEOUT);
57909
58010
  }
58011
+ function validateMethodFilter(serverConfig, serverName = "unknown") {
58012
+ const result = { allowedMethods: null, blockedMethods: null };
58013
+ const debug = process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1";
58014
+ if (serverConfig.allowedMethods && serverConfig.blockedMethods) {
58015
+ console.error(`[MCP WARN] Server '${serverName}' has both allowedMethods and blockedMethods - using allowedMethods only`);
58016
+ }
58017
+ if (serverConfig.allowedMethods) {
58018
+ if (!Array.isArray(serverConfig.allowedMethods)) {
58019
+ console.error(`[MCP WARN] Server '${serverName}' allowedMethods must be an array, ignoring`);
58020
+ } else {
58021
+ const validMethods = serverConfig.allowedMethods.filter((m) => typeof m === "string" && m.length > 0);
58022
+ if (validMethods.length !== serverConfig.allowedMethods.length) {
58023
+ console.error(`[MCP WARN] Server '${serverName}' allowedMethods contains non-string values, skipping those`);
58024
+ }
58025
+ if (validMethods.length > 0) {
58026
+ result.allowedMethods = validMethods;
58027
+ if (debug) {
58028
+ console.error(`[MCP DEBUG] Server '${serverName}' allowedMethods: ${validMethods.join(", ")}`);
58029
+ }
58030
+ }
58031
+ }
58032
+ return result;
58033
+ }
58034
+ if (serverConfig.blockedMethods) {
58035
+ if (!Array.isArray(serverConfig.blockedMethods)) {
58036
+ console.error(`[MCP WARN] Server '${serverName}' blockedMethods must be an array, ignoring`);
58037
+ } else {
58038
+ const validMethods = serverConfig.blockedMethods.filter((m) => typeof m === "string" && m.length > 0);
58039
+ if (validMethods.length !== serverConfig.blockedMethods.length) {
58040
+ console.error(`[MCP WARN] Server '${serverName}' blockedMethods contains non-string values, skipping those`);
58041
+ }
58042
+ if (validMethods.length > 0) {
58043
+ result.blockedMethods = validMethods;
58044
+ if (debug) {
58045
+ console.error(`[MCP DEBUG] Server '${serverName}' blockedMethods: ${validMethods.join(", ")}`);
58046
+ }
58047
+ }
58048
+ }
58049
+ }
58050
+ return result;
58051
+ }
57910
58052
  function loadMCPConfigurationFromPath(configPath) {
57911
58053
  if (!configPath) {
57912
58054
  throw new Error("Config path is required");
@@ -58000,6 +58142,12 @@ function mergeWithEnvironment(config) {
58000
58142
  console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
58001
58143
  }
58002
58144
  break;
58145
+ case "ALLOWLIST":
58146
+ config.mcpServers[normalizedName].allowedMethods = value.split(",").map((m) => m.trim()).filter(Boolean);
58147
+ break;
58148
+ case "BLOCKLIST":
58149
+ config.mcpServers[normalizedName].blockedMethods = value.split(",").map((m) => m.trim()).filter(Boolean);
58150
+ break;
58003
58151
  }
58004
58152
  }
58005
58153
  }
@@ -58050,6 +58198,9 @@ function parseEnabledServers(config) {
58050
58198
  }
58051
58199
  server.timeout = validatedTimeout;
58052
58200
  }
58201
+ const methodFilter = validateMethodFilter(serverConfig, name);
58202
+ server.allowedMethods = methodFilter.allowedMethods;
58203
+ server.blockedMethods = methodFilter.blockedMethods;
58053
58204
  servers.push(server);
58054
58205
  }
58055
58206
  return servers;
@@ -58087,6 +58238,22 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
58087
58238
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
58088
58239
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
58089
58240
  import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
58241
+ function isMethodAllowed(methodName, allowedMethods, blockedMethods) {
58242
+ const matchesPattern2 = (name, pattern) => {
58243
+ if (!pattern.includes("*")) {
58244
+ return name === pattern;
58245
+ }
58246
+ const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
58247
+ return new RegExp(`^${regexPattern}$`).test(name);
58248
+ };
58249
+ if (allowedMethods && allowedMethods.length > 0) {
58250
+ return allowedMethods.some((pattern) => matchesPattern2(methodName, pattern));
58251
+ }
58252
+ if (blockedMethods && blockedMethods.length > 0) {
58253
+ return !blockedMethods.some((pattern) => matchesPattern2(methodName, pattern));
58254
+ }
58255
+ return true;
58256
+ }
58090
58257
  function createTransport(serverConfig) {
58091
58258
  const { transport, command, args, url, env } = serverConfig;
58092
58259
  switch (transport) {
@@ -58167,6 +58334,17 @@ var init_client = __esm({
58167
58334
  this.tools = /* @__PURE__ */ new Map();
58168
58335
  this.debug = options.debug || process.env.DEBUG_MCP === "1";
58169
58336
  this.config = null;
58337
+ this.tracer = options.tracer || null;
58338
+ }
58339
+ /**
58340
+ * Record an MCP telemetry event if tracer is available
58341
+ * @param {string} eventType - Event type (e.g., 'server.connect', 'tool.discovered')
58342
+ * @param {Object} data - Event data
58343
+ */
58344
+ recordMcpEvent(eventType, data = {}) {
58345
+ if (this.tracer && typeof this.tracer.recordMcpEvent === "function") {
58346
+ this.tracer.recordMcpEvent(eventType, data);
58347
+ }
58170
58348
  }
58171
58349
  /**
58172
58350
  * Initialize MCP clients from configuration
@@ -58175,10 +58353,20 @@ var init_client = __esm({
58175
58353
  async initialize(config = null) {
58176
58354
  this.config = config || loadMCPConfiguration();
58177
58355
  const servers = parseEnabledServers(this.config);
58356
+ this.recordMcpEvent("initialization.started", {
58357
+ serverCount: servers.length,
58358
+ serverNames: servers.map((s) => s.name)
58359
+ });
58178
58360
  console.error(`[MCP INFO] Found ${servers.length} enabled MCP server${servers.length !== 1 ? "s" : ""}`);
58179
58361
  if (servers.length === 0) {
58180
58362
  console.error("[MCP INFO] No MCP servers configured or enabled");
58181
58363
  console.error("[MCP INFO] 0 MCP tools available");
58364
+ this.recordMcpEvent("initialization.completed", {
58365
+ connected: 0,
58366
+ total: 0,
58367
+ toolCount: 0,
58368
+ tools: []
58369
+ });
58182
58370
  return {
58183
58371
  connected: 0,
58184
58372
  total: 0,
@@ -58215,10 +58403,17 @@ var init_client = __esm({
58215
58403
  console.error(`[MCP DEBUG] - ${toolName}`);
58216
58404
  });
58217
58405
  }
58406
+ const toolNames = Array.from(this.tools.keys());
58407
+ this.recordMcpEvent("initialization.completed", {
58408
+ connected: connectedCount,
58409
+ total: servers.length,
58410
+ toolCount: this.tools.size,
58411
+ tools: toolNames
58412
+ });
58218
58413
  return {
58219
58414
  connected: connectedCount,
58220
58415
  total: servers.length,
58221
- tools: Array.from(this.tools.keys())
58416
+ tools: toolNames
58222
58417
  };
58223
58418
  }
58224
58419
  /**
@@ -58227,6 +58422,12 @@ var init_client = __esm({
58227
58422
  */
58228
58423
  async connectToServer(serverConfig) {
58229
58424
  const { name } = serverConfig;
58425
+ this.recordMcpEvent("server.connecting", {
58426
+ serverName: name,
58427
+ transport: serverConfig.transport,
58428
+ hasAllowedMethods: !!(serverConfig.allowedMethods && serverConfig.allowedMethods.length > 0),
58429
+ hasBlockedMethods: !!(serverConfig.blockedMethods && serverConfig.blockedMethods.length > 0)
58430
+ });
58230
58431
  try {
58231
58432
  if (this.debug) {
58232
58433
  console.error(`[MCP DEBUG] Connecting to ${name} via ${serverConfig.transport}...`);
@@ -58248,27 +58449,92 @@ var init_client = __esm({
58248
58449
  config: serverConfig
58249
58450
  });
58250
58451
  const toolsResponse = await client.listTools();
58251
- const toolCount = toolsResponse?.tools?.length || 0;
58452
+ const totalToolCount = toolsResponse?.tools?.length || 0;
58453
+ let registeredCount = 0;
58454
+ let filteredCount = 0;
58455
+ const registeredTools = [];
58456
+ const filteredTools = [];
58252
58457
  if (toolsResponse && toolsResponse.tools) {
58458
+ const { allowedMethods, blockedMethods } = serverConfig;
58459
+ const allToolNames = toolsResponse.tools.map((t) => t.name);
58460
+ this.recordMcpEvent("tools.discovered", {
58461
+ serverName: name,
58462
+ toolCount: totalToolCount,
58463
+ tools: allToolNames
58464
+ });
58253
58465
  for (const tool4 of toolsResponse.tools) {
58466
+ if (!isMethodAllowed(tool4.name, allowedMethods, blockedMethods)) {
58467
+ filteredCount++;
58468
+ filteredTools.push(tool4.name);
58469
+ if (this.debug) {
58470
+ console.error(`[MCP DEBUG] Filtered out tool: ${tool4.name} (not allowed by method filter)`);
58471
+ }
58472
+ continue;
58473
+ }
58254
58474
  const qualifiedName = `${name}_${tool4.name}`;
58255
58475
  this.tools.set(qualifiedName, {
58256
58476
  ...tool4,
58257
58477
  serverName: name,
58258
58478
  originalName: tool4.name
58259
58479
  });
58480
+ registeredCount++;
58481
+ registeredTools.push(qualifiedName);
58260
58482
  if (this.debug) {
58261
58483
  console.error(`[MCP DEBUG] Registered tool: ${qualifiedName}`);
58262
58484
  }
58263
58485
  }
58486
+ if (filteredCount > 0) {
58487
+ this.recordMcpEvent("tools.filtered", {
58488
+ serverName: name,
58489
+ filteredCount,
58490
+ filteredTools,
58491
+ allowedMethods: allowedMethods || [],
58492
+ blockedMethods: blockedMethods || []
58493
+ });
58494
+ }
58495
+ if (allowedMethods && allowedMethods.length > 0) {
58496
+ const unmatchedPatterns = allowedMethods.filter((pattern) => {
58497
+ return !allToolNames.some((toolName) => isMethodAllowed(toolName, [pattern], null));
58498
+ });
58499
+ if (unmatchedPatterns.length > 0) {
58500
+ console.error(`[MCP WARN] Server '${name}': The following allowedMethods patterns did not match any tools: ${unmatchedPatterns.join(", ")}`);
58501
+ console.error(`[MCP WARN] Available methods from '${name}': ${allToolNames.join(", ")}`);
58502
+ }
58503
+ }
58504
+ if (blockedMethods && blockedMethods.length > 0) {
58505
+ const unmatchedPatterns = blockedMethods.filter((pattern) => {
58506
+ return !allToolNames.some((toolName) => !isMethodAllowed(toolName, null, [pattern]));
58507
+ });
58508
+ if (unmatchedPatterns.length > 0) {
58509
+ console.error(`[MCP WARN] Server '${name}': The following blockedMethods patterns did not match any tools: ${unmatchedPatterns.join(", ")}`);
58510
+ console.error(`[MCP WARN] Available methods from '${name}': ${allToolNames.join(", ")}`);
58511
+ }
58512
+ }
58264
58513
  }
58265
- console.error(`[MCP INFO] Connected to ${name}: ${toolCount} tool${toolCount !== 1 ? "s" : ""} loaded`);
58514
+ if (filteredCount > 0) {
58515
+ console.error(`[MCP INFO] Connected to ${name}: ${registeredCount} tool${registeredCount !== 1 ? "s" : ""} loaded (${filteredCount} filtered out)`);
58516
+ } else {
58517
+ console.error(`[MCP INFO] Connected to ${name}: ${registeredCount} tool${registeredCount !== 1 ? "s" : ""} loaded`);
58518
+ }
58519
+ this.recordMcpEvent("server.connected", {
58520
+ serverName: name,
58521
+ transport: serverConfig.transport,
58522
+ totalToolCount,
58523
+ registeredCount,
58524
+ filteredCount,
58525
+ registeredTools
58526
+ });
58266
58527
  return true;
58267
58528
  } catch (error) {
58268
58529
  console.error(`[MCP ERROR] Error connecting to ${name}:`, error.message);
58269
58530
  if (this.debug) {
58270
58531
  console.error(`[MCP DEBUG] Full error details:`, error);
58271
58532
  }
58533
+ this.recordMcpEvent("server.connection_failed", {
58534
+ serverName: name,
58535
+ transport: serverConfig.transport,
58536
+ error: error.message
58537
+ });
58272
58538
  return false;
58273
58539
  }
58274
58540
  }
@@ -58280,12 +58546,27 @@ var init_client = __esm({
58280
58546
  async callTool(toolName, args) {
58281
58547
  const tool4 = this.tools.get(toolName);
58282
58548
  if (!tool4) {
58549
+ this.recordMcpEvent("tool.call_failed", {
58550
+ toolName,
58551
+ error: "Unknown tool"
58552
+ });
58283
58553
  throw new Error(`Unknown tool: ${toolName}`);
58284
58554
  }
58285
58555
  const clientInfo = this.clients.get(tool4.serverName);
58286
58556
  if (!clientInfo) {
58557
+ this.recordMcpEvent("tool.call_failed", {
58558
+ toolName,
58559
+ serverName: tool4.serverName,
58560
+ error: "Server not connected"
58561
+ });
58287
58562
  throw new Error(`Server ${tool4.serverName} not connected`);
58288
58563
  }
58564
+ const startTime = Date.now();
58565
+ this.recordMcpEvent("tool.call_started", {
58566
+ toolName,
58567
+ serverName: tool4.serverName,
58568
+ originalToolName: tool4.originalName
58569
+ });
58289
58570
  try {
58290
58571
  if (this.debug) {
58291
58572
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
@@ -58302,18 +58583,34 @@ var init_client = __esm({
58302
58583
  clientInfo.client.callTool({
58303
58584
  name: tool4.originalName,
58304
58585
  arguments: args
58305
- }),
58586
+ }, void 0, { timeout }),
58306
58587
  timeoutPromise
58307
58588
  ]);
58589
+ const durationMs = Date.now() - startTime;
58308
58590
  if (this.debug) {
58309
58591
  console.error(`[MCP DEBUG] Tool ${toolName} executed successfully`);
58310
58592
  }
58593
+ this.recordMcpEvent("tool.call_completed", {
58594
+ toolName,
58595
+ serverName: tool4.serverName,
58596
+ originalToolName: tool4.originalName,
58597
+ durationMs
58598
+ });
58311
58599
  return result;
58312
58600
  } catch (error) {
58601
+ const durationMs = Date.now() - startTime;
58313
58602
  console.error(`[MCP ERROR] Error calling tool ${toolName}:`, error.message);
58314
58603
  if (this.debug) {
58315
58604
  console.error(`[MCP DEBUG] Full error details:`, error);
58316
58605
  }
58606
+ this.recordMcpEvent("tool.call_failed", {
58607
+ toolName,
58608
+ serverName: tool4.serverName,
58609
+ originalToolName: tool4.originalName,
58610
+ error: error.message,
58611
+ durationMs,
58612
+ isTimeout: error.message.includes("timeout")
58613
+ });
58317
58614
  throw error;
58318
58615
  }
58319
58616
  }
@@ -58358,12 +58655,17 @@ var init_client = __esm({
58358
58655
  */
58359
58656
  async disconnect() {
58360
58657
  const disconnectPromises = [];
58658
+ const serverNames = Array.from(this.clients.keys());
58361
58659
  if (this.clients.size === 0) {
58362
58660
  if (this.debug) {
58363
58661
  console.error("[MCP DEBUG] No MCP clients to disconnect");
58364
58662
  }
58365
58663
  return;
58366
58664
  }
58665
+ this.recordMcpEvent("disconnection.started", {
58666
+ serverCount: this.clients.size,
58667
+ serverNames
58668
+ });
58367
58669
  if (this.debug) {
58368
58670
  console.error(`[MCP DEBUG] Disconnecting from ${this.clients.size} MCP server${this.clients.size !== 1 ? "s" : ""}...`);
58369
58671
  }
@@ -58373,14 +58675,25 @@ var init_client = __esm({
58373
58675
  if (this.debug) {
58374
58676
  console.error(`[MCP DEBUG] Disconnected from ${name}`);
58375
58677
  }
58678
+ this.recordMcpEvent("server.disconnected", {
58679
+ serverName: name
58680
+ });
58376
58681
  }).catch((error) => {
58377
58682
  console.error(`[MCP ERROR] Error disconnecting from ${name}:`, error.message);
58683
+ this.recordMcpEvent("server.disconnect_failed", {
58684
+ serverName: name,
58685
+ error: error.message
58686
+ });
58378
58687
  })
58379
58688
  );
58380
58689
  }
58381
58690
  await Promise.all(disconnectPromises);
58382
58691
  this.clients.clear();
58383
58692
  this.tools.clear();
58693
+ this.recordMcpEvent("disconnection.completed", {
58694
+ serverCount: serverNames.length,
58695
+ serverNames
58696
+ });
58384
58697
  if (this.debug) {
58385
58698
  console.error("[MCP DEBUG] All MCP connections closed");
58386
58699
  }
@@ -58524,6 +58837,7 @@ var init_xmlBridge = __esm({
58524
58837
  MCPXmlBridge = class {
58525
58838
  constructor(options = {}) {
58526
58839
  this.debug = options.debug || false;
58840
+ this.tracer = options.tracer || null;
58527
58841
  this.mcpTools = {};
58528
58842
  this.mcpManager = null;
58529
58843
  this.xmlDefinitions = {};
@@ -58566,7 +58880,7 @@ var init_xmlBridge = __esm({
58566
58880
  if (this.debug) {
58567
58881
  console.error("[MCP DEBUG] Initializing MCP client manager...");
58568
58882
  }
58569
- this.mcpManager = new MCPClientManager({ debug: this.debug });
58883
+ this.mcpManager = new MCPClientManager({ debug: this.debug, tracer: this.tracer });
58570
58884
  const result = await this.mcpManager.initialize(mcpConfigs);
58571
58885
  const vercelTools = this.mcpManager.getVercelTools();
58572
58886
  this.mcpTools = vercelTools;
@@ -58590,11 +58904,15 @@ var init_xmlBridge = __esm({
58590
58904
  }
58591
58905
  }
58592
58906
  /**
58593
- * Get all XML tool definitions for inclusion in system prompt
58907
+ * Get XML tool definitions for inclusion in system prompt
58908
+ * @param {Array<string>|null} filterToolNames - Optional list of tool names to include (if null, include all)
58594
58909
  * @returns {string} Combined XML tool definitions
58595
58910
  */
58596
- getXmlToolDefinitions() {
58597
- return Object.values(this.xmlDefinitions).join("\n\n");
58911
+ getXmlToolDefinitions(filterToolNames = null) {
58912
+ if (filterToolNames === null) {
58913
+ return Object.values(this.xmlDefinitions).join("\n\n");
58914
+ }
58915
+ return Object.entries(this.xmlDefinitions).filter(([name]) => filterToolNames.includes(name)).map(([, def]) => def).join("\n\n");
58598
58916
  }
58599
58917
  /**
58600
58918
  * Get list of MCP tool names
@@ -68820,7 +69138,7 @@ var init_ProbeAgent = __esm({
68820
69138
  this.maxIterations = options.maxIterations || null;
68821
69139
  this.disableMermaidValidation = !!options.disableMermaidValidation;
68822
69140
  this.disableJsonValidation = !!options.disableJsonValidation;
68823
- this.enableSkills = options.disableSkills ? false : options.enableSkills !== void 0 ? !!options.enableSkills : true;
69141
+ this.enableSkills = options.disableSkills ? false : !!(options.allowSkills || options.enableSkills);
68824
69142
  if (Array.isArray(options.skillDirs)) {
68825
69143
  this.skillDirs = options.skillDirs;
68826
69144
  } else if (typeof options.skillDirs === "string") {
@@ -72797,8 +73115,8 @@ function parseArgs() {
72797
73115
  // Tool filtering: ['*'] = all, [] = none, ['tool1', 'tool2'] = specific
72798
73116
  disableTools: false,
72799
73117
  // Convenience flag to disable all tools
72800
- disableSkills: false,
72801
- // Disable skill discovery and activation
73118
+ allowSkills: false,
73119
+ // Enable skill discovery and activation (disabled by default)
72802
73120
  skillDirs: null,
72803
73121
  // Comma-separated list of repo-relative skill directories
72804
73122
  // Task management
@@ -72870,8 +73188,8 @@ function parseArgs() {
72870
73188
  }
72871
73189
  } else if (arg === "--disable-tools") {
72872
73190
  config.disableTools = true;
72873
- } else if (arg === "--no-skills") {
72874
- config.disableSkills = true;
73191
+ } else if (arg === "--allow-skills") {
73192
+ config.allowSkills = true;
72875
73193
  } else if (arg === "--skills-dir" && i + 1 < args.length) {
72876
73194
  config.skillDirs = args[++i].split(",").map((dir) => dir.trim()).filter(Boolean);
72877
73195
  } else if (arg === "--allow-tasks") {
@@ -72928,8 +73246,8 @@ Options:
72928
73246
  Supports exclusion: '*,!bash' (all except bash)
72929
73247
  --disable-tools Disable all tools (raw AI mode, no code analysis)
72930
73248
  Convenience flag equivalent to --allowed-tools none
73249
+ --allow-skills Enable skill discovery and activation (disabled by default)
72931
73250
  --skills-dir <dirs> Comma-separated list of repo-relative skill directories to scan
72932
- --no-skills Disable skill discovery and activation
72933
73251
  --allow-tasks Enable task management for tracking multi-step progress
72934
73252
  --verbose Enable verbose output
72935
73253
  --outline Use outline-xml format for code search results
@@ -73401,7 +73719,7 @@ async function main() {
73401
73719
  disableMermaidValidation: config.noMermaidValidation,
73402
73720
  allowedTools: config.allowedTools,
73403
73721
  disableTools: config.disableTools,
73404
- enableSkills: !config.disableSkills,
73722
+ allowSkills: config.allowSkills,
73405
73723
  skillDirs: config.skillDirs,
73406
73724
  enableBash: config.enableBash,
73407
73725
  bashConfig,