@togglhq/mcp 1.8.0 → 1.8.1

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/build/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as initProductAnalytics, c as shutdownProductAnalytics, i as getProductAnalyticsDistinctId, n as runMcpCli, o as redactUnsafeSentryMessages, r as captureToolInvocation, s as resolveProductAnalyticsDistinctId } from "./src-BHdIWjE4.js";
2
+ import { a as initProductAnalytics, c as shutdownProductAnalytics, i as getProductAnalyticsDistinctId, n as runMcpCli, o as redactUnsafeSentryMessages, r as captureToolInvocation, s as resolveProductAnalyticsDistinctId } from "./src-Dh4qJKIU.js";
3
3
  import * as Sentry from "@sentry/node";
4
4
  //#region src/analytics-tool-metadata.ts
5
5
  /**
@@ -135,12 +135,15 @@ function wrapServerWithProductAnalytics(server) {
135
135
  const action = readToolAction(handlerArgs);
136
136
  let distinctId = resolveProductAnalyticsDistinctId("mcp") ?? getProductAnalyticsDistinctId();
137
137
  let outcome = "error";
138
+ let result;
139
+ let thrown;
138
140
  try {
139
- const result = await toolHandler(...handlerArgs);
141
+ result = await toolHandler(...handlerArgs);
140
142
  outcome = classifyToolResult(result);
141
143
  if (IDENTITY_CHANGING_MCP_TOOLS.has(name) && outcome === "success") distinctId = resolveProductAnalyticsDistinctId("mcp") ?? distinctId;
142
144
  return result;
143
145
  } catch (error) {
146
+ thrown = error;
144
147
  outcome = "error";
145
148
  throw error;
146
149
  } finally {
@@ -148,7 +151,8 @@ function wrapServerWithProductAnalytics(server) {
148
151
  toolName: name,
149
152
  action,
150
153
  outcome,
151
- distinctId
154
+ distinctId,
155
+ error: outcome === "error" ? thrown ?? result : void 0
152
156
  });
153
157
  }
154
158
  };
@@ -161,7 +165,7 @@ function wrapServerWithProductAnalytics(server) {
161
165
  }
162
166
  //#endregion
163
167
  //#region src/cli.ts
164
- const packageVersion = "1.8.0";
168
+ const packageVersion = "1.8.1";
165
169
  let sentryEnabled = false;
166
170
  let productAnalyticsEnabled = false;
167
171
  runMcpCli({
package/build/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { n as runMcpCli, t as bootstrapServer } from "./src-BHdIWjE4.js";
2
+ import { n as runMcpCli, t as bootstrapServer } from "./src-Dh4qJKIU.js";
3
3
  export { bootstrapServer, runMcpCli };
@@ -32689,6 +32689,51 @@ function listCachedMcpWorkspaces(profile) {
32689
32689
  active: workspace.workspace_id === auth.workspace_id
32690
32690
  }));
32691
32691
  }
32692
+ const CLI_GENERIC_ERROR_CATEGORY = "cli.command_error";
32693
+ const MCP_GENERIC_ERROR_CATEGORY = "mcp.tool_error";
32694
+ const ERROR_CATEGORY_SET = new Set([
32695
+ "cli.validation_error",
32696
+ "cli.api_error",
32697
+ CLI_GENERIC_ERROR_CATEGORY,
32698
+ "mcp.validation_error",
32699
+ "mcp.api_error",
32700
+ "mcp.auth_error",
32701
+ MCP_GENERIC_ERROR_CATEGORY
32702
+ ]);
32703
+ function isDeclaredErrorCategory(value) {
32704
+ return typeof value === "string" && ERROR_CATEGORY_SET.has(value);
32705
+ }
32706
+ function firstToolResultText(source) {
32707
+ if (!source || typeof source !== "object") return null;
32708
+ const content = source.content;
32709
+ if (!Array.isArray(content)) return null;
32710
+ const first = content[0];
32711
+ if (first?.type === "text" && typeof first.text === "string") return first.text;
32712
+ return null;
32713
+ }
32714
+ function errorTextForClassification(source) {
32715
+ if (source instanceof Error) return source.message;
32716
+ if (typeof source === "string") return source;
32717
+ const toolText = firstToolResultText(source);
32718
+ if (toolText !== null) return toolText;
32719
+ return "";
32720
+ }
32721
+ function classifyCli(message) {
32722
+ if (message.startsWith("Invalid input:") || message.startsWith("Invalid input ")) return "cli.validation_error";
32723
+ if (/^\d{3}:\s/.test(message)) return "cli.api_error";
32724
+ return CLI_GENERIC_ERROR_CATEGORY;
32725
+ }
32726
+ function classifyMcp(message) {
32727
+ if (message.startsWith("Invalid input:") || message.startsWith("Invalid input ")) return "mcp.validation_error";
32728
+ if (message.startsWith("API Error (")) return "mcp.api_error";
32729
+ if (message.startsWith("Authentication failed:") || message.startsWith("Not authenticated.")) return "mcp.auth_error";
32730
+ return MCP_GENERIC_ERROR_CATEGORY;
32731
+ }
32732
+ function classifyErrorCategory(client, source) {
32733
+ const message = errorTextForClassification(source);
32734
+ if (isDeclaredErrorCategory(message) && message.startsWith(`${client}.`)) return message;
32735
+ return client === "cli" ? classifyCli(message) : classifyMcp(message);
32736
+ }
32692
32737
  /**
32693
32738
  * Exception messages are the one channel `sendDefaultPii: false` does not cover,
32694
32739
  * and this repo's errors put user data in them: validation failures embed the
@@ -32700,15 +32745,14 @@ function listCachedMcpWorkspaces(profile) {
32700
32745
  * Shared between the CLI and the public MCP build so the two cannot drift.
32701
32746
  */
32702
32747
  /**
32703
- * Fixed categories are `<surface>.<snake_case>` — anchored at both ends, because
32704
- * a prefix test would pass anything that merely *starts* that way. A real message
32705
- * like `cli.ts:12: unexpected token "secret"` begins with `cli.` and would
32706
- * otherwise sail through unredacted.
32748
+ * Fixed categories are the seven declared `<surface>.<snake_case>` values, not
32749
+ * a `cli|mcp` prefix regex. A prefix or regex test would pass a caught message
32750
+ * like `cli.customer_name`. A real filename message such as
32751
+ * `cli.ts:12: unexpected token "secret"` would also begin with `cli.`.
32707
32752
  */
32708
- const SAFE_CATEGORY_PATTERN = /^(?:cli|mcp)\.[a-z][a-z0-9_]*$/;
32709
32753
  const REDACTED_SENTRY_MESSAGE = "redacted";
32710
32754
  function isSafeSentryMessage(value) {
32711
- return typeof value === "string" && SAFE_CATEGORY_PATTERN.test(value);
32755
+ return isDeclaredErrorCategory(value);
32712
32756
  }
32713
32757
  /**
32714
32758
  * Replace every exception message that is not a known category, and any top-level
@@ -32793,7 +32837,7 @@ function normalizeAction(action) {
32793
32837
  /** Strict allowlist — never accept args/results. */
32794
32838
  function captureToolInvocation(event) {
32795
32839
  if (!enabled || !apiKey) return;
32796
- const task = sendCapture(TOOL_INVOCATION_EVENT, {
32840
+ const properties = {
32797
32841
  tool_name: event.toolName,
32798
32842
  action: normalizeAction(event.action),
32799
32843
  outcome: event.outcome,
@@ -32801,7 +32845,9 @@ function captureToolInvocation(event) {
32801
32845
  client,
32802
32846
  session_id: sessionId,
32803
32847
  package_version: packageVersion$1
32804
- }, event.distinctId).finally(() => {
32848
+ };
32849
+ if (event.outcome === "error") properties.error_category = classifyErrorCategory(client, event.error);
32850
+ const task = sendCapture(TOOL_INVOCATION_EVENT, properties, event.distinctId).finally(() => {
32805
32851
  pending.delete(task);
32806
32852
  });
32807
32853
  pending.add(task);
@@ -45440,7 +45486,7 @@ import_main.default.config({
45440
45486
  quiet: true,
45441
45487
  ignore: ["MISSING_ENV_FILE"]
45442
45488
  });
45443
- const packageVersion = "1.8.0";
45489
+ const packageVersion = "1.8.1";
45444
45490
  function resolvePublicUrls() {
45445
45491
  return {
45446
45492
  focusApiUrl: process.env.TOGGL_FOCUS_API_URL ?? "https://focus.toggl.com",
@@ -45504,4 +45550,4 @@ function bootstrapServer(options = {}) {
45504
45550
  //#endregion
45505
45551
  export { initProductAnalytics as a, shutdownProductAnalytics as c, getProductAnalyticsDistinctId as i, runMcpCli as n, redactUnsafeSentryMessages as o, captureToolInvocation as r, resolveProductAnalyticsDistinctId as s, bootstrapServer as t };
45506
45552
 
45507
- //# sourceMappingURL=src-BHdIWjE4.js.map
45553
+ //# sourceMappingURL=src-Dh4qJKIU.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@togglhq/mcp",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Toggl 2.0 MCP server for Claude Code, Claude Desktop, and other MCP clients.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",