gogcli-mcp 2.0.8 → 2.0.9

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/lib.js CHANGED
@@ -3104,6 +3104,9 @@ var require_utils = __commonJS({
3104
3104
  "use strict";
3105
3105
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
3106
3106
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
3107
+ var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
3108
+ var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
3109
+ var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
3107
3110
  function stringArrayToHexStripped(input) {
3108
3111
  let acc = "";
3109
3112
  let code = 0;
@@ -3296,27 +3299,77 @@ var require_utils = __commonJS({
3296
3299
  }
3297
3300
  return output.join("");
3298
3301
  }
3299
- function normalizeComponentEncoding(component, esc2) {
3300
- const func = esc2 !== true ? escape : unescape;
3301
- if (component.scheme !== void 0) {
3302
- component.scheme = func(component.scheme);
3303
- }
3304
- if (component.userinfo !== void 0) {
3305
- component.userinfo = func(component.userinfo);
3306
- }
3307
- if (component.host !== void 0) {
3308
- component.host = func(component.host);
3302
+ var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
3303
+ var HOST_DELIM_RE = /[@/?#:]/g;
3304
+ var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
3305
+ function reescapeHostDelimiters(host, isIP) {
3306
+ const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
3307
+ re.lastIndex = 0;
3308
+ return host.replace(re, (ch) => HOST_DELIMS[ch]);
3309
+ }
3310
+ function normalizePercentEncoding(input, decodeUnreserved = false) {
3311
+ if (input.indexOf("%") === -1) {
3312
+ return input;
3309
3313
  }
3310
- if (component.path !== void 0) {
3311
- component.path = func(component.path);
3314
+ let output = "";
3315
+ for (let i = 0; i < input.length; i++) {
3316
+ if (input[i] === "%" && i + 2 < input.length) {
3317
+ const hex3 = input.slice(i + 1, i + 3);
3318
+ if (isHexPair(hex3)) {
3319
+ const normalizedHex = hex3.toUpperCase();
3320
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
3321
+ if (decodeUnreserved && isUnreserved(decoded)) {
3322
+ output += decoded;
3323
+ } else {
3324
+ output += "%" + normalizedHex;
3325
+ }
3326
+ i += 2;
3327
+ continue;
3328
+ }
3329
+ }
3330
+ output += input[i];
3312
3331
  }
3313
- if (component.query !== void 0) {
3314
- component.query = func(component.query);
3332
+ return output;
3333
+ }
3334
+ function normalizePathEncoding(input) {
3335
+ let output = "";
3336
+ for (let i = 0; i < input.length; i++) {
3337
+ if (input[i] === "%" && i + 2 < input.length) {
3338
+ const hex3 = input.slice(i + 1, i + 3);
3339
+ if (isHexPair(hex3)) {
3340
+ const normalizedHex = hex3.toUpperCase();
3341
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
3342
+ if (decoded !== "." && isUnreserved(decoded)) {
3343
+ output += decoded;
3344
+ } else {
3345
+ output += "%" + normalizedHex;
3346
+ }
3347
+ i += 2;
3348
+ continue;
3349
+ }
3350
+ }
3351
+ if (isPathCharacter(input[i])) {
3352
+ output += input[i];
3353
+ } else {
3354
+ output += escape(input[i]);
3355
+ }
3315
3356
  }
3316
- if (component.fragment !== void 0) {
3317
- component.fragment = func(component.fragment);
3357
+ return output;
3358
+ }
3359
+ function escapePreservingEscapes(input) {
3360
+ let output = "";
3361
+ for (let i = 0; i < input.length; i++) {
3362
+ if (input[i] === "%" && i + 2 < input.length) {
3363
+ const hex3 = input.slice(i + 1, i + 3);
3364
+ if (isHexPair(hex3)) {
3365
+ output += "%" + hex3.toUpperCase();
3366
+ i += 2;
3367
+ continue;
3368
+ }
3369
+ }
3370
+ output += escape(input[i]);
3318
3371
  }
3319
- return component;
3372
+ return output;
3320
3373
  }
3321
3374
  function recomposeAuthority(component) {
3322
3375
  const uriTokens = [];
@@ -3331,7 +3384,7 @@ var require_utils = __commonJS({
3331
3384
  if (ipV6res.isIPV6 === true) {
3332
3385
  host = `[${ipV6res.escapedHost}]`;
3333
3386
  } else {
3334
- host = component.host;
3387
+ host = reescapeHostDelimiters(host, false);
3335
3388
  }
3336
3389
  }
3337
3390
  uriTokens.push(host);
@@ -3345,7 +3398,10 @@ var require_utils = __commonJS({
3345
3398
  module.exports = {
3346
3399
  nonSimpleDomain,
3347
3400
  recomposeAuthority,
3348
- normalizeComponentEncoding,
3401
+ reescapeHostDelimiters,
3402
+ normalizePercentEncoding,
3403
+ normalizePathEncoding,
3404
+ escapePreservingEscapes,
3349
3405
  removeDotSegments,
3350
3406
  isIPv4,
3351
3407
  isUUID,
@@ -3569,12 +3625,12 @@ var require_schemes = __commonJS({
3569
3625
  var require_fast_uri = __commonJS({
3570
3626
  "../../node_modules/fast-uri/index.js"(exports, module) {
3571
3627
  "use strict";
3572
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
3628
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
3573
3629
  var { SCHEMES, getSchemeHandler } = require_schemes();
3574
3630
  function normalize(uri, options) {
3575
3631
  if (typeof uri === "string") {
3576
3632
  uri = /** @type {T} */
3577
- serialize(parse3(uri, options), options);
3633
+ normalizeString(uri, options);
3578
3634
  } else if (typeof uri === "object") {
3579
3635
  uri = /** @type {T} */
3580
3636
  parse3(serialize(uri, options), options);
@@ -3641,19 +3697,9 @@ var require_fast_uri = __commonJS({
3641
3697
  return target;
3642
3698
  }
3643
3699
  function equal(uriA, uriB, options) {
3644
- if (typeof uriA === "string") {
3645
- uriA = unescape(uriA);
3646
- uriA = serialize(normalizeComponentEncoding(parse3(uriA, options), true), { ...options, skipEscape: true });
3647
- } else if (typeof uriA === "object") {
3648
- uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
3649
- }
3650
- if (typeof uriB === "string") {
3651
- uriB = unescape(uriB);
3652
- uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), { ...options, skipEscape: true });
3653
- } else if (typeof uriB === "object") {
3654
- uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
3655
- }
3656
- return uriA.toLowerCase() === uriB.toLowerCase();
3700
+ const normalizedA = normalizeComparableURI(uriA, options);
3701
+ const normalizedB = normalizeComparableURI(uriB, options);
3702
+ return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
3657
3703
  }
3658
3704
  function serialize(cmpts, opts) {
3659
3705
  const component = {
@@ -3678,12 +3724,12 @@ var require_fast_uri = __commonJS({
3678
3724
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
3679
3725
  if (component.path !== void 0) {
3680
3726
  if (!options.skipEscape) {
3681
- component.path = escape(component.path);
3727
+ component.path = escapePreservingEscapes(component.path);
3682
3728
  if (component.scheme !== void 0) {
3683
3729
  component.path = component.path.split("%3A").join(":");
3684
3730
  }
3685
3731
  } else {
3686
- component.path = unescape(component.path);
3732
+ component.path = normalizePercentEncoding(component.path);
3687
3733
  }
3688
3734
  }
3689
3735
  if (options.reference !== "suffix" && component.scheme) {
@@ -3718,7 +3764,16 @@ var require_fast_uri = __commonJS({
3718
3764
  return uriTokens.join("");
3719
3765
  }
3720
3766
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3721
- function parse3(uri, opts) {
3767
+ function getParseError(parsed, matches) {
3768
+ if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
3769
+ return 'URI path must start with "/" when authority is present.';
3770
+ }
3771
+ if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
3772
+ return "URI port is malformed.";
3773
+ }
3774
+ return void 0;
3775
+ }
3776
+ function parseWithStatus(uri, opts) {
3722
3777
  const options = Object.assign({}, opts);
3723
3778
  const parsed = {
3724
3779
  scheme: void 0,
@@ -3729,6 +3784,7 @@ var require_fast_uri = __commonJS({
3729
3784
  query: void 0,
3730
3785
  fragment: void 0
3731
3786
  };
3787
+ let malformedAuthorityOrPort = false;
3732
3788
  let isIP = false;
3733
3789
  if (options.reference === "suffix") {
3734
3790
  if (options.scheme) {
@@ -3749,6 +3805,11 @@ var require_fast_uri = __commonJS({
3749
3805
  if (isNaN(parsed.port)) {
3750
3806
  parsed.port = matches[5];
3751
3807
  }
3808
+ const parseError = getParseError(parsed, matches);
3809
+ if (parseError !== void 0) {
3810
+ parsed.error = parsed.error || parseError;
3811
+ malformedAuthorityOrPort = true;
3812
+ }
3752
3813
  if (parsed.host) {
3753
3814
  const ipv4result = isIPv4(parsed.host);
3754
3815
  if (ipv4result === false) {
@@ -3787,14 +3848,18 @@ var require_fast_uri = __commonJS({
3787
3848
  parsed.scheme = unescape(parsed.scheme);
3788
3849
  }
3789
3850
  if (parsed.host !== void 0) {
3790
- parsed.host = unescape(parsed.host);
3851
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
3791
3852
  }
3792
3853
  }
3793
3854
  if (parsed.path) {
3794
- parsed.path = escape(unescape(parsed.path));
3855
+ parsed.path = normalizePathEncoding(parsed.path);
3795
3856
  }
3796
3857
  if (parsed.fragment) {
3797
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
3858
+ try {
3859
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
3860
+ } catch {
3861
+ parsed.error = parsed.error || "URI malformed";
3862
+ }
3798
3863
  }
3799
3864
  }
3800
3865
  if (schemeHandler && schemeHandler.parse) {
@@ -3803,7 +3868,29 @@ var require_fast_uri = __commonJS({
3803
3868
  } else {
3804
3869
  parsed.error = parsed.error || "URI can not be parsed.";
3805
3870
  }
3806
- return parsed;
3871
+ return { parsed, malformedAuthorityOrPort };
3872
+ }
3873
+ function parse3(uri, opts) {
3874
+ return parseWithStatus(uri, opts).parsed;
3875
+ }
3876
+ function normalizeString(uri, opts) {
3877
+ return normalizeStringWithStatus(uri, opts).normalized;
3878
+ }
3879
+ function normalizeStringWithStatus(uri, opts) {
3880
+ const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
3881
+ return {
3882
+ normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
3883
+ malformedAuthorityOrPort
3884
+ };
3885
+ }
3886
+ function normalizeComparableURI(uri, opts) {
3887
+ if (typeof uri === "string") {
3888
+ const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
3889
+ return malformedAuthorityOrPort ? void 0 : normalized;
3890
+ }
3891
+ if (typeof uri === "object") {
3892
+ return serialize(uri, opts);
3893
+ }
3807
3894
  }
3808
3895
  var fastUri = {
3809
3896
  SCHEMES,
@@ -13515,14 +13602,14 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
13515
13602
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
13516
13603
  };
13517
13604
  doc.write(`const input = payload.value;`);
13518
- const ids = /* @__PURE__ */ Object.create(null);
13605
+ const ids2 = /* @__PURE__ */ Object.create(null);
13519
13606
  let counter = 0;
13520
13607
  for (const key of normalized.keys) {
13521
- ids[key] = `key_${counter++}`;
13608
+ ids2[key] = `key_${counter++}`;
13522
13609
  }
13523
13610
  doc.write(`const newResult = {};`);
13524
13611
  for (const key of normalized.keys) {
13525
- const id = ids[key];
13612
+ const id = ids2[key];
13526
13613
  const k = esc(key);
13527
13614
  const schema = shape[key];
13528
13615
  const isOptionalIn = schema?._zod?.optin === "optional";
@@ -30777,6 +30864,32 @@ function envOrUndefined(key) {
30777
30864
  if (!value || value.startsWith("${")) return void 0;
30778
30865
  return value;
30779
30866
  }
30867
+ function sanitizedEnv() {
30868
+ const result = {};
30869
+ for (const [key, value] of Object.entries(process.env)) {
30870
+ if (key === "GOG_ACCESS_TOKEN") continue;
30871
+ if (key === "GOOGLE_APPLICATION_CREDENTIALS") continue;
30872
+ if (/(_TOKEN|_SECRET|_API_KEY|_PRIVATE_KEY)$/.test(key)) continue;
30873
+ result[key] = value;
30874
+ }
30875
+ return result;
30876
+ }
30877
+ var TOKEN_PATTERNS = [
30878
+ /Bearer\s+[A-Za-z0-9._\-+/=]+/gi,
30879
+ /ya29\.[A-Za-z0-9._\-]+/g,
30880
+ // OAuth2 access tokens
30881
+ /1\/\/[A-Za-z0-9._\-]+/g,
30882
+ // OAuth2 refresh tokens
30883
+ /AIza[A-Za-z0-9_\-]{35}/g
30884
+ // Google API keys
30885
+ ];
30886
+ function redactSecrets(text) {
30887
+ let redacted = text;
30888
+ for (const re of TOKEN_PATTERNS) {
30889
+ redacted = redacted.replace(re, "[REDACTED]");
30890
+ }
30891
+ return redacted;
30892
+ }
30780
30893
  function augmentedPath() {
30781
30894
  const home = process.env.HOME;
30782
30895
  const candidates = [
@@ -30819,8 +30932,7 @@ async function run(args, options = {}) {
30819
30932
  fullArgs.push(...args);
30820
30933
  const effectiveTimeout = timeout ?? TIMEOUT_MS;
30821
30934
  return new Promise((resolve, reject) => {
30822
- const { GOG_ACCESS_TOKEN: _, ...cleanEnv } = process.env;
30823
- const childEnv = { ...cleanEnv, PATH: augmentedPath() };
30935
+ const childEnv = { ...sanitizedEnv(), PATH: augmentedPath() };
30824
30936
  const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env: childEnv });
30825
30937
  const stdoutChunks = [];
30826
30938
  const stderrChunks = [];
@@ -30849,7 +30961,7 @@ async function run(args, options = {}) {
30849
30961
  resolve(stdout);
30850
30962
  }
30851
30963
  } else {
30852
- reject(new Error(stderr || `gog exited with code ${code}`));
30964
+ reject(new Error(redactSecrets(stderr || `gog exited with code ${code}`)));
30853
30965
  }
30854
30966
  });
30855
30967
  child.on("error", (err) => {
@@ -30871,6 +30983,60 @@ async function run(args, options = {}) {
30871
30983
  var accountParam = external_exports.string().optional().describe(
30872
30984
  "Google account email to use (overrides GOG_ACCOUNT env var)"
30873
30985
  );
30986
+ var ids = {
30987
+ course: external_exports.string().describe("Course ID"),
30988
+ coursework: external_exports.string().describe("Coursework ID"),
30989
+ submission: external_exports.string().describe("Submission ID"),
30990
+ announcement: external_exports.string().describe("Announcement ID"),
30991
+ topic: external_exports.string().describe("Topic ID"),
30992
+ invitation: external_exports.string().describe("Invitation ID"),
30993
+ spreadsheet: external_exports.string().describe("Spreadsheet ID (from the URL)"),
30994
+ doc: external_exports.string().describe("Doc ID (from the URL)"),
30995
+ presentation: external_exports.string().describe("Presentation ID"),
30996
+ slide: external_exports.string().describe("Slide ID"),
30997
+ file: external_exports.string().describe("File ID"),
30998
+ message: external_exports.string().describe("Message ID"),
30999
+ thread: external_exports.string().describe("Thread ID"),
31000
+ draft: external_exports.string().describe("Draft ID"),
31001
+ label: external_exports.string().describe("Label ID or name"),
31002
+ attachment: external_exports.string().describe("Attachment ID"),
31003
+ comment: external_exports.string().describe("Comment ID"),
31004
+ meetingCode: external_exports.string().describe("Meeting code (e.g. abc-defg-hij)"),
31005
+ permission: external_exports.string().describe("Permission ID"),
31006
+ user: external_exports.string().describe("User ID"),
31007
+ // People API uses fully-qualified resource names ("people/c123") not bare IDs.
31008
+ person: external_exports.string().describe("Person resource name (people/...) or email")
31009
+ };
31010
+ var paginationParams = {
31011
+ max: external_exports.number().int().optional().describe("Max results"),
31012
+ page: external_exports.string().optional().describe("Page token"),
31013
+ all: external_exports.boolean().optional().describe("Fetch all pages")
31014
+ };
31015
+ function pushPaginationFlags(args, p) {
31016
+ if (p.max !== void 0) args.push(`--max=${p.max}`);
31017
+ if (p.page) args.push(`--page=${p.page}`);
31018
+ if (p.all) args.push("--all");
31019
+ }
31020
+ function registerRunTool(server, options) {
31021
+ const { service, examples, omitAccount = false, note } = options;
31022
+ const baseDescription = `Run any gog ${service} subcommand not covered by the other tools. Run \`gog ${service} --help\` for the full list of subcommands, or \`gog ${service} <subcommand> --help\` for flags on a specific subcommand.`;
31023
+ const description = note ? `${baseDescription} ${note}` : baseDescription;
31024
+ const inputSchema = {
31025
+ subcommand: external_exports.string().describe(`The gog ${service} subcommand to run, e.g. ${examples}`),
31026
+ args: external_exports.array(external_exports.string()).describe("Additional positional args and flags")
31027
+ };
31028
+ if (!omitAccount) {
31029
+ inputSchema.account = accountParam;
31030
+ }
31031
+ server.registerTool(`gog_${service}_run`, {
31032
+ description,
31033
+ annotations: { destructiveHint: true },
31034
+ inputSchema
31035
+ }, async (rawArgs) => {
31036
+ const { subcommand, args, account } = rawArgs;
31037
+ return runOrDiagnose([service, subcommand, ...args], { account });
31038
+ });
31039
+ }
30874
31040
  function toText(output) {
30875
31041
  return { content: [{ type: "text", text: output }] };
30876
31042
  }
@@ -30956,15 +31122,11 @@ function registerAuthTools(server) {
30956
31122
  return toError(err);
30957
31123
  }
30958
31124
  });
30959
- server.registerTool("gog_auth_run", {
30960
- description: "Run any gog auth subcommand. Run `gog auth --help` to see all available subcommands and flags. Note: for browser-based authorization, use gog_auth_add instead.",
30961
- annotations: { destructiveHint: true },
30962
- inputSchema: {
30963
- subcommand: external_exports.string().describe('The gog auth subcommand, e.g. "remove", "alias", "tokens"'),
30964
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags")
30965
- }
30966
- }, async ({ subcommand, args }) => {
30967
- return runOrDiagnose(["auth", subcommand, ...args], {});
31125
+ registerRunTool(server, {
31126
+ service: "auth",
31127
+ examples: '"remove", "alias", "tokens"',
31128
+ omitAccount: true,
31129
+ note: "For browser-based authorization, use gog_auth_add instead."
30968
31130
  });
30969
31131
  }
30970
31132
 
@@ -31075,17 +31237,7 @@ function registerCalendarTools(server) {
31075
31237
  if (comment) args.push(`--comment=${comment}`);
31076
31238
  return runOrDiagnose(args, { account });
31077
31239
  });
31078
- server.registerTool("gog_calendar_run", {
31079
- description: "Run any gog calendar subcommand not covered by the other tools. Run `gog calendar --help` for the full list of subcommands, or `gog calendar <subcommand> --help` for flags on a specific subcommand.",
31080
- annotations: { destructiveHint: true },
31081
- inputSchema: {
31082
- subcommand: external_exports.string().describe('The gog calendar subcommand to run, e.g. "calendars", "freebusy"'),
31083
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31084
- account: accountParam
31085
- }
31086
- }, async ({ subcommand, args, account }) => {
31087
- return runOrDiagnose(["calendar", subcommand, ...args], { account });
31088
- });
31240
+ registerRunTool(server, { service: "calendar", examples: '"calendars", "freebusy"' });
31089
31241
  }
31090
31242
 
31091
31243
  // src/tools/classroom.ts
@@ -31450,16 +31602,10 @@ function registerClassroomTools(server) {
31450
31602
  if (userId) args.push(userId);
31451
31603
  return runOrDiagnose(args, { account });
31452
31604
  });
31453
- server.registerTool("gog_classroom_run", {
31454
- description: "Run any gog classroom subcommand not covered by the other tools (guardians, guardian-invitations, materials, coursework assignees, announcement assignees, etc.). Run `gog classroom --help` for the full list, or `gog classroom <subcommand> --help` for flags.",
31455
- annotations: { destructiveHint: true },
31456
- inputSchema: {
31457
- subcommand: external_exports.string().describe('The gog classroom subcommand to run, e.g. "guardians", "materials", "guardian-invitations"'),
31458
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31459
- account: accountParam
31460
- }
31461
- }, async ({ subcommand, args, account }) => {
31462
- return runOrDiagnose(["classroom", subcommand, ...args], { account });
31605
+ registerRunTool(server, {
31606
+ service: "classroom",
31607
+ examples: '"guardians", "materials", "guardian-invitations"',
31608
+ note: "Covers anything not wrapped by the dedicated tools (guardians, guardian-invitations, materials, coursework assignees, announcement assignees, etc.)."
31463
31609
  });
31464
31610
  }
31465
31611
 
@@ -31515,17 +31661,7 @@ function registerContactsTools(server) {
31515
31661
  if (title) args.push(`--title=${title}`);
31516
31662
  return runOrDiagnose(args, { account });
31517
31663
  });
31518
- server.registerTool("gog_contacts_run", {
31519
- description: "Run any gog contacts subcommand not covered by the other tools. Run `gog contacts --help` for the full list of subcommands, or `gog contacts <subcommand> --help` for flags on a specific subcommand.",
31520
- annotations: { destructiveHint: true },
31521
- inputSchema: {
31522
- subcommand: external_exports.string().describe('The gog contacts subcommand to run, e.g. "update", "delete", "directory"'),
31523
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31524
- account: accountParam
31525
- }
31526
- }, async ({ subcommand, args, account }) => {
31527
- return runOrDiagnose(["contacts", subcommand, ...args], { account });
31528
- });
31664
+ registerRunTool(server, { service: "contacts", examples: '"update", "delete", "directory"' });
31529
31665
  }
31530
31666
 
31531
31667
  // src/tools/docs.ts
@@ -31595,17 +31731,7 @@ function registerDocsTools(server) {
31595
31731
  }, async ({ docId, account }) => {
31596
31732
  return runOrDiagnose(["docs", "structure", docId], { account });
31597
31733
  });
31598
- server.registerTool("gog_docs_run", {
31599
- description: "Run any gog docs subcommand not covered by the other tools. Run `gog docs --help` for the full list of subcommands, or `gog docs <subcommand> --help` for flags on a specific subcommand.",
31600
- annotations: { destructiveHint: true },
31601
- inputSchema: {
31602
- subcommand: external_exports.string().describe('The gog docs subcommand to run, e.g. "copy", "clear", "insert", "sed", "export"'),
31603
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31604
- account: accountParam
31605
- }
31606
- }, async ({ subcommand, args, account }) => {
31607
- return runOrDiagnose(["docs", subcommand, ...args], { account });
31608
- });
31734
+ registerRunTool(server, { service: "docs", examples: '"copy", "clear", "insert", "sed", "export"' });
31609
31735
  }
31610
31736
 
31611
31737
  // src/tools/drive.ts
@@ -31713,17 +31839,7 @@ function registerDriveTools(server) {
31713
31839
  if (role) args.push(`--role=${role}`);
31714
31840
  return runOrDiagnose(args, { account });
31715
31841
  });
31716
- server.registerTool("gog_drive_run", {
31717
- description: "Run any gog drive subcommand not covered by the other tools. Run `gog drive --help` for the full list of subcommands, or `gog drive <subcommand> --help` for flags on a specific subcommand.",
31718
- annotations: { destructiveHint: true },
31719
- inputSchema: {
31720
- subcommand: external_exports.string().describe('The gog drive subcommand to run, e.g. "copy", "upload", "download", "permissions"'),
31721
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31722
- account: accountParam
31723
- }
31724
- }, async ({ subcommand, args, account }) => {
31725
- return runOrDiagnose(["drive", subcommand, ...args], { account });
31726
- });
31842
+ registerRunTool(server, { service: "drive", examples: '"copy", "upload", "download", "permissions"' });
31727
31843
  }
31728
31844
 
31729
31845
  // src/tools/gmail.ts
@@ -31775,17 +31891,7 @@ function registerGmailTools(server) {
31775
31891
  if (threadId) args.push(`--thread-id=${threadId}`);
31776
31892
  return runOrDiagnose(args, { account });
31777
31893
  });
31778
- server.registerTool("gog_gmail_run", {
31779
- description: "Run any gog gmail subcommand not covered by the other tools. Run `gog gmail --help` for the full list of subcommands, or `gog gmail <subcommand> --help` for flags on a specific subcommand.",
31780
- annotations: { destructiveHint: true },
31781
- inputSchema: {
31782
- subcommand: external_exports.string().describe('The gog gmail subcommand to run, e.g. "archive", "mark-read", "labels"'),
31783
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31784
- account: accountParam
31785
- }
31786
- }, async ({ subcommand, args, account }) => {
31787
- return runOrDiagnose(["gmail", subcommand, ...args], { account });
31788
- });
31894
+ registerRunTool(server, { service: "gmail", examples: '"archive", "mark-read", "labels"' });
31789
31895
  }
31790
31896
 
31791
31897
  // src/tools/sheets.ts
@@ -31874,17 +31980,7 @@ function registerSheetsTools(server) {
31874
31980
  }, async ({ spreadsheetId, find, replace, account }) => {
31875
31981
  return runOrDiagnose(["sheets", "find-replace", spreadsheetId, find, replace], { account });
31876
31982
  });
31877
- server.registerTool("gog_sheets_run", {
31878
- description: "Run any gog sheets subcommand not covered by the other tools. Run `gog sheets --help` for the full list of subcommands, or `gog sheets <subcommand> --help` for flags on a specific subcommand.",
31879
- annotations: { destructiveHint: true },
31880
- inputSchema: {
31881
- subcommand: external_exports.string().describe('The gog sheets subcommand to run, e.g. "freeze", "add-tab", "rename-tab"'),
31882
- args: external_exports.array(external_exports.string()).describe('Additional positional args and flags, e.g. ["<spreadsheetId>", "--rows=1"]'),
31883
- account: accountParam
31884
- }
31885
- }, async ({ subcommand, args, account }) => {
31886
- return runOrDiagnose(["sheets", subcommand, ...args], { account });
31887
- });
31983
+ registerRunTool(server, { service: "sheets", examples: '"freeze", "add-tab", "rename-tab"' });
31888
31984
  }
31889
31985
 
31890
31986
  // src/tools/slides.ts
@@ -31962,17 +32058,7 @@ function registerSlidesTools(server) {
31962
32058
  }, async ({ presentationId, slideId, account }) => {
31963
32059
  return runOrDiagnose(["slides", "read-slide", presentationId, slideId], { account });
31964
32060
  });
31965
- server.registerTool("gog_slides_run", {
31966
- description: "Run any gog slides subcommand not covered by the other tools. Run `gog slides --help` for the full list of subcommands, or `gog slides <subcommand> --help` for flags on a specific subcommand.",
31967
- annotations: { destructiveHint: true },
31968
- inputSchema: {
31969
- subcommand: external_exports.string().describe("The gog slides subcommand to run"),
31970
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31971
- account: accountParam
31972
- }
31973
- }, async ({ subcommand, args, account }) => {
31974
- return runOrDiagnose(["slides", subcommand, ...args], { account });
31975
- });
32061
+ registerRunTool(server, { service: "slides", examples: '"add-slide", "delete-slide", "update-notes"' });
31976
32062
  }
31977
32063
 
31978
32064
  // src/tools/tasks.ts
@@ -32045,21 +32131,11 @@ function registerTasksTools(server) {
32045
32131
  }, async ({ tasklistId, taskId, account }) => {
32046
32132
  return runOrDiagnose(["tasks", "delete", tasklistId, taskId], { account });
32047
32133
  });
32048
- server.registerTool("gog_tasks_run", {
32049
- description: "Run any gog tasks subcommand not covered by the other tools. Run `gog tasks --help` for the full list of subcommands, or `gog tasks <subcommand> --help` for flags on a specific subcommand.",
32050
- annotations: { destructiveHint: true },
32051
- inputSchema: {
32052
- subcommand: external_exports.string().describe('The gog tasks subcommand to run, e.g. "update", "undo", "clear"'),
32053
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
32054
- account: accountParam
32055
- }
32056
- }, async ({ subcommand, args, account }) => {
32057
- return runOrDiagnose(["tasks", subcommand, ...args], { account });
32058
- });
32134
+ registerRunTool(server, { service: "tasks", examples: '"update", "undo", "clear"' });
32059
32135
  }
32060
32136
 
32061
32137
  // src/server.ts
32062
- var VERSION = true ? "2.0.8" : "0.0.0";
32138
+ var VERSION = true ? "2.0.9" : "0.0.0";
32063
32139
  function createServer(options) {
32064
32140
  return new McpServer({
32065
32141
  name: options?.name ?? "gogcli",
@@ -32085,6 +32161,9 @@ export {
32085
32161
  accountParam,
32086
32162
  createBaseServer,
32087
32163
  createServer,
32164
+ ids,
32165
+ paginationParams,
32166
+ pushPaginationFlags,
32088
32167
  registerAuthTools,
32089
32168
  registerCalendarTools,
32090
32169
  registerClassroomTools,
@@ -32092,6 +32171,7 @@ export {
32092
32171
  registerDocsTools,
32093
32172
  registerDriveTools,
32094
32173
  registerGmailTools,
32174
+ registerRunTool,
32095
32175
  registerSheetsTools,
32096
32176
  registerSlidesTools,
32097
32177
  registerTasksTools,
package/manifest.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifest_version": "0.3",
4
4
  "name": "gogcli-mcp",
5
5
  "display_name": "gogcli",
6
- "version": "2.0.8",
6
+ "version": "2.0.9",
7
7
  "description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
8
8
  "author": {
9
9
  "name": "Chris Hall",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gogcli-mcp",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "mcpName": "io.github.chrischall/gogcli-mcp",
5
5
  "description": "MCP server wrapping gogcli for Google service access",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -46,9 +46,9 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^25.6.2",
49
- "@vitest/coverage-v8": "^4.1.2",
49
+ "@vitest/coverage-v8": "^4.1.6",
50
50
  "esbuild": "^0.28.0",
51
51
  "typescript": "^6.0.2",
52
- "vitest": "^4.1.2"
52
+ "vitest": "^4.1.6"
53
53
  }
54
54
  }
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "source": "github",
8
8
  "subfolder": "packages/gogcli-mcp"
9
9
  },
10
- "version": "2.0.8",
10
+ "version": "2.0.9",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "gogcli-mcp",
15
- "version": "2.0.8",
15
+ "version": "2.0.9",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },