@posthog/mcp 0.17.0 → 0.18.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.
- package/README.md +36 -15
- package/dist/extensions/constants.d.ts +45 -45
- package/dist/extensions/constants.d.ts.map +1 -1
- package/dist/extensions/event-types.d.ts +11 -11
- package/dist/extensions/event-types.d.ts.map +1 -1
- package/dist/extensions/feedback.d.ts +1 -1
- package/dist/extensions/internal.d.ts.map +1 -1
- package/dist/extensions/posthog-mcp.d.ts +52 -17
- package/dist/extensions/posthog-mcp.d.ts.map +1 -1
- package/dist/extensions/posthog-mcp.js +107 -25
- package/dist/extensions/posthog-mcp.mjs +108 -26
- package/dist/extensions/sink.d.ts.map +1 -1
- package/dist/extensions/tools.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +31 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +5 -4
- package/src/extensions/posthog-mcp.ts +184 -46
- package/src/index.ts +1 -0
- package/src/types.ts +32 -2
- package/src/version.ts +1 -1
|
@@ -2,6 +2,7 @@ import { PostHog, type PostHogOptions } from 'posthog-node'
|
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
FeedbackCaptureData,
|
|
5
|
+
AnalyticsParameterOwnership,
|
|
5
6
|
CollectFeedbackOptions,
|
|
6
7
|
CollectFeedbackConfig,
|
|
7
8
|
InitializeCaptureData,
|
|
@@ -11,6 +12,7 @@ import type {
|
|
|
11
12
|
McpEvent,
|
|
12
13
|
MissingCapabilityCaptureData,
|
|
13
14
|
PreparedToolCall,
|
|
15
|
+
PreparedToolResult,
|
|
14
16
|
PrepareToolCallOptions,
|
|
15
17
|
PrepareToolListOptions,
|
|
16
18
|
ToolCallCaptureData,
|
|
@@ -24,7 +26,13 @@ import {
|
|
|
24
26
|
resolveCollectFeedbackOptions,
|
|
25
27
|
SEND_FEEDBACK_TOOL_NAME,
|
|
26
28
|
} from './feedback'
|
|
27
|
-
import {
|
|
29
|
+
import { getAnalyticsParameterOwnership, stripOwnedAnalyticsArguments } from './analytics-parameters'
|
|
30
|
+
import {
|
|
31
|
+
addConversationIdToTools,
|
|
32
|
+
canInjectConversationIdPromptBack,
|
|
33
|
+
injectConversationIdPromptBack,
|
|
34
|
+
resolveConversationId,
|
|
35
|
+
} from './conversation-id'
|
|
28
36
|
import {
|
|
29
37
|
addContextParameterToTools,
|
|
30
38
|
getContextDescription,
|
|
@@ -44,6 +52,8 @@ import {
|
|
|
44
52
|
setEventModel,
|
|
45
53
|
} from './model-parameters'
|
|
46
54
|
import { McpEventSink } from './sink'
|
|
55
|
+
import { addInstructionsToOutputSchemas, mirrorInstructionsIntoStructuredContent } from './output-instructions'
|
|
56
|
+
import { deriveSessionIdFromConversation } from './session'
|
|
47
57
|
import { GET_MORE_TOOLS_NAME, getReportMissingToolDescriptor } from './tools'
|
|
48
58
|
|
|
49
59
|
/**
|
|
@@ -74,6 +84,23 @@ export interface PostHogMCPOptions extends PostHogOptions {
|
|
|
74
84
|
* `llm_model` argument as fallback. On by default; `false` disables it.
|
|
75
85
|
*/
|
|
76
86
|
captureModel?: MCPAnalyticsOptions['captureModel']
|
|
87
|
+
/**
|
|
88
|
+
* Correlate calls with an agent-carried `conversation_id` and a derived
|
|
89
|
+
* PostHog session id. On by default; `false` leaves schemas, arguments, tool
|
|
90
|
+
* results, and capture data unchanged.
|
|
91
|
+
*/
|
|
92
|
+
enableConversationId?: boolean
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface PreparedConversationState {
|
|
96
|
+
minted: boolean
|
|
97
|
+
outputInstructions: boolean
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const PREPARED_CONVERSATION_STATE_KEY = '__posthogMcpConversationState'
|
|
101
|
+
|
|
102
|
+
type PreparedToolCallWithConversationState = PreparedToolCall & {
|
|
103
|
+
[PREPARED_CONVERSATION_STATE_KEY]?: PreparedConversationState
|
|
77
104
|
}
|
|
78
105
|
|
|
79
106
|
/**
|
|
@@ -123,7 +150,8 @@ export class PostHogMCP extends PostHog {
|
|
|
123
150
|
// real tool by that name, and flagging it would shadow the real handler.
|
|
124
151
|
readonly #feedbackOptions: CollectFeedbackOptions | undefined
|
|
125
152
|
readonly #captureModel: MCPAnalyticsOptions['captureModel']
|
|
126
|
-
readonly #
|
|
153
|
+
readonly #enableConversationId: boolean
|
|
154
|
+
readonly #analyticsParameterOwnership = new Map<string, AnalyticsParameterOwnership>()
|
|
127
155
|
|
|
128
156
|
constructor(apiKey: string, options: PostHogMCPOptions = {}) {
|
|
129
157
|
super(apiKey, options)
|
|
@@ -138,6 +166,7 @@ export class PostHogMCP extends PostHog {
|
|
|
138
166
|
)
|
|
139
167
|
}
|
|
140
168
|
this.#captureModel = options.captureModel
|
|
169
|
+
this.#enableConversationId = options.enableConversationId ?? true
|
|
141
170
|
applyMcpLibIdentity(this)
|
|
142
171
|
}
|
|
143
172
|
|
|
@@ -199,9 +228,10 @@ export class PostHogMCP extends PostHog {
|
|
|
199
228
|
* Decorate your `tools/list` response with PostHog's analytics affordances:
|
|
200
229
|
* injects the `context` argument into every tool (so agents state their intent,
|
|
201
230
|
* captured as `$mcp_intent`), injects `llm_model` when the constructor's
|
|
202
|
-
* `captureModel` option is enabled,
|
|
203
|
-
*
|
|
204
|
-
* on. Returns a new array; your tools
|
|
231
|
+
* `captureModel` option is enabled, and injects the optional `conversation_id`
|
|
232
|
+
* handle by default. It appends `get_more_tools` when `reportMissing` is on and
|
|
233
|
+
* `send_feedback` when `collectFeedback` is on. Returns a new array; your tools
|
|
234
|
+
* are untouched.
|
|
205
235
|
*
|
|
206
236
|
* The appended `get_more_tools` descriptor carries only the base MCP tool fields
|
|
207
237
|
* (name, description, input schema) — not any framework-specific fields your
|
|
@@ -209,8 +239,9 @@ export class PostHogMCP extends PostHog {
|
|
|
209
239
|
* {@link prepareToolCall}'s `isMissingCapability`, not dispatched through a handler.
|
|
210
240
|
*
|
|
211
241
|
* Call this when there is no `Server` to wrap — it does for a custom dispatcher
|
|
212
|
-
* what `instrument()` does for a `Server`. Pair it with
|
|
213
|
-
* on the inbound side
|
|
242
|
+
* what `instrument()` does for a `Server`. Pair it with
|
|
243
|
+
* {@link prepareToolCall} on the inbound side and {@link prepareToolResult} on
|
|
244
|
+
* the outbound side.
|
|
214
245
|
*
|
|
215
246
|
* @example
|
|
216
247
|
* ```ts
|
|
@@ -223,9 +254,12 @@ export class PostHogMCP extends PostHog {
|
|
|
223
254
|
let prepared = isContextEnabled(contextOption)
|
|
224
255
|
? addContextParameterToTools(tools, getContextDescription(contextOption))
|
|
225
256
|
: [...tools]
|
|
257
|
+
const ownershipSources: TTool[] = [...tools]
|
|
226
258
|
|
|
227
259
|
if (options.reportMissing && !prepared.some((tool) => tool?.name === this.#missingCapabilityToolName)) {
|
|
228
|
-
|
|
260
|
+
const virtualTool = getReportMissingToolDescriptor(this.#missingCapabilityToolName) as TTool
|
|
261
|
+
prepared = [...prepared, virtualTool]
|
|
262
|
+
ownershipSources.push(virtualTool)
|
|
229
263
|
}
|
|
230
264
|
|
|
231
265
|
if (
|
|
@@ -233,29 +267,38 @@ export class PostHogMCP extends PostHog {
|
|
|
233
267
|
this.#feedbackOptions !== undefined &&
|
|
234
268
|
!prepared.some((tool) => tool?.name === this.#feedbackToolName)
|
|
235
269
|
) {
|
|
236
|
-
|
|
270
|
+
const virtualTool = getFeedbackToolDescriptor(this.#feedbackOptions) as TTool
|
|
271
|
+
prepared = [...prepared, virtualTool]
|
|
272
|
+
ownershipSources.push(virtualTool)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
this.#analyticsParameterOwnership.clear()
|
|
276
|
+
const ownershipByName = collectAnalyticsParameterOwnership(ownershipSources)
|
|
277
|
+
for (const [toolName, ownership] of ownershipByName) {
|
|
278
|
+
this.#analyticsParameterOwnership.set(toolName, ownership)
|
|
237
279
|
}
|
|
238
280
|
|
|
239
281
|
if (isCaptureModelEnabled(this.#captureModel)) {
|
|
240
|
-
this.#modelParameterOwnership.clear()
|
|
241
|
-
const ownershipByName = new Map<string, boolean>()
|
|
242
|
-
for (const tool of prepared) {
|
|
243
|
-
if (typeof tool.name !== 'string') {
|
|
244
|
-
continue
|
|
245
|
-
}
|
|
246
|
-
const ownsModel = analyticsOwnsParameter(tool.inputSchema, 'llm_model')
|
|
247
|
-
ownershipByName.set(tool.name, (ownershipByName.get(tool.name) ?? true) && ownsModel)
|
|
248
|
-
}
|
|
249
|
-
for (const [toolName, ownsModel] of ownershipByName) {
|
|
250
|
-
this.#modelParameterOwnership.set(toolName, ownsModel)
|
|
251
|
-
}
|
|
252
282
|
const modelDescription = getModelDescription(this.#captureModel)
|
|
253
283
|
prepared = prepared.map((tool) =>
|
|
254
|
-
typeof tool.name === 'string' && ownershipByName.get(tool.name) === false
|
|
284
|
+
typeof tool.name === 'string' && ownershipByName.get(tool.name)?.llmModel === false
|
|
255
285
|
? tool
|
|
256
286
|
: addModelParameterToTool(tool, modelDescription)
|
|
257
287
|
)
|
|
258
288
|
}
|
|
289
|
+
|
|
290
|
+
if (this.#enableConversationId) {
|
|
291
|
+
prepared = prepared.map((tool) =>
|
|
292
|
+
typeof tool.name === 'string' && ownershipByName.get(tool.name)?.conversationId === false
|
|
293
|
+
? tool
|
|
294
|
+
: addConversationIdToTools([tool])[0]
|
|
295
|
+
)
|
|
296
|
+
prepared = prepared.map((tool) =>
|
|
297
|
+
typeof tool.name === 'string' && ownershipByName.get(tool.name)?.outputInstructions === false
|
|
298
|
+
? tool
|
|
299
|
+
: addInstructionsToOutputSchemas([tool])[0]
|
|
300
|
+
)
|
|
301
|
+
}
|
|
259
302
|
return prepared
|
|
260
303
|
}
|
|
261
304
|
|
|
@@ -264,8 +307,10 @@ export class PostHogMCP extends PostHog {
|
|
|
264
307
|
* from SDK-owned arguments, strips those arguments before validation, and flags
|
|
265
308
|
* whether the call targeted the `get_more_tools` virtual tool.
|
|
266
309
|
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
310
|
+
* Dispatch the returned `args` to your tool. Then pass the tool result and
|
|
311
|
+
* this prepared call to {@link prepareToolResult}. Use its result as the MCP
|
|
312
|
+
* response and its session and conversation values with
|
|
313
|
+
* {@link captureToolCall}.
|
|
269
314
|
*
|
|
270
315
|
* On stateless or multi-replica servers, pass the original tool descriptor
|
|
271
316
|
* so ownership does not depend on which process served `tools/list`.
|
|
@@ -279,17 +324,30 @@ export class PostHogMCP extends PostHog {
|
|
|
279
324
|
* @example
|
|
280
325
|
* ```ts
|
|
281
326
|
* const originalTool = myTools.find((tool) => tool.name === name)
|
|
282
|
-
* const
|
|
283
|
-
* posthog.prepareToolCall(name, rawArgs, {
|
|
327
|
+
* const preparedCall = posthog.prepareToolCall(name, rawArgs, {
|
|
284
328
|
* originalTool,
|
|
285
329
|
* requestMeta: request.params?._meta,
|
|
286
330
|
* })
|
|
287
|
-
* if (isMissingCapability) {
|
|
288
|
-
* posthog.
|
|
289
|
-
*
|
|
331
|
+
* if (preparedCall.isMissingCapability) {
|
|
332
|
+
* const preparedResult = posthog.prepareToolResult(getMoreToolsResult(), preparedCall)
|
|
333
|
+
* posthog.captureMissingCapability({
|
|
334
|
+
* context: preparedCall.intent,
|
|
335
|
+
* sessionId: preparedResult.sessionId,
|
|
336
|
+
* conversationId: preparedResult.conversationId,
|
|
337
|
+
* ...identity,
|
|
338
|
+
* })
|
|
339
|
+
* return preparedResult.result
|
|
290
340
|
* }
|
|
291
|
-
* const
|
|
292
|
-
* posthog.
|
|
341
|
+
* const toolResult = await runTool(name, preparedCall.args)
|
|
342
|
+
* const preparedResult = posthog.prepareToolResult(toolResult, preparedCall)
|
|
343
|
+
* posthog.captureToolCall({
|
|
344
|
+
* toolName: name,
|
|
345
|
+
* intent: preparedCall.intent,
|
|
346
|
+
* sessionId: preparedResult.sessionId,
|
|
347
|
+
* conversationId: preparedResult.conversationId,
|
|
348
|
+
* ...identity,
|
|
349
|
+
* })
|
|
350
|
+
* return preparedResult.result
|
|
293
351
|
* ```
|
|
294
352
|
*/
|
|
295
353
|
prepareToolCall(
|
|
@@ -299,15 +357,22 @@ export class PostHogMCP extends PostHog {
|
|
|
299
357
|
): PreparedToolCall {
|
|
300
358
|
const rawContext = args?.context
|
|
301
359
|
const intent = typeof rawContext === 'string' && rawContext.trim() ? rawContext.trim() : undefined
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
(
|
|
305
|
-
|
|
306
|
-
: this.#modelParameterOwnership.get(name) === true)
|
|
360
|
+
const ownership = options.originalTool
|
|
361
|
+
? getAnalyticsParameterOwnership(options.originalTool.inputSchema, options.originalTool.outputSchema)
|
|
362
|
+
: this.#analyticsParameterOwnership.get(name)
|
|
363
|
+
const ownsModel = isCaptureModelEnabled(this.#captureModel) && ownership?.llmModel === true
|
|
307
364
|
const resolvedModel = isCaptureModelEnabled(this.#captureModel)
|
|
308
365
|
? resolveModel({ params: { arguments: args, _meta: options.requestMeta } }, ownsModel)
|
|
309
366
|
: undefined
|
|
310
367
|
const strippedArgs = stripContext(args)
|
|
368
|
+
const canReadConversationId = this.#enableConversationId && (ownership?.conversationId ?? true)
|
|
369
|
+
const resolvedConversation = resolveConversationId(canReadConversationId, args)
|
|
370
|
+
const conversation =
|
|
371
|
+
resolvedConversation.minted && options.sessionId
|
|
372
|
+
? ({ minted: false, conversationId: undefined } as const)
|
|
373
|
+
: resolvedConversation
|
|
374
|
+
const conversationId = conversation.conversationId
|
|
375
|
+
const sessionId = conversationId ? deriveSessionIdFromConversation(conversationId) : options.sessionId
|
|
311
376
|
// A supplied `originalTool` is a real application tool by this name (it
|
|
312
377
|
// comes from the host's own list, which never holds the virtual tool), so
|
|
313
378
|
// the real tool wins — the stateless twin of instrument()'s listing-derived
|
|
@@ -315,28 +380,75 @@ export class PostHogMCP extends PostHog {
|
|
|
315
380
|
// remedy for a collision is configuring a non-colliding `toolName`.
|
|
316
381
|
const isFeedback =
|
|
317
382
|
this.#feedbackOptions !== undefined && name === this.#feedbackToolName && options.originalTool == null
|
|
318
|
-
|
|
383
|
+
const preparedCall: PreparedToolCallWithConversationState = {
|
|
319
384
|
intent,
|
|
320
385
|
intentSource: intent ? 'context_parameter' : undefined,
|
|
321
386
|
llmModel: resolvedModel?.model,
|
|
322
387
|
llmModelSource: resolvedModel?.source,
|
|
323
|
-
args:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
388
|
+
args: stripOwnedAnalyticsArguments(strippedArgs, {
|
|
389
|
+
context: false,
|
|
390
|
+
conversationId: this.#enableConversationId && ownership?.conversationId === true,
|
|
391
|
+
llmModel: ownsModel,
|
|
392
|
+
}) as Record<string, unknown> | undefined,
|
|
393
|
+
sessionId,
|
|
394
|
+
conversationId,
|
|
330
395
|
isMissingCapability: name === this.#missingCapabilityToolName,
|
|
331
396
|
isFeedback,
|
|
332
397
|
feedbackReport: isFeedback ? parseFeedbackReport(args, this.#feedbackOptions) : undefined,
|
|
398
|
+
// Keep the internal state serializable. Custom dispatchers can pass this
|
|
399
|
+
// value through workers or clone it before preparing the result.
|
|
400
|
+
[PREPARED_CONVERSATION_STATE_KEY]: {
|
|
401
|
+
minted: conversation.minted,
|
|
402
|
+
outputInstructions: this.#enableConversationId && ownership?.outputInstructions === true,
|
|
403
|
+
},
|
|
404
|
+
}
|
|
405
|
+
return preparedCall
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Add the conversation handle to a tool result without changing the original
|
|
410
|
+
* value. A new handle is appended to text content once. When the advertised
|
|
411
|
+
* output schema supports it, the handle is also mirrored into
|
|
412
|
+
* `structuredContent`.
|
|
413
|
+
*
|
|
414
|
+
* Use the returned session and conversation values for capture. If a new
|
|
415
|
+
* handle could not reach the client, the conversation value is omitted while
|
|
416
|
+
* the derived session value is kept.
|
|
417
|
+
*/
|
|
418
|
+
prepareToolResult<TResult>(result: TResult, preparedCall: PreparedToolCall): PreparedToolResult<TResult> {
|
|
419
|
+
const state = (preparedCall as PreparedToolCallWithConversationState)[PREPARED_CONVERSATION_STATE_KEY]
|
|
420
|
+
const conversationId = preparedCall.conversationId
|
|
421
|
+
if (!conversationId) {
|
|
422
|
+
return { result, sessionId: preparedCall.sessionId, conversationId }
|
|
423
|
+
}
|
|
424
|
+
if (!state) {
|
|
425
|
+
return { result, sessionId: preparedCall.sessionId, conversationId: undefined }
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
let preparedResult: unknown = result
|
|
429
|
+
let delivered = false
|
|
430
|
+
if (state.outputInstructions) {
|
|
431
|
+
const mirrored = mirrorInstructionsIntoStructuredContent(preparedResult, conversationId)
|
|
432
|
+
delivered = mirrored !== preparedResult
|
|
433
|
+
preparedResult = mirrored
|
|
434
|
+
}
|
|
435
|
+
if (state.minted && canInjectConversationIdPromptBack(preparedResult)) {
|
|
436
|
+
preparedResult = injectConversationIdPromptBack(preparedResult, conversationId)
|
|
437
|
+
delivered = true
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
result: preparedResult as TResult,
|
|
442
|
+
sessionId: preparedCall.sessionId,
|
|
443
|
+
conversationId: state.minted && !delivered ? undefined : conversationId,
|
|
333
444
|
}
|
|
334
445
|
}
|
|
335
446
|
|
|
336
447
|
/**
|
|
337
448
|
* Capture a `get_more_tools` call as a missing-capability report. Emits
|
|
338
449
|
* `$mcp_missing_capability` with the agent's description as `$mcp_intent`. Reply
|
|
339
|
-
* to the agent with `getMoreToolsResult()
|
|
450
|
+
* to the agent with `getMoreToolsResult()` after passing it through
|
|
451
|
+
* {@link prepareToolResult}.
|
|
340
452
|
*/
|
|
341
453
|
captureMissingCapability(data: MissingCapabilityCaptureData): void {
|
|
342
454
|
const event = baseEvent(MCPAnalyticsEventType.mcpMissingCapability, data)
|
|
@@ -352,7 +464,7 @@ export class PostHogMCP extends PostHog {
|
|
|
352
464
|
* `$mcp_feedback` with the report's `$mcp_feedback_*` properties and its
|
|
353
465
|
* summary/details as `$mcp_intent`. Reply to the agent with
|
|
354
466
|
* `sendFeedbackResult()` (or a custom text) after routing the report to your
|
|
355
|
-
* own feedback backend.
|
|
467
|
+
* own feedback backend and passing the reply through {@link prepareToolResult}.
|
|
356
468
|
*/
|
|
357
469
|
captureFeedback(data: FeedbackCaptureData): void {
|
|
358
470
|
const event = baseEvent(MCPAnalyticsEventType.mcpFeedback, data)
|
|
@@ -388,6 +500,7 @@ function baseEvent(eventType: MCPAnalyticsEventType, common: McpCaptureCommon):
|
|
|
388
500
|
const event: McpEvent = {
|
|
389
501
|
eventType,
|
|
390
502
|
sessionId: common.sessionId,
|
|
503
|
+
conversationId: common.conversationId,
|
|
391
504
|
protocolVersion: common.protocolVersion,
|
|
392
505
|
// There is no `extra` on this path, so the host reads the request headers and
|
|
393
506
|
// passes them per capture — the SDK has no transport to read them from. Normalized
|
|
@@ -408,6 +521,31 @@ function baseEvent(eventType: MCPAnalyticsEventType, common: McpCaptureCommon):
|
|
|
408
521
|
return event
|
|
409
522
|
}
|
|
410
523
|
|
|
524
|
+
function collectAnalyticsParameterOwnership<TTool extends ContextInjectableTool>(
|
|
525
|
+
tools: TTool[]
|
|
526
|
+
): Map<string, AnalyticsParameterOwnership> {
|
|
527
|
+
const ownershipByName = new Map<string, AnalyticsParameterOwnership>()
|
|
528
|
+
for (const tool of tools) {
|
|
529
|
+
if (typeof tool.name !== 'string') {
|
|
530
|
+
continue
|
|
531
|
+
}
|
|
532
|
+
const next = getAnalyticsParameterOwnership(tool.inputSchema, tool.outputSchema)
|
|
533
|
+
const current = ownershipByName.get(tool.name)
|
|
534
|
+
ownershipByName.set(
|
|
535
|
+
tool.name,
|
|
536
|
+
current
|
|
537
|
+
? {
|
|
538
|
+
context: current.context && next.context,
|
|
539
|
+
conversationId: current.conversationId && next.conversationId,
|
|
540
|
+
llmModel: current.llmModel && next.llmModel,
|
|
541
|
+
outputInstructions: current.outputInstructions && next.outputInstructions,
|
|
542
|
+
}
|
|
543
|
+
: next
|
|
544
|
+
)
|
|
545
|
+
}
|
|
546
|
+
return ownershipByName
|
|
547
|
+
}
|
|
548
|
+
|
|
411
549
|
/**
|
|
412
550
|
* Set the agent intent on an event → `$mcp_intent` / `$mcp_intent_source`. No-op
|
|
413
551
|
* for blank intents, so a missing `context` argument simply leaves them off.
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -541,6 +541,12 @@ export interface McpCaptureCommon {
|
|
|
541
541
|
distinctId?: string
|
|
542
542
|
/** Session id → `$session_id`. Omitted from the event entirely when not provided. */
|
|
543
543
|
sessionId?: string
|
|
544
|
+
/**
|
|
545
|
+
* Conversation handle → `$mcp_conversation_id`. For custom dispatchers,
|
|
546
|
+
* use the value returned by {@link PostHogMCP.prepareToolResult} so a newly
|
|
547
|
+
* minted handle is captured only when it reached the client.
|
|
548
|
+
*/
|
|
549
|
+
conversationId?: string
|
|
544
550
|
/**
|
|
545
551
|
* Negotiated MCP protocol (spec) version → `$mcp_protocol_version`. Pass it on
|
|
546
552
|
* every capture for the session (like `sessionId`) so later events carry it too,
|
|
@@ -695,9 +701,15 @@ export interface PrepareToolCallOptions {
|
|
|
695
701
|
* Passing it also disambiguates a feedback-tool name collision: a real tool
|
|
696
702
|
* by that name is dispatched normally instead of being flagged as feedback.
|
|
697
703
|
*/
|
|
698
|
-
originalTool?: { inputSchema?: unknown }
|
|
704
|
+
originalTool?: { inputSchema?: unknown; outputSchema?: unknown }
|
|
699
705
|
/** The incoming `tools/call` request's `_meta`, used for recognized client model metadata. */
|
|
700
706
|
requestMeta?: JsonRecord
|
|
707
|
+
/**
|
|
708
|
+
* A session id carried by the request or transport. A valid echoed
|
|
709
|
+
* `conversation_id` takes precedence. Otherwise this value prevents the SDK
|
|
710
|
+
* from minting a second session handle.
|
|
711
|
+
*/
|
|
712
|
+
sessionId?: string
|
|
701
713
|
}
|
|
702
714
|
|
|
703
715
|
/**
|
|
@@ -714,8 +726,16 @@ export interface PreparedToolCall {
|
|
|
714
726
|
llmModel?: string
|
|
715
727
|
/** How the model id was obtained. */
|
|
716
728
|
llmModelSource?: MCPAnalyticsModelSource
|
|
717
|
-
/** The call arguments with SDK-owned
|
|
729
|
+
/** The call arguments with SDK-owned analytics keys removed. */
|
|
718
730
|
args?: Record<string, unknown>
|
|
731
|
+
/** The resolved session id to use when capturing this call. */
|
|
732
|
+
sessionId?: string
|
|
733
|
+
/**
|
|
734
|
+
* The resolved conversation handle. Use the value from
|
|
735
|
+
* {@link PostHogMCP.prepareToolResult} for capture because result delivery can
|
|
736
|
+
* remove a newly minted handle from analytics.
|
|
737
|
+
*/
|
|
738
|
+
conversationId?: string
|
|
719
739
|
/** True when `name` is the `get_more_tools` virtual tool. */
|
|
720
740
|
isMissingCapability: boolean
|
|
721
741
|
/**
|
|
@@ -734,6 +754,16 @@ export interface PreparedToolCall {
|
|
|
734
754
|
feedbackReport?: FeedbackReport
|
|
735
755
|
}
|
|
736
756
|
|
|
757
|
+
/** Result of {@link PostHogMCP.prepareToolResult}. */
|
|
758
|
+
export interface PreparedToolResult<TResult = unknown> {
|
|
759
|
+
/** The result to return to the MCP client. */
|
|
760
|
+
result: TResult
|
|
761
|
+
/** The resolved session id to use when capturing this call. */
|
|
762
|
+
sessionId?: string
|
|
763
|
+
/** The conversation handle to capture, if it reached the client. */
|
|
764
|
+
conversationId?: string
|
|
765
|
+
}
|
|
766
|
+
|
|
737
767
|
/** Payload for {@link PostHogMCP.captureMissingCapability}. Emits `$mcp_missing_capability`. */
|
|
738
768
|
export interface MissingCapabilityCaptureData extends McpCaptureCommon {
|
|
739
769
|
/**
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.18.0'
|