@posthog/mcp 0.10.8 → 0.10.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"instrument-lowlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-lowlevel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAiD,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAkBxC;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CA0BtF"}
1
+ {"version":3,"file":"instrument-lowlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-lowlevel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAiD,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAmBxC;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CA0BtF"}
@@ -26,7 +26,6 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  instrumentLowLevelServer: ()=>instrumentLowLevelServer
28
28
  });
29
- const types_js_namespaceObject = require("@modelcontextprotocol/sdk/types.js");
30
29
  const external_event_types_js_namespaceObject = require("./event-types.js");
31
30
  const external_internal_js_namespaceObject = require("./internal.js");
32
31
  const external_tools_js_namespaceObject = require("./tools.js");
@@ -35,20 +34,22 @@ const external_tracing_helpers_js_namespaceObject = require("./tracing-helpers.j
35
34
  function instrumentLowLevelServer(server, logger) {
36
35
  try {
37
36
  const hadCallToolHandler = server._requestHandlers.has('tools/call');
37
+ const traceToolCall = (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger);
38
38
  const handlers = {
39
39
  initialize: (server, originalHandler, request, extra)=>(0, external_instrumentation_js_namespaceObject.handleInitializeRequest)(server, originalHandler, request, extra, logger),
40
40
  'tools/list': (server, originalHandler, request, extra)=>(0, external_instrumentation_js_namespaceObject.handleListToolsRequest)(server, originalHandler, request, extra, logger),
41
- 'tools/call': (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger)
41
+ 'tools/call': traceToolCall
42
42
  };
43
43
  (0, external_instrumentation_js_namespaceObject.patchRequestHandlers)(server, handlers);
44
- if (!hadCallToolHandler) server.setRequestHandler(types_js_namespaceObject.CallToolRequestSchema, async (request)=>{
45
- throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
46
- });
44
+ if (!hadCallToolHandler) (0, external_instrumentation_js_namespaceObject.registerFallbackRequestHandler)(server, 'tools/call', unknownToolHandler, traceToolCall);
47
45
  } catch (error) {
48
46
  logger(`Warning: Failed to setup tool call instrumentation - ${error}`);
49
47
  throw error;
50
48
  }
51
49
  }
50
+ async function unknownToolHandler(request) {
51
+ throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
52
+ }
52
53
  async function handleToolCallRequest(server, originalCallToolHandler, request, extra, logger) {
53
54
  const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
54
55
  if (!data) {
@@ -1,26 +1,27 @@
1
- import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
2
1
  import { MCPAnalyticsEventType } from "./event-types.mjs";
3
2
  import { getServerTrackingData } from "./internal.mjs";
4
3
  import { handleReportMissing, resolveMissingCapabilityToolName } from "./tools.mjs";
5
- import { captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers } from "./instrumentation.mjs";
4
+ import { captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, registerFallbackRequestHandler } from "./instrumentation.mjs";
6
5
  import { getContextArgument } from "./tracing-helpers.mjs";
7
6
  function instrumentLowLevelServer(server, logger) {
8
7
  try {
9
8
  const hadCallToolHandler = server._requestHandlers.has('tools/call');
9
+ const traceToolCall = (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger);
10
10
  const handlers = {
11
11
  initialize: (server, originalHandler, request, extra)=>handleInitializeRequest(server, originalHandler, request, extra, logger),
12
12
  'tools/list': (server, originalHandler, request, extra)=>handleListToolsRequest(server, originalHandler, request, extra, logger),
13
- 'tools/call': (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger)
13
+ 'tools/call': traceToolCall
14
14
  };
15
15
  patchRequestHandlers(server, handlers);
16
- if (!hadCallToolHandler) server.setRequestHandler(CallToolRequestSchema, async (request)=>{
17
- throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
18
- });
16
+ if (!hadCallToolHandler) registerFallbackRequestHandler(server, 'tools/call', unknownToolHandler, traceToolCall);
19
17
  } catch (error) {
20
18
  logger(`Warning: Failed to setup tool call instrumentation - ${error}`);
21
19
  throw error;
22
20
  }
23
21
  }
22
+ async function unknownToolHandler(request) {
23
+ throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
24
+ }
24
25
  async function handleToolCallRequest(server, originalCallToolHandler, request, extra, logger) {
25
26
  const data = getServerTrackingData(server);
26
27
  if (!data) {
@@ -55,6 +55,28 @@ export declare function captureToolCall(params: TraceToolCallParams): Promise<un
55
55
  * supplies `request` and `extra` per call.
56
56
  */
57
57
  export type HandlerPatch = (server: MCPServerLike, originalHandler: MCPRequestHandler, request: MCPRequestLike, extra: CompatibleRequestHandlerExtra | undefined) => Promise<unknown>;
58
+ /**
59
+ * Registers a synthetic fallback handler for `handlerName`, already wrapped in
60
+ * `patch`, by writing straight into `_requestHandlers` instead of going through
61
+ * `setRequestHandler`.
62
+ *
63
+ * Bypassing the SDK setter is deliberate, on three counts:
64
+ *
65
+ * - **Capability assertion.** `setRequestHandler` refuses a method the server
66
+ * never declared a capability for, so instrumenting a low-level server built
67
+ * without `capabilities.tools` used to throw `Server does not support tools`
68
+ * and leave instrumentation half-applied. Our fallback is not a capability the
69
+ * server offers — it exists only so a call for a tool nobody claims is still
70
+ * captured — so the assertion has nothing to protect here.
71
+ * - **Schema validation.** The setter also wraps the handler in request/result
72
+ * parsing, which a handler that can only ever throw `Unknown tool` never needs.
73
+ * - **Portability.** The setter's first argument is a Zod schema on SDK v1 and a
74
+ * method string on v2; the map key is the same string on both, so this is the
75
+ * one registration form that does not need to know which major it is talking
76
+ * to — and it drops the last runtime `@modelcontextprotocol/sdk` import from
77
+ * the shipped bundle.
78
+ */
79
+ export declare function registerFallbackRequestHandler(server: MCPServerLike, handlerName: string, fallbackHandler: MCPRequestHandler, patch: HandlerPatch): void;
58
80
  export declare function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void;
59
81
  /**
60
82
  * Checks the server's raw listing for a real owner of a candidate virtual tool.
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"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"}
@@ -31,6 +31,7 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  readToolMetaCategory: ()=>readToolMetaCategory,
32
32
  cacheToolCategories: ()=>cacheToolCategories,
33
33
  handleListToolsRequest: ()=>handleListToolsRequest,
34
+ registerFallbackRequestHandler: ()=>registerFallbackRequestHandler,
34
35
  patchRequestHandlers: ()=>patchRequestHandlers
35
36
  });
36
37
  const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
@@ -174,6 +175,10 @@ function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
174
175
  }
175
176
  handlers.set(handlerName, originalHandler);
176
177
  }
178
+ function registerFallbackRequestHandler(server, handlerName, fallbackHandler, patch) {
179
+ rememberOriginalRequestHandler(server, handlerName, fallbackHandler);
180
+ server._requestHandlers.set(handlerName, (request, extra)=>patch(server, fallbackHandler, request, extra));
181
+ }
177
182
  function patchRequestHandlers(server, patches) {
178
183
  for (const [handlerName, patch] of Object.entries(patches)){
179
184
  const originalHandler = server._requestHandlers.get(handlerName);
@@ -183,12 +188,11 @@ function patchRequestHandlers(server, patches) {
183
188
  }
184
189
  }
185
190
  const originalSetRequestHandler = server.setRequestHandler.bind(server);
186
- server.setRequestHandler = (requestSchema, originalHandler)=>{
187
- const shape = (0, external_mcp_sdk_compat_js_namespaceObject.getObjectShape)(requestSchema);
188
- const handlerName = shape?.method ? (0, external_mcp_sdk_compat_js_namespaceObject.getLiteralValue)(shape.method) : void 0;
189
- const patch = 'string' == typeof handlerName ? patches[handlerName] : void 0;
190
- if (!patch || 'string' != typeof handlerName) return originalSetRequestHandler(requestSchema, originalHandler);
191
- const result = originalSetRequestHandler(requestSchema, originalHandler);
191
+ server.setRequestHandler = (...args)=>{
192
+ const handlerName = (0, external_mcp_sdk_compat_js_namespaceObject.readRequestHandlerMethod)(args[0]);
193
+ const patch = void 0 !== handlerName && Object.prototype.hasOwnProperty.call(patches, handlerName) ? patches[handlerName] : void 0;
194
+ if (void 0 === handlerName || !patch) return originalSetRequestHandler(...args);
195
+ const result = originalSetRequestHandler(...args);
192
196
  const registeredHandler = server._requestHandlers.get(handlerName);
193
197
  if (registeredHandler) {
194
198
  rememberOriginalRequestHandler(server, handlerName, registeredHandler);
@@ -429,6 +433,7 @@ exports.handleListToolsRequest = __webpack_exports__.handleListToolsRequest;
429
433
  exports.isToolAdvertised = __webpack_exports__.isToolAdvertised;
430
434
  exports.patchRequestHandlers = __webpack_exports__.patchRequestHandlers;
431
435
  exports.readToolMetaCategory = __webpack_exports__.readToolMetaCategory;
436
+ exports.registerFallbackRequestHandler = __webpack_exports__.registerFallbackRequestHandler;
432
437
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
433
438
  "cacheToolCategories",
434
439
  "cacheToolDescriptions",
@@ -437,7 +442,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
437
442
  "handleListToolsRequest",
438
443
  "isToolAdvertised",
439
444
  "patchRequestHandlers",
440
- "readToolMetaCategory"
445
+ "readToolMetaCategory",
446
+ "registerFallbackRequestHandler"
441
447
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
442
448
  Object.defineProperty(exports, '__esModule', {
443
449
  value: true
@@ -9,7 +9,7 @@ import { captureException } from "./exceptions.mjs";
9
9
  import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from "./intent.mjs";
10
10
  import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from "./internal.mjs";
11
11
  import { buildCapturedMcpParameters } from "./mcp-payloads.mjs";
12
- import { getLiteralValue, getObjectShape } from "./mcp-sdk-compat.mjs";
12
+ import { readRequestHandlerMethod } from "./mcp-sdk-compat.mjs";
13
13
  import { getSessionId, getSessionInfo, newSessionId } from "./session.mjs";
14
14
  import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from "./session-token.mjs";
15
15
  import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from "./tools.mjs";
@@ -139,6 +139,10 @@ function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
139
139
  }
140
140
  handlers.set(handlerName, originalHandler);
141
141
  }
142
+ function registerFallbackRequestHandler(server, handlerName, fallbackHandler, patch) {
143
+ rememberOriginalRequestHandler(server, handlerName, fallbackHandler);
144
+ server._requestHandlers.set(handlerName, (request, extra)=>patch(server, fallbackHandler, request, extra));
145
+ }
142
146
  function patchRequestHandlers(server, patches) {
143
147
  for (const [handlerName, patch] of Object.entries(patches)){
144
148
  const originalHandler = server._requestHandlers.get(handlerName);
@@ -148,12 +152,11 @@ function patchRequestHandlers(server, patches) {
148
152
  }
149
153
  }
150
154
  const originalSetRequestHandler = server.setRequestHandler.bind(server);
151
- server.setRequestHandler = (requestSchema, originalHandler)=>{
152
- const shape = getObjectShape(requestSchema);
153
- const handlerName = shape?.method ? getLiteralValue(shape.method) : void 0;
154
- const patch = 'string' == typeof handlerName ? patches[handlerName] : void 0;
155
- if (!patch || 'string' != typeof handlerName) return originalSetRequestHandler(requestSchema, originalHandler);
156
- const result = originalSetRequestHandler(requestSchema, originalHandler);
155
+ server.setRequestHandler = (...args)=>{
156
+ const handlerName = readRequestHandlerMethod(args[0]);
157
+ const patch = void 0 !== handlerName && Object.prototype.hasOwnProperty.call(patches, handlerName) ? patches[handlerName] : void 0;
158
+ if (void 0 === handlerName || !patch) return originalSetRequestHandler(...args);
159
+ const result = originalSetRequestHandler(...args);
157
160
  const registeredHandler = server._requestHandlers.get(handlerName);
158
161
  if (registeredHandler) {
159
162
  rememberOriginalRequestHandler(server, handlerName, registeredHandler);
@@ -386,4 +389,4 @@ function readProtocolVersion(result, request) {
386
389
  const requested = request.params?.protocolVersion;
387
390
  return 'string' == typeof requested && requested.length > 0 ? requested : void 0;
388
391
  }
389
- export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory };
392
+ export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory, registerFallbackRequestHandler };
@@ -30,5 +30,15 @@ export declare function createWrappedTool(originalTool: RegisteredTool, wrappedF
30
30
  export declare function isZ4Schema(schema: unknown): boolean;
31
31
  export declare function isZodRawShapeCompat(schema: unknown): schema is Record<string, unknown>;
32
32
  export declare function getObjectShape(schema: unknown): Record<string, unknown> | undefined;
33
+ /**
34
+ * Reads the method name a `setRequestHandler` registration is for.
35
+ *
36
+ * The two SDK majors disagree on what the first argument is: v1 passes the Zod
37
+ * schema for the request and carries the method as a literal on its shape, v2
38
+ * passes the method string itself. A registration we cannot name is one we
39
+ * cannot match against a patch — which is how a handler registered after
40
+ * `instrument()` on v2 ends up replacing our wrapper instead of being wrapped.
41
+ */
42
+ export declare function readRequestHandlerMethod(requestSchema: unknown): string | undefined;
33
43
  export declare function getLiteralValue(schema: unknown): unknown;
34
44
  //# sourceMappingURL=mcp-sdk-compat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-sdk-compat.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-sdk-compat.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAK5D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAQlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAKxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,GAAG,cAAc,CAM7G;AAyBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKnD;AAaD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA6BnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAkCxD"}
1
+ {"version":3,"file":"mcp-sdk-compat.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-sdk-compat.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAK5D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAQlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAKxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,GAAG,cAAc,CAM7G;AAyBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKnD;AAaD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA6BnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAkCxD"}
@@ -31,7 +31,8 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  getToolFunctionKey: ()=>getToolFunctionKey,
32
32
  hasToolFunction: ()=>hasToolFunction,
33
33
  isZ4Schema: ()=>isZ4Schema,
34
- isZodRawShapeCompat: ()=>isZodRawShapeCompat
34
+ isZodRawShapeCompat: ()=>isZodRawShapeCompat,
35
+ readRequestHandlerMethod: ()=>readRequestHandlerMethod
35
36
  });
36
37
  function getToolFunction(tool) {
37
38
  if ('handler' in tool && 'function' == typeof tool.handler) return tool.handler;
@@ -82,6 +83,12 @@ function getObjectShape(schema) {
82
83
  }
83
84
  return rawShape;
84
85
  }
86
+ function readRequestHandlerMethod(requestSchema) {
87
+ if ('string' == typeof requestSchema) return requestSchema;
88
+ const shape = getObjectShape(requestSchema);
89
+ const method = shape?.method ? getLiteralValue(shape.method) : void 0;
90
+ return 'string' == typeof method ? method : void 0;
91
+ }
85
92
  function getLiteralValue(schema) {
86
93
  if (!schema || 'object' != typeof schema) return;
87
94
  if (isZ4Schema(schema)) {
@@ -106,6 +113,7 @@ exports.getToolFunctionKey = __webpack_exports__.getToolFunctionKey;
106
113
  exports.hasToolFunction = __webpack_exports__.hasToolFunction;
107
114
  exports.isZ4Schema = __webpack_exports__.isZ4Schema;
108
115
  exports.isZodRawShapeCompat = __webpack_exports__.isZodRawShapeCompat;
116
+ exports.readRequestHandlerMethod = __webpack_exports__.readRequestHandlerMethod;
109
117
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
110
118
  "createWrappedTool",
111
119
  "getLiteralValue",
@@ -114,7 +122,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
114
122
  "getToolFunctionKey",
115
123
  "hasToolFunction",
116
124
  "isZ4Schema",
117
- "isZodRawShapeCompat"
125
+ "isZodRawShapeCompat",
126
+ "readRequestHandlerMethod"
118
127
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
119
128
  Object.defineProperty(exports, '__esModule', {
120
129
  value: true
@@ -47,6 +47,12 @@ function getObjectShape(schema) {
47
47
  }
48
48
  return rawShape;
49
49
  }
50
+ function readRequestHandlerMethod(requestSchema) {
51
+ if ('string' == typeof requestSchema) return requestSchema;
52
+ const shape = getObjectShape(requestSchema);
53
+ const method = shape?.method ? getLiteralValue(shape.method) : void 0;
54
+ return 'string' == typeof method ? method : void 0;
55
+ }
50
56
  function getLiteralValue(schema) {
51
57
  if (!schema || 'object' != typeof schema) return;
52
58
  if (isZ4Schema(schema)) {
@@ -63,4 +69,4 @@ function getLiteralValue(schema) {
63
69
  const directValue = schema.value;
64
70
  if (void 0 !== directValue) return directValue;
65
71
  }
66
- export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema, isZodRawShapeCompat };
72
+ export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema, isZodRawShapeCompat, readRequestHandlerMethod };
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version = "0.10.8";
1
+ export declare const version = "0.10.9";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  version: ()=>version
28
28
  });
29
- const version = '0.10.8';
29
+ const version = '0.10.9';
30
30
  exports.version = __webpack_exports__.version;
31
31
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
32
32
  "version"
package/dist/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- const version = '0.10.8';
1
+ const version = '0.10.9';
2
2
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/mcp",
3
- "version": "0.10.8",
3
+ "version": "0.10.9",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },
@@ -3,7 +3,6 @@
3
3
  // Copyright (c) 2025 AgentCat, Inc. (formerly MCPcat)
4
4
  // Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
5
5
 
6
- import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'
7
6
  import type { CompatibleRequestHandlerExtra, MCPRequestLike, MCPServerLike } from '../types'
8
7
  import { MCPAnalyticsEventType } from './event-types'
9
8
  import { getServerTrackingData } from './internal'
@@ -13,6 +12,7 @@ import {
13
12
  handleInitializeRequest,
14
13
  handleListToolsRequest,
15
14
  patchRequestHandlers,
15
+ registerFallbackRequestHandler,
16
16
  captureToolCall,
17
17
  isToolAdvertised,
18
18
  type HandlerPatch,
@@ -34,23 +34,23 @@ export function instrumentLowLevelServer(server: MCPServerLike, logger: LoggerFn
34
34
  try {
35
35
  // Patch already existing handlers, and patch setRequestHandler to capture dynamically created handlers.
36
36
  const hadCallToolHandler = server._requestHandlers.has('tools/call')
37
+ const traceToolCall: HandlerPatch = (server, originalHandler, request, extra) =>
38
+ handleToolCallRequest(server, originalHandler, request, extra, logger)
37
39
  const handlers: Record<string, HandlerPatch> = {
38
40
  initialize: (server, originalHandler, request, extra) =>
39
41
  handleInitializeRequest(server, originalHandler, request, extra, logger),
40
42
  'tools/list': (server, originalHandler, request, extra) =>
41
43
  handleListToolsRequest(server, originalHandler, request, extra, logger),
42
- 'tools/call': (server, originalHandler, request, extra) =>
43
- handleToolCallRequest(server, originalHandler, request, extra, logger),
44
+ 'tools/call': traceToolCall,
44
45
  }
45
46
  patchRequestHandlers(server, handlers)
46
47
 
47
48
  if (!hadCallToolHandler) {
48
- // Register a raw fallback through the patched setter so reportMissing works
49
- // even before an application dispatcher is attached. A later registration
50
- // replaces it and is wrapped by patchRequestHandlers.
51
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
52
- throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`)
53
- })
49
+ // Register a raw fallback so reportMissing works even before an application
50
+ // dispatcher is attached. A later registration replaces it and is wrapped by
51
+ // the patched setRequestHandler. Written into the handler map directly — see
52
+ // registerFallbackRequestHandler for why the SDK setter is the wrong door.
53
+ registerFallbackRequestHandler(server, 'tools/call', unknownToolHandler, traceToolCall)
54
54
  }
55
55
  } catch (error) {
56
56
  logger(`Warning: Failed to setup tool call instrumentation - ${error}`)
@@ -58,6 +58,11 @@ export function instrumentLowLevelServer(server: MCPServerLike, logger: LoggerFn
58
58
  }
59
59
  }
60
60
 
61
+ /** Stands in for an application dispatcher that has not been attached yet. */
62
+ async function unknownToolHandler(request: MCPRequestLike): Promise<never> {
63
+ throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`)
64
+ }
65
+
61
66
  async function handleToolCallRequest(
62
67
  server: MCPServerLike,
63
68
  originalCallToolHandler: MCPRequestHandler | undefined,
@@ -32,7 +32,7 @@ import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from
32
32
  import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from './internal'
33
33
  import type { LoggerFn } from './logger'
34
34
  import { buildCapturedMcpParameters } from './mcp-payloads'
35
- import { getLiteralValue, getObjectShape } from './mcp-sdk-compat'
35
+ import { readRequestHandlerMethod } from './mcp-sdk-compat'
36
36
  import { getSessionId, getSessionInfo, newSessionId } from './session'
37
37
  import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from './session-token'
38
38
  import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from './tools'
@@ -386,6 +386,37 @@ function rememberOriginalRequestHandler(
386
386
  handlers.set(handlerName, originalHandler)
387
387
  }
388
388
 
389
+ /**
390
+ * Registers a synthetic fallback handler for `handlerName`, already wrapped in
391
+ * `patch`, by writing straight into `_requestHandlers` instead of going through
392
+ * `setRequestHandler`.
393
+ *
394
+ * Bypassing the SDK setter is deliberate, on three counts:
395
+ *
396
+ * - **Capability assertion.** `setRequestHandler` refuses a method the server
397
+ * never declared a capability for, so instrumenting a low-level server built
398
+ * without `capabilities.tools` used to throw `Server does not support tools`
399
+ * and leave instrumentation half-applied. Our fallback is not a capability the
400
+ * server offers — it exists only so a call for a tool nobody claims is still
401
+ * captured — so the assertion has nothing to protect here.
402
+ * - **Schema validation.** The setter also wraps the handler in request/result
403
+ * parsing, which a handler that can only ever throw `Unknown tool` never needs.
404
+ * - **Portability.** The setter's first argument is a Zod schema on SDK v1 and a
405
+ * method string on v2; the map key is the same string on both, so this is the
406
+ * one registration form that does not need to know which major it is talking
407
+ * to — and it drops the last runtime `@modelcontextprotocol/sdk` import from
408
+ * the shipped bundle.
409
+ */
410
+ export function registerFallbackRequestHandler(
411
+ server: MCPServerLike,
412
+ handlerName: string,
413
+ fallbackHandler: MCPRequestHandler,
414
+ patch: HandlerPatch
415
+ ): void {
416
+ rememberOriginalRequestHandler(server, handlerName, fallbackHandler)
417
+ server._requestHandlers.set(handlerName, (request, extra) => patch(server, fallbackHandler, request, extra))
418
+ }
419
+
389
420
  export function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void {
390
421
  // Monkey patch existing handlers.
391
422
  for (const [handlerName, patch] of Object.entries(patches)) {
@@ -397,18 +428,31 @@ export function patchRequestHandlers(server: MCPServerLike, patches: Record<stri
397
428
  }
398
429
 
399
430
  // Monkey patch dynamically added handlers (registered after instrument()).
400
- const originalSetRequestHandler = server.setRequestHandler.bind(server)
401
- server.setRequestHandler = ((requestSchema: unknown, originalHandler: MCPRequestHandler) => {
402
- const shape = getObjectShape(requestSchema)
403
- const handlerName = shape?.method ? getLiteralValue(shape.method) : undefined
404
- const patch = typeof handlerName === 'string' ? patches[handlerName] : undefined
405
- if (!patch || typeof handlerName !== 'string') {
406
- return originalSetRequestHandler(requestSchema, originalHandler)
431
+ //
432
+ // Variadic, and every argument is forwarded verbatim. The registration form is
433
+ // the SDK's business, not ours — only *that* a registration happened is ours.
434
+ // SDK v2 has a three-argument form for custom methods,
435
+ // `setRequestHandler(method, { params, result }, handler)`, and a two-parameter
436
+ // wrapper drops the handler: the SDK then sees the schemas object where the
437
+ // handler should be and throws `setRequestHandler: handler is required`, which
438
+ // takes down the host server rather than just our instrumentation.
439
+ const originalSetRequestHandler = server.setRequestHandler.bind(server) as (...args: unknown[]) => unknown
440
+ server.setRequestHandler = ((...args: unknown[]) => {
441
+ const handlerName = readRequestHandlerMethod(args[0])
442
+ // `hasOwnProperty`, not a bare index: `handlerName` is now an arbitrary
443
+ // caller-supplied string, and a custom method named `toString` would
444
+ // otherwise resolve to an inherited function and be treated as a patch.
445
+ const patch =
446
+ handlerName !== undefined && Object.prototype.hasOwnProperty.call(patches, handlerName)
447
+ ? patches[handlerName]
448
+ : undefined
449
+ if (handlerName === undefined || !patch) {
450
+ return originalSetRequestHandler(...args)
407
451
  }
408
452
 
409
453
  // Register first so the MCP SDK's request/result validation stays inside
410
454
  // our analytics wrapper, matching handlers that existed before instrument().
411
- const result = originalSetRequestHandler(requestSchema, originalHandler)
455
+ const result = originalSetRequestHandler(...args)
412
456
  const registeredHandler = server._requestHandlers.get(handlerName)
413
457
  if (registeredHandler) {
414
458
  rememberOriginalRequestHandler(server, handlerName, registeredHandler)
@@ -143,6 +143,24 @@ export function getObjectShape(schema: unknown): Record<string, unknown> | undef
143
143
  return rawShape
144
144
  }
145
145
 
146
+ /**
147
+ * Reads the method name a `setRequestHandler` registration is for.
148
+ *
149
+ * The two SDK majors disagree on what the first argument is: v1 passes the Zod
150
+ * schema for the request and carries the method as a literal on its shape, v2
151
+ * passes the method string itself. A registration we cannot name is one we
152
+ * cannot match against a patch — which is how a handler registered after
153
+ * `instrument()` on v2 ends up replacing our wrapper instead of being wrapped.
154
+ */
155
+ export function readRequestHandlerMethod(requestSchema: unknown): string | undefined {
156
+ if (typeof requestSchema === 'string') {
157
+ return requestSchema
158
+ }
159
+ const shape = getObjectShape(requestSchema)
160
+ const method = shape?.method ? getLiteralValue(shape.method) : undefined
161
+ return typeof method === 'string' ? method : undefined
162
+ }
163
+
146
164
  export function getLiteralValue(schema: unknown): unknown {
147
165
  if (!schema || typeof schema !== 'object') {
148
166
  return
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.10.8'
1
+ export const version = '0.10.9'