@sentientui/mcp 0.17.5 → 0.17.6

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.
@@ -942,7 +942,7 @@ function registerGoalTools(server, client) {
942
942
  "get_goal_funnel",
943
943
  {
944
944
  title: "Goal funnel",
945
- description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
945
+ description: "Get goal hit counts and unique-session conversion rates for a window (default: last 30 calendar days), plus a per-variant breakdown. NOTE: the per-variant completionRate values are ALL-TIME (bounded only by plan retention), NOT windowed \u2014 a variant completion rate needs the full assignment history as its denominator, so it does not change when you narrow `range`, and retired components keep appearing in it. Only hits/uniqueSessions/conversionRate/revenue respect the window. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
946
946
  inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
947
947
  _meta: uiMeta("goal-funnel"),
948
948
  outputSchema: {
@@ -960,9 +960,13 @@ function registerGoalTools(server, client) {
960
960
  z6.object({
961
961
  componentId: z6.string(),
962
962
  variantId: z6.string(),
963
- completionRate: z6.number().describe("Completion rate per assigned session (0-1)")
963
+ completionRate: z6.number().describe(
964
+ "ALL-TIME completion rate per assigned session (0-1). Not windowed: unaffected by `range`/`from`/`to`, and bounded only by plan retention."
965
+ )
964
966
  })
965
- ).describe("Per-variant breakdown")
967
+ ).describe(
968
+ "Per-variant breakdown. ALL-TIME, not windowed \u2014 do not compare these against the windowed hits/conversionRate above, and expect retired components here."
969
+ )
966
970
  })
967
971
  ).describe("Configured goals (empty if none)"),
968
972
  window: windowOutputSchema
@@ -1011,11 +1015,18 @@ function registerGoalTools(server, client) {
1011
1015
  var _a2;
1012
1016
  return [
1013
1017
  `${untrusted(g.goalName)}: ${g.hits} hits, ${g.uniqueSessions} unique sessions, ${(g.pct * 100).toFixed(1)}% conversion` + (g.revenue != null ? `, ${g.revenue.toFixed(2)} ${currency} revenue (${((_a2 = g.avgOrderValue) != null ? _a2 : 0).toFixed(2)} avg order)` : ""),
1014
- ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session`),
1018
+ // The per-variant rates come from an all-time query (analytics.ts
1019
+ // query 2, deliberately unwindowed so the denominator is the full
1020
+ // assignment history). The dashboard labels them; this text had not,
1021
+ // so a narrowed `range` returned identical variant rates next to a
1022
+ // windowed headline and read as a windowed comparison.
1023
+ ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session (all-time)`),
1015
1024
  ""
1016
1025
  ];
1017
1026
  });
1018
- const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
1027
+ const hasVariants = data.goals.some((g) => g.variants.length > 0);
1028
+ const caveat = hasVariants ? ["", "Note: goal hits/conversion respect the window above; per-variant rates marked (all-time) do not."] : [];
1029
+ const text = (win ? [win, "", ...lines, ...caveat] : [...lines, ...caveat]).join("\n").trim();
1019
1030
  return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
1020
1031
  })
1021
1032
  );
@@ -1247,8 +1258,11 @@ function registerGuardrailTools(server, client) {
1247
1258
  "list_guardrail_events",
1248
1259
  {
1249
1260
  title: "List guardrail events",
1250
- description: "List variants currently paused by the guardrail in the last 24 hours." + UNTRUSTED_FIELDS_NOTE,
1251
- inputSchema: { projectId: projectIdSchema },
1261
+ description: "List every variant currently paused by a guardrail (a paused variant stops serving until unpaused, however long ago the pause fired). Pass `days` to narrow to pauses fired within the last N days." + UNTRUSTED_FIELDS_NOTE,
1262
+ inputSchema: {
1263
+ projectId: projectIdSchema,
1264
+ days: z8.number().int().min(1).max(365).optional().describe("Only pauses fired within the last N days. Omit for every still-paused variant.")
1265
+ },
1252
1266
  outputSchema: {
1253
1267
  events: z8.array(
1254
1268
  z8.object({
@@ -1257,7 +1271,7 @@ function registerGuardrailTools(server, client) {
1257
1271
  pausedAt: z8.string().nullable().describe("ISO timestamp the pause fired, or null"),
1258
1272
  funnelId: z8.string().nullable().describe("Set when the pause came from a funnel guardrail")
1259
1273
  })
1260
- ).describe("Guardrail events in the last 24h (empty if none)")
1274
+ ).describe("Currently paused variants (empty if none)")
1261
1275
  },
1262
1276
  annotations: {
1263
1277
  readOnlyHint: true,
@@ -1265,9 +1279,10 @@ function registerGuardrailTools(server, client) {
1265
1279
  openWorldHint: false
1266
1280
  }
1267
1281
  },
1268
- withApiErrorGuidance(async ({ projectId }) => {
1282
+ withApiErrorGuidance(async ({ projectId, days }) => {
1269
1283
  const id = encodeURIComponent(projectId);
1270
- const data = await client.get(`/projects/${id}/guardrail-events`);
1284
+ const query = days != null ? `?days=${days}` : "";
1285
+ const data = await client.get(`/projects/${id}/guardrail-events${query}`);
1271
1286
  const structuredContent = {
1272
1287
  events: data.guardrailEvents.map((e) => {
1273
1288
  var _a;
@@ -1280,8 +1295,9 @@ function registerGuardrailTools(server, client) {
1280
1295
  })
1281
1296
  };
1282
1297
  if (!data.guardrailEvents.length) {
1298
+ const scope = days != null ? `paused by a guardrail in the last ${days} days` : "currently paused by a guardrail";
1283
1299
  return {
1284
- content: [{ type: "text", text: "No active guardrail events in the last 24 hours." }],
1300
+ content: [{ type: "text", text: `No variants ${scope}.` }],
1285
1301
  structuredContent
1286
1302
  };
1287
1303
  }
@@ -2003,7 +2019,7 @@ function registerAgentTrafficTools(server, client) {
2003
2019
  }
2004
2020
 
2005
2021
  // src/server.ts
2006
- var PKG_VERSION = true ? "0.17.5" : "0.0.0-dev";
2022
+ var PKG_VERSION = true ? "0.17.6" : "0.0.0-dev";
2007
2023
  function createMcpServer(client) {
2008
2024
  const server = new McpServer(
2009
2025
  {
package/dist/index.cjs CHANGED
@@ -948,7 +948,7 @@ function registerGoalTools(server, client) {
948
948
  "get_goal_funnel",
949
949
  {
950
950
  title: "Goal funnel",
951
- description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
951
+ description: "Get goal hit counts and unique-session conversion rates for a window (default: last 30 calendar days), plus a per-variant breakdown. NOTE: the per-variant completionRate values are ALL-TIME (bounded only by plan retention), NOT windowed \u2014 a variant completion rate needs the full assignment history as its denominator, so it does not change when you narrow `range`, and retired components keep appearing in it. Only hits/uniqueSessions/conversionRate/revenue respect the window. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
952
952
  inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
953
953
  _meta: uiMeta("goal-funnel"),
954
954
  outputSchema: {
@@ -966,9 +966,13 @@ function registerGoalTools(server, client) {
966
966
  import_zod6.z.object({
967
967
  componentId: import_zod6.z.string(),
968
968
  variantId: import_zod6.z.string(),
969
- completionRate: import_zod6.z.number().describe("Completion rate per assigned session (0-1)")
969
+ completionRate: import_zod6.z.number().describe(
970
+ "ALL-TIME completion rate per assigned session (0-1). Not windowed: unaffected by `range`/`from`/`to`, and bounded only by plan retention."
971
+ )
970
972
  })
971
- ).describe("Per-variant breakdown")
973
+ ).describe(
974
+ "Per-variant breakdown. ALL-TIME, not windowed \u2014 do not compare these against the windowed hits/conversionRate above, and expect retired components here."
975
+ )
972
976
  })
973
977
  ).describe("Configured goals (empty if none)"),
974
978
  window: windowOutputSchema
@@ -1017,11 +1021,18 @@ function registerGoalTools(server, client) {
1017
1021
  var _a3;
1018
1022
  return [
1019
1023
  `${untrusted(g.goalName)}: ${g.hits} hits, ${g.uniqueSessions} unique sessions, ${(g.pct * 100).toFixed(1)}% conversion` + (g.revenue != null ? `, ${g.revenue.toFixed(2)} ${currency} revenue (${((_a3 = g.avgOrderValue) != null ? _a3 : 0).toFixed(2)} avg order)` : ""),
1020
- ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session`),
1024
+ // The per-variant rates come from an all-time query (analytics.ts
1025
+ // query 2, deliberately unwindowed so the denominator is the full
1026
+ // assignment history). The dashboard labels them; this text had not,
1027
+ // so a narrowed `range` returned identical variant rates next to a
1028
+ // windowed headline and read as a windowed comparison.
1029
+ ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session (all-time)`),
1021
1030
  ""
1022
1031
  ];
1023
1032
  });
1024
- const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
1033
+ const hasVariants = data.goals.some((g) => g.variants.length > 0);
1034
+ const caveat = hasVariants ? ["", "Note: goal hits/conversion respect the window above; per-variant rates marked (all-time) do not."] : [];
1035
+ const text = (win ? [win, "", ...lines, ...caveat] : [...lines, ...caveat]).join("\n").trim();
1025
1036
  return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
1026
1037
  })
1027
1038
  );
@@ -1253,8 +1264,11 @@ function registerGuardrailTools(server, client) {
1253
1264
  "list_guardrail_events",
1254
1265
  {
1255
1266
  title: "List guardrail events",
1256
- description: "List variants currently paused by the guardrail in the last 24 hours." + UNTRUSTED_FIELDS_NOTE,
1257
- inputSchema: { projectId: projectIdSchema },
1267
+ description: "List every variant currently paused by a guardrail (a paused variant stops serving until unpaused, however long ago the pause fired). Pass `days` to narrow to pauses fired within the last N days." + UNTRUSTED_FIELDS_NOTE,
1268
+ inputSchema: {
1269
+ projectId: projectIdSchema,
1270
+ days: import_zod8.z.number().int().min(1).max(365).optional().describe("Only pauses fired within the last N days. Omit for every still-paused variant.")
1271
+ },
1258
1272
  outputSchema: {
1259
1273
  events: import_zod8.z.array(
1260
1274
  import_zod8.z.object({
@@ -1263,7 +1277,7 @@ function registerGuardrailTools(server, client) {
1263
1277
  pausedAt: import_zod8.z.string().nullable().describe("ISO timestamp the pause fired, or null"),
1264
1278
  funnelId: import_zod8.z.string().nullable().describe("Set when the pause came from a funnel guardrail")
1265
1279
  })
1266
- ).describe("Guardrail events in the last 24h (empty if none)")
1280
+ ).describe("Currently paused variants (empty if none)")
1267
1281
  },
1268
1282
  annotations: {
1269
1283
  readOnlyHint: true,
@@ -1271,9 +1285,10 @@ function registerGuardrailTools(server, client) {
1271
1285
  openWorldHint: false
1272
1286
  }
1273
1287
  },
1274
- withApiErrorGuidance(async ({ projectId }) => {
1288
+ withApiErrorGuidance(async ({ projectId, days }) => {
1275
1289
  const id = encodeURIComponent(projectId);
1276
- const data = await client.get(`/projects/${id}/guardrail-events`);
1290
+ const query = days != null ? `?days=${days}` : "";
1291
+ const data = await client.get(`/projects/${id}/guardrail-events${query}`);
1277
1292
  const structuredContent = {
1278
1293
  events: data.guardrailEvents.map((e) => {
1279
1294
  var _a2;
@@ -1286,8 +1301,9 @@ function registerGuardrailTools(server, client) {
1286
1301
  })
1287
1302
  };
1288
1303
  if (!data.guardrailEvents.length) {
1304
+ const scope = days != null ? `paused by a guardrail in the last ${days} days` : "currently paused by a guardrail";
1289
1305
  return {
1290
- content: [{ type: "text", text: "No active guardrail events in the last 24 hours." }],
1306
+ content: [{ type: "text", text: `No variants ${scope}.` }],
1291
1307
  structuredContent
1292
1308
  };
1293
1309
  }
@@ -2009,7 +2025,7 @@ function registerAgentTrafficTools(server, client) {
2009
2025
  }
2010
2026
 
2011
2027
  // src/server.ts
2012
- var PKG_VERSION = true ? "0.17.5" : "0.0.0-dev";
2028
+ var PKG_VERSION = true ? "0.17.6" : "0.0.0-dev";
2013
2029
  function createMcpServer(client) {
2014
2030
  const server = new import_mcp.McpServer(
2015
2031
  {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ApiClient,
4
4
  createMcpServer
5
- } from "./chunk-H763K2O3.js";
5
+ } from "./chunk-FBRHD7R7.js";
6
6
 
7
7
  // src/index.ts
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/lib.cjs CHANGED
@@ -972,7 +972,7 @@ function registerGoalTools(server, client) {
972
972
  "get_goal_funnel",
973
973
  {
974
974
  title: "Goal funnel",
975
- description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
975
+ description: "Get goal hit counts and unique-session conversion rates for a window (default: last 30 calendar days), plus a per-variant breakdown. NOTE: the per-variant completionRate values are ALL-TIME (bounded only by plan retention), NOT windowed \u2014 a variant completion rate needs the full assignment history as its denominator, so it does not change when you narrow `range`, and retired components keep appearing in it. Only hits/uniqueSessions/conversionRate/revenue respect the window. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report." + UNTRUSTED_FIELDS_NOTE,
976
976
  inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
977
977
  _meta: uiMeta("goal-funnel"),
978
978
  outputSchema: {
@@ -990,9 +990,13 @@ function registerGoalTools(server, client) {
990
990
  import_zod6.z.object({
991
991
  componentId: import_zod6.z.string(),
992
992
  variantId: import_zod6.z.string(),
993
- completionRate: import_zod6.z.number().describe("Completion rate per assigned session (0-1)")
993
+ completionRate: import_zod6.z.number().describe(
994
+ "ALL-TIME completion rate per assigned session (0-1). Not windowed: unaffected by `range`/`from`/`to`, and bounded only by plan retention."
995
+ )
994
996
  })
995
- ).describe("Per-variant breakdown")
997
+ ).describe(
998
+ "Per-variant breakdown. ALL-TIME, not windowed \u2014 do not compare these against the windowed hits/conversionRate above, and expect retired components here."
999
+ )
996
1000
  })
997
1001
  ).describe("Configured goals (empty if none)"),
998
1002
  window: windowOutputSchema
@@ -1041,11 +1045,18 @@ function registerGoalTools(server, client) {
1041
1045
  var _a2;
1042
1046
  return [
1043
1047
  `${untrusted(g.goalName)}: ${g.hits} hits, ${g.uniqueSessions} unique sessions, ${(g.pct * 100).toFixed(1)}% conversion` + (g.revenue != null ? `, ${g.revenue.toFixed(2)} ${currency} revenue (${((_a2 = g.avgOrderValue) != null ? _a2 : 0).toFixed(2)} avg order)` : ""),
1044
- ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session`),
1048
+ // The per-variant rates come from an all-time query (analytics.ts
1049
+ // query 2, deliberately unwindowed so the denominator is the full
1050
+ // assignment history). The dashboard labels them; this text had not,
1051
+ // so a narrowed `range` returned identical variant rates next to a
1052
+ // windowed headline and read as a windowed comparison.
1053
+ ...g.variants.map((v) => ` ${untrusted(v.componentId)}/${untrusted(v.variantId)}: ${(v.completionRate * 100).toFixed(1)}% per assigned session (all-time)`),
1045
1054
  ""
1046
1055
  ];
1047
1056
  });
1048
- const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
1057
+ const hasVariants = data.goals.some((g) => g.variants.length > 0);
1058
+ const caveat = hasVariants ? ["", "Note: goal hits/conversion respect the window above; per-variant rates marked (all-time) do not."] : [];
1059
+ const text = (win ? [win, "", ...lines, ...caveat] : [...lines, ...caveat]).join("\n").trim();
1049
1060
  return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
1050
1061
  })
1051
1062
  );
@@ -1277,8 +1288,11 @@ function registerGuardrailTools(server, client) {
1277
1288
  "list_guardrail_events",
1278
1289
  {
1279
1290
  title: "List guardrail events",
1280
- description: "List variants currently paused by the guardrail in the last 24 hours." + UNTRUSTED_FIELDS_NOTE,
1281
- inputSchema: { projectId: projectIdSchema },
1291
+ description: "List every variant currently paused by a guardrail (a paused variant stops serving until unpaused, however long ago the pause fired). Pass `days` to narrow to pauses fired within the last N days." + UNTRUSTED_FIELDS_NOTE,
1292
+ inputSchema: {
1293
+ projectId: projectIdSchema,
1294
+ days: import_zod8.z.number().int().min(1).max(365).optional().describe("Only pauses fired within the last N days. Omit for every still-paused variant.")
1295
+ },
1282
1296
  outputSchema: {
1283
1297
  events: import_zod8.z.array(
1284
1298
  import_zod8.z.object({
@@ -1287,7 +1301,7 @@ function registerGuardrailTools(server, client) {
1287
1301
  pausedAt: import_zod8.z.string().nullable().describe("ISO timestamp the pause fired, or null"),
1288
1302
  funnelId: import_zod8.z.string().nullable().describe("Set when the pause came from a funnel guardrail")
1289
1303
  })
1290
- ).describe("Guardrail events in the last 24h (empty if none)")
1304
+ ).describe("Currently paused variants (empty if none)")
1291
1305
  },
1292
1306
  annotations: {
1293
1307
  readOnlyHint: true,
@@ -1295,9 +1309,10 @@ function registerGuardrailTools(server, client) {
1295
1309
  openWorldHint: false
1296
1310
  }
1297
1311
  },
1298
- withApiErrorGuidance(async ({ projectId }) => {
1312
+ withApiErrorGuidance(async ({ projectId, days }) => {
1299
1313
  const id = encodeURIComponent(projectId);
1300
- const data = await client.get(`/projects/${id}/guardrail-events`);
1314
+ const query = days != null ? `?days=${days}` : "";
1315
+ const data = await client.get(`/projects/${id}/guardrail-events${query}`);
1301
1316
  const structuredContent = {
1302
1317
  events: data.guardrailEvents.map((e) => {
1303
1318
  var _a;
@@ -1310,8 +1325,9 @@ function registerGuardrailTools(server, client) {
1310
1325
  })
1311
1326
  };
1312
1327
  if (!data.guardrailEvents.length) {
1328
+ const scope = days != null ? `paused by a guardrail in the last ${days} days` : "currently paused by a guardrail";
1313
1329
  return {
1314
- content: [{ type: "text", text: "No active guardrail events in the last 24 hours." }],
1330
+ content: [{ type: "text", text: `No variants ${scope}.` }],
1315
1331
  structuredContent
1316
1332
  };
1317
1333
  }
@@ -2033,7 +2049,7 @@ function registerAgentTrafficTools(server, client) {
2033
2049
  }
2034
2050
 
2035
2051
  // src/server.ts
2036
- var PKG_VERSION = true ? "0.17.5" : "0.0.0-dev";
2052
+ var PKG_VERSION = true ? "0.17.6" : "0.0.0-dev";
2037
2053
  function createMcpServer(client) {
2038
2054
  const server = new import_mcp.McpServer(
2039
2055
  {
package/dist/lib.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  ApiError,
5
5
  PUBLIC_UI_RESOURCE_URIS,
6
6
  createMcpServer
7
- } from "./chunk-H763K2O3.js";
7
+ } from "./chunk-FBRHD7R7.js";
8
8
  export {
9
9
  ApiClient,
10
10
  ApiError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/mcp",
3
- "version": "0.17.5",
3
+ "version": "0.17.6",
4
4
  "description": "MCP server for SentientUI — exposes project data and actions to AI agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://sentient-ui.com",