@testdriverai/mcp 7.11.179-test → 7.11.180-test

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.
@@ -18,6 +18,8 @@ import * as Sentry from "@sentry/node";
18
18
  import * as fs from "fs";
19
19
  import * as os from "os";
20
20
  import * as path from "path";
21
+ import { instrument } from "@posthog/mcp";
22
+ import { PostHog } from "posthog-node";
21
23
  import { fileURLToPath, pathToFileURL } from "url";
22
24
  import { z } from "zod";
23
25
  import * as core from "./core/actions.js";
@@ -112,6 +114,27 @@ if (isSentryEnabled()) {
112
114
  },
113
115
  });
114
116
  }
117
+ // =============================================================================
118
+ // PostHog MCP Analytics
119
+ // =============================================================================
120
+ // Public project write key (project 106760, us.posthog.com). Same value ships in
121
+ // the browser bundle (web/src/main.js) and api/api/services/posthog.js. Only
122
+ // phc_ project keys can write events; anything else falls back to the built-in.
123
+ const POSTHOG_PROJECT_KEY = process.env.POSTHOG_API_KEY?.startsWith("phc_")
124
+ ? process.env.POSTHOG_API_KEY
125
+ : "phc_ovOQ2HFpqFwPVqaxE5plJmI9buPMsz024FB2iajItqn";
126
+ // One client for the process (docs: create at module scope, not per request).
127
+ // Gated by the same TD_TELEMETRY switch as Sentry.
128
+ const posthog = isSentryEnabled()
129
+ ? new PostHog(POSTHOG_PROJECT_KEY, {
130
+ host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
131
+ })
132
+ : null;
133
+ async function flushPostHog() {
134
+ if (!posthog)
135
+ return;
136
+ await posthog.shutdown().catch(() => { });
137
+ }
115
138
  function captureException(error, context = {}) {
116
139
  if (!isSentryEnabled())
117
140
  return;
@@ -438,16 +461,20 @@ function createToolResult(success, textContent, structuredData, generatedCode) {
438
461
  * copy of the registration code serves every connection correctly.
439
462
  */
440
463
  function buildServer() {
441
- // Create MCP server wrapped with Sentry for automatic tracing
442
- const server = isSentryEnabled()
443
- ? Sentry.wrapMcpServerWithSentry(new McpServer({
444
- name: "testdriver",
445
- version: version,
446
- }))
447
- : new McpServer({
448
- name: "testdriver",
449
- version: version,
464
+ const baseServer = new McpServer({
465
+ name: "testdriver",
466
+ version: version,
467
+ });
468
+ // PostHog MCP analytics: proxies _registeredTools, so tools registered below
469
+ // are captured as $mcp_tool_call events. Instrument the raw server before the
470
+ // Sentry proxy wraps it.
471
+ if (posthog) {
472
+ instrument(baseServer, posthog, {
473
+ logger: (msg) => logger.debug(`posthog-mcp: ${msg}`),
450
474
  });
475
+ }
476
+ // Wrap with Sentry for automatic tracing
477
+ const server = isSentryEnabled() ? Sentry.wrapMcpServerWithSentry(baseServer) : baseServer;
451
478
  // =============================================================================
452
479
  // Register UI Resource
453
480
  // =============================================================================
@@ -1912,6 +1939,7 @@ async function startHttpServer() {
1912
1939
  await conn.transport.close().catch(() => { });
1913
1940
  }
1914
1941
  connections.clear();
1942
+ await flushPostHog();
1915
1943
  await flushSentry();
1916
1944
  process.exit(0);
1917
1945
  };
@@ -1944,6 +1972,7 @@ async function main() {
1944
1972
  // Handle graceful shutdown
1945
1973
  const shutdown = async () => {
1946
1974
  logger.info("Shutting down MCP Server");
1975
+ await flushPostHog();
1947
1976
  await flushSentry();
1948
1977
  process.exit(0);
1949
1978
  };
@@ -1953,6 +1982,7 @@ async function main() {
1953
1982
  main().catch(async (error) => {
1954
1983
  logger.error("Server failed to start", { error: String(error) });
1955
1984
  captureException(error, { tags: { phase: "startup" } });
1985
+ await flushPostHog();
1956
1986
  await flushSentry();
1957
1987
  process.exit(1);
1958
1988
  });
@@ -10,8 +10,10 @@
10
10
  "dependencies": {
11
11
  "@modelcontextprotocol/ext-apps": "^1.0.0",
12
12
  "@modelcontextprotocol/sdk": "^1.24.0",
13
+ "@posthog/mcp": "^0.18.1",
13
14
  "@sentry/node": "^9.0.0",
14
15
  "jose": "^5.10.0",
16
+ "posthog-node": "^5.54.1",
15
17
  "semver": "^7.7.4",
16
18
  "zod": "^3.24.0"
17
19
  },
@@ -531,12 +533,12 @@
531
533
  }
532
534
  },
533
535
  "node_modules/@modelcontextprotocol/sdk": {
534
- "version": "1.25.3",
535
- "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz",
536
- "integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==",
536
+ "version": "1.30.1",
537
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.1.tgz",
538
+ "integrity": "sha512-H2HxLvC3HDNybePJaLdSrU1hhUK5iQw+WvV1b01myFyI7sdVGe1u/IPTE5D9fGCiJDVtgMV/lmFkQXLmQyIFYA==",
537
539
  "license": "MIT",
538
540
  "dependencies": {
539
- "@hono/node-server": "^1.19.9",
541
+ "@hono/node-server": "^1.19.9 || ^2.0.5",
540
542
  "ajv": "^8.17.1",
541
543
  "ajv-formats": "^3.0.1",
542
544
  "content-type": "^1.0.5",
@@ -544,14 +546,15 @@
544
546
  "cross-spawn": "^7.0.5",
545
547
  "eventsource": "^3.0.2",
546
548
  "eventsource-parser": "^3.0.0",
547
- "express": "^5.0.1",
548
- "express-rate-limit": "^7.5.0",
549
- "jose": "^6.1.1",
549
+ "express": "^5.2.1",
550
+ "express-rate-limit": "^8.2.1",
551
+ "hono": "^4.11.4",
552
+ "jose": "^6.1.3",
550
553
  "json-schema-typed": "^8.0.2",
551
554
  "pkce-challenge": "^5.0.0",
552
555
  "raw-body": "^3.0.0",
553
556
  "zod": "^3.25 || ^4.0",
554
- "zod-to-json-schema": "^3.25.0"
557
+ "zod-to-json-schema": "^3.25.1"
555
558
  },
556
559
  "engines": {
557
560
  "node": ">=18"
@@ -1258,6 +1261,46 @@
1258
1261
  "win32"
1259
1262
  ]
1260
1263
  },
1264
+ "node_modules/@posthog/core": {
1265
+ "version": "1.55.2",
1266
+ "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.55.2.tgz",
1267
+ "integrity": "sha512-2mYxGbDmTLUs096VbcZqSWo0lrI48/BrX65r54NynxxFq409BOx9w73HxOAtOKZ1vblkdV6/GxQTe7KDcIQidg==",
1268
+ "license": "MIT",
1269
+ "dependencies": {
1270
+ "@posthog/types": "^1.412.4"
1271
+ }
1272
+ },
1273
+ "node_modules/@posthog/mcp": {
1274
+ "version": "0.18.1",
1275
+ "resolved": "https://registry.npmjs.org/@posthog/mcp/-/mcp-0.18.1.tgz",
1276
+ "integrity": "sha512-w+mu1kWRgZ6sZ0b4geABAS2QiuKX8MJlKiCe2DSwZ6gB48YF3Ijo67V7XPrpT1tph6X90lMvQm3lS8CxdYJfHQ==",
1277
+ "license": "MIT",
1278
+ "dependencies": {
1279
+ "@posthog/core": "^1.55.2"
1280
+ },
1281
+ "engines": {
1282
+ "node": "^20.20.0 || >=22.22.0"
1283
+ },
1284
+ "peerDependencies": {
1285
+ "@modelcontextprotocol/sdk": ">=1.26.0",
1286
+ "@modelcontextprotocol/server": ">=2.0.0",
1287
+ "posthog-node": "^5.0.0"
1288
+ },
1289
+ "peerDependenciesMeta": {
1290
+ "@modelcontextprotocol/sdk": {
1291
+ "optional": true
1292
+ },
1293
+ "@modelcontextprotocol/server": {
1294
+ "optional": true
1295
+ }
1296
+ }
1297
+ },
1298
+ "node_modules/@posthog/types": {
1299
+ "version": "1.412.4",
1300
+ "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.412.4.tgz",
1301
+ "integrity": "sha512-Q7lV9O9TbLngjOYw1ucm3bS3tn48xb1B4ZQdDy8gv7yfKe99hCTeWYG4xZ36nJM80VxpTF9TriiJt5hngDOkBg==",
1302
+ "license": "MIT"
1303
+ },
1261
1304
  "node_modules/@prisma/instrumentation": {
1262
1305
  "version": "6.11.1",
1263
1306
  "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz",
@@ -2009,20 +2052,20 @@
2009
2052
  "license": "MIT"
2010
2053
  },
2011
2054
  "node_modules/body-parser": {
2012
- "version": "2.2.2",
2013
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
2014
- "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
2055
+ "version": "2.3.0",
2056
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
2057
+ "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
2015
2058
  "license": "MIT",
2016
2059
  "dependencies": {
2017
2060
  "bytes": "^3.1.2",
2018
- "content-type": "^1.0.5",
2061
+ "content-type": "^2.0.0",
2019
2062
  "debug": "^4.4.3",
2020
- "http-errors": "^2.0.0",
2021
- "iconv-lite": "^0.7.0",
2063
+ "http-errors": "^2.0.1",
2064
+ "iconv-lite": "^0.7.2",
2022
2065
  "on-finished": "^2.4.1",
2023
- "qs": "^6.14.1",
2024
- "raw-body": "^3.0.1",
2025
- "type-is": "^2.0.1"
2066
+ "qs": "^6.15.2",
2067
+ "raw-body": "^3.0.2",
2068
+ "type-is": "^2.1.0"
2026
2069
  },
2027
2070
  "engines": {
2028
2071
  "node": ">=18"
@@ -2032,6 +2075,19 @@
2032
2075
  "url": "https://opencollective.com/express"
2033
2076
  }
2034
2077
  },
2078
+ "node_modules/body-parser/node_modules/content-type": {
2079
+ "version": "2.1.0",
2080
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
2081
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
2082
+ "license": "MIT",
2083
+ "engines": {
2084
+ "node": ">=18"
2085
+ },
2086
+ "funding": {
2087
+ "type": "opencollective",
2088
+ "url": "https://opencollective.com/express"
2089
+ }
2090
+ },
2035
2091
  "node_modules/brace-expansion": {
2036
2092
  "version": "2.0.2",
2037
2093
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
@@ -2109,9 +2165,9 @@
2109
2165
  "license": "MIT"
2110
2166
  },
2111
2167
  "node_modules/content-disposition": {
2112
- "version": "1.0.1",
2113
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
2114
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
2168
+ "version": "1.1.0",
2169
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
2170
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
2115
2171
  "license": "MIT",
2116
2172
  "engines": {
2117
2173
  "node": ">=18"
@@ -2286,9 +2342,9 @@
2286
2342
  "license": "MIT"
2287
2343
  },
2288
2344
  "node_modules/es-object-atoms": {
2289
- "version": "1.1.1",
2290
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
2291
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
2345
+ "version": "1.1.2",
2346
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
2347
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
2292
2348
  "license": "MIT",
2293
2349
  "dependencies": {
2294
2350
  "es-errors": "^1.3.0"
@@ -2439,10 +2495,14 @@
2439
2495
  }
2440
2496
  },
2441
2497
  "node_modules/express-rate-limit": {
2442
- "version": "7.5.1",
2443
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz",
2444
- "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==",
2498
+ "version": "8.7.0",
2499
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.0.tgz",
2500
+ "integrity": "sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g==",
2445
2501
  "license": "MIT",
2502
+ "dependencies": {
2503
+ "debug": "^4.4.3",
2504
+ "ip-address": "^10.2.0"
2505
+ },
2446
2506
  "engines": {
2447
2507
  "node": ">= 16"
2448
2508
  },
@@ -2666,7 +2726,6 @@
2666
2726
  "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
2667
2727
  "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
2668
2728
  "license": "MIT",
2669
- "peer": true,
2670
2729
  "engines": {
2671
2730
  "node": ">=16.9.0"
2672
2731
  }
@@ -2692,9 +2751,9 @@
2692
2751
  }
2693
2752
  },
2694
2753
  "node_modules/iconv-lite": {
2695
- "version": "0.7.2",
2696
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
2697
- "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
2754
+ "version": "0.7.3",
2755
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
2756
+ "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==",
2698
2757
  "license": "MIT",
2699
2758
  "dependencies": {
2700
2759
  "safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -2725,6 +2784,15 @@
2725
2784
  "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
2726
2785
  "license": "ISC"
2727
2786
  },
2787
+ "node_modules/ip-address": {
2788
+ "version": "10.7.2",
2789
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz",
2790
+ "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==",
2791
+ "license": "MIT",
2792
+ "engines": {
2793
+ "node": ">= 12"
2794
+ }
2795
+ },
2728
2796
  "node_modules/ipaddr.js": {
2729
2797
  "version": "1.9.1",
2730
2798
  "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -2812,12 +2880,16 @@
2812
2880
  }
2813
2881
  },
2814
2882
  "node_modules/media-typer": {
2815
- "version": "1.1.0",
2816
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
2817
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
2883
+ "version": "1.1.1",
2884
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz",
2885
+ "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==",
2818
2886
  "license": "MIT",
2819
2887
  "engines": {
2820
2888
  "node": ">= 0.8"
2889
+ },
2890
+ "funding": {
2891
+ "type": "opencollective",
2892
+ "url": "https://opencollective.com/express"
2821
2893
  }
2822
2894
  },
2823
2895
  "node_modules/merge-descriptors": {
@@ -2931,12 +3003,32 @@
2931
3003
  }
2932
3004
  },
2933
3005
  "node_modules/negotiator": {
2934
- "version": "1.0.0",
2935
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
2936
- "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
3006
+ "version": "1.1.0",
3007
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz",
3008
+ "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==",
2937
3009
  "license": "MIT",
3010
+ "dependencies": {
3011
+ "content-type": "^2.1.0"
3012
+ },
2938
3013
  "engines": {
2939
- "node": ">= 0.6"
3014
+ "node": ">=18"
3015
+ },
3016
+ "funding": {
3017
+ "type": "opencollective",
3018
+ "url": "https://opencollective.com/express"
3019
+ }
3020
+ },
3021
+ "node_modules/negotiator/node_modules/content-type": {
3022
+ "version": "2.1.0",
3023
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
3024
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
3025
+ "license": "MIT",
3026
+ "engines": {
3027
+ "node": ">=18"
3028
+ },
3029
+ "funding": {
3030
+ "type": "opencollective",
3031
+ "url": "https://opencollective.com/express"
2940
3032
  }
2941
3033
  },
2942
3034
  "node_modules/object-assign": {
@@ -3017,9 +3109,9 @@
3017
3109
  "license": "MIT"
3018
3110
  },
3019
3111
  "node_modules/path-to-regexp": {
3020
- "version": "8.3.0",
3021
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
3022
- "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
3112
+ "version": "8.4.2",
3113
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
3114
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
3023
3115
  "license": "MIT",
3024
3116
  "funding": {
3025
3117
  "type": "opencollective",
@@ -3161,10 +3253,30 @@
3161
3253
  "node": ">=0.10.0"
3162
3254
  }
3163
3255
  },
3256
+ "node_modules/posthog-node": {
3257
+ "version": "5.54.1",
3258
+ "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.54.1.tgz",
3259
+ "integrity": "sha512-3+tg86gLKRaR+MjQOdALGUJQDAXHWVyDUJI2h3EJa0c4GWTQu3+R62C3t49dz1T3QWyJq1msq5Qa+B55/ZEHxg==",
3260
+ "license": "MIT",
3261
+ "dependencies": {
3262
+ "@posthog/core": "^1.55.2"
3263
+ },
3264
+ "engines": {
3265
+ "node": "^20.20.0 || >=22.22.0"
3266
+ },
3267
+ "peerDependencies": {
3268
+ "rxjs": "^7.0.0"
3269
+ },
3270
+ "peerDependenciesMeta": {
3271
+ "rxjs": {
3272
+ "optional": true
3273
+ }
3274
+ }
3275
+ },
3164
3276
  "node_modules/proxy-addr": {
3165
- "version": "2.0.7",
3166
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
3167
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
3277
+ "version": "2.0.8",
3278
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz",
3279
+ "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==",
3168
3280
  "license": "MIT",
3169
3281
  "dependencies": {
3170
3282
  "forwarded": "0.2.0",
@@ -3172,15 +3284,20 @@
3172
3284
  },
3173
3285
  "engines": {
3174
3286
  "node": ">= 0.10"
3287
+ },
3288
+ "funding": {
3289
+ "type": "opencollective",
3290
+ "url": "https://opencollective.com/express"
3175
3291
  }
3176
3292
  },
3177
3293
  "node_modules/qs": {
3178
- "version": "6.14.1",
3179
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
3180
- "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
3294
+ "version": "6.16.0",
3295
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz",
3296
+ "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==",
3181
3297
  "license": "BSD-3-Clause",
3182
3298
  "dependencies": {
3183
- "side-channel": "^1.1.0"
3299
+ "es-define-property": "^1.0.1",
3300
+ "side-channel": "^1.1.1"
3184
3301
  },
3185
3302
  "engines": {
3186
3303
  "node": ">=0.6"
@@ -3190,12 +3307,16 @@
3190
3307
  }
3191
3308
  },
3192
3309
  "node_modules/range-parser": {
3193
- "version": "1.2.1",
3194
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
3195
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
3310
+ "version": "1.3.0",
3311
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz",
3312
+ "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==",
3196
3313
  "license": "MIT",
3197
3314
  "engines": {
3198
3315
  "node": ">= 0.6"
3316
+ },
3317
+ "funding": {
3318
+ "type": "opencollective",
3319
+ "url": "https://opencollective.com/express"
3199
3320
  }
3200
3321
  },
3201
3322
  "node_modules/raw-body": {
@@ -3424,14 +3545,14 @@
3424
3545
  "license": "BSD-2-Clause"
3425
3546
  },
3426
3547
  "node_modules/side-channel": {
3427
- "version": "1.1.0",
3428
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
3429
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
3548
+ "version": "1.1.1",
3549
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
3550
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
3430
3551
  "license": "MIT",
3431
3552
  "dependencies": {
3432
3553
  "es-errors": "^1.3.0",
3433
- "object-inspect": "^1.13.3",
3434
- "side-channel-list": "^1.0.0",
3554
+ "object-inspect": "^1.13.4",
3555
+ "side-channel-list": "^1.0.1",
3435
3556
  "side-channel-map": "^1.0.1",
3436
3557
  "side-channel-weakmap": "^1.0.2"
3437
3558
  },
@@ -3443,13 +3564,13 @@
3443
3564
  }
3444
3565
  },
3445
3566
  "node_modules/side-channel-list": {
3446
- "version": "1.0.0",
3447
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
3448
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
3567
+ "version": "1.0.1",
3568
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
3569
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
3449
3570
  "license": "MIT",
3450
3571
  "dependencies": {
3451
3572
  "es-errors": "^1.3.0",
3452
- "object-inspect": "^1.13.3"
3573
+ "object-inspect": "^1.13.4"
3453
3574
  },
3454
3575
  "engines": {
3455
3576
  "node": ">= 0.4"
@@ -3634,17 +3755,34 @@
3634
3755
  }
3635
3756
  },
3636
3757
  "node_modules/type-is": {
3637
- "version": "2.0.1",
3638
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
3639
- "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
3758
+ "version": "2.1.0",
3759
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
3760
+ "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
3640
3761
  "license": "MIT",
3641
3762
  "dependencies": {
3642
- "content-type": "^1.0.5",
3763
+ "content-type": "^2.0.0",
3643
3764
  "media-typer": "^1.1.0",
3644
3765
  "mime-types": "^3.0.0"
3645
3766
  },
3646
3767
  "engines": {
3647
- "node": ">= 0.6"
3768
+ "node": ">= 18"
3769
+ },
3770
+ "funding": {
3771
+ "type": "opencollective",
3772
+ "url": "https://opencollective.com/express"
3773
+ }
3774
+ },
3775
+ "node_modules/type-is/node_modules/content-type": {
3776
+ "version": "2.1.0",
3777
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
3778
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
3779
+ "license": "MIT",
3780
+ "engines": {
3781
+ "node": ">=18"
3782
+ },
3783
+ "funding": {
3784
+ "type": "opencollective",
3785
+ "url": "https://opencollective.com/express"
3648
3786
  }
3649
3787
  },
3650
3788
  "node_modules/typescript": {
@@ -17,8 +17,10 @@
17
17
  "dependencies": {
18
18
  "@modelcontextprotocol/ext-apps": "^1.0.0",
19
19
  "@modelcontextprotocol/sdk": "^1.24.0",
20
+ "@posthog/mcp": "^0.18.1",
20
21
  "@sentry/node": "^9.0.0",
21
22
  "jose": "^5.10.0",
23
+ "posthog-node": "^5.54.1",
22
24
  "semver": "^7.7.4",
23
25
  "zod": "^3.24.0"
24
26
  },
@@ -23,6 +23,8 @@ import * as Sentry from "@sentry/node";
23
23
  import * as fs from "fs";
24
24
  import * as os from "os";
25
25
  import * as path from "path";
26
+ import { instrument } from "@posthog/mcp";
27
+ import { PostHog } from "posthog-node";
26
28
  import { fileURLToPath, pathToFileURL } from "url";
27
29
  import { z } from "zod";
28
30
 
@@ -135,6 +137,30 @@ if (isSentryEnabled()) {
135
137
  });
136
138
  }
137
139
 
140
+ // =============================================================================
141
+ // PostHog MCP Analytics
142
+ // =============================================================================
143
+
144
+ // Public project write key (project 106760, us.posthog.com). Same value ships in
145
+ // the browser bundle (web/src/main.js) and api/api/services/posthog.js. Only
146
+ // phc_ project keys can write events; anything else falls back to the built-in.
147
+ const POSTHOG_PROJECT_KEY = process.env.POSTHOG_API_KEY?.startsWith("phc_")
148
+ ? process.env.POSTHOG_API_KEY
149
+ : "phc_ovOQ2HFpqFwPVqaxE5plJmI9buPMsz024FB2iajItqn";
150
+
151
+ // One client for the process (docs: create at module scope, not per request).
152
+ // Gated by the same TD_TELEMETRY switch as Sentry.
153
+ const posthog = isSentryEnabled()
154
+ ? new PostHog(POSTHOG_PROJECT_KEY, {
155
+ host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
156
+ })
157
+ : null;
158
+
159
+ async function flushPostHog() {
160
+ if (!posthog) return;
161
+ await posthog.shutdown().catch(() => {});
162
+ }
163
+
138
164
  function captureException(error: Error, context: { tags?: Record<string, string>; extra?: Record<string, unknown> } = {}) {
139
165
  if (!isSentryEnabled()) return;
140
166
 
@@ -564,18 +590,22 @@ function createToolResult(
564
590
  * copy of the registration code serves every connection correctly.
565
591
  */
566
592
  function buildServer(): McpServer {
567
- // Create MCP server wrapped with Sentry for automatic tracing
568
- const server = isSentryEnabled()
569
- ? Sentry.wrapMcpServerWithSentry(
570
- new McpServer({
571
- name: "testdriver",
572
- version: version,
573
- })
574
- )
575
- : new McpServer({
576
- name: "testdriver",
577
- version: version,
578
- });
593
+ const baseServer = new McpServer({
594
+ name: "testdriver",
595
+ version: version,
596
+ });
597
+
598
+ // PostHog MCP analytics: proxies _registeredTools, so tools registered below
599
+ // are captured as $mcp_tool_call events. Instrument the raw server before the
600
+ // Sentry proxy wraps it.
601
+ if (posthog) {
602
+ instrument(baseServer, posthog, {
603
+ logger: (msg) => logger.debug(`posthog-mcp: ${msg}`),
604
+ });
605
+ }
606
+
607
+ // Wrap with Sentry for automatic tracing
608
+ const server = isSentryEnabled() ? Sentry.wrapMcpServerWithSentry(baseServer) : baseServer;
579
609
 
580
610
  // =============================================================================
581
611
  // Register UI Resource
@@ -2338,6 +2368,7 @@ async function startHttpServer() {
2338
2368
  await conn.transport.close().catch(() => {});
2339
2369
  }
2340
2370
  connections.clear();
2371
+ await flushPostHog();
2341
2372
  await flushSentry();
2342
2373
  process.exit(0);
2343
2374
  };
@@ -2376,6 +2407,7 @@ async function main() {
2376
2407
  // Handle graceful shutdown
2377
2408
  const shutdown = async () => {
2378
2409
  logger.info("Shutting down MCP Server");
2410
+ await flushPostHog();
2379
2411
  await flushSentry();
2380
2412
  process.exit(0);
2381
2413
  };
@@ -2387,6 +2419,7 @@ async function main() {
2387
2419
  main().catch(async (error) => {
2388
2420
  logger.error("Server failed to start", { error: String(error) });
2389
2421
  captureException(error as Error, { tags: { phase: "startup" } });
2422
+ await flushPostHog();
2390
2423
  await flushSentry();
2391
2424
  process.exit(1);
2392
2425
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testdriverai/mcp",
3
- "version": "7.11.179-test",
3
+ "version": "7.11.180-test",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "sdk.js",
6
6
  "types": "sdk.d.ts",