@posthog/mcp 0.14.1 → 0.16.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/LICENSE +64 -0
- package/README.md +64 -0
- package/dist/extensions/constants.d.ts +9 -0
- package/dist/extensions/constants.d.ts.map +1 -1
- package/dist/extensions/constants.js +9 -0
- package/dist/extensions/constants.mjs +9 -0
- package/dist/extensions/event-types.d.ts +1 -0
- package/dist/extensions/event-types.d.ts.map +1 -1
- package/dist/extensions/event-types.js +1 -0
- package/dist/extensions/event-types.mjs +1 -0
- package/dist/extensions/feedback.d.ts +41 -0
- package/dist/extensions/feedback.d.ts.map +1 -0
- package/dist/extensions/feedback.js +259 -0
- package/dist/extensions/feedback.mjs +200 -0
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +23 -2
- package/dist/extensions/instrument-highlevel.mjs +25 -4
- package/dist/extensions/instrument-lowlevel.d.ts +4 -3
- package/dist/extensions/instrument-lowlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-lowlevel.js +23 -2
- package/dist/extensions/instrument-lowlevel.mjs +25 -4
- package/dist/extensions/instrumentation.d.ts +33 -13
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +103 -9
- package/dist/extensions/instrumentation.mjs +99 -8
- package/dist/extensions/internal.js +9 -2
- package/dist/extensions/internal.mjs +9 -2
- package/dist/extensions/mcp-payloads.d.ts +19 -0
- package/dist/extensions/mcp-payloads.d.ts.map +1 -1
- package/dist/extensions/mcp-payloads.js +217 -7
- package/dist/extensions/mcp-payloads.mjs +210 -6
- package/dist/extensions/posthog-events.d.ts.map +1 -1
- package/dist/extensions/posthog-events.js +1 -0
- package/dist/extensions/posthog-events.mjs +1 -0
- package/dist/extensions/posthog-mcp.d.ts +23 -3
- package/dist/extensions/posthog-mcp.d.ts.map +1 -1
- package/dist/extensions/posthog-mcp.js +27 -1
- package/dist/extensions/posthog-mcp.mjs +27 -1
- package/dist/extensions/sanitization.d.ts.map +1 -1
- package/dist/extensions/sanitization.js +2 -1
- package/dist/extensions/sanitization.mjs +3 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.mjs +5 -1
- package/dist/types.d.ts +114 -0
- 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 +4 -4
- package/src/extensions/constants.ts +9 -0
- package/src/extensions/event-types.ts +1 -0
- package/src/extensions/feedback.ts +349 -0
- package/src/extensions/instrument-highlevel.ts +45 -2
- package/src/extensions/instrument-lowlevel.ts +49 -5
- package/src/extensions/instrumentation.ts +170 -17
- package/src/extensions/internal.ts +13 -2
- package/src/extensions/mcp-payloads.ts +443 -7
- package/src/extensions/posthog-events.ts +1 -0
- package/src/extensions/posthog-mcp.ts +74 -3
- package/src/extensions/sanitization.ts +14 -6
- package/src/index.ts +24 -3
- package/src/types.ts +120 -0
- package/src/version.ts +1 -1
|
@@ -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 {
|
|
7
|
+
import { sanitizeCapturedValue, sanitizeFreeText } from './mcp-payloads'
|
|
8
8
|
|
|
9
9
|
type SanitizedRecord = Record<string, unknown>
|
|
10
10
|
|
|
@@ -32,14 +32,22 @@ export function sanitizeEvent<T extends Event | McpEvent>(event: T): T {
|
|
|
32
32
|
result.parameters = sanitizeParameters(result.parameters)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// Every event type, not just `resources/read`: `$identify` and the `$exception`
|
|
36
|
+
// sibling carry the same name, and a tool or prompt name is free text an
|
|
37
|
+
// application can spell as a URL too.
|
|
38
|
+
if (result.resourceName != null) {
|
|
39
|
+
result.resourceName = sanitizeCapturedValue(result.resourceName) as string
|
|
40
|
+
}
|
|
41
|
+
|
|
35
42
|
// The intent comes straight from an agent-narrated `context` string, so it can
|
|
36
43
|
// contain a secret the LLM read aloud or personal data it narrated about the
|
|
37
|
-
// user.
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// parameters and responses often hold the same shapes as
|
|
44
|
+
// user. `sanitizeFreeText` adds structured PII redaction (emails, phone numbers,
|
|
45
|
+
// IPs, cards, SSNs) to the passes every captured value gets, in the one order
|
|
46
|
+
// that works — see its doc comment. PII redaction is scoped to the intent only:
|
|
47
|
+
// structured tool parameters and responses often hold the same shapes as
|
|
48
|
+
// legitimate data.
|
|
41
49
|
if (result.userIntent != null) {
|
|
42
|
-
result.userIntent =
|
|
50
|
+
result.userIntent = sanitizeFreeText(result.userIntent)
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
if (result.llmModel != null) {
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { applyMcpLibIdentity } from './extensions/lib-identity'
|
|
|
14
14
|
import { deriveSessionIdFromMCPSession, getSessionInfo, newSessionId } from './extensions/session'
|
|
15
15
|
import { instrumentLowLevelServer } from './extensions/instrument-lowlevel'
|
|
16
16
|
import { instrumentHighLevelServer } from './extensions/instrument-highlevel'
|
|
17
|
+
import { getFeedbackToolDescriptor, resolveCollectFeedbackOptions } from './extensions/feedback'
|
|
17
18
|
import type {
|
|
18
19
|
CaptureEventData,
|
|
19
20
|
HighLevelMCPServerLike,
|
|
@@ -25,9 +26,9 @@ import type {
|
|
|
25
26
|
} from './types'
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
* Instruments an MCP server so PostHog auto-captures tool calls, tool listings,
|
|
29
|
-
* requests, identity, and exceptions. Returns a handle whose
|
|
30
|
-
* custom events, so you don't pass the server around after wiring it up.
|
|
29
|
+
* Instruments an MCP server so PostHog auto-captures tool calls, tool and resource listings,
|
|
30
|
+
* resource reads, initialize requests, identity, and exceptions. Returns a handle whose
|
|
31
|
+
* `capture()` method records custom events, so you don't pass the server around after wiring it up.
|
|
31
32
|
*
|
|
32
33
|
* **Idempotent per server instance.** Per-server tracking state lives in a module-level
|
|
33
34
|
* `WeakMap<MCPServerLike, MCPAnalyticsData>` (`internal.ts`); a second `instrument()` call
|
|
@@ -52,6 +53,17 @@ import type {
|
|
|
52
53
|
*/
|
|
53
54
|
function instrument(server: unknown, posthog: PostHog, options: MCPAnalyticsOptions = {}): McpAnalytics {
|
|
54
55
|
const logger = createLogger(options?.logger)
|
|
56
|
+
|
|
57
|
+
// Fail fast on a `collectFeedback` config error (reserved extra key,
|
|
58
|
+
// undeclared extraRequired). Above the graceful-degradation try so it throws
|
|
59
|
+
// out of instrument() like PostHogMCP's constructor does — inside the catch it
|
|
60
|
+
// would silently disable ALL analytics for the server, not just feedback.
|
|
61
|
+
// `options?.` — untyped JavaScript can pass null options (see logger-isolation.test.ts).
|
|
62
|
+
const feedbackOptions = resolveCollectFeedbackOptions(options?.collectFeedback)
|
|
63
|
+
if (feedbackOptions) {
|
|
64
|
+
getFeedbackToolDescriptor(feedbackOptions)
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
try {
|
|
56
68
|
if (!posthog) {
|
|
57
69
|
logger('Warning: No PostHog client passed to instrument(). Events will not be sent anywhere.')
|
|
@@ -129,6 +141,7 @@ function getLowLevelServer(server: MCPServerLike | HighLevelMCPServerLike): MCPS
|
|
|
129
141
|
*/
|
|
130
142
|
const DEFAULT_OPTIONS = {
|
|
131
143
|
reportMissing: false,
|
|
144
|
+
collectFeedback: false,
|
|
132
145
|
enableConversationId: false,
|
|
133
146
|
} satisfies Partial<MCPAnalyticsOptions>
|
|
134
147
|
|
|
@@ -215,14 +228,22 @@ export {
|
|
|
215
228
|
export { getRequestHeaders } from './extensions/request-headers'
|
|
216
229
|
export { PostHogMCP, type PostHogMCPOptions } from './extensions/posthog-mcp'
|
|
217
230
|
export { getMoreToolsResult } from './extensions/tools'
|
|
231
|
+
export { sendFeedbackResult, SEND_FEEDBACK_TOOL_NAME } from './extensions/feedback'
|
|
218
232
|
export { setLogger } from './extensions/logger'
|
|
219
233
|
// Re-export the posthog-node client so a single import works:
|
|
220
234
|
// import { PostHog, instrument } from "@posthog/mcp"
|
|
221
235
|
// posthog-node stays a peer dependency, so this resolves the host app's installed copy.
|
|
222
236
|
export { PostHog, type PostHogOptions } from 'posthog-node'
|
|
223
237
|
export type {
|
|
238
|
+
FeedbackCaptureData,
|
|
239
|
+
FeedbackExtraPropertySchema,
|
|
240
|
+
CollectFeedbackOptions,
|
|
241
|
+
FeedbackReport,
|
|
242
|
+
FeedbackSentiment,
|
|
243
|
+
FeedbackType,
|
|
224
244
|
BeforeSendFn,
|
|
225
245
|
CaptureEventData,
|
|
246
|
+
CollectFeedbackConfig,
|
|
226
247
|
InitializeCaptureData,
|
|
227
248
|
McpAnalytics,
|
|
228
249
|
McpCaptureCommon,
|
package/src/types.ts
CHANGED
|
@@ -70,6 +70,7 @@ export interface MCPRequestParamsLike {
|
|
|
70
70
|
_meta?: JsonRecord
|
|
71
71
|
arguments?: JsonRecord
|
|
72
72
|
name?: string
|
|
73
|
+
uri?: string
|
|
73
74
|
[key: string]: unknown
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -100,6 +101,20 @@ export interface MCPAnalyticsOptions {
|
|
|
100
101
|
logger?: LoggerFn
|
|
101
102
|
/** Enable the `get_more_tools` virtual tool so agents can report missing functionality. */
|
|
102
103
|
reportMissing?: boolean
|
|
104
|
+
/**
|
|
105
|
+
* Inject the `send_feedback` virtual tool so agents can send feedback about
|
|
106
|
+
* this server to its developers — a missing capability (the priority
|
|
107
|
+
* category), a tool that failed or confused them, or praise. Calls to it emit
|
|
108
|
+
* `$mcp_feedback` (never a `$mcp_tool_call`). Off by default.
|
|
109
|
+
*
|
|
110
|
+
* `true` uses the defaults; the object form renames the tool, replaces its
|
|
111
|
+
* description, declares host-specific `extraProperties`, or wires an
|
|
112
|
+
* `onFeedback` handler that routes reports to a real backend.
|
|
113
|
+
*
|
|
114
|
+
* Covers what `reportMissing` covers (as `feedback_type: "missing_capability"`),
|
|
115
|
+
* so new integrations should enable only one of the two.
|
|
116
|
+
*/
|
|
117
|
+
collectFeedback?: CollectFeedbackConfig
|
|
103
118
|
/**
|
|
104
119
|
* Rename the `get_more_tools` virtual tool (the `reportMissing` feature).
|
|
105
120
|
* Defaults to `get_more_tools`. Set once here so the tool is advertised and
|
|
@@ -185,6 +200,78 @@ export interface MCPAnalyticsContextOptions {
|
|
|
185
200
|
description?: string
|
|
186
201
|
}
|
|
187
202
|
|
|
203
|
+
export type FeedbackType = 'missing_capability' | 'issue' | 'praise' | 'other'
|
|
204
|
+
export type FeedbackSentiment = 'positive' | 'neutral' | 'negative' | 'mixed'
|
|
205
|
+
|
|
206
|
+
/** The `collectFeedback` option: `true` for the defaults, or the object form. */
|
|
207
|
+
export type CollectFeedbackConfig = boolean | CollectFeedbackOptions
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* A host-declared input-schema fragment for one `send_feedback` extra property —
|
|
211
|
+
* plain JSON Schema, the same shape the MCP `tools/list` wire format uses.
|
|
212
|
+
*/
|
|
213
|
+
export interface FeedbackExtraPropertySchema {
|
|
214
|
+
type: string
|
|
215
|
+
description?: string
|
|
216
|
+
enum?: string[]
|
|
217
|
+
[key: string]: unknown
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Object form of {@link CollectFeedbackConfig}. */
|
|
221
|
+
export interface CollectFeedbackOptions {
|
|
222
|
+
/**
|
|
223
|
+
* Rename the `send_feedback` virtual tool. Set once so the tool is advertised
|
|
224
|
+
* and detected under the same name. Defaults to `send_feedback`.
|
|
225
|
+
*/
|
|
226
|
+
toolName?: string
|
|
227
|
+
/** Replace the default tool description. */
|
|
228
|
+
description?: string
|
|
229
|
+
/**
|
|
230
|
+
* Host-specific fields merged into the tool's advertised input schema. Each
|
|
231
|
+
* declared key is captured as a `$mcp_feedback_<key>` event property (through
|
|
232
|
+
* the standard sanitize/truncate pipeline); arguments the agent invents beyond
|
|
233
|
+
* the schema are never captured. A key that collides with a core field or an
|
|
234
|
+
* SDK-injected argument throws at configuration time.
|
|
235
|
+
*/
|
|
236
|
+
extraProperties?: Record<string, FeedbackExtraPropertySchema>
|
|
237
|
+
/** Keys of `extraProperties` to advertise as required. */
|
|
238
|
+
extraRequired?: string[]
|
|
239
|
+
/**
|
|
240
|
+
* Route each report to a real backend (`instrument()` path only — a custom
|
|
241
|
+
* dispatcher routes reports itself, see {@link PreparedToolCall.isFeedback}).
|
|
242
|
+
* Return a string to replace the default acknowledgement text. A throw is
|
|
243
|
+
* logged and falls back to the default reply; the `$mcp_feedback` event is
|
|
244
|
+
* captured either way. The returned string is captured as `$mcp_response`
|
|
245
|
+
* through the generic sanitize pipeline only — unlike `$mcp_feedback_summary`
|
|
246
|
+
* / `details`, it does not get structured-PII redaction, so avoid echoing
|
|
247
|
+
* the agent's raw report text back in it.
|
|
248
|
+
*/
|
|
249
|
+
onFeedback?: (report: FeedbackReport) => MaybePromise<string | void>
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** One parsed `send_feedback` call, as handed to `onFeedback` and the dispatcher. */
|
|
253
|
+
export interface FeedbackReport {
|
|
254
|
+
/** Invalid or missing values fall back to `other`. */
|
|
255
|
+
feedbackType: FeedbackType
|
|
256
|
+
/** One-sentence summary; empty string when the agent omitted it. */
|
|
257
|
+
summary: string
|
|
258
|
+
sentiment?: FeedbackSentiment
|
|
259
|
+
frictionPoints?: string
|
|
260
|
+
suggestedImprovement?: string
|
|
261
|
+
details?: string
|
|
262
|
+
/** The existing tool the feedback is about (`tool_name` argument). */
|
|
263
|
+
toolName?: string
|
|
264
|
+
taskCompleted?: boolean
|
|
265
|
+
/**
|
|
266
|
+
* Values of the declared `extraProperties` fields that match their declared
|
|
267
|
+
* `type`/`enum`. A value the agent sent with the wrong shape is left out
|
|
268
|
+
* (find it in `raw` if you need it), so these are safe to trust as declared.
|
|
269
|
+
*/
|
|
270
|
+
extras: JsonRecord
|
|
271
|
+
/** The full raw arguments, for the handler only — never captured. */
|
|
272
|
+
raw: JsonRecord
|
|
273
|
+
}
|
|
274
|
+
|
|
188
275
|
export interface MCPAnalyticsModelOptions {
|
|
189
276
|
description?: string
|
|
190
277
|
}
|
|
@@ -589,6 +676,14 @@ export interface PrepareToolListOptions {
|
|
|
589
676
|
* {@link PostHogMCP.captureMissingCapability} and reply with `getMoreToolsResult()`.
|
|
590
677
|
*/
|
|
591
678
|
reportMissing?: boolean
|
|
679
|
+
/**
|
|
680
|
+
* Append the `send_feedback` virtual tool so agents can send feedback.
|
|
681
|
+
* Defaults to `false`, and requires the `PostHogMCP` constructor's
|
|
682
|
+
* `collectFeedback` option (the enable switch that also gates detection).
|
|
683
|
+
* When the agent calls it, route the call to
|
|
684
|
+
* {@link PostHogMCP.captureFeedback} and reply with `sendFeedbackResult()`.
|
|
685
|
+
*/
|
|
686
|
+
collectFeedback?: boolean
|
|
592
687
|
}
|
|
593
688
|
|
|
594
689
|
/** Options for {@link PostHogMCP.prepareToolCall}. */
|
|
@@ -620,6 +715,18 @@ export interface PreparedToolCall {
|
|
|
620
715
|
args?: Record<string, unknown>
|
|
621
716
|
/** True when `name` is the `get_more_tools` virtual tool. */
|
|
622
717
|
isMissingCapability: boolean
|
|
718
|
+
/**
|
|
719
|
+
* True when `name` is the `send_feedback` virtual tool AND the constructor's
|
|
720
|
+
* `collectFeedback` option is set. Always false without that opt-in, so a real
|
|
721
|
+
* tool that happens to use the name is never shadowed.
|
|
722
|
+
*/
|
|
723
|
+
isFeedback: boolean
|
|
724
|
+
/**
|
|
725
|
+
* The parsed feedback report, set only when {@link PreparedToolCall.isFeedback}
|
|
726
|
+
* is true. Pass it to {@link PostHogMCP.captureFeedback} and to your own
|
|
727
|
+
* feedback backend, then reply with `sendFeedbackResult()` or a custom text.
|
|
728
|
+
*/
|
|
729
|
+
feedbackReport?: FeedbackReport
|
|
623
730
|
}
|
|
624
731
|
|
|
625
732
|
/** Payload for {@link PostHogMCP.captureMissingCapability}. Emits `$mcp_missing_capability`. */
|
|
@@ -636,3 +743,16 @@ export interface MissingCapabilityCaptureData extends McpCaptureCommon {
|
|
|
636
743
|
/** Captured call arguments → `$mcp_parameters` (sanitized + truncated). */
|
|
637
744
|
parameters?: unknown
|
|
638
745
|
}
|
|
746
|
+
|
|
747
|
+
/** Payload for {@link PostHogMCP.captureFeedback}. Emits `$mcp_feedback`. */
|
|
748
|
+
export interface FeedbackCaptureData extends McpCaptureCommon {
|
|
749
|
+
/**
|
|
750
|
+
* The parsed report (from {@link PreparedToolCall.feedbackReport}) →
|
|
751
|
+
* `$mcp_feedback_*` properties, with the summary and details as `$mcp_intent`.
|
|
752
|
+
*/
|
|
753
|
+
report: FeedbackReport
|
|
754
|
+
/** The calling model id -> `$mcp_llm_model`. */
|
|
755
|
+
llmModel?: string
|
|
756
|
+
/** How the model id was obtained -> `$mcp_llm_model_source`. */
|
|
757
|
+
llmModelSource?: MCPAnalyticsModelSource
|
|
758
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.16.0'
|