gogcli-mcp-docs 2.27.1 → 2.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +86 -8
- package/manifest.json +1 -1
- package/mint.yaml +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/src/tools/docs-extra.ts +1 -1
- package/tests/tools/docs-extra.test.ts +13 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "Extended Google Docs for Claude via gogcli — auth + full Docs and comments support",
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.29.0"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"displayName": "gogcli (Docs)",
|
|
16
16
|
"source": "./",
|
|
17
17
|
"description": "Extended Google Docs for Claude via gogcli — auth + full Docs and comments support",
|
|
18
|
-
"version": "2.
|
|
18
|
+
"version": "2.29.0",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
package/dist/index.js
CHANGED
|
@@ -31323,6 +31323,56 @@ function redactSecrets(text) {
|
|
|
31323
31323
|
return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
|
|
31324
31324
|
}
|
|
31325
31325
|
|
|
31326
|
+
// ../../node_modules/@chrischall/mcp-utils/dist/response/view.js
|
|
31327
|
+
function minifiedResult(data) {
|
|
31328
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
31329
|
+
}
|
|
31330
|
+
|
|
31331
|
+
// ../../node_modules/@chrischall/mcp-utils/dist/response/media.js
|
|
31332
|
+
var MEDIA_NOUN = "(?:avatar|tall_avatar|cover_photo|cover_image|picture|photo|thumbnail|thumb|image|icon|banner|profile_pic(?:ture)?|logo)";
|
|
31333
|
+
var MEDIA_KEY = new RegExp(`^${MEDIA_NOUN}s?(?:(?:link|uri|url)s?)?$`, "i");
|
|
31334
|
+
var MEDIA_URL = /^https?:\/\/[^\s]+?\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)([?#]|$)/i;
|
|
31335
|
+
function stripMediaUrls(value, opts = {}) {
|
|
31336
|
+
const keep = new Set((opts.keep ?? []).map((k) => k.toLowerCase()));
|
|
31337
|
+
const drop = (opts.drop ?? []).map((rule) => typeof rule === "string" ? rule.toLowerCase() : new RegExp(rule.source, rule.flags));
|
|
31338
|
+
return walk(value, keep, drop);
|
|
31339
|
+
}
|
|
31340
|
+
function alsoDrop(key, drop) {
|
|
31341
|
+
const lower = key.toLowerCase();
|
|
31342
|
+
for (const rule of drop) {
|
|
31343
|
+
if (typeof rule === "string") {
|
|
31344
|
+
if (rule === lower)
|
|
31345
|
+
return true;
|
|
31346
|
+
continue;
|
|
31347
|
+
}
|
|
31348
|
+
rule.lastIndex = 0;
|
|
31349
|
+
if (rule.test(key))
|
|
31350
|
+
return true;
|
|
31351
|
+
}
|
|
31352
|
+
return false;
|
|
31353
|
+
}
|
|
31354
|
+
function walk(value, keep, drop) {
|
|
31355
|
+
if (Array.isArray(value))
|
|
31356
|
+
return value.map((v) => walk(v, keep, drop));
|
|
31357
|
+
if (value === null || typeof value !== "object")
|
|
31358
|
+
return value;
|
|
31359
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
|
|
31360
|
+
return value;
|
|
31361
|
+
const out = {};
|
|
31362
|
+
for (const [key, v] of Object.entries(value)) {
|
|
31363
|
+
if (keep.has(key.toLowerCase())) {
|
|
31364
|
+
out[key] = v;
|
|
31365
|
+
continue;
|
|
31366
|
+
}
|
|
31367
|
+
if (MEDIA_KEY.test(key) || alsoDrop(key, drop))
|
|
31368
|
+
continue;
|
|
31369
|
+
if (typeof v === "string" && MEDIA_URL.test(v))
|
|
31370
|
+
continue;
|
|
31371
|
+
out[key] = walk(v, keep, drop);
|
|
31372
|
+
}
|
|
31373
|
+
return out;
|
|
31374
|
+
}
|
|
31375
|
+
|
|
31326
31376
|
// ../../node_modules/@chrischall/mcp-utils/dist/response/index.js
|
|
31327
31377
|
function rawTextResult(text) {
|
|
31328
31378
|
return { content: [{ type: "text", text }] };
|
|
@@ -31842,11 +31892,11 @@ function parseTimestampValue(key, value, assumeNaiveIn) {
|
|
|
31842
31892
|
}
|
|
31843
31893
|
return null;
|
|
31844
31894
|
}
|
|
31845
|
-
function
|
|
31895
|
+
function walk2(node, tz, naiveTz) {
|
|
31846
31896
|
let changed = false;
|
|
31847
31897
|
if (Array.isArray(node)) {
|
|
31848
31898
|
for (const item of node) {
|
|
31849
|
-
if (
|
|
31899
|
+
if (walk2(item, tz, naiveTz)) changed = true;
|
|
31850
31900
|
}
|
|
31851
31901
|
return changed;
|
|
31852
31902
|
}
|
|
@@ -31855,7 +31905,7 @@ function walk(node, tz, naiveTz) {
|
|
|
31855
31905
|
for (const key of Object.keys(obj)) {
|
|
31856
31906
|
const value = obj[key];
|
|
31857
31907
|
if (value !== null && typeof value === "object") {
|
|
31858
|
-
if (
|
|
31908
|
+
if (walk2(value, tz, naiveTz)) changed = true;
|
|
31859
31909
|
continue;
|
|
31860
31910
|
}
|
|
31861
31911
|
if (ZONE_NAME_KEYS.has(key) || !TIMESTAMP_KEYS.has(key)) continue;
|
|
@@ -31881,7 +31931,7 @@ function normalizeTimestamps(text, tz = displayTimeZone(), naiveTz = naiveSource
|
|
|
31881
31931
|
} catch {
|
|
31882
31932
|
return text;
|
|
31883
31933
|
}
|
|
31884
|
-
if (!
|
|
31934
|
+
if (!walk2(parsed, tz, naiveTz)) return text;
|
|
31885
31935
|
return JSON.stringify(parsed, null, detectIndent(text));
|
|
31886
31936
|
}
|
|
31887
31937
|
|
|
@@ -32030,10 +32080,38 @@ ${accounts || "(none)"}${hint}`);
|
|
|
32030
32080
|
return errorResult(`${errText}${hint}`);
|
|
32031
32081
|
}
|
|
32032
32082
|
}
|
|
32083
|
+
function minifiedOrRawText(text, stripMedia = false) {
|
|
32084
|
+
const trimmed = text.trim();
|
|
32085
|
+
if (trimmed === "" || !/^[[{]/.test(trimmed)) return rawTextResult(text);
|
|
32086
|
+
try {
|
|
32087
|
+
const parsed = JSON.parse(trimmed);
|
|
32088
|
+
return minifiedResult(stripMedia ? stripMediaUrls(parsed) : parsed);
|
|
32089
|
+
} catch {
|
|
32090
|
+
return rawTextResult(text);
|
|
32091
|
+
}
|
|
32092
|
+
}
|
|
32093
|
+
function isRejectedFieldMask(err) {
|
|
32094
|
+
return /invalidParameter|invalid field selection/i.test(String(err));
|
|
32095
|
+
}
|
|
32096
|
+
async function runProjected(args, options) {
|
|
32097
|
+
const { fieldsMask } = options;
|
|
32098
|
+
if (!fieldsMask) return run(args, options);
|
|
32099
|
+
try {
|
|
32100
|
+
return await run([...args, `--fields=${fieldsMask}`], options);
|
|
32101
|
+
} catch (err) {
|
|
32102
|
+
if (!isRejectedFieldMask(err)) throw err;
|
|
32103
|
+
process.stderr.write(
|
|
32104
|
+
`gogcli-mcp: Google rejected the compact field mask (${fieldsMask}); retrying unprojected
|
|
32105
|
+
`
|
|
32106
|
+
);
|
|
32107
|
+
return run(args, options);
|
|
32108
|
+
}
|
|
32109
|
+
}
|
|
32033
32110
|
async function runOrDiagnose(args, options) {
|
|
32034
32111
|
try {
|
|
32035
|
-
const raw = await
|
|
32036
|
-
|
|
32112
|
+
const raw = await runProjected(args, options);
|
|
32113
|
+
if (options.lossless) return rawTextResult(raw);
|
|
32114
|
+
return minifiedOrRawText(stripConsumedPageToken(normalizeTimestamps(raw)), options.stripMedia);
|
|
32037
32115
|
} catch (err) {
|
|
32038
32116
|
return diagnose(err);
|
|
32039
32117
|
}
|
|
@@ -32372,7 +32450,7 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
|
|
|
32372
32450
|
);
|
|
32373
32451
|
|
|
32374
32452
|
// ../gogcli-mcp/src/server.ts
|
|
32375
|
-
var VERSION = true ? "2.
|
|
32453
|
+
var VERSION = true ? "2.29.0" : "0.0.0";
|
|
32376
32454
|
|
|
32377
32455
|
// ../gogcli-mcp/src/auth-log.ts
|
|
32378
32456
|
var FAILURES = /* @__PURE__ */ new Set([
|
|
@@ -33666,7 +33744,7 @@ function registerExtraDocsTools(server) {
|
|
|
33666
33744
|
inputSchema: {
|
|
33667
33745
|
docId: external_exports.string().describe("Doc ID (from the URL)"),
|
|
33668
33746
|
layout: external_exports.enum(["pageless", "pages"]).optional().describe("Page layout (default: pageless)"),
|
|
33669
|
-
pageSize: external_exports.enum(["A4", "A5", "Letter", "Legal", "Tabloid"]).optional().describe("Named page size preset (only applies in paged layout)"),
|
|
33747
|
+
pageSize: external_exports.enum(["A3", "A4", "A5", "Letter", "Legal", "Tabloid"]).optional().describe("Named page size preset (only applies in paged layout)"),
|
|
33670
33748
|
pageWidth: external_exports.string().optional().describe('Page width (points by default; supports pt, in, cm, mm \u2014 e.g. "8.5in")'),
|
|
33671
33749
|
pageHeight: external_exports.string().optional().describe("Page height (points by default; supports pt, in, cm, mm)"),
|
|
33672
33750
|
marginTop: external_exports.string().optional().describe("Top page margin (points by default; supports pt, in, cm, mm)"),
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-docs",
|
|
5
5
|
"display_name": "gogcli (Docs)",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.29.0",
|
|
7
7
|
"description": "Extended Google Docs for Claude via gogcli — auth + full Docs and comments support",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
package/mint.yaml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-docs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.29.0",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-docs",
|
|
5
5
|
"description": "Extended Google Docs MCP server via gogcli — all base tools plus full Docs support",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"test:coverage": "vitest run --coverage"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@chrischall/mcp-utils": "^0.
|
|
27
|
+
"@chrischall/mcp-utils": "^0.23.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
29
29
|
"zod": "^4.4.3"
|
|
30
30
|
},
|
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"source": "github",
|
|
8
8
|
"subfolder": "packages/gogcli-mcp-docs"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.29.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "gogcli-mcp-docs",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.29.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|
package/src/tools/docs-extra.ts
CHANGED
|
@@ -897,7 +897,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
897
897
|
inputSchema: {
|
|
898
898
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
899
899
|
layout: z.enum(['pageless', 'pages']).optional().describe('Page layout (default: pageless)'),
|
|
900
|
-
pageSize: z.enum(['A4', 'A5', 'Letter', 'Legal', 'Tabloid']).optional().describe('Named page size preset (only applies in paged layout)'),
|
|
900
|
+
pageSize: z.enum(['A3', 'A4', 'A5', 'Letter', 'Legal', 'Tabloid']).optional().describe('Named page size preset (only applies in paged layout)'),
|
|
901
901
|
pageWidth: z.string().optional().describe('Page width (points by default; supports pt, in, cm, mm — e.g. "8.5in")'),
|
|
902
902
|
pageHeight: z.string().optional().describe('Page height (points by default; supports pt, in, cm, mm)'),
|
|
903
903
|
marginTop: z.string().optional().describe('Top page margin (points by default; supports pt, in, cm, mm)'),
|
|
@@ -1050,6 +1050,19 @@ describe('gog_docs_page_layout', () => {
|
|
|
1050
1050
|
{ account: undefined },
|
|
1051
1051
|
);
|
|
1052
1052
|
});
|
|
1053
|
+
|
|
1054
|
+
// A3 joined the preset list in gog 0.39.0. The enum is the only gate — a
|
|
1055
|
+
// value it rejects never reaches gog, so a missing preset is a tool that
|
|
1056
|
+
// cannot do something the binary underneath it can.
|
|
1057
|
+
it('accepts the A3 preset (gog >= 0.39.0)', async () => {
|
|
1058
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1059
|
+
const harness = await setupHandlers();
|
|
1060
|
+
await harness.callTool('gog_docs_page_layout', { docId: 'd1', pageSize: 'A3' });
|
|
1061
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1062
|
+
['docs', 'page-layout', 'd1', '--page-size=A3'],
|
|
1063
|
+
{ account: undefined },
|
|
1064
|
+
);
|
|
1065
|
+
});
|
|
1053
1066
|
});
|
|
1054
1067
|
|
|
1055
1068
|
describe('gog_docs_cell_update', () => {
|