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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +257 -157
- package/dist/lib.js +266 -157
- package/manifest.json +1 -1
- package/package.json +3 -3
- package/server.json +2 -2
- package/src/lib.ts +10 -1
- package/src/runner.ts +72 -5
- package/src/tools/auth.ts +6 -10
- package/src/tools/calendar.ts +2 -12
- package/src/tools/classroom.ts +5 -11
- package/src/tools/contacts.ts +2 -12
- package/src/tools/docs.ts +2 -12
- package/src/tools/drive.ts +2 -12
- package/src/tools/gmail.ts +2 -12
- package/src/tools/sheets.ts +2 -12
- package/src/tools/slides.ts +2 -12
- package/src/tools/tasks.ts +2 -12
- package/src/tools/utils.ts +80 -0
- package/tests/helpers/{extras-harness.ts → test-harness.ts} +4 -8
- package/tests/runner.test.ts +147 -1
- package/tests/tools/auth.test.ts +2 -13
- package/tests/tools/calendar.test.ts +2 -13
- package/tests/tools/classroom.test.ts +2 -13
- package/tests/tools/contacts.test.ts +2 -13
- package/tests/tools/docs.test.ts +2 -13
- package/tests/tools/drive.test.ts +2 -13
- package/tests/tools/gmail.test.ts +2 -13
- package/tests/tools/sheets.test.ts +2 -13
- package/tests/tools/slides.test.ts +2 -13
- package/tests/tools/tasks.test.ts +2 -13
- package/tests/tools/utils.test.ts +35 -1
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
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
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
|
-
|
|
3311
|
-
|
|
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
|
-
|
|
3314
|
-
|
|
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
|
-
|
|
3317
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
3855
|
+
parsed.path = normalizePathEncoding(parsed.path);
|
|
3795
3856
|
}
|
|
3796
3857
|
if (parsed.fragment) {
|
|
3797
|
-
|
|
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 = (
|
|
12048
|
-
const escapedDelim = escapeRegex(
|
|
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
|
|
13605
|
+
const ids2 = /* @__PURE__ */ Object.create(null);
|
|
13519
13606
|
let counter = 0;
|
|
13520
13607
|
for (const key of normalized.keys) {
|
|
13521
|
-
|
|
13608
|
+
ids2[key] = `key_${counter++}`;
|
|
13522
13609
|
}
|
|
13523
13610
|
doc.write(`const newResult = {};`);
|
|
13524
13611
|
for (const key of normalized.keys) {
|
|
13525
|
-
const id =
|
|
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
|
|
30801
|
-
const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env:
|
|
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
|
|
30931
|
-
|
|
30932
|
-
|
|
30933
|
-
|
|
30934
|
-
|
|
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
|
|
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
|
|
31425
|
-
|
|
31426
|
-
|
|
31427
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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",
|