@posthog/mcp 0.13.0 → 0.14.0

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 (39) hide show
  1. package/README.md +25 -10
  2. package/dist/extensions/constants.d.ts +1 -1
  3. package/dist/extensions/constants.d.ts.map +1 -1
  4. package/dist/extensions/constants.js +1 -1
  5. package/dist/extensions/constants.mjs +1 -1
  6. package/dist/extensions/instrumentation.d.ts.map +1 -1
  7. package/dist/extensions/instrumentation.js +4 -1
  8. package/dist/extensions/instrumentation.mjs +5 -2
  9. package/dist/extensions/mcp-payloads.d.ts +10 -0
  10. package/dist/extensions/mcp-payloads.d.ts.map +1 -1
  11. package/dist/extensions/mcp-payloads.js +64 -0
  12. package/dist/extensions/mcp-payloads.mjs +62 -1
  13. package/dist/extensions/model-parameters.d.ts +20 -13
  14. package/dist/extensions/model-parameters.d.ts.map +1 -1
  15. package/dist/extensions/model-parameters.js +26 -2
  16. package/dist/extensions/model-parameters.mjs +24 -3
  17. package/dist/extensions/posthog-mcp.d.ts +3 -3
  18. package/dist/extensions/posthog-mcp.d.ts.map +1 -1
  19. package/dist/extensions/posthog-mcp.js +8 -9
  20. package/dist/extensions/posthog-mcp.mjs +9 -10
  21. package/dist/extensions/sanitization.d.ts.map +1 -1
  22. package/dist/extensions/sanitization.js +1 -1
  23. package/dist/extensions/sanitization.mjs +2 -2
  24. package/dist/types.d.ts +20 -20
  25. package/dist/types.d.ts.map +1 -1
  26. package/dist/version.d.ts +1 -1
  27. package/dist/version.js +1 -1
  28. package/dist/version.mjs +1 -1
  29. package/package.json +3 -3
  30. package/src/extensions/capture.ts +2 -2
  31. package/src/extensions/constants.ts +1 -1
  32. package/src/extensions/instrumentation.ts +6 -7
  33. package/src/extensions/mcp-payloads.ts +129 -0
  34. package/src/extensions/model-parameters.ts +50 -14
  35. package/src/extensions/posthog-events.ts +2 -2
  36. package/src/extensions/posthog-mcp.ts +11 -15
  37. package/src/extensions/sanitization.ts +8 -5
  38. package/src/types.ts +20 -20
  39. package/src/version.ts +1 -1
@@ -27,9 +27,9 @@ import { applyMcpLibIdentity } from './lib-identity'
27
27
  import { log } from './logger'
28
28
  import {
29
29
  addModelParameterToTool,
30
- getModelArgument,
31
30
  getModelDescription,
32
31
  isCaptureModelEnabled,
32
+ resolveModel,
33
33
  setEventModel,
34
34
  } from './model-parameters'
35
35
  import { McpEventSink } from './sink'
@@ -48,8 +48,8 @@ export interface PostHogMCPOptions extends PostHogOptions {
48
48
  */
49
49
  missingCapabilityToolName?: string
50
50
  /**
51
- * Inject a required `llm_model` argument into advertised tools and capture
52
- * the agent's self-reported value. Off by default.
51
+ * Capture the calling model from recognized client metadata, with an injected
52
+ * `llm_model` argument as fallback. Off by default.
53
53
  */
54
54
  captureModel?: MCPAnalyticsOptions['captureModel']
55
55
  }
@@ -118,10 +118,7 @@ export class PostHogMCP extends PostHog {
118
118
  event.isError = data.isError
119
119
  event.errorType = data.errorType
120
120
  applyIntent(event, data.intent, data.intentSource)
121
- setEventModel(event, data.llmModel)
122
- if (event.llmModel && data.llmModelSource) {
123
- event.llmModelSource = data.llmModelSource
124
- }
121
+ setEventModel(event, data.llmModel, data.llmModelSource)
125
122
  if (data.isError) {
126
123
  event.error = captureException(data.error ?? `Tool ${data.toolName} returned an error`)
127
124
  }
@@ -234,7 +231,7 @@ export class PostHogMCP extends PostHog {
234
231
  * @example
235
232
  * ```ts
236
233
  * const { intent, intentSource, llmModel, llmModelSource, args, isMissingCapability } =
237
- * posthog.prepareToolCall(name, rawArgs)
234
+ * posthog.prepareToolCall(name, rawArgs, { requestMeta: request.params?._meta })
238
235
  * if (isMissingCapability) {
239
236
  * posthog.captureMissingCapability({ context: intent, llmModel, llmModelSource, ...identity })
240
237
  * return getMoreToolsResult()
@@ -255,13 +252,15 @@ export class PostHogMCP extends PostHog {
255
252
  (options.originalTool
256
253
  ? analyticsOwnsParameter(options.originalTool.inputSchema, 'llm_model')
257
254
  : this.#modelParameterOwnership.get(name) === true)
258
- const llmModel = ownsModel ? getModelArgument({ params: { arguments: args } }) : undefined
255
+ const resolvedModel = isCaptureModelEnabled(this.#captureModel)
256
+ ? resolveModel({ params: { arguments: args, _meta: options.requestMeta } }, ownsModel)
257
+ : undefined
259
258
  const strippedArgs = stripContext(args)
260
259
  return {
261
260
  intent,
262
261
  intentSource: intent ? 'context_parameter' : undefined,
263
- llmModel,
264
- llmModelSource: llmModel ? 'self_reported' : undefined,
262
+ llmModel: resolvedModel?.model,
263
+ llmModelSource: resolvedModel?.source,
265
264
  args: ownsModel
266
265
  ? (stripOwnedAnalyticsArguments(strippedArgs, {
267
266
  context: false,
@@ -283,10 +282,7 @@ export class PostHogMCP extends PostHog {
283
282
  event.resourceName = this.#missingCapabilityToolName
284
283
  event.parameters = data.parameters
285
284
  applyIntent(event, data.context, 'context_parameter')
286
- setEventModel(event, data.llmModel)
287
- if (event.llmModel && data.llmModelSource) {
288
- event.llmModelSource = data.llmModelSource
289
- }
285
+ setEventModel(event, data.llmModel, data.llmModelSource)
290
286
  this.#emit(event)
291
287
  }
292
288
 
@@ -4,7 +4,7 @@
4
4
  // Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
5
5
 
6
6
  import type { ErrorProperties, Event, McpEvent } from '../types'
7
- import { sanitizeCapturedValue } from './mcp-payloads'
7
+ import { redactPii, sanitizeCapturedValue } from './mcp-payloads'
8
8
 
9
9
  type SanitizedRecord = Record<string, unknown>
10
10
 
@@ -32,11 +32,14 @@ export function sanitizeEvent<T extends Event | McpEvent>(event: T): T {
32
32
  result.parameters = sanitizeParameters(result.parameters)
33
33
  }
34
34
 
35
- // The intent comes straight from an agent-narrated `context` string, so it
36
- // can contain a secret the LLM read aloud. Redact it like any other captured
37
- // value rather than shipping it raw as `$mcp_intent`.
35
+ // The intent comes straight from an agent-narrated `context` string, so it can
36
+ // contain a secret the LLM read aloud or personal data it narrated about the
37
+ // user. Redact it like any other captured value, then strip structured PII
38
+ // (emails, phone numbers, IPs, cards, SSNs) rather than shipping it raw as
39
+ // `$mcp_intent`. PII redaction is scoped to the intent only — structured tool
40
+ // parameters and responses often hold the same shapes as legitimate data.
38
41
  if (result.userIntent != null) {
39
- result.userIntent = sanitizeCapturedValue(result.userIntent) as string
42
+ result.userIntent = redactPii(sanitizeCapturedValue(result.userIntent) as string)
40
43
  }
41
44
 
42
45
  if (result.llmModel != null) {
package/src/types.ts CHANGED
@@ -67,6 +67,7 @@ export interface CompatibleTextToolResult {
67
67
  }
68
68
 
69
69
  export interface MCPRequestParamsLike {
70
+ _meta?: JsonRecord
70
71
  arguments?: JsonRecord
71
72
  name?: string
72
73
  [key: string]: unknown
@@ -130,17 +131,15 @@ export interface MCPAnalyticsOptions {
130
131
  /** Inject a required `context` parameter on every tool to capture user intent. */
131
132
  context?: boolean | MCPAnalyticsContextOptions
132
133
  /**
133
- * Inject a required `llm_model` parameter on every tool so the calling agent
134
- * self-reports the model it runs as, captured as `$mcp_llm_model` with
135
- * `$mcp_llm_model_source = "self_reported"`. Off by default.
134
+ * Capture the calling model as `$mcp_llm_model`. Recognized client metadata
135
+ * takes precedence, with an injected `llm_model` parameter as the fallback.
136
+ * Off by default.
136
137
  *
137
- * The MCP wire deliberately carries no model identity, so self-report is the
138
- * only capture path — harnesses inject the model id into the agent's system
139
- * prompt, and agents restate it accurately. Like `clientInfo` in the MCP
140
- * spec, the value is unverified: use it for per-model quality analytics, not
141
- * billing or security. An honest `"unknown"` from the agent is dropped
142
- * rather than captured. Reasoning effort is intentionally not collected —
143
- * agents don't reliably know it, so it would only ever be noise.
138
+ * MCP does not standardize model identity. Some clients expose it through
139
+ * vendor metadata; other harnesses inject it into the agent's system prompt
140
+ * so the agent can restate it. `$mcp_llm_model_source` records which path won.
141
+ * Both paths are unverified: use them for quality analytics, not billing or
142
+ * security. Missing, blank, and `"unknown"` values are dropped.
144
143
  */
145
144
  captureModel?: boolean | MCPAnalyticsModelOptions
146
145
  /**
@@ -192,7 +191,7 @@ export interface MCPAnalyticsModelOptions {
192
191
 
193
192
  export type MaybePromise<T> = T | Promise<T>
194
193
  export type MCPAnalyticsIntentSource = 'context_parameter' | 'inferred'
195
- export type MCPAnalyticsModelSource = 'self_reported'
194
+ export type MCPAnalyticsModelSource = 'client_metadata' | 'self_reported'
196
195
 
197
196
  export type ToolCallback =
198
197
  | ((
@@ -245,12 +244,11 @@ export interface Event {
245
244
  eventType: MCPAnalyticsEventType
246
245
  groups?: Record<string, string>
247
246
  /**
248
- * The calling agent's self-reported model id → `$mcp_llm_model`. Read off
249
- * the SDK-injected `llm_model` argument (`captureModel` option); unverified
250
- * by design, like the MCP spec's own `clientInfo`.
247
+ * The calling model id → `$mcp_llm_model`. Resolved from recognized client
248
+ * metadata first, then the SDK-injected `llm_model` argument; unverified.
251
249
  */
252
250
  llmModel?: string
253
- /** How the model id was obtained → `$mcp_llm_model_source`. Always `self_reported` today. */
251
+ /** How the model id was obtained → `$mcp_llm_model_source`. */
254
252
  llmModelSource?: MCPAnalyticsModelSource
255
253
  /**
256
254
  * Explicit PostHog event name. When set (via `capture(server, { event })`) it
@@ -512,8 +510,8 @@ export interface ToolCallCaptureData extends McpCaptureCommon {
512
510
  */
513
511
  intentSource?: MCPAnalyticsIntentSource
514
512
  /**
515
- * The calling agent's self-reported model id -> `$mcp_llm_model`. On the
516
- * custom-dispatcher path, read it from {@link PostHogMCP.prepareToolCall}.
513
+ * The calling model id -> `$mcp_llm_model`. On the custom-dispatcher path,
514
+ * read it from {@link PostHogMCP.prepareToolCall}.
517
515
  */
518
516
  llmModel?: string
519
517
  /** How the model id was obtained -> `$mcp_llm_model_source`. */
@@ -600,6 +598,8 @@ export interface PrepareToolCallOptions {
600
598
  * multi-replica servers so SDK argument ownership is resolved per request.
601
599
  */
602
600
  originalTool?: { inputSchema?: unknown }
601
+ /** The incoming `tools/call` request's `_meta`, used for recognized client model metadata. */
602
+ requestMeta?: JsonRecord
603
603
  }
604
604
 
605
605
  /**
@@ -612,9 +612,9 @@ export interface PreparedToolCall {
612
612
  intent?: string
613
613
  /** Where the intent came from. Always `context_parameter` here when set. */
614
614
  intentSource?: MCPAnalyticsIntentSource
615
- /** The agent's self-reported model id, when `captureModel` is enabled and owned by the SDK. */
615
+ /** The calling model id, when `captureModel` is enabled and a supported source provides it. */
616
616
  llmModel?: string
617
- /** How the model id was obtained. Always `self_reported` when present. */
617
+ /** How the model id was obtained. */
618
618
  llmModelSource?: MCPAnalyticsModelSource
619
619
  /** The call arguments with SDK-owned `context` and `llm_model` keys removed. */
620
620
  args?: Record<string, unknown>
@@ -629,7 +629,7 @@ export interface MissingCapabilityCaptureData extends McpCaptureCommon {
629
629
  * on the `get_more_tools` call) → `$mcp_intent`.
630
630
  */
631
631
  context?: string
632
- /** The calling agent's self-reported model id -> `$mcp_llm_model`. */
632
+ /** The calling model id -> `$mcp_llm_model`. */
633
633
  llmModel?: string
634
634
  /** How the model id was obtained -> `$mcp_llm_model_source`. */
635
635
  llmModelSource?: MCPAnalyticsModelSource
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.13.0'
1
+ export const version = '0.14.0'