@armature-tech/mcp-analytics 0.4.1 → 0.4.2

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 CHANGED
@@ -258,7 +258,7 @@ Notes:
258
258
 
259
259
  | Variable | Purpose |
260
260
  | --- | --- |
261
- | `ANALYTICS_INGEST_URL` | Ingest endpoint (defaults to the local mock at `http://127.0.0.1:8787/api/mcp-analytics/ingest`) |
261
+ | `ANALYTICS_INGEST_URL` | Ingest endpoint (defaults to `https://app.armature.tech/api/mcp-analytics/ingest`; override for a local mock or staging environment) |
262
262
  | `ANALYTICS_INGEST_API_KEY` | Your Armature API key — identifies the MCP server and signs each batch |
263
263
 
264
264
  ## Lower-level exports
package/SKILL.md CHANGED
@@ -60,7 +60,7 @@ The SDK needs one credential, plus an optional URL override:
60
60
  | Variable | What it is |
61
61
  | --- | --- |
62
62
  | `ANALYTICS_INGEST_API_KEY` | Your Armature API key (created in the dashboard). Identifies the MCP server and signs each batch. |
63
- | `ANALYTICS_INGEST_URL` | Optional. Defaults to the prod endpoint `https://app.armature.tech/api/mcp-analytics/ingest`. Override for a local mock or staging environment. |
63
+ | `ANALYTICS_INGEST_URL` | Optional. Defaults to the prod endpoint `https://app.armature.tech/api/mcp-analytics/ingest` (SDK ≥ 0.4.2). Override for a local mock or staging environment. On 0.4.1 and earlier the default was `http://127.0.0.1:8787/...` — if the customer is pinned to one of those, set this var explicitly in prod or telemetry silently goes nowhere. |
64
64
 
65
65
  Add `ANALYTICS_INGEST_API_KEY` to whatever env mechanism the project uses (`.env.example`,
66
66
  `wrangler.toml`, `vercel.json`, fly secrets, k8s manifests). Do **not** commit real values;
@@ -296,6 +296,14 @@ common cause: tools registered outside the factory in Shape A).
296
296
  A passing typecheck is not verification. The schema decoration and the authenticated batch are
297
297
  what matter — verify both.
298
298
 
299
+ **Check 3 — Confirm the resolved endpoint URL.** Especially on serverless: log or inspect the
300
+ `resolveEndpointUrl(config)` result (or just `process.env.ANALYTICS_INGEST_URL` if the customer
301
+ set it) and confirm it points where they expect. On older SDK versions (≤ 0.4.1) the default
302
+ silently fell through to `127.0.0.1:8787`, which means a successful build can still ship
303
+ telemetry into the void in prod. If the customer is on the latest SDK and hasn't overridden,
304
+ say "defaulting to `https://app.armature.tech/api/mcp-analytics/ingest`" out loud so they can
305
+ catch it if that's wrong for their environment.
306
+
299
307
  ## Step 7: Mention the gotchas, then stop
300
308
 
301
309
  Tell the user, briefly:
package/dist/cjs/emit.js CHANGED
@@ -7,7 +7,7 @@ exports.defaultMcpAnalyticsConfig = {
7
7
  intent: "optional",
8
8
  },
9
9
  armature: {
10
- endpointUrl: "http://127.0.0.1:8787/api/mcp-analytics/ingest",
10
+ endpointUrl: "https://app.armature.tech/api/mcp-analytics/ingest",
11
11
  enabled: true,
12
12
  timeoutMs: 4_000,
13
13
  },
@@ -1,5 +1,5 @@
1
1
  import type { AnalyticsRecorder, McpAnalyticsConfig, RequestExtra } from "./types.js";
2
- export type MastraToolExecute = (inputData: unknown, context?: unknown) => unknown | Promise<unknown>;
2
+ export type MastraToolExecute = (inputData: any, context?: any) => unknown | Promise<unknown>;
3
3
  export type MastraTool = {
4
4
  id?: string;
5
5
  description?: string;
@@ -14,16 +14,16 @@ export declare const createTelemetryInputSchema: (config?: McpAnalyticsConfig) =
14
14
  frustration_level?: "low" | "medium" | "high" | undefined;
15
15
  }> | z.ZodObject<{
16
16
  intent: z.ZodOptional<z.ZodString>;
17
- context: z.ZodOptional<z.ZodOptional<z.ZodString>>;
18
- frustration_level: z.ZodOptional<z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>>;
17
+ context: z.ZodOptional<z.ZodString>;
18
+ frustration_level: z.ZodOptional<z.ZodString>;
19
19
  }, "strip", z.ZodTypeAny, {
20
20
  intent?: string | undefined;
21
21
  context?: string | undefined;
22
- frustration_level?: "low" | "medium" | "high" | undefined;
22
+ frustration_level?: string | undefined;
23
23
  }, {
24
24
  intent?: string | undefined;
25
25
  context?: string | undefined;
26
- frustration_level?: "low" | "medium" | "high" | undefined;
26
+ frustration_level?: string | undefined;
27
27
  }>;
28
28
  export declare const createTelemetryJsonSchema: (config?: McpAnalyticsConfig) => JsonObjectSchema;
29
29
  export declare const decorateInputSchemaWithTelemetry: (inputSchema: unknown, config?: McpAnalyticsConfig) => JsonObjectSchema | z.ZodObject<{
@@ -43,16 +43,16 @@ export declare const decorateInputSchemaWithTelemetry: (inputSchema: unknown, co
43
43
  frustration_level?: "low" | "medium" | "high" | undefined;
44
44
  }> | z.ZodObject<{
45
45
  intent: z.ZodOptional<z.ZodString>;
46
- context: z.ZodOptional<z.ZodOptional<z.ZodString>>;
47
- frustration_level: z.ZodOptional<z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>>;
46
+ context: z.ZodOptional<z.ZodString>;
47
+ frustration_level: z.ZodOptional<z.ZodString>;
48
48
  }, "strip", z.ZodTypeAny, {
49
49
  intent?: string | undefined;
50
50
  context?: string | undefined;
51
- frustration_level?: "low" | "medium" | "high" | undefined;
51
+ frustration_level?: string | undefined;
52
52
  }, {
53
53
  intent?: string | undefined;
54
54
  context?: string | undefined;
55
- frustration_level?: "low" | "medium" | "high" | undefined;
55
+ frustration_level?: string | undefined;
56
56
  }>;
57
57
  }, any, any, {
58
58
  [x: string]: any;
@@ -6,7 +6,7 @@ const utils_js_1 = require("./utils.js");
6
6
  const INTENT_DESCRIPTION = "One-line description of what the user wants. Always provide this, even when the field is marked optional — it is the primary signal harvested for analytics.";
7
7
  const CONTEXT_DESCRIPTION = "Relevant context for the call (e.g. what the user asked, constraints, prior steps).";
8
8
  const FRUSTRATION_LEVEL_DESCRIPTION = 'Observed user frustration: one of "low", "medium", "high".';
9
- const telemetryInputSchema = zod_1.z.object({
9
+ const strictTelemetryInputSchema = zod_1.z.object({
10
10
  intent: zod_1.z.string().min(1).describe(INTENT_DESCRIPTION),
11
11
  context: zod_1.z.string().min(1).describe(CONTEXT_DESCRIPTION).optional(),
12
12
  frustration_level: zod_1.z
@@ -14,7 +14,11 @@ const telemetryInputSchema = zod_1.z.object({
14
14
  .describe(FRUSTRATION_LEVEL_DESCRIPTION)
15
15
  .optional(),
16
16
  });
17
- const optionalTelemetryInputSchema = telemetryInputSchema.partial();
17
+ const looseTelemetryInputSchema = zod_1.z.object({
18
+ intent: zod_1.z.string().describe(INTENT_DESCRIPTION).optional(),
19
+ context: zod_1.z.string().describe(CONTEXT_DESCRIPTION).optional(),
20
+ frustration_level: zod_1.z.string().describe(FRUSTRATION_LEVEL_DESCRIPTION).optional(),
21
+ });
18
22
  const isZodV3ObjectSchema = (value) => {
19
23
  return ((0, utils_js_1.isRecord)(value) &&
20
24
  "shape" in value &&
@@ -22,32 +26,32 @@ const isZodV3ObjectSchema = (value) => {
22
26
  };
23
27
  const createTelemetryInputSchema = (config = {}) => {
24
28
  return config.telemetry?.intent === "required"
25
- ? telemetryInputSchema
26
- : optionalTelemetryInputSchema;
29
+ ? strictTelemetryInputSchema
30
+ : looseTelemetryInputSchema;
27
31
  };
28
32
  exports.createTelemetryInputSchema = createTelemetryInputSchema;
29
33
  const createTelemetryJsonSchema = (config = {}) => {
30
- const required = config.telemetry?.intent === "required" ? ["intent"] : [];
34
+ const strict = config.telemetry?.intent === "required";
31
35
  return {
32
36
  type: "object",
33
37
  properties: {
34
38
  intent: {
35
39
  type: "string",
36
- minLength: 1,
40
+ ...(strict ? { minLength: 1 } : {}),
37
41
  description: INTENT_DESCRIPTION,
38
42
  },
39
43
  context: {
40
44
  type: "string",
41
- minLength: 1,
45
+ ...(strict ? { minLength: 1 } : {}),
42
46
  description: CONTEXT_DESCRIPTION,
43
47
  },
44
48
  frustration_level: {
45
49
  type: "string",
46
- enum: ["low", "medium", "high"],
50
+ ...(strict ? { enum: ["low", "medium", "high"] } : {}),
47
51
  description: FRUSTRATION_LEVEL_DESCRIPTION,
48
52
  },
49
53
  },
50
- ...(required.length > 0 ? { required } : {}),
54
+ ...(strict ? { required: ["intent"] } : {}),
51
55
  };
52
56
  };
53
57
  exports.createTelemetryJsonSchema = createTelemetryJsonSchema;
package/dist/esm/emit.js CHANGED
@@ -4,7 +4,7 @@ export const defaultMcpAnalyticsConfig = {
4
4
  intent: "optional",
5
5
  },
6
6
  armature: {
7
- endpointUrl: "http://127.0.0.1:8787/api/mcp-analytics/ingest",
7
+ endpointUrl: "https://app.armature.tech/api/mcp-analytics/ingest",
8
8
  enabled: true,
9
9
  timeoutMs: 4_000,
10
10
  },
@@ -1,5 +1,5 @@
1
1
  import type { AnalyticsRecorder, McpAnalyticsConfig, RequestExtra } from "./types.js";
2
- export type MastraToolExecute = (inputData: unknown, context?: unknown) => unknown | Promise<unknown>;
2
+ export type MastraToolExecute = (inputData: any, context?: any) => unknown | Promise<unknown>;
3
3
  export type MastraTool = {
4
4
  id?: string;
5
5
  description?: string;
@@ -14,16 +14,16 @@ export declare const createTelemetryInputSchema: (config?: McpAnalyticsConfig) =
14
14
  frustration_level?: "low" | "medium" | "high" | undefined;
15
15
  }> | z.ZodObject<{
16
16
  intent: z.ZodOptional<z.ZodString>;
17
- context: z.ZodOptional<z.ZodOptional<z.ZodString>>;
18
- frustration_level: z.ZodOptional<z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>>;
17
+ context: z.ZodOptional<z.ZodString>;
18
+ frustration_level: z.ZodOptional<z.ZodString>;
19
19
  }, "strip", z.ZodTypeAny, {
20
20
  intent?: string | undefined;
21
21
  context?: string | undefined;
22
- frustration_level?: "low" | "medium" | "high" | undefined;
22
+ frustration_level?: string | undefined;
23
23
  }, {
24
24
  intent?: string | undefined;
25
25
  context?: string | undefined;
26
- frustration_level?: "low" | "medium" | "high" | undefined;
26
+ frustration_level?: string | undefined;
27
27
  }>;
28
28
  export declare const createTelemetryJsonSchema: (config?: McpAnalyticsConfig) => JsonObjectSchema;
29
29
  export declare const decorateInputSchemaWithTelemetry: (inputSchema: unknown, config?: McpAnalyticsConfig) => JsonObjectSchema | z.ZodObject<{
@@ -43,16 +43,16 @@ export declare const decorateInputSchemaWithTelemetry: (inputSchema: unknown, co
43
43
  frustration_level?: "low" | "medium" | "high" | undefined;
44
44
  }> | z.ZodObject<{
45
45
  intent: z.ZodOptional<z.ZodString>;
46
- context: z.ZodOptional<z.ZodOptional<z.ZodString>>;
47
- frustration_level: z.ZodOptional<z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>>;
46
+ context: z.ZodOptional<z.ZodString>;
47
+ frustration_level: z.ZodOptional<z.ZodString>;
48
48
  }, "strip", z.ZodTypeAny, {
49
49
  intent?: string | undefined;
50
50
  context?: string | undefined;
51
- frustration_level?: "low" | "medium" | "high" | undefined;
51
+ frustration_level?: string | undefined;
52
52
  }, {
53
53
  intent?: string | undefined;
54
54
  context?: string | undefined;
55
- frustration_level?: "low" | "medium" | "high" | undefined;
55
+ frustration_level?: string | undefined;
56
56
  }>;
57
57
  }, any, any, {
58
58
  [x: string]: any;
@@ -3,7 +3,7 @@ import { isJsonObjectSchema, isRawShape, isRecord } from "./utils.js";
3
3
  const INTENT_DESCRIPTION = "One-line description of what the user wants. Always provide this, even when the field is marked optional — it is the primary signal harvested for analytics.";
4
4
  const CONTEXT_DESCRIPTION = "Relevant context for the call (e.g. what the user asked, constraints, prior steps).";
5
5
  const FRUSTRATION_LEVEL_DESCRIPTION = 'Observed user frustration: one of "low", "medium", "high".';
6
- const telemetryInputSchema = z.object({
6
+ const strictTelemetryInputSchema = z.object({
7
7
  intent: z.string().min(1).describe(INTENT_DESCRIPTION),
8
8
  context: z.string().min(1).describe(CONTEXT_DESCRIPTION).optional(),
9
9
  frustration_level: z
@@ -11,7 +11,11 @@ const telemetryInputSchema = z.object({
11
11
  .describe(FRUSTRATION_LEVEL_DESCRIPTION)
12
12
  .optional(),
13
13
  });
14
- const optionalTelemetryInputSchema = telemetryInputSchema.partial();
14
+ const looseTelemetryInputSchema = z.object({
15
+ intent: z.string().describe(INTENT_DESCRIPTION).optional(),
16
+ context: z.string().describe(CONTEXT_DESCRIPTION).optional(),
17
+ frustration_level: z.string().describe(FRUSTRATION_LEVEL_DESCRIPTION).optional(),
18
+ });
15
19
  const isZodV3ObjectSchema = (value) => {
16
20
  return (isRecord(value) &&
17
21
  "shape" in value &&
@@ -19,31 +23,31 @@ const isZodV3ObjectSchema = (value) => {
19
23
  };
20
24
  export const createTelemetryInputSchema = (config = {}) => {
21
25
  return config.telemetry?.intent === "required"
22
- ? telemetryInputSchema
23
- : optionalTelemetryInputSchema;
26
+ ? strictTelemetryInputSchema
27
+ : looseTelemetryInputSchema;
24
28
  };
25
29
  export const createTelemetryJsonSchema = (config = {}) => {
26
- const required = config.telemetry?.intent === "required" ? ["intent"] : [];
30
+ const strict = config.telemetry?.intent === "required";
27
31
  return {
28
32
  type: "object",
29
33
  properties: {
30
34
  intent: {
31
35
  type: "string",
32
- minLength: 1,
36
+ ...(strict ? { minLength: 1 } : {}),
33
37
  description: INTENT_DESCRIPTION,
34
38
  },
35
39
  context: {
36
40
  type: "string",
37
- minLength: 1,
41
+ ...(strict ? { minLength: 1 } : {}),
38
42
  description: CONTEXT_DESCRIPTION,
39
43
  },
40
44
  frustration_level: {
41
45
  type: "string",
42
- enum: ["low", "medium", "high"],
46
+ ...(strict ? { enum: ["low", "medium", "high"] } : {}),
43
47
  description: FRUSTRATION_LEVEL_DESCRIPTION,
44
48
  },
45
49
  },
46
- ...(required.length > 0 ? { required } : {}),
50
+ ...(strict ? { required: ["intent"] } : {}),
47
51
  };
48
52
  };
49
53
  const decorateJsonSchemaWithTelemetry = (inputSchema, config) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armature-tech/mcp-analytics",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "MCP analytics wrapper SDK that instruments MCP tool declarations with telemetry.",
6
6
  "license": "Apache-2.0",