@posthog/mcp 0.0.1 → 0.0.3
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.
- package/README.md +46 -1
- package/dist/index.cjs +110 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.mts +21 -1
- package/dist/index.mjs +109 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,7 @@ interface MCPAnalyticsOptions {
|
|
|
28
28
|
eventTags?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Record<string, string> | null | Promise<Record<string, string> | null>;
|
|
29
29
|
host?: string;
|
|
30
30
|
identify?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<UserIdentity | null>;
|
|
31
|
+
intentFallback?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => MaybePromise<string | null | undefined>;
|
|
31
32
|
posthogClient?: PostHogCaptureClient;
|
|
32
33
|
posthogOptions?: Pick<PostHogOptions, "fetch" | "flushAt" | "flushInterval" | "host" | "requestTimeout" | "waitUntil" | "waitUntilDebounceMs" | "waitUntilMaxWaitMs">;
|
|
33
34
|
redactSensitiveInformation?: RedactFunction;
|
|
@@ -36,6 +37,8 @@ interface MCPAnalyticsOptions {
|
|
|
36
37
|
interface MCPAnalyticsContextOptions {
|
|
37
38
|
description?: string;
|
|
38
39
|
}
|
|
40
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
41
|
+
type MCPAnalyticsIntentSource = "context_parameter" | "inferred";
|
|
39
42
|
type RedactFunction = (text: string) => Promise<string>;
|
|
40
43
|
interface CompatibleRequestHandlerExtra {
|
|
41
44
|
headers?: Record<string, string | string[]>;
|
|
@@ -62,6 +65,21 @@ interface CustomEventData {
|
|
|
62
65
|
}
|
|
63
66
|
//#endregion
|
|
64
67
|
//#region src/modules/constants.d.ts
|
|
68
|
+
declare const POSTHOG_MCP_ANALYTICS_SOURCE = "posthog_mcp_analytics";
|
|
69
|
+
declare const PostHogMCPAnalyticsEvent: {
|
|
70
|
+
readonly AiSpan: "$ai_span";
|
|
71
|
+
readonly Custom: "mcp_custom";
|
|
72
|
+
readonly Exception: "$exception";
|
|
73
|
+
readonly Identify: "$identify";
|
|
74
|
+
readonly Initialize: "mcp_initialize";
|
|
75
|
+
readonly PromptGet: "mcp_prompt_get";
|
|
76
|
+
readonly PromptsList: "mcp_prompts_list";
|
|
77
|
+
readonly ResourceRead: "mcp_resource_read";
|
|
78
|
+
readonly ResourcesList: "mcp_resources_list";
|
|
79
|
+
readonly ToolCall: "mcp_tool_call";
|
|
80
|
+
readonly ToolsList: "mcp_tools_list";
|
|
81
|
+
};
|
|
82
|
+
type PostHogMCPAnalyticsEvent = (typeof PostHogMCPAnalyticsEvent)[keyof typeof PostHogMCPAnalyticsEvent];
|
|
65
83
|
declare const PostHogMCPAnalyticsProperty: {
|
|
66
84
|
readonly AiInputState: "$ai_input_state";
|
|
67
85
|
readonly AiIsError: "$ai_is_error";
|
|
@@ -77,6 +95,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
77
95
|
readonly DurationMs: "$mcp_duration_ms";
|
|
78
96
|
readonly IsError: "$mcp_is_error";
|
|
79
97
|
readonly Intent: "$mcp_intent";
|
|
98
|
+
readonly IntentSource: "$mcp_intent_source";
|
|
80
99
|
readonly Parameters: "$mcp_parameters";
|
|
81
100
|
readonly ResourceName: "$mcp_resource_name";
|
|
82
101
|
readonly Response: "$mcp_response";
|
|
@@ -100,6 +119,7 @@ type PostHogMCPAnalyticsProperty = (typeof PostHogMCPAnalyticsProperty)[keyof ty
|
|
|
100
119
|
* @param options.enableAITracing - Emits `$ai_span` events for tool calls so MCP activity appears in PostHog LLM analytics. Defaults to false.
|
|
101
120
|
* @param options.enableTracing - Enables tracking of tool calls and usage patterns.
|
|
102
121
|
* @param options.context - Enables the required "context" parameter on tools to capture user intent. Pass false to disable, or an object with a custom description.
|
|
122
|
+
* @param options.intentFallback - Optional consumer-supplied callback invoked when a tool call has no explicit `context` argument. Return a short user intent string to capture as `$mcp_intent` (with `$mcp_intent_source = "inferred"`). The SDK does not infer anything on its own — this is purely a slot for your own derivation logic (e.g. a switch on `request.params.name`, an LLM call, etc.). Runs on the hot path of every uncontextualized tool call.
|
|
103
123
|
* @param options.identify - Async function to identify users and attach custom data to their sessions.
|
|
104
124
|
* @param options.redactSensitiveInformation - Function to redact sensitive data before sending to PostHog.
|
|
105
125
|
* @param options.eventTags - Callback invoked on every auto-captured event (tool calls, tool lists, initialize) to attach string key-value tags. Tags are intended to be indexed and queryable in PostHog — use them for structured metadata you'll want to filter or group by (e.g., trace IDs, environments, regions). Tags are validated client-side: keys must be ≤32 chars matching `[a-zA-Z0-9$_.:\- ]`, values must be strings ≤200 chars with no newlines, max 50 entries per event. Invalid entries are silently dropped with a warning logged to `~/posthog-mcp-analytics.log`. If the callback throws or returns null, tags are omitted. Receives the same `(request, extra)` arguments as `identify`.
|
|
@@ -236,5 +256,5 @@ declare function track<TServer>(server: TServer, options?: MCPAnalyticsOptions):
|
|
|
236
256
|
declare function publishCustomEvent(serverOrSessionId: unknown, eventData?: CustomEventData): Promise<void>;
|
|
237
257
|
type IdentifyFunction = MCPAnalyticsOptions["identify"];
|
|
238
258
|
//#endregion
|
|
239
|
-
export { type CustomEventData, IdentifyFunction, type MCPAnalyticsContextOptions, type MCPAnalyticsOptions, PostHogMCPAnalyticsProperty, type RedactFunction, type UserIdentity, publishCustomEvent, track };
|
|
259
|
+
export { type CustomEventData, IdentifyFunction, type MCPAnalyticsContextOptions, type MCPAnalyticsIntentSource, type MCPAnalyticsOptions, POSTHOG_MCP_ANALYTICS_SOURCE, PostHogMCPAnalyticsEvent, PostHogMCPAnalyticsProperty, type RedactFunction, type UserIdentity, publishCustomEvent, track };
|
|
240
260
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,7 @@ interface MCPAnalyticsOptions {
|
|
|
27
27
|
eventTags?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Record<string, string> | null | Promise<Record<string, string> | null>;
|
|
28
28
|
host?: string;
|
|
29
29
|
identify?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<UserIdentity | null>;
|
|
30
|
+
intentFallback?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => MaybePromise<string | null | undefined>;
|
|
30
31
|
posthogClient?: PostHogCaptureClient;
|
|
31
32
|
posthogOptions?: Pick<PostHogOptions, "fetch" | "flushAt" | "flushInterval" | "host" | "requestTimeout" | "waitUntil" | "waitUntilDebounceMs" | "waitUntilMaxWaitMs">;
|
|
32
33
|
redactSensitiveInformation?: RedactFunction;
|
|
@@ -35,6 +36,8 @@ interface MCPAnalyticsOptions {
|
|
|
35
36
|
interface MCPAnalyticsContextOptions {
|
|
36
37
|
description?: string;
|
|
37
38
|
}
|
|
39
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
40
|
+
type MCPAnalyticsIntentSource = "context_parameter" | "inferred";
|
|
38
41
|
type RedactFunction = (text: string) => Promise<string>;
|
|
39
42
|
interface CompatibleRequestHandlerExtra {
|
|
40
43
|
headers?: Record<string, string | string[]>;
|
|
@@ -61,6 +64,21 @@ interface CustomEventData {
|
|
|
61
64
|
}
|
|
62
65
|
//#endregion
|
|
63
66
|
//#region src/modules/constants.d.ts
|
|
67
|
+
declare const POSTHOG_MCP_ANALYTICS_SOURCE = "posthog_mcp_analytics";
|
|
68
|
+
declare const PostHogMCPAnalyticsEvent: {
|
|
69
|
+
readonly AiSpan: "$ai_span";
|
|
70
|
+
readonly Custom: "mcp_custom";
|
|
71
|
+
readonly Exception: "$exception";
|
|
72
|
+
readonly Identify: "$identify";
|
|
73
|
+
readonly Initialize: "mcp_initialize";
|
|
74
|
+
readonly PromptGet: "mcp_prompt_get";
|
|
75
|
+
readonly PromptsList: "mcp_prompts_list";
|
|
76
|
+
readonly ResourceRead: "mcp_resource_read";
|
|
77
|
+
readonly ResourcesList: "mcp_resources_list";
|
|
78
|
+
readonly ToolCall: "mcp_tool_call";
|
|
79
|
+
readonly ToolsList: "mcp_tools_list";
|
|
80
|
+
};
|
|
81
|
+
type PostHogMCPAnalyticsEvent = (typeof PostHogMCPAnalyticsEvent)[keyof typeof PostHogMCPAnalyticsEvent];
|
|
64
82
|
declare const PostHogMCPAnalyticsProperty: {
|
|
65
83
|
readonly AiInputState: "$ai_input_state";
|
|
66
84
|
readonly AiIsError: "$ai_is_error";
|
|
@@ -76,6 +94,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
76
94
|
readonly DurationMs: "$mcp_duration_ms";
|
|
77
95
|
readonly IsError: "$mcp_is_error";
|
|
78
96
|
readonly Intent: "$mcp_intent";
|
|
97
|
+
readonly IntentSource: "$mcp_intent_source";
|
|
79
98
|
readonly Parameters: "$mcp_parameters";
|
|
80
99
|
readonly ResourceName: "$mcp_resource_name";
|
|
81
100
|
readonly Response: "$mcp_response";
|
|
@@ -99,6 +118,7 @@ type PostHogMCPAnalyticsProperty = (typeof PostHogMCPAnalyticsProperty)[keyof ty
|
|
|
99
118
|
* @param options.enableAITracing - Emits `$ai_span` events for tool calls so MCP activity appears in PostHog LLM analytics. Defaults to false.
|
|
100
119
|
* @param options.enableTracing - Enables tracking of tool calls and usage patterns.
|
|
101
120
|
* @param options.context - Enables the required "context" parameter on tools to capture user intent. Pass false to disable, or an object with a custom description.
|
|
121
|
+
* @param options.intentFallback - Optional consumer-supplied callback invoked when a tool call has no explicit `context` argument. Return a short user intent string to capture as `$mcp_intent` (with `$mcp_intent_source = "inferred"`). The SDK does not infer anything on its own — this is purely a slot for your own derivation logic (e.g. a switch on `request.params.name`, an LLM call, etc.). Runs on the hot path of every uncontextualized tool call.
|
|
102
122
|
* @param options.identify - Async function to identify users and attach custom data to their sessions.
|
|
103
123
|
* @param options.redactSensitiveInformation - Function to redact sensitive data before sending to PostHog.
|
|
104
124
|
* @param options.eventTags - Callback invoked on every auto-captured event (tool calls, tool lists, initialize) to attach string key-value tags. Tags are intended to be indexed and queryable in PostHog — use them for structured metadata you'll want to filter or group by (e.g., trace IDs, environments, regions). Tags are validated client-side: keys must be ≤32 chars matching `[a-zA-Z0-9$_.:\- ]`, values must be strings ≤200 chars with no newlines, max 50 entries per event. Invalid entries are silently dropped with a warning logged to `~/posthog-mcp-analytics.log`. If the callback throws or returns null, tags are omitted. Receives the same `(request, extra)` arguments as `identify`.
|
|
@@ -235,5 +255,5 @@ declare function track<TServer>(server: TServer, options?: MCPAnalyticsOptions):
|
|
|
235
255
|
declare function publishCustomEvent(serverOrSessionId: unknown, eventData?: CustomEventData): Promise<void>;
|
|
236
256
|
type IdentifyFunction = MCPAnalyticsOptions["identify"];
|
|
237
257
|
//#endregion
|
|
238
|
-
export { type CustomEventData, IdentifyFunction, type MCPAnalyticsContextOptions, type MCPAnalyticsOptions, PostHogMCPAnalyticsProperty, type RedactFunction, type UserIdentity, publishCustomEvent, track };
|
|
258
|
+
export { type CustomEventData, IdentifyFunction, type MCPAnalyticsContextOptions, type MCPAnalyticsIntentSource, type MCPAnalyticsOptions, POSTHOG_MCP_ANALYTICS_SOURCE, PostHogMCPAnalyticsEvent, PostHogMCPAnalyticsProperty, type RedactFunction, type UserIdentity, publishCustomEvent, track };
|
|
239
259
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -119,15 +119,14 @@ function getMCPCompatibleErrorMessage(error) {
|
|
|
119
119
|
return "Unknown error";
|
|
120
120
|
}
|
|
121
121
|
//#endregion
|
|
122
|
-
//#region src/modules/ids.ts
|
|
123
|
-
function newPrefixedId(prefix) {
|
|
124
|
-
return `${prefix}_${randomUUID()}`;
|
|
125
|
-
}
|
|
126
|
-
function deterministicPrefixedId(prefix, input) {
|
|
127
|
-
return `${prefix}_${createHash("sha256").update(input).digest("hex").slice(0, 32)}`;
|
|
128
|
-
}
|
|
129
|
-
//#endregion
|
|
130
122
|
//#region src/modules/event-types.ts
|
|
123
|
+
/**
|
|
124
|
+
* Internal SDK event vocabulary.
|
|
125
|
+
*
|
|
126
|
+
* These values are not imported from `@modelcontextprotocol/sdk`; they are the
|
|
127
|
+
* protocol-shaped event types this SDK observes before mapping them to PostHog
|
|
128
|
+
* event names.
|
|
129
|
+
*/
|
|
131
130
|
const MCPAnalyticsEventType = {
|
|
132
131
|
identify: "posthog:identify",
|
|
133
132
|
custom: "posthog:custom",
|
|
@@ -140,6 +139,14 @@ const MCPAnalyticsEventType = {
|
|
|
140
139
|
mcpToolsList: "mcp:tools/list"
|
|
141
140
|
};
|
|
142
141
|
//#endregion
|
|
142
|
+
//#region src/modules/ids.ts
|
|
143
|
+
function newPrefixedId(prefix) {
|
|
144
|
+
return `${prefix}_${randomUUID()}`;
|
|
145
|
+
}
|
|
146
|
+
function deterministicPrefixedId(prefix, input) {
|
|
147
|
+
return `${prefix}_${createHash("sha256").update(input).digest("hex").slice(0, 32)}`;
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
143
150
|
//#region src/modules/validation.ts
|
|
144
151
|
const TAG_KEY_REGEX = /^[a-zA-Z0-9$_.:\- ]+$/;
|
|
145
152
|
const MAX_TAG_KEY_LENGTH = 32;
|
|
@@ -343,6 +350,19 @@ function getRequestResourceName(request) {
|
|
|
343
350
|
//#region src/modules/constants.ts
|
|
344
351
|
const DEFAULT_CONTEXT_PARAMETER_DESCRIPTION = `Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): "Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization."`;
|
|
345
352
|
const POSTHOG_MCP_ANALYTICS_SOURCE = "posthog_mcp_analytics";
|
|
353
|
+
const PostHogMCPAnalyticsEvent = {
|
|
354
|
+
AiSpan: "$ai_span",
|
|
355
|
+
Custom: "mcp_custom",
|
|
356
|
+
Exception: "$exception",
|
|
357
|
+
Identify: "$identify",
|
|
358
|
+
Initialize: "mcp_initialize",
|
|
359
|
+
PromptGet: "mcp_prompt_get",
|
|
360
|
+
PromptsList: "mcp_prompts_list",
|
|
361
|
+
ResourceRead: "mcp_resource_read",
|
|
362
|
+
ResourcesList: "mcp_resources_list",
|
|
363
|
+
ToolCall: "mcp_tool_call",
|
|
364
|
+
ToolsList: "mcp_tools_list"
|
|
365
|
+
};
|
|
346
366
|
const PostHogMCPAnalyticsProperty = {
|
|
347
367
|
AiInputState: "$ai_input_state",
|
|
348
368
|
AiIsError: "$ai_is_error",
|
|
@@ -358,6 +378,7 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
358
378
|
DurationMs: "$mcp_duration_ms",
|
|
359
379
|
IsError: "$mcp_is_error",
|
|
360
380
|
Intent: "$mcp_intent",
|
|
381
|
+
IntentSource: "$mcp_intent_source",
|
|
361
382
|
Parameters: "$mcp_parameters",
|
|
362
383
|
ResourceName: "$mcp_resource_name",
|
|
363
384
|
Response: "$mcp_response",
|
|
@@ -369,8 +390,17 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
369
390
|
};
|
|
370
391
|
//#endregion
|
|
371
392
|
//#region src/modules/posthog-events.ts
|
|
372
|
-
const
|
|
373
|
-
|
|
393
|
+
const BUILT_IN_EVENT_NAME_BY_TYPE = {
|
|
394
|
+
[MCPAnalyticsEventType.custom]: PostHogMCPAnalyticsEvent.Custom,
|
|
395
|
+
[MCPAnalyticsEventType.identify]: PostHogMCPAnalyticsEvent.Identify,
|
|
396
|
+
[MCPAnalyticsEventType.mcpInitialize]: PostHogMCPAnalyticsEvent.Initialize,
|
|
397
|
+
[MCPAnalyticsEventType.mcpPromptsGet]: PostHogMCPAnalyticsEvent.PromptGet,
|
|
398
|
+
[MCPAnalyticsEventType.mcpPromptsList]: PostHogMCPAnalyticsEvent.PromptsList,
|
|
399
|
+
[MCPAnalyticsEventType.mcpResourcesList]: PostHogMCPAnalyticsEvent.ResourcesList,
|
|
400
|
+
[MCPAnalyticsEventType.mcpResourcesRead]: PostHogMCPAnalyticsEvent.ResourceRead,
|
|
401
|
+
[MCPAnalyticsEventType.mcpToolsCall]: PostHogMCPAnalyticsEvent.ToolCall,
|
|
402
|
+
[MCPAnalyticsEventType.mcpToolsList]: PostHogMCPAnalyticsEvent.ToolsList
|
|
403
|
+
};
|
|
374
404
|
function getDistinctId(event) {
|
|
375
405
|
return event.identifyActorGivenId || event.sessionId || "anonymous";
|
|
376
406
|
}
|
|
@@ -385,7 +415,6 @@ function buildPostHogCaptureEvents(event, options = {}) {
|
|
|
385
415
|
}
|
|
386
416
|
function buildCaptureEvent(event, options) {
|
|
387
417
|
const distinctId = getDistinctId(event);
|
|
388
|
-
const eventName = mapEventType(event.eventType);
|
|
389
418
|
const timestamp = getTimestamp(event);
|
|
390
419
|
const properties = {
|
|
391
420
|
[PostHogMCPAnalyticsProperty.SessionId]: event.sessionId,
|
|
@@ -395,7 +424,7 @@ function buildCaptureEvent(event, options) {
|
|
|
395
424
|
addTraceReferenceProperties(event, properties, options);
|
|
396
425
|
addCustomEventProperties(event, properties);
|
|
397
426
|
return {
|
|
398
|
-
event:
|
|
427
|
+
event: BUILT_IN_EVENT_NAME_BY_TYPE[event.eventType],
|
|
399
428
|
distinct_id: distinctId,
|
|
400
429
|
properties,
|
|
401
430
|
timestamp,
|
|
@@ -427,6 +456,7 @@ function addCommonEventProperties(event, properties) {
|
|
|
427
456
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
428
457
|
if (event.clientVersion) properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
429
458
|
if (event.userIntent) properties[PostHogMCPAnalyticsProperty.Intent] = event.userIntent;
|
|
459
|
+
if (event.userIntentSource) properties[PostHogMCPAnalyticsProperty.IntentSource] = event.userIntentSource;
|
|
430
460
|
if (event.isError !== void 0) properties[PostHogMCPAnalyticsProperty.IsError] = event.isError;
|
|
431
461
|
if (event.parameters !== void 0) properties[PostHogMCPAnalyticsProperty.Parameters] = event.parameters;
|
|
432
462
|
if (event.response !== void 0) properties[PostHogMCPAnalyticsProperty.Response] = event.response;
|
|
@@ -460,7 +490,7 @@ function buildExceptionEvent(event) {
|
|
|
460
490
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
461
491
|
if (event.clientVersion) properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
462
492
|
return {
|
|
463
|
-
event:
|
|
493
|
+
event: PostHogMCPAnalyticsEvent.Exception,
|
|
464
494
|
distinct_id: distinctId,
|
|
465
495
|
properties,
|
|
466
496
|
timestamp,
|
|
@@ -486,27 +516,17 @@ function buildAISpanEvent(event) {
|
|
|
486
516
|
if (event.serverName) properties[PostHogMCPAnalyticsProperty.ServerName] = event.serverName;
|
|
487
517
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
488
518
|
if (event.userIntent) properties[PostHogMCPAnalyticsProperty.Intent] = event.userIntent;
|
|
519
|
+
if (event.userIntentSource) properties[PostHogMCPAnalyticsProperty.IntentSource] = event.userIntentSource;
|
|
489
520
|
if (event.tags) for (const [key, value] of Object.entries(event.tags)) properties[key] = value;
|
|
490
521
|
if (event.properties) for (const [key, value] of Object.entries(event.properties)) properties[key] = value;
|
|
491
522
|
return {
|
|
492
|
-
event:
|
|
523
|
+
event: PostHogMCPAnalyticsEvent.AiSpan,
|
|
493
524
|
distinct_id: distinctId,
|
|
494
525
|
properties,
|
|
495
526
|
timestamp,
|
|
496
527
|
type: "capture"
|
|
497
528
|
};
|
|
498
529
|
}
|
|
499
|
-
function mapEventType(eventType) {
|
|
500
|
-
return {
|
|
501
|
-
[MCPAnalyticsEventType.mcpToolsCall]: "mcp_tool_call",
|
|
502
|
-
[MCPAnalyticsEventType.mcpToolsList]: "mcp_tools_list",
|
|
503
|
-
[MCPAnalyticsEventType.mcpInitialize]: "mcp_initialize",
|
|
504
|
-
[MCPAnalyticsEventType.mcpResourcesRead]: "mcp_resource_read",
|
|
505
|
-
[MCPAnalyticsEventType.mcpResourcesList]: "mcp_resources_list",
|
|
506
|
-
[MCPAnalyticsEventType.mcpPromptsGet]: "mcp_prompt_get",
|
|
507
|
-
[MCPAnalyticsEventType.mcpPromptsList]: "mcp_prompts_list"
|
|
508
|
-
}[eventType] || `mcp_${eventType.replace(MCP_EVENT_PREFIX_REGEX, "").replace(SLASH_REGEX, "_")}`;
|
|
509
|
-
}
|
|
510
530
|
//#endregion
|
|
511
531
|
//#region src/modules/redaction.ts
|
|
512
532
|
/**
|
|
@@ -700,7 +720,7 @@ function sanitizeParameters(obj) {
|
|
|
700
720
|
}
|
|
701
721
|
//#endregion
|
|
702
722
|
//#region package.json
|
|
703
|
-
var version = "0.0.
|
|
723
|
+
var version = "0.0.3";
|
|
704
724
|
//#endregion
|
|
705
725
|
//#region src/modules/session.ts
|
|
706
726
|
function newSessionId() {
|
|
@@ -1084,7 +1104,6 @@ var EventQueue = class {
|
|
|
1084
1104
|
timestamp: new Date(captureEvent.timestamp)
|
|
1085
1105
|
});
|
|
1086
1106
|
writeToLog(`Queued PostHog event ${event.id} | ${event.eventType} | ${event.duration} ms | ${event.identifyActorGivenId || "anonymous"}`);
|
|
1087
|
-
writeToLog(`Event details: ${JSON.stringify(event)}`);
|
|
1088
1107
|
} catch (error) {
|
|
1089
1108
|
writeToLog(`Failed to queue PostHog event ${event.id}: ${getMCPCompatibleErrorMessage(error)}`);
|
|
1090
1109
|
throw error;
|
|
@@ -1147,7 +1166,7 @@ function publishEvent(server, eventInput) {
|
|
|
1147
1166
|
id: eventInput.id || "",
|
|
1148
1167
|
sessionId: eventInput.sessionId || data.sessionId,
|
|
1149
1168
|
apiKey: data.apiKey,
|
|
1150
|
-
eventType: eventInput.eventType ||
|
|
1169
|
+
eventType: eventInput.eventType || MCPAnalyticsEventType.custom,
|
|
1151
1170
|
timestamp: eventInput.timestamp || /* @__PURE__ */ new Date(),
|
|
1152
1171
|
duration,
|
|
1153
1172
|
ipAddress: sessionInfo.ipAddress,
|
|
@@ -1164,6 +1183,7 @@ function publishEvent(server, eventInput) {
|
|
|
1164
1183
|
parameters: eventInput.parameters,
|
|
1165
1184
|
response: eventInput.response,
|
|
1166
1185
|
userIntent: eventInput.userIntent,
|
|
1186
|
+
userIntentSource: eventInput.userIntentSource,
|
|
1167
1187
|
isError: eventInput.isError,
|
|
1168
1188
|
error: eventInput.error,
|
|
1169
1189
|
redactionFn: eventInput.redactionFn,
|
|
@@ -1902,6 +1922,49 @@ function setupMCPAnalyticsTools(server) {
|
|
|
1902
1922
|
}
|
|
1903
1923
|
}
|
|
1904
1924
|
//#endregion
|
|
1925
|
+
//#region src/modules/intent.ts
|
|
1926
|
+
function getContextArgument$2(request) {
|
|
1927
|
+
const context = request.params?.arguments?.context;
|
|
1928
|
+
return typeof context === "string" && context.trim() ? context : void 0;
|
|
1929
|
+
}
|
|
1930
|
+
function normalizeIntent(intent) {
|
|
1931
|
+
if (typeof intent !== "string") return null;
|
|
1932
|
+
const trimmed = intent.trim();
|
|
1933
|
+
return trimmed ? trimmed : null;
|
|
1934
|
+
}
|
|
1935
|
+
async function runIntentFallback(data, request, extra) {
|
|
1936
|
+
if (!data.options.intentFallback) return null;
|
|
1937
|
+
try {
|
|
1938
|
+
const intent = normalizeIntent(await data.options.intentFallback(request, extra));
|
|
1939
|
+
return intent ? {
|
|
1940
|
+
intent,
|
|
1941
|
+
source: "inferred"
|
|
1942
|
+
} : null;
|
|
1943
|
+
} catch (error) {
|
|
1944
|
+
writeToLog(`intentFallback callback error: ${error}`);
|
|
1945
|
+
return null;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
async function resolveToolCallIntent(data, request, extra) {
|
|
1949
|
+
const contextArgument = getContextArgument$2(request);
|
|
1950
|
+
if (isContextEnabled(data.options.context) && request.params?.name !== "get_more_tools" && contextArgument) return {
|
|
1951
|
+
intent: contextArgument,
|
|
1952
|
+
source: "context_parameter"
|
|
1953
|
+
};
|
|
1954
|
+
return await runIntentFallback(data, request, extra);
|
|
1955
|
+
}
|
|
1956
|
+
function setEventIntent(event, resolvedIntent) {
|
|
1957
|
+
if (!resolvedIntent) return;
|
|
1958
|
+
event.userIntent = resolvedIntent.intent;
|
|
1959
|
+
event.userIntentSource = resolvedIntent.source;
|
|
1960
|
+
}
|
|
1961
|
+
function setExplicitContextIntent(event, context) {
|
|
1962
|
+
const intent = normalizeIntent(context);
|
|
1963
|
+
if (!intent) return;
|
|
1964
|
+
event.userIntent = intent;
|
|
1965
|
+
event.userIntentSource = "context_parameter";
|
|
1966
|
+
}
|
|
1967
|
+
//#endregion
|
|
1905
1968
|
//#region src/modules/tracing.ts
|
|
1906
1969
|
function isToolResultError$1(result) {
|
|
1907
1970
|
return !!result && typeof result === "object" && "isError" in result && result.isError === true;
|
|
@@ -2049,18 +2112,20 @@ async function handleToolCallRequest(server, originalCallToolHandler, request, e
|
|
|
2049
2112
|
try {
|
|
2050
2113
|
await handleIdentify(server, data, request, extra);
|
|
2051
2114
|
await applyResolvedMetadata$1(event, data, request, extra);
|
|
2052
|
-
|
|
2115
|
+
setEventIntent(event, await resolveToolCallIntent(data, request, extra));
|
|
2053
2116
|
const result = await executeToolCall(server, originalCallToolHandler, request, extra, event);
|
|
2054
2117
|
if (isToolResultError$1(result)) {
|
|
2055
2118
|
event.isError = true;
|
|
2056
2119
|
event.error = captureException(result);
|
|
2057
|
-
}
|
|
2120
|
+
} else event.isError = false;
|
|
2058
2121
|
event.response = result;
|
|
2122
|
+
event.duration = getEventDuration(event);
|
|
2059
2123
|
publishEvent(server, event);
|
|
2060
2124
|
return result;
|
|
2061
2125
|
} catch (error) {
|
|
2062
2126
|
event.isError = true;
|
|
2063
2127
|
event.error = captureException(error);
|
|
2128
|
+
event.duration = getEventDuration(event);
|
|
2064
2129
|
publishEvent(server, event);
|
|
2065
2130
|
throw error;
|
|
2066
2131
|
}
|
|
@@ -2068,7 +2133,7 @@ async function handleToolCallRequest(server, originalCallToolHandler, request, e
|
|
|
2068
2133
|
async function executeToolCall(server, originalCallToolHandler, request, extra, event) {
|
|
2069
2134
|
if (request.params?.name === "get_more_tools") {
|
|
2070
2135
|
const context = getContextArgument$1(request) || "";
|
|
2071
|
-
event
|
|
2136
|
+
setExplicitContextIntent(event, context);
|
|
2072
2137
|
return handleReportMissing({ context });
|
|
2073
2138
|
}
|
|
2074
2139
|
if (originalCallToolHandler) return await originalCallToolHandler(request, extra);
|
|
@@ -2084,11 +2149,6 @@ async function applyResolvedMetadata$1(event, data, request, extra) {
|
|
|
2084
2149
|
const resolvedProperties = await resolveEventProperties(data, request, extra);
|
|
2085
2150
|
if (resolvedProperties) event.properties = resolvedProperties;
|
|
2086
2151
|
}
|
|
2087
|
-
function setToolCallContext(event, context, request) {
|
|
2088
|
-
if (!(isContextEnabled(context) && request.params?.name !== "get_more_tools")) return;
|
|
2089
|
-
const contextArgument = getContextArgument$1(request);
|
|
2090
|
-
if (contextArgument) event.userIntent = contextArgument;
|
|
2091
|
-
}
|
|
2092
2152
|
function getContextArgument$1(request) {
|
|
2093
2153
|
const context = request.params?.arguments?.context;
|
|
2094
2154
|
return typeof context === "string" ? context : void 0;
|
|
@@ -2322,8 +2382,7 @@ async function initializeToolCallEvent(server, request, extra, startTime) {
|
|
|
2322
2382
|
await handleIdentify(server, data, request, extra);
|
|
2323
2383
|
event.sessionId = data.sessionId;
|
|
2324
2384
|
await applyResolvedMetadata(event, data, request, extra);
|
|
2325
|
-
|
|
2326
|
-
if (isContextEnabled(data.options.context) && contextArgument) event.userIntent = contextArgument;
|
|
2385
|
+
setEventIntent(event, await resolveToolCallIntent(data, request, extra));
|
|
2327
2386
|
return {
|
|
2328
2387
|
event,
|
|
2329
2388
|
shouldPublishEvent: true
|
|
@@ -2346,7 +2405,10 @@ async function executeReportMissingTool(server, request, tracing, startTime) {
|
|
|
2346
2405
|
try {
|
|
2347
2406
|
const context = getContextArgument(request) || "";
|
|
2348
2407
|
const result = await handleReportMissing({ context });
|
|
2349
|
-
publishSuccessfulToolEvent(server, tracing, result, startTime, {
|
|
2408
|
+
publishSuccessfulToolEvent(server, tracing, result, startTime, {
|
|
2409
|
+
userIntent: context,
|
|
2410
|
+
userIntentSource: "context_parameter"
|
|
2411
|
+
});
|
|
2350
2412
|
return result;
|
|
2351
2413
|
} catch (error) {
|
|
2352
2414
|
publishFailedToolEvent(server, tracing, error, startTime);
|
|
@@ -2374,12 +2436,15 @@ function getContextArgument(request) {
|
|
|
2374
2436
|
}
|
|
2375
2437
|
function publishSuccessfulToolEvent(server, tracing, result, startTime, options = {}) {
|
|
2376
2438
|
if (!(tracing.event && tracing.shouldPublishEvent)) return;
|
|
2377
|
-
if (options.userIntent)
|
|
2439
|
+
if (options.userIntent) {
|
|
2440
|
+
setExplicitContextIntent(tracing.event, options.userIntent);
|
|
2441
|
+
if (options.userIntentSource) tracing.event.userIntentSource = options.userIntentSource;
|
|
2442
|
+
}
|
|
2378
2443
|
if (isToolResultError(result)) {
|
|
2379
2444
|
tracing.event.isError = true;
|
|
2380
2445
|
tracing.event.error = captureException(options.capturedError || result);
|
|
2381
2446
|
options.clearCapturedError?.();
|
|
2382
|
-
}
|
|
2447
|
+
} else tracing.event.isError = false;
|
|
2383
2448
|
tracing.event.response = result;
|
|
2384
2449
|
tracing.event.duration = Date.now() - startTime.getTime();
|
|
2385
2450
|
publishEvent(server, tracing.event);
|
|
@@ -2416,6 +2481,7 @@ function setupTracking(server) {
|
|
|
2416
2481
|
* @param options.enableAITracing - Emits `$ai_span` events for tool calls so MCP activity appears in PostHog LLM analytics. Defaults to false.
|
|
2417
2482
|
* @param options.enableTracing - Enables tracking of tool calls and usage patterns.
|
|
2418
2483
|
* @param options.context - Enables the required "context" parameter on tools to capture user intent. Pass false to disable, or an object with a custom description.
|
|
2484
|
+
* @param options.intentFallback - Optional consumer-supplied callback invoked when a tool call has no explicit `context` argument. Return a short user intent string to capture as `$mcp_intent` (with `$mcp_intent_source = "inferred"`). The SDK does not infer anything on its own — this is purely a slot for your own derivation logic (e.g. a switch on `request.params.name`, an LLM call, etc.). Runs on the hot path of every uncontextualized tool call.
|
|
2419
2485
|
* @param options.identify - Async function to identify users and attach custom data to their sessions.
|
|
2420
2486
|
* @param options.redactSensitiveInformation - Function to redact sensitive data before sending to PostHog.
|
|
2421
2487
|
* @param options.eventTags - Callback invoked on every auto-captured event (tool calls, tool lists, initialize) to attach string key-value tags. Tags are intended to be indexed and queryable in PostHog — use them for structured metadata you'll want to filter or group by (e.g., trace IDs, environments, regions). Tags are validated client-side: keys must be ≤32 chars matching `[a-zA-Z0-9$_.:\- ]`, values must be strings ≤200 chars with no newlines, max 50 entries per event. Invalid entries are silently dropped with a warning logged to `~/posthog-mcp-analytics.log`. If the callback throws or returns null, tags are omitted. Receives the same `(request, extra)` arguments as `identify`.
|
|
@@ -2543,6 +2609,7 @@ function buildTrackingData(lowLevelServer, options) {
|
|
|
2543
2609
|
enableAITracing: options.enableAITracing ?? false,
|
|
2544
2610
|
enableTracing: options.enableTracing ?? true,
|
|
2545
2611
|
context: options.context,
|
|
2612
|
+
intentFallback: options.intentFallback,
|
|
2546
2613
|
identify: options.identify,
|
|
2547
2614
|
redactSensitiveInformation: options.redactSensitiveInformation,
|
|
2548
2615
|
eventTags: options.eventTags,
|
|
@@ -2687,6 +2754,6 @@ function publishResolvedCustomEvent(target, event) {
|
|
|
2687
2754
|
eventQueue.add(event);
|
|
2688
2755
|
}
|
|
2689
2756
|
//#endregion
|
|
2690
|
-
export { PostHogMCPAnalyticsProperty, publishCustomEvent, track };
|
|
2757
|
+
export { POSTHOG_MCP_ANALYTICS_SOURCE, PostHogMCPAnalyticsEvent, PostHogMCPAnalyticsProperty, publishCustomEvent, track };
|
|
2691
2758
|
|
|
2692
2759
|
//# sourceMappingURL=index.mjs.map
|