@alpic-ai/insights 1.157.3 → 1.159.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/dist/index.d.mts CHANGED
@@ -50,8 +50,8 @@ interface Analytics {
50
50
  /** Records a custom event on the current session's timeline, interleaved with tool calls. */
51
51
  capture(name: string, options?: CaptureOptions): void;
52
52
  /**
53
- * Attaches traits to the current request's user (e.g. email, name, plan). The target user is
54
- * resolved by Alpic from the request auth context — no id or sessionId is passed.
53
+ * Replaces the current request user's trait snapshot (e.g. email, name, plan). The target user
54
+ * is resolved by Alpic from the request auth context — no id or sessionId is passed.
55
55
  */
56
56
  identify(traits: Record<string, string>): void;
57
57
  }
@@ -62,13 +62,26 @@ interface Analytics {
62
62
  interface AnalyticsExtra {
63
63
  analytics: Analytics;
64
64
  }
65
+ interface AnalyticsEvent extends CaptureOptions {
66
+ name: string;
67
+ timestamp: number;
68
+ }
69
+ interface AnalyticsBatch {
70
+ events: AnalyticsEvent[];
71
+ traits?: Record<string, string>;
72
+ }
73
+ interface AnalyticsMiddlewareOptions {
74
+ /** Receives each request's analytics locally, whether or not the server is hosted by Alpic. */
75
+ handler?: (batch: AnalyticsBatch) => Promise<void> | void;
76
+ }
65
77
  /**
66
78
  * Lets MCP server builders record custom analytics events and user traits from inside tool
67
79
  * handlers, via `extra.analytics.capture(...)` / `extra.analytics.identify(...)`. Calls are
68
- * buffered during the request and flushed into the response `_meta`, where the Alpic proxy
69
- * ingests and strips them before the result reaches the client.
80
+ * buffered during the request. On Alpic, private environment-provided `_meta` keys carry them to
81
+ * the proxy for ingestion. Locally, pass a handler to receive them without exposing analytics in
82
+ * the MCP response.
70
83
  */
71
- declare function analyticsMiddleware(): McpMiddlewareFn;
84
+ declare function analyticsMiddleware(options?: AnalyticsMiddlewareOptions): McpMiddlewareFn;
72
85
  //#endregion
73
86
  //#region src/feedback-middleware.d.ts
74
87
  interface FeedbackData {
@@ -116,7 +129,8 @@ declare const captureIntents: (server: McpServer | Server, options?: IntentMiddl
116
129
  * Enables custom analytics events on a vanilla `@modelcontextprotocol/sdk` server. Accepts the
117
130
  * high-level `McpServer` or the low-level `Server` and patches the `tools/call` request handlers
118
131
  * so tool handlers can call `extra.analytics.capture(...)` / `extra.analytics.identify(...)`.
132
+ * Pass a handler in `options` to receive analytics when running outside Alpic.
119
133
  */
120
- declare const track: (server: McpServer | Server) => void;
134
+ declare const track: (server: McpServer | Server, options?: AnalyticsMiddlewareOptions) => void;
121
135
  //#endregion
122
- export { type Analytics, type AnalyticsExtra, type CaptureOptions, type FeedbackData, type FeedbackMiddlewareOptions, type IntentMiddlewareOptions, type McpMiddlewareFn, type PromptData, analyticsMiddleware, captureFeedback, captureIntents, feedbackMiddleware, intentMiddleware, track };
136
+ export { type Analytics, type AnalyticsBatch, type AnalyticsEvent, type AnalyticsExtra, type AnalyticsMiddlewareOptions, type CaptureOptions, type FeedbackData, type FeedbackMiddlewareOptions, type IntentMiddlewareOptions, type McpMiddlewareFn, type PromptData, analyticsMiddleware, captureFeedback, captureIntents, feedbackMiddleware, intentMiddleware, track };
package/dist/index.mjs CHANGED
@@ -1,7 +1,5 @@
1
1
  import { CallToolRequestSchema, CallToolResultSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
2
2
  //#region src/analytics-middleware.ts
3
- const ALPIC_EVENTS_META_KEY = "alpic/events";
4
- const ALPIC_IDENTIFY_META_KEY = "alpic/identify";
5
3
  const MAX_EVENTS_PER_REQUEST = 50;
6
4
  function warnInDev(message) {
7
5
  if (process.env.NODE_ENV !== "production") console.warn(`[insights] ${message}`);
@@ -32,10 +30,7 @@ function createAnalyticsBuffer() {
32
30
  warnInDev("analytics.identify() was called after the request settled; the traits were dropped. Identify before the tool handler returns.");
33
31
  return;
34
32
  }
35
- traits = {
36
- ...traits,
37
- ...newTraits
38
- };
33
+ traits = { ...newTraits };
39
34
  }
40
35
  },
41
36
  settle: () => {
@@ -52,10 +47,11 @@ function createAnalyticsBuffer() {
52
47
  /**
53
48
  * Lets MCP server builders record custom analytics events and user traits from inside tool
54
49
  * handlers, via `extra.analytics.capture(...)` / `extra.analytics.identify(...)`. Calls are
55
- * buffered during the request and flushed into the response `_meta`, where the Alpic proxy
56
- * ingests and strips them before the result reaches the client.
50
+ * buffered during the request. On Alpic, private environment-provided `_meta` keys carry them to
51
+ * the proxy for ingestion. Locally, pass a handler to receive them without exposing analytics in
52
+ * the MCP response.
57
53
  */
58
- function analyticsMiddleware() {
54
+ function analyticsMiddleware(options) {
59
55
  return async (request, extra, next) => {
60
56
  if (request.method !== "tools/call" || extra === null || typeof extra !== "object") return next();
61
57
  const buffer = createAnalyticsBuffer();
@@ -67,11 +63,23 @@ function analyticsMiddleware() {
67
63
  buffer.settle();
68
64
  }
69
65
  if (buffer.events.length === 0 && buffer.traits === void 0) return rawResult;
66
+ const batch = {
67
+ events: [...buffer.events],
68
+ ...buffer.traits === void 0 ? {} : { traits: { ...buffer.traits } }
69
+ };
70
+ if (options?.handler) try {
71
+ await options.handler(batch);
72
+ } catch (error) {
73
+ console.error("Error calling analytics handler", error);
74
+ }
75
+ const eventsMetaKey = process.env.ALPIC_EVENTS_META_KEY || void 0;
76
+ const identifyMetaKey = process.env.ALPIC_IDENTIFY_META_KEY || void 0;
77
+ if (eventsMetaKey === void 0 && identifyMetaKey === void 0) return rawResult;
70
78
  if (!CallToolResultSchema.safeParse(rawResult).success) return rawResult;
71
79
  const result = rawResult;
72
80
  const meta = { ...result._meta };
73
- if (buffer.events.length > 0) meta[ALPIC_EVENTS_META_KEY] = buffer.events;
74
- if (buffer.traits !== void 0) meta[ALPIC_IDENTIFY_META_KEY] = buffer.traits;
81
+ if (eventsMetaKey !== void 0 && buffer.events.length > 0) meta[eventsMetaKey] = buffer.events;
82
+ if (identifyMetaKey !== void 0 && buffer.traits !== void 0) meta[identifyMetaKey] = buffer.traits;
75
83
  return {
76
84
  ...result,
77
85
  _meta: meta
@@ -356,10 +364,11 @@ const captureIntents = (server, options) => {
356
364
  * Enables custom analytics events on a vanilla `@modelcontextprotocol/sdk` server. Accepts the
357
365
  * high-level `McpServer` or the low-level `Server` and patches the `tools/call` request handlers
358
366
  * so tool handlers can call `extra.analytics.capture(...)` / `extra.analytics.identify(...)`.
367
+ * Pass a handler in `options` to receive analytics when running outside Alpic.
359
368
  */
360
- const track = (server) => {
369
+ const track = (server, options) => {
361
370
  installCaptureMiddleware(server, {
362
- middleware: analyticsMiddleware(),
371
+ middleware: analyticsMiddleware(options),
363
372
  installedMarker: "__alpicTrackInstalled",
364
373
  disabledWarning: "Analytics capture disabled."
365
374
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpic-ai/insights",
3
- "version": "1.157.3",
3
+ "version": "1.159.0",
4
4
  "description": "User insights middlewares for Alpic-hosted MCP servers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -41,11 +41,11 @@
41
41
  "@types/node": "^25.9.5",
42
42
  "@types/react": "19.2.17",
43
43
  "jsdom": "^29.1.1",
44
- "react": "^19.2.7",
45
- "react-dom": "^19.2.7",
44
+ "react": "^19.2.8",
45
+ "react-dom": "^19.2.8",
46
46
  "shx": "^0.4.0",
47
- "skybridge": "^1.2.7",
48
- "tsdown": "^0.22.9",
47
+ "skybridge": "^1.3.0",
48
+ "tsdown": "^0.22.14",
49
49
  "typescript": "^6.0.3",
50
50
  "vitest": "^4.1.10",
51
51
  "zod": "^4.4.3"