@togglhq/mcp 1.11.82 → 1.11.83

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
@@ -104,7 +104,7 @@ Disable product analytics:
104
104
  TOGGL_PRODUCT_ANALYTICS=off
105
105
  ```
106
106
 
107
- Optional error reporting via Sentry is off unless you set `TOGGL_SENTRY=1` and `SENTRY_DSN`.
107
+ Error reporting is on by default. It sends the tool name, a redacted error category, the stack trace with package-relative file paths, the MCP, Node and OS versions, and sampled request timings without query strings. It never sends tool arguments, results, exception text, console output, your hostname, local paths, or your project's dependency list. Disable it with `TOGGL_SENTRY=off`, or send it to your own Sentry project with `TOGGL_SENTRY_DSN`.
108
108
 
109
109
  ## License
110
110
 
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-CuNUrEWK.js";
2
+ import { a as getProductAnalyticsDistinctId, c as resolvePublicSentryDsn, i as captureToolInvocation, l as shutdownProductAnalytics, n as runMcpCli, o as initProductAnalytics, r as PUBLIC_SENTRY_PRIVACY_OPTIONS, s as resolveProductAnalyticsDistinctId } from "./src-LMB5VU2N.js";
3
3
  import * as Sentry from "@sentry/node";
4
4
  //#region src/analytics-tool-metadata.ts
5
5
  /**
@@ -66,25 +66,22 @@ function classifyToolResult(result) {
66
66
  }
67
67
  //#endregion
68
68
  //#region src/public-analytics.ts
69
- function envEnabled(raw) {
70
- if (raw === void 0) return false;
71
- const normalized = raw.trim().toLowerCase();
72
- return normalized === "1" || normalized === "true" || normalized === "on" || normalized === "yes";
73
- }
74
- function initPublicSentry(environment) {
75
- if (!envEnabled(process.env.TOGGL_SENTRY)) return false;
76
- const dsn = process.env.SENTRY_DSN;
77
- if (!dsn || dsn === "off") {
78
- console.error("[Analytics] TOGGL_SENTRY is set but SENTRY_DSN is missing; Sentry left disabled");
79
- return false;
80
- }
69
+ /**
70
+ * Public client DSN for the `toggl-mcp` Sentry project. Safe to ship: it only
71
+ * accepts events. The pack audit allowlists this exact value and still rejects
72
+ * any other `ingest.sentry.io` DSN.
73
+ */
74
+ const PUBLIC_SENTRY_DSN = "https://c37820699688a7c0393aa257dbe7a99e@o43910.ingest.us.sentry.io/4512156592046081";
75
+ function initPublicSentry(environment, release) {
76
+ const dsn = resolvePublicSentryDsn(PUBLIC_SENTRY_DSN);
77
+ if (!dsn) return false;
81
78
  Sentry.init({
82
79
  dsn,
83
80
  environment: environment ?? "production",
81
+ release: release ? `@togglhq/mcp@${release}` : void 0,
84
82
  tracesSampleRate: .2,
85
83
  enableLogs: false,
86
- sendDefaultPii: false,
87
- beforeSend: (event) => redactUnsafeSentryMessages(event)
84
+ ...PUBLIC_SENTRY_PRIVACY_OPTIONS
88
85
  });
89
86
  return true;
90
87
  }
@@ -165,13 +162,13 @@ function wrapServerWithProductAnalytics(server) {
165
162
  }
166
163
  //#endregion
167
164
  //#region src/cli.ts
168
- const packageVersion = "1.11.82";
165
+ const packageVersion = "1.11.83";
169
166
  let sentryEnabled = false;
170
167
  let productAnalyticsEnabled = false;
171
168
  runMcpCli({
172
169
  beforeRegister(server) {
173
170
  productAnalyticsEnabled = initMcpProductAnalytics({ packageVersion });
174
- sentryEnabled = initPublicSentry(process.env.NODE_ENV);
171
+ sentryEnabled = initPublicSentry(process.env.NODE_ENV, packageVersion);
175
172
  let next = server;
176
173
  if (sentryEnabled) next = wrapPublicServerWithSentry(next);
177
174
  if (productAnalyticsEnabled) wrapServerWithProductAnalytics(next);
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-CuNUrEWK.js";
2
+ import { n as runMcpCli, t as bootstrapServer } from "./src-LMB5VU2N.js";
3
3
  export { bootstrapServer, runMcpCli };
@@ -40012,6 +40012,120 @@ function redactUnsafeSentryMessages(event) {
40012
40012
  for (const value of event.exception?.values ?? []) if (!isSafeSentryMessage(value.value)) value.value = REDACTED_SENTRY_MESSAGE;
40013
40013
  return event;
40014
40014
  }
40015
+ /**
40016
+ * Shared Sentry setup for the public CLI and MCP packages. Reporting is on by
40017
+ * default there, so everything the SDK attaches on its own has to be safe to
40018
+ * send from any user's machine, not only the exception message. Both packages
40019
+ * build their `Sentry.init` options from here so the two cannot drift.
40020
+ */
40021
+ function normalized(raw) {
40022
+ const value = raw?.trim();
40023
+ return value ? value.toLowerCase() : void 0;
40024
+ }
40025
+ function isOff(raw) {
40026
+ const value = normalized(raw);
40027
+ return value === "0" || value === "false" || value === "off" || value === "no";
40028
+ }
40029
+ function isOn(raw) {
40030
+ const value = normalized(raw);
40031
+ return value === "1" || value === "true" || value === "on" || value === "yes";
40032
+ }
40033
+ /**
40034
+ * Picks the DSN the public build reports to, or `undefined` when reporting is
40035
+ * off.
40036
+ *
40037
+ * `TOGGL_SENTRY_DSN` is the override. The generic `SENTRY_DSN` is what most Node
40038
+ * apps set, and the MCP loads the working directory's `.env`, so on its own it
40039
+ * must not redirect Toggl's errors into the user's project. It is still honoured
40040
+ * with an explicit `TOGGL_SENTRY=1`, the old opt-in, and `SENTRY_DSN=off` still
40041
+ * switches reporting off.
40042
+ */
40043
+ function resolvePublicSentryDsn(builtIn, env = process.env) {
40044
+ if (isOff(env.TOGGL_SENTRY) || normalized(env.SENTRY_DSN) === "off") return void 0;
40045
+ const override = env.TOGGL_SENTRY_DSN?.trim();
40046
+ if (override) return override.toLowerCase() === "off" ? void 0 : override;
40047
+ const legacy = env.SENTRY_DSN?.trim();
40048
+ if (legacy && isOn(env.TOGGL_SENTRY)) return legacy;
40049
+ return builtIn;
40050
+ }
40051
+ /**
40052
+ * `/Users/jane/.npm/_npx/…/node_modules/@togglhq/mcp/build/cli.js` becomes
40053
+ * `@togglhq/mcp/build/cli.js`. A path outside `node_modules` keeps only its file
40054
+ * name, so no home directory or login leaves the machine.
40055
+ */
40056
+ function toPackageRelativePath(path) {
40057
+ const unified = path.replace(/^file:\/\//, "").replaceAll("\\", "/");
40058
+ const at = unified.lastIndexOf("/node_modules/");
40059
+ if (at !== -1) return unified.slice(at + 14);
40060
+ if (!unified.includes("/")) return unified;
40061
+ return unified.slice(unified.lastIndexOf("/") + 1);
40062
+ }
40063
+ function scrubStacktrace(stacktrace) {
40064
+ for (const frame of stacktrace?.frames ?? []) {
40065
+ if (typeof frame.filename === "string") frame.filename = toPackageRelativePath(frame.filename);
40066
+ if (typeof frame.abs_path === "string") frame.abs_path = toPackageRelativePath(frame.abs_path);
40067
+ }
40068
+ }
40069
+ const QUERY_ATTRIBUTES = [
40070
+ "http.query",
40071
+ "url.query",
40072
+ "http.fragment",
40073
+ "url.fragment"
40074
+ ];
40075
+ const URL_ATTRIBUTES = [
40076
+ "url.full",
40077
+ "http.url",
40078
+ "http.target",
40079
+ "url"
40080
+ ];
40081
+ function stripQuery(value) {
40082
+ return value.replace(/[?#]\S*/, "");
40083
+ }
40084
+ function scrubSpan(span) {
40085
+ if (!span) return;
40086
+ if (typeof span.description === "string") span.description = stripQuery(span.description);
40087
+ const data = span.data;
40088
+ if (!data) return;
40089
+ for (const key of QUERY_ATTRIBUTES) delete data[key];
40090
+ for (const key of URL_ATTRIBUTES) {
40091
+ const value = data[key];
40092
+ if (typeof value === "string") data[key] = stripQuery(value);
40093
+ }
40094
+ }
40095
+ /**
40096
+ * Last word on every event the public build sends: messages reduced to fixed
40097
+ * categories, no hostname, no breadcrumbs, no dependency list, no request data,
40098
+ * package-relative stack paths, and no query strings on spans.
40099
+ */
40100
+ function scrubPublicSentryEvent(event) {
40101
+ redactUnsafeSentryMessages(event);
40102
+ delete event.server_name;
40103
+ delete event.breadcrumbs;
40104
+ delete event.modules;
40105
+ delete event.request;
40106
+ for (const value of event.exception?.values ?? []) scrubStacktrace(value.stacktrace);
40107
+ for (const thread of event.threads?.values ?? []) scrubStacktrace(thread.stacktrace);
40108
+ for (const span of event.spans ?? []) scrubSpan(span);
40109
+ scrubSpan(event.contexts?.trace);
40110
+ return event;
40111
+ }
40112
+ /**
40113
+ * Privacy options shared by `initCliTelemetry` and `initPublicSentry`.
40114
+ *
40115
+ * `sendDefaultPii: false` leaves the hostname (`server_name`), console and fetch
40116
+ * breadcrumbs, absolute stack paths, the working directory's package.json
40117
+ * dependencies (`Modules`) and incoming request data in place. Console
40118
+ * breadcrumbs in the MCP include the workspace name it logs at startup.
40119
+ */
40120
+ const PUBLIC_SENTRY_PRIVACY_OPTIONS = {
40121
+ sendDefaultPii: false,
40122
+ includeServerName: false,
40123
+ maxBreadcrumbs: 0,
40124
+ integrations: (defaults) => defaults.filter((integration) => integration.name !== "Modules"),
40125
+ beforeBreadcrumb: () => null,
40126
+ beforeSend: (event) => scrubPublicSentryEvent(event),
40127
+ beforeSendTransaction: (event) => scrubPublicSentryEvent(event)
40128
+ };
40015
40129
  const DEFAULT_POSTHOG_HOST = "https://eu.i.posthog.com";
40016
40130
  /**
40017
40131
  * The shared Toggl **production** PostHog project — the same token the Track
@@ -54723,7 +54837,7 @@ function registerWorkspaceTools(server) {
54723
54837
  //#region src/package-version.ts
54724
54838
  function mcpPackageVersion() {
54725
54839
  try {
54726
- return "1.11.82";
54840
+ return "1.11.83";
54727
54841
  } catch {
54728
54842
  return "unknown";
54729
54843
  }
@@ -54898,7 +55012,7 @@ import_main.default.config({
54898
55012
  quiet: true,
54899
55013
  ignore: ["MISSING_ENV_FILE"]
54900
55014
  });
54901
- const packageVersion = "1.11.82";
55015
+ const packageVersion = "1.11.83";
54902
55016
  function resolvePublicUrls() {
54903
55017
  return {
54904
55018
  focusApiUrl: process.env.TOGGL_FOCUS_API_URL ?? "https://focus.toggl.com",
@@ -54961,6 +55075,6 @@ function bootstrapServer(options = {}) {
54961
55075
  if (options.beforeExit) process.on("beforeExit", async () => await options.beforeExit?.());
54962
55076
  }
54963
55077
  //#endregion
54964
- 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 };
55078
+ export { getProductAnalyticsDistinctId as a, resolvePublicSentryDsn as c, captureToolInvocation as i, shutdownProductAnalytics as l, runMcpCli as n, initProductAnalytics as o, PUBLIC_SENTRY_PRIVACY_OPTIONS as r, resolveProductAnalyticsDistinctId as s, bootstrapServer as t };
54965
55079
 
54966
- //# sourceMappingURL=src-CuNUrEWK.js.map
55080
+ //# sourceMappingURL=src-LMB5VU2N.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@togglhq/mcp",
3
- "version": "1.11.82",
3
+ "version": "1.11.83",
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",