gogcli-mcp-calendar 2.25.0 → 2.26.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.js CHANGED
@@ -31000,9 +31000,82 @@ var StdioServerTransport = class {
31000
31000
  }
31001
31001
  };
31002
31002
 
31003
+ // ../../node_modules/@chrischall/mcp-utils/dist/errors/index.js
31004
+ var McpToolError = class extends Error {
31005
+ /** Actionable remediation text, when one applies. */
31006
+ hint;
31007
+ constructor(message, opts) {
31008
+ super(message, opts?.cause !== void 0 ? { cause: opts.cause } : void 0);
31009
+ this.name = "McpToolError";
31010
+ if (opts?.hint !== void 0)
31011
+ this.hint = opts.hint;
31012
+ Object.setPrototypeOf(this, new.target.prototype);
31013
+ }
31014
+ };
31015
+ var BEARER_RE = /(bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi;
31016
+ var JWT_RE = /\b[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{8,}\b/g;
31017
+ var BASIC_AUTH_RE = /(authorization\s*:\s*basic\s+)[A-Za-z0-9+/=_-]{6,}/gi;
31018
+ var SET_COOKIE_RE = /(\bset-cookie\s*:\s*)([^=;,\s]+)=[^;,\s]*/gi;
31019
+ var COOKIE_HEADER_RE = /((?<!set-)\bcookie\s*:\s*)((?:[^=;,\s]+=[^;,\s]*)(?:;\s*[^=;,\s]+=[^;,\s]*)*)/gi;
31020
+ var API_KEY_RE = new RegExp([
31021
+ "sk-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])",
31022
+ // OpenAI / Anthropic (incl. sk-ant-…)
31023
+ "gh[pousr]_[A-Za-z0-9]{36,}\\b",
31024
+ // GitHub ghp_/gho_/ghu_/ghs_/ghr_
31025
+ "xox[baprs]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])",
31026
+ // Slack
31027
+ "AIza[0-9A-Za-z_-]{35}(?![0-9A-Za-z_-])",
31028
+ // Google API key (39 chars total)
31029
+ "AKIA[0-9A-Z]{16}\\b",
31030
+ // AWS access key id (20 chars total)
31031
+ "whsec_[A-Za-z0-9]{16,}\\b"
31032
+ // webhook signing secret (Stripe-style)
31033
+ ].map((p) => `\\b${p}`).join("|"), "g");
31034
+ var QUERY_SECRET_RE = /([?&](?:access_token|refresh_token|client_secret|api_?key|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
31035
+ var AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
31036
+ var JSON_SECRET_KEYS = "access_token|refresh_token|client_secret|api_?key|password|passwd|secret|token";
31037
+ var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")[^"]*(")`, "gi");
31038
+ var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')[^']*(')`, "gi");
31039
+ function redactSecrets(text) {
31040
+ return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
31041
+ }
31042
+
31043
+ // ../../node_modules/@chrischall/mcp-utils/dist/response/index.js
31044
+ function rawTextResult(text) {
31045
+ return { content: [{ type: "text", text }] };
31046
+ }
31047
+ function errorResult(message) {
31048
+ return {
31049
+ content: [{ type: "text", text: redactSecrets(message) }],
31050
+ isError: true
31051
+ };
31052
+ }
31053
+
31003
31054
  // ../../node_modules/@chrischall/mcp-utils/dist/server/index.js
31055
+ function hintResultOrRethrow(err) {
31056
+ if (err instanceof McpToolError && err.hint) {
31057
+ return errorResult(`${err.message}
31058
+
31059
+ Hint: ${err.hint}`);
31060
+ }
31061
+ throw err;
31062
+ }
31063
+ function surfaceToolHints(server) {
31064
+ const register = server.registerTool.bind(server);
31065
+ server.registerTool = (name, config2, cb) => register(name, config2, (...args) => {
31066
+ let result;
31067
+ try {
31068
+ result = cb(...args);
31069
+ } catch (err) {
31070
+ return hintResultOrRethrow(err);
31071
+ }
31072
+ return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
31073
+ });
31074
+ }
31004
31075
  async function createMcpServer(opts) {
31005
31076
  const server = new McpServer({ name: opts.name, version: opts.version });
31077
+ if (opts.surfaceHints !== false)
31078
+ surfaceToolHints(server);
31006
31079
  if (opts.banner !== void 0) {
31007
31080
  console.error(opts.banner);
31008
31081
  }
@@ -31047,46 +31120,6 @@ async function runMcp(opts) {
31047
31120
  return server;
31048
31121
  }
31049
31122
 
31050
- // ../../node_modules/@chrischall/mcp-utils/dist/errors/index.js
31051
- var BEARER_RE = /(bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi;
31052
- var JWT_RE = /\b[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{8,}\b/g;
31053
- var BASIC_AUTH_RE = /(authorization\s*:\s*basic\s+)[A-Za-z0-9+/=_-]{6,}/gi;
31054
- var SET_COOKIE_RE = /(\bset-cookie\s*:\s*)([^=;,\s]+)=[^;,\s]*/gi;
31055
- var COOKIE_HEADER_RE = /((?<!set-)\bcookie\s*:\s*)((?:[^=;,\s]+=[^;,\s]*)(?:;\s*[^=;,\s]+=[^;,\s]*)*)/gi;
31056
- var API_KEY_RE = new RegExp([
31057
- "sk-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])",
31058
- // OpenAI / Anthropic (incl. sk-ant-…)
31059
- "gh[pousr]_[A-Za-z0-9]{36,}\\b",
31060
- // GitHub ghp_/gho_/ghu_/ghs_/ghr_
31061
- "xox[baprs]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])",
31062
- // Slack
31063
- "AIza[0-9A-Za-z_-]{35}(?![0-9A-Za-z_-])",
31064
- // Google API key (39 chars total)
31065
- "AKIA[0-9A-Z]{16}\\b",
31066
- // AWS access key id (20 chars total)
31067
- "whsec_[A-Za-z0-9]{16,}\\b"
31068
- // webhook signing secret (Stripe-style)
31069
- ].map((p) => `\\b${p}`).join("|"), "g");
31070
- var QUERY_SECRET_RE = /([?&](?:access_token|refresh_token|client_secret|api_?key|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
31071
- var AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
31072
- var JSON_SECRET_KEYS = "access_token|refresh_token|client_secret|api_?key|password|passwd|secret|token";
31073
- var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")[^"]*(")`, "gi");
31074
- var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')[^']*(')`, "gi");
31075
- function redactSecrets(text) {
31076
- return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
31077
- }
31078
-
31079
- // ../../node_modules/@chrischall/mcp-utils/dist/response/index.js
31080
- function rawTextResult(text) {
31081
- return { content: [{ type: "text", text }] };
31082
- }
31083
- function errorResult(message) {
31084
- return {
31085
- content: [{ type: "text", text: redactSecrets(message) }],
31086
- isError: true
31087
- };
31088
- }
31089
-
31090
31123
  // ../../node_modules/@chrischall/mcp-utils/dist/config/index.js
31091
31124
  var PLACEHOLDER_RE = /^\$\{[^}]*\}$/;
31092
31125
  function readEnvVar(key, opts = {}) {
@@ -31912,6 +31945,29 @@ function authToolsFor(defaultServices) {
31912
31945
  }
31913
31946
 
31914
31947
  // ../gogcli-mcp/src/tools/calendar.ts
31948
+ var reminderParams = {
31949
+ reminders: external_exports.array(external_exports.string()).max(5).optional().describe(
31950
+ `Reminders as method:duration, e.g. ["popup:30m", "email:1d"]. Method is popup or email; duration accepts m/h/d (max 40320 minutes = 4 weeks). Google allows at most 5. These REPLACE the event's reminders \u2014 on update, pass an EMPTY array to drop custom reminders and go back to the calendar's defaults. Cannot be combined with noReminders.`
31951
+ ),
31952
+ noReminders: external_exports.boolean().optional().describe(
31953
+ "Give the event no reminders at all, overriding the calendar's defaults. Different from an empty reminders array, which RESTORES those defaults. Cannot be combined with reminders."
31954
+ )
31955
+ };
31956
+ function pushReminderFlags(args, p) {
31957
+ if (p.noReminders) {
31958
+ if (p.reminders !== void 0) {
31959
+ throw new Error("reminders and noReminders are mutually exclusive: pass reminders to set custom ones, noReminders for none, or an empty reminders array to restore the calendar defaults.");
31960
+ }
31961
+ args.push("--no-reminders");
31962
+ return;
31963
+ }
31964
+ if (p.reminders === void 0) return;
31965
+ if (p.reminders.length === 0) {
31966
+ args.push("--reminder=");
31967
+ return;
31968
+ }
31969
+ for (const reminder of p.reminders) args.push(`--reminder=${reminder}`);
31970
+ }
31915
31971
  function registerCalendarTools(server) {
31916
31972
  server.registerTool("gog_calendar_events", {
31917
31973
  description: 'List calendar events. Describe the window ONE way and one way only (gog >= 0.36.0 rejects the rest as ambiguous rather than silently discarding a flag): today on its own; or from + to; or from + days; or days on its own (a window of that many days starting today). today cannot be combined with from, to or days, and days cannot be combined with to. gog returns only 10 events by default, so a wide date range is USUALLY INCOMPLETE: raise max, or page with pageToken until the response carries no nextPageToken. A response carrying "truncated": true is an incomplete view \u2014 never conclude an event does not exist from one.',
@@ -31981,9 +32037,10 @@ function registerCalendarTools(server) {
31981
32037
  allDay: external_exports.boolean().optional().describe("All-day event (use date-only in from/to)"),
31982
32038
  timezone: external_exports.string().optional().describe("IANA timezone metadata applied to from/to (e.g. America/New_York). Sets both start and end timezone unless start/end timezone are overridden."),
31983
32039
  withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event (requires Zoom S2S OAuth setup)"),
32040
+ ...reminderParams,
31984
32041
  account: accountParam
31985
32042
  }
31986
- }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, timezone, withZoom, account }) => {
32043
+ }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, timezone, withZoom, reminders, noReminders, account }) => {
31987
32044
  const args = ["calendar", "create", calendarId, `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
31988
32045
  if (description) args.push(`--description=${description}`);
31989
32046
  if (location) args.push(`--location=${location}`);
@@ -31991,6 +32048,7 @@ function registerCalendarTools(server) {
31991
32048
  if (allDay) args.push("--all-day");
31992
32049
  if (timezone) args.push(`--timezone=${timezone}`);
31993
32050
  if (withZoom) args.push("--with-zoom");
32051
+ pushReminderFlags(args, { reminders, noReminders });
31994
32052
  return runOrDiagnose(args, { account });
31995
32053
  });
31996
32054
  server.registerTool("gog_calendar_update", {
@@ -32011,9 +32069,10 @@ function registerCalendarTools(server) {
32011
32069
  regenerateZoom: external_exports.boolean().optional().describe("Replace the event's existing Zoom video conference"),
32012
32070
  removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
32013
32071
  removeMeet: external_exports.boolean().optional().describe("Remove the event's Google Meet video conference (clears conference data only)"),
32072
+ ...reminderParams,
32014
32073
  account: accountParam
32015
32074
  }
32016
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, addAttendees, attachments, withZoom, regenerateZoom, removeZoom, removeMeet, account }) => {
32075
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, addAttendees, attachments, withZoom, regenerateZoom, removeZoom, removeMeet, reminders, noReminders, account }) => {
32017
32076
  const args = ["calendar", "update", calendarId, eventId];
32018
32077
  if (summary !== void 0) args.push(`--summary=${summary}`);
32019
32078
  if (from !== void 0) args.push(`--from=${from}`);
@@ -32027,6 +32086,7 @@ function registerCalendarTools(server) {
32027
32086
  if (regenerateZoom) args.push("--regenerate-zoom");
32028
32087
  if (removeZoom) args.push("--remove-zoom");
32029
32088
  if (removeMeet) args.push("--remove-meet");
32089
+ pushReminderFlags(args, { reminders, noReminders });
32030
32090
  return runOrDiagnose(args, { account });
32031
32091
  });
32032
32092
  server.registerTool("gog_calendar_delete", {
@@ -32088,7 +32148,7 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
32088
32148
  );
32089
32149
 
32090
32150
  // ../gogcli-mcp/src/server.ts
32091
- var VERSION = true ? "2.25.0" : "0.0.0";
32151
+ var VERSION = true ? "2.26.0" : "0.0.0";
32092
32152
 
32093
32153
  // ../gogcli-mcp/src/auth-log.ts
32094
32154
  var FAILURES = /* @__PURE__ */ new Set([
package/manifest.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifest_version": "0.3",
4
4
  "name": "gogcli-mcp-calendar",
5
5
  "display_name": "gogcli (Calendar)",
6
- "version": "2.25.0",
6
+ "version": "2.26.0",
7
7
  "description": "Extended Google Calendar for Claude via gogcli — auth + Calendar events + Meet space management",
8
8
  "author": {
9
9
  "name": "Chris Hall",
package/mint.yaml ADDED
@@ -0,0 +1,107 @@
1
+ version: 1
2
+ name: Google Calendar (gogcli)
3
+ slug: gogcli-mcp-calendar
4
+ summary: >-
5
+ Extended Google Calendar + Meet MCP server via gogcli — auth + Calendar
6
+ events + Meet space management
7
+ command:
8
+ # This package publishes a single bin; naming it keeps the install
9
+ # unambiguous alongside its eight sibling packages.
10
+ bin: gogcli-mcp-calendar
11
+ env:
12
+ - name: GOG_CLIENT_ID
13
+ required: false
14
+ help: >-
15
+ Google OAuth client id. NOTE: on the local-spawn path the child `gog`
16
+ receives a sanitized env — runner.ts drops GOG_ACCESS_TOKEN and every
17
+ *_TOKEN / *_SECRET / *_API_KEY / *_PRIVATE_KEY variable — so the CLI
18
+ authenticates from its own stored credentials under $HOME (see
19
+ state.dataDir), not from these variables being passed through.
20
+ - name: GOG_CLIENT_SECRET
21
+ secret: true
22
+ required: false
23
+ help: >-
24
+ Google OAuth client secret. Stripped from the spawned CLI's environment
25
+ by runner.ts's *_SECRET rule — see GOG_CLIENT_ID.
26
+ - name: GOG_REFRESH_TOKEN
27
+ secret: true
28
+ required: false
29
+ help: >-
30
+ Google OAuth refresh token. Stripped from the spawned CLI's environment
31
+ by runner.ts's *_TOKEN rule — see GOG_CLIENT_ID. A hosted deployment must
32
+ therefore carry gog's authorised-account state in its persisted data dir,
33
+ or drive a remote runner via GOG_RUNNER_URL.
34
+ - name: GOG_ACCESS_TOKEN
35
+ secret: true
36
+ required: false
37
+ help: >-
38
+ Deliberately removed from the spawned CLI's environment by runner.ts, so
39
+ that a stale directly-passed token cannot shadow gog's stored refresh
40
+ credential. Leave unset.
41
+ - name: GOG_ACCOUNT
42
+ required: false
43
+ help: >-
44
+ Which configured Google account to act as, when more than one is
45
+ authorised. Defaults to the single/most recent account.
46
+ - name: GOG_READONLY
47
+ required: false
48
+ help: >-
49
+ Set to 1 to refuse every mutating operation. Recommended when the
50
+ connector is shared or you only need reads.
51
+ - name: GOG_PATH
52
+ required: false
53
+ help: >-
54
+ Path to the `gog` binary. Leave unset when the dependency below supplies
55
+ it; set it only to point at a binary you manage yourself.
56
+ - name: GOG_RUNNER_URL
57
+ required: false
58
+ help: >-
59
+ URL of a remote gog runner to execute against instead of spawning the
60
+ local binary. If you set this, add its host to egress.allow.
61
+ - name: GOG_RUNNER_KEY
62
+ secret: true
63
+ required: false
64
+ help: >-
65
+ Shared key authenticating calls to GOG_RUNNER_URL. Required whenever that
66
+ is set.
67
+ - name: GOG_TIMEZONE
68
+ required: false
69
+ help: >-
70
+ The IANA zone gog itself formats its naive timestamps in. The wrapper
71
+ reads it (naiveSourceTimeZone) to re-attach the correct offset, so it
72
+ should match gog's own configuration. Falls back to DISPLAY_TZ, then to
73
+ America/New_York.
74
+ - name: DISPLAY_TZ
75
+ required: false
76
+ help: >-
77
+ The IANA zone every rendered *Display field uses (displayTimeZone,
78
+ default America/New_York). It does not read GOG_TIMEZONE — the fallback
79
+ runs the other way, so this is also what GOG_TIMEZONE falls back to. An
80
+ invalid value degrades to the default rather than throwing.
81
+ dependencies:
82
+ # Every tool shells out to the `gog` CLI; without it the server starts and
83
+ # then fails on the first call. This tag must track
84
+ # packages/gogcli-mcp/src/runner.ts's MIN_GOG_VERSION (the floor the tools
85
+ # assume) and the fly-gog-runner/Dockerfile GOG_VERSION build arg. See
86
+ # CLAUDE.md "Required gog version" — bumping the floor means bumping these
87
+ # nine pins too.
88
+ - kind: github-release
89
+ repo: openclaw/gogcli
90
+ tag: v0.38.1
91
+ asset: "gogcli_*_linux_amd64.tar.gz"
92
+ bin: [gog]
93
+ state:
94
+ dataDir: true
95
+ reason: >-
96
+ `gog` keeps its authorised-account state and token cache under $HOME.
97
+ Without a persistent data dir every cold start has no account configured and
98
+ every tool call fails until the credentials are re-supplied.
99
+ egress:
100
+ allow:
101
+ # Google OAuth token exchange and the Google REST APIs the CLI calls.
102
+ - oauth2.googleapis.com
103
+ - www.googleapis.com
104
+ - googleapis.com
105
+ #
106
+ # NOTE: if you set GOG_RUNNER_URL to run against a remote gog runner, add
107
+ # that host here too — it is supplied at runtime and cannot be declared.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gogcli-mcp-calendar",
3
- "version": "2.25.0",
3
+ "version": "2.26.0",
4
4
  "mcpName": "io.github.chrischall/gogcli-mcp-calendar",
5
5
  "description": "Extended Google Calendar + Meet MCP server via gogcli — auth + Calendar events + Meet space management",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -24,7 +24,7 @@
24
24
  "test:coverage": "vitest run --coverage"
25
25
  },
26
26
  "dependencies": {
27
- "@chrischall/mcp-utils": "^0.14.0",
27
+ "@chrischall/mcp-utils": "^0.15.0",
28
28
  "@modelcontextprotocol/sdk": "^1.30.0",
29
29
  "zod": "^4.4.3"
30
30
  },