gogcli-mcp 2.0.7 → 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,
@@ -12044,8 +12131,8 @@ function emoji() {
12044
12131
  }
12045
12132
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
12046
12133
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
12047
- var mac = (delimiter) => {
12048
- const escapedDelim = escapeRegex(delimiter ?? ":");
12134
+ var mac = (delimiter2) => {
12135
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
12049
12136
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
12050
12137
  };
12051
12138
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -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";
@@ -30770,12 +30857,60 @@ var EMPTY_COMPLETION_RESULT = {
30770
30857
 
30771
30858
  // src/runner.ts
30772
30859
  import { spawn } from "node:child_process";
30860
+ import { delimiter } from "node:path";
30773
30861
  var TIMEOUT_MS = 3e4;
30774
30862
  function envOrUndefined(key) {
30775
30863
  const value = process.env[key];
30776
30864
  if (!value || value.startsWith("${")) return void 0;
30777
30865
  return value;
30778
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
+ }
30893
+ function augmentedPath() {
30894
+ const home = process.env.HOME;
30895
+ const candidates = [
30896
+ process.env.PATH ?? "",
30897
+ "/opt/homebrew/bin",
30898
+ "/usr/local/bin",
30899
+ home ? `${home}/.local/bin` : "",
30900
+ home ? `${home}/go/bin` : ""
30901
+ ];
30902
+ const seen = /* @__PURE__ */ new Set();
30903
+ const parts = [];
30904
+ for (const c of candidates) {
30905
+ if (!c) continue;
30906
+ for (const dir of c.split(delimiter)) {
30907
+ if (!dir || seen.has(dir)) continue;
30908
+ seen.add(dir);
30909
+ parts.push(dir);
30910
+ }
30911
+ }
30912
+ return parts.join(delimiter);
30913
+ }
30779
30914
  function formatTimeout(ms) {
30780
30915
  const seconds = Math.round(ms / 1e3);
30781
30916
  if (seconds >= 60) {
@@ -30797,8 +30932,8 @@ async function run(args, options = {}) {
30797
30932
  fullArgs.push(...args);
30798
30933
  const effectiveTimeout = timeout ?? TIMEOUT_MS;
30799
30934
  return new Promise((resolve, reject) => {
30800
- const { GOG_ACCESS_TOKEN: _, ...cleanEnv } = process.env;
30801
- const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env: cleanEnv });
30935
+ const childEnv = { ...sanitizedEnv(), PATH: augmentedPath() };
30936
+ const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env: childEnv });
30802
30937
  const stdoutChunks = [];
30803
30938
  const stderrChunks = [];
30804
30939
  let settled = false;
@@ -30826,13 +30961,19 @@ async function run(args, options = {}) {
30826
30961
  resolve(stdout);
30827
30962
  }
30828
30963
  } else {
30829
- reject(new Error(stderr || `gog exited with code ${code}`));
30964
+ reject(new Error(redactSecrets(stderr || `gog exited with code ${code}`)));
30830
30965
  }
30831
30966
  });
30832
30967
  child.on("error", (err) => {
30833
30968
  clearTimeout(timer);
30834
30969
  if (settled) return;
30835
30970
  settled = true;
30971
+ if (err.code === "ENOENT") {
30972
+ reject(new Error(
30973
+ "gog executable not found. Install gogcli (https://github.com/steipete/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
30974
+ ));
30975
+ return;
30976
+ }
30836
30977
  reject(err);
30837
30978
  });
30838
30979
  });
@@ -30842,6 +30983,60 @@ async function run(args, options = {}) {
30842
30983
  var accountParam = external_exports.string().optional().describe(
30843
30984
  "Google account email to use (overrides GOG_ACCOUNT env var)"
30844
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
+ }
30845
31040
  function toText(output) {
30846
31041
  return { content: [{ type: "text", text: output }] };
30847
31042
  }
@@ -30927,15 +31122,11 @@ function registerAuthTools(server) {
30927
31122
  return toError(err);
30928
31123
  }
30929
31124
  });
30930
- server.registerTool("gog_auth_run", {
30931
- 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.",
30932
- annotations: { destructiveHint: true },
30933
- inputSchema: {
30934
- subcommand: external_exports.string().describe('The gog auth subcommand, e.g. "remove", "alias", "tokens"'),
30935
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags")
30936
- }
30937
- }, async ({ subcommand, args }) => {
30938
- 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."
30939
31130
  });
30940
31131
  }
30941
31132
 
@@ -31046,17 +31237,7 @@ function registerCalendarTools(server) {
31046
31237
  if (comment) args.push(`--comment=${comment}`);
31047
31238
  return runOrDiagnose(args, { account });
31048
31239
  });
31049
- server.registerTool("gog_calendar_run", {
31050
- 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.",
31051
- annotations: { destructiveHint: true },
31052
- inputSchema: {
31053
- subcommand: external_exports.string().describe('The gog calendar subcommand to run, e.g. "calendars", "freebusy"'),
31054
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31055
- account: accountParam
31056
- }
31057
- }, async ({ subcommand, args, account }) => {
31058
- return runOrDiagnose(["calendar", subcommand, ...args], { account });
31059
- });
31240
+ registerRunTool(server, { service: "calendar", examples: '"calendars", "freebusy"' });
31060
31241
  }
31061
31242
 
31062
31243
  // src/tools/classroom.ts
@@ -31421,16 +31602,10 @@ function registerClassroomTools(server) {
31421
31602
  if (userId) args.push(userId);
31422
31603
  return runOrDiagnose(args, { account });
31423
31604
  });
31424
- server.registerTool("gog_classroom_run", {
31425
- 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.",
31426
- annotations: { destructiveHint: true },
31427
- inputSchema: {
31428
- subcommand: external_exports.string().describe('The gog classroom subcommand to run, e.g. "guardians", "materials", "guardian-invitations"'),
31429
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31430
- account: accountParam
31431
- }
31432
- }, async ({ subcommand, args, account }) => {
31433
- 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.)."
31434
31609
  });
31435
31610
  }
31436
31611
 
@@ -31486,17 +31661,7 @@ function registerContactsTools(server) {
31486
31661
  if (title) args.push(`--title=${title}`);
31487
31662
  return runOrDiagnose(args, { account });
31488
31663
  });
31489
- server.registerTool("gog_contacts_run", {
31490
- 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.",
31491
- annotations: { destructiveHint: true },
31492
- inputSchema: {
31493
- subcommand: external_exports.string().describe('The gog contacts subcommand to run, e.g. "update", "delete", "directory"'),
31494
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31495
- account: accountParam
31496
- }
31497
- }, async ({ subcommand, args, account }) => {
31498
- return runOrDiagnose(["contacts", subcommand, ...args], { account });
31499
- });
31664
+ registerRunTool(server, { service: "contacts", examples: '"update", "delete", "directory"' });
31500
31665
  }
31501
31666
 
31502
31667
  // src/tools/docs.ts
@@ -31566,17 +31731,7 @@ function registerDocsTools(server) {
31566
31731
  }, async ({ docId, account }) => {
31567
31732
  return runOrDiagnose(["docs", "structure", docId], { account });
31568
31733
  });
31569
- server.registerTool("gog_docs_run", {
31570
- 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.",
31571
- annotations: { destructiveHint: true },
31572
- inputSchema: {
31573
- subcommand: external_exports.string().describe('The gog docs subcommand to run, e.g. "copy", "clear", "insert", "sed", "export"'),
31574
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31575
- account: accountParam
31576
- }
31577
- }, async ({ subcommand, args, account }) => {
31578
- return runOrDiagnose(["docs", subcommand, ...args], { account });
31579
- });
31734
+ registerRunTool(server, { service: "docs", examples: '"copy", "clear", "insert", "sed", "export"' });
31580
31735
  }
31581
31736
 
31582
31737
  // src/tools/drive.ts
@@ -31684,17 +31839,7 @@ function registerDriveTools(server) {
31684
31839
  if (role) args.push(`--role=${role}`);
31685
31840
  return runOrDiagnose(args, { account });
31686
31841
  });
31687
- server.registerTool("gog_drive_run", {
31688
- 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.",
31689
- annotations: { destructiveHint: true },
31690
- inputSchema: {
31691
- subcommand: external_exports.string().describe('The gog drive subcommand to run, e.g. "copy", "upload", "download", "permissions"'),
31692
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31693
- account: accountParam
31694
- }
31695
- }, async ({ subcommand, args, account }) => {
31696
- return runOrDiagnose(["drive", subcommand, ...args], { account });
31697
- });
31842
+ registerRunTool(server, { service: "drive", examples: '"copy", "upload", "download", "permissions"' });
31698
31843
  }
31699
31844
 
31700
31845
  // src/tools/gmail.ts
@@ -31746,17 +31891,7 @@ function registerGmailTools(server) {
31746
31891
  if (threadId) args.push(`--thread-id=${threadId}`);
31747
31892
  return runOrDiagnose(args, { account });
31748
31893
  });
31749
- server.registerTool("gog_gmail_run", {
31750
- 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.",
31751
- annotations: { destructiveHint: true },
31752
- inputSchema: {
31753
- subcommand: external_exports.string().describe('The gog gmail subcommand to run, e.g. "archive", "mark-read", "labels"'),
31754
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31755
- account: accountParam
31756
- }
31757
- }, async ({ subcommand, args, account }) => {
31758
- return runOrDiagnose(["gmail", subcommand, ...args], { account });
31759
- });
31894
+ registerRunTool(server, { service: "gmail", examples: '"archive", "mark-read", "labels"' });
31760
31895
  }
31761
31896
 
31762
31897
  // src/tools/sheets.ts
@@ -31845,17 +31980,7 @@ function registerSheetsTools(server) {
31845
31980
  }, async ({ spreadsheetId, find, replace, account }) => {
31846
31981
  return runOrDiagnose(["sheets", "find-replace", spreadsheetId, find, replace], { account });
31847
31982
  });
31848
- server.registerTool("gog_sheets_run", {
31849
- 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.",
31850
- annotations: { destructiveHint: true },
31851
- inputSchema: {
31852
- subcommand: external_exports.string().describe('The gog sheets subcommand to run, e.g. "freeze", "add-tab", "rename-tab"'),
31853
- args: external_exports.array(external_exports.string()).describe('Additional positional args and flags, e.g. ["<spreadsheetId>", "--rows=1"]'),
31854
- account: accountParam
31855
- }
31856
- }, async ({ subcommand, args, account }) => {
31857
- return runOrDiagnose(["sheets", subcommand, ...args], { account });
31858
- });
31983
+ registerRunTool(server, { service: "sheets", examples: '"freeze", "add-tab", "rename-tab"' });
31859
31984
  }
31860
31985
 
31861
31986
  // src/tools/slides.ts
@@ -31933,17 +32058,7 @@ function registerSlidesTools(server) {
31933
32058
  }, async ({ presentationId, slideId, account }) => {
31934
32059
  return runOrDiagnose(["slides", "read-slide", presentationId, slideId], { account });
31935
32060
  });
31936
- server.registerTool("gog_slides_run", {
31937
- 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.",
31938
- annotations: { destructiveHint: true },
31939
- inputSchema: {
31940
- subcommand: external_exports.string().describe("The gog slides subcommand to run"),
31941
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
31942
- account: accountParam
31943
- }
31944
- }, async ({ subcommand, args, account }) => {
31945
- return runOrDiagnose(["slides", subcommand, ...args], { account });
31946
- });
32061
+ registerRunTool(server, { service: "slides", examples: '"add-slide", "delete-slide", "update-notes"' });
31947
32062
  }
31948
32063
 
31949
32064
  // src/tools/tasks.ts
@@ -32016,21 +32131,11 @@ function registerTasksTools(server) {
32016
32131
  }, async ({ tasklistId, taskId, account }) => {
32017
32132
  return runOrDiagnose(["tasks", "delete", tasklistId, taskId], { account });
32018
32133
  });
32019
- server.registerTool("gog_tasks_run", {
32020
- 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.",
32021
- annotations: { destructiveHint: true },
32022
- inputSchema: {
32023
- subcommand: external_exports.string().describe('The gog tasks subcommand to run, e.g. "update", "undo", "clear"'),
32024
- args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
32025
- account: accountParam
32026
- }
32027
- }, async ({ subcommand, args, account }) => {
32028
- return runOrDiagnose(["tasks", subcommand, ...args], { account });
32029
- });
32134
+ registerRunTool(server, { service: "tasks", examples: '"update", "undo", "clear"' });
32030
32135
  }
32031
32136
 
32032
32137
  // src/server.ts
32033
- var VERSION = true ? "2.0.7" : "0.0.0";
32138
+ var VERSION = true ? "2.0.9" : "0.0.0";
32034
32139
  function createServer(options) {
32035
32140
  return new McpServer({
32036
32141
  name: options?.name ?? "gogcli",
@@ -32056,6 +32161,9 @@ export {
32056
32161
  accountParam,
32057
32162
  createBaseServer,
32058
32163
  createServer,
32164
+ ids,
32165
+ paginationParams,
32166
+ pushPaginationFlags,
32059
32167
  registerAuthTools,
32060
32168
  registerCalendarTools,
32061
32169
  registerClassroomTools,
@@ -32063,6 +32171,7 @@ export {
32063
32171
  registerDocsTools,
32064
32172
  registerDriveTools,
32065
32173
  registerGmailTools,
32174
+ registerRunTool,
32066
32175
  registerSheetsTools,
32067
32176
  registerSlidesTools,
32068
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.7",
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",