gogcli-mcp 2.0.6 → 2.0.7

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.
@@ -6,16 +6,16 @@
6
6
  "email": "chris.c.hall@gmail.com"
7
7
  },
8
8
  "metadata": {
9
- "description": "Google Sheets (and more) for Claude via gogcli \u2014 read, write, and manage spreadsheets",
10
- "version": "2.0.3"
9
+ "description": "Google Sheets (and more) for Claude via gogcli read, write, and manage spreadsheets",
10
+ "version": "2.0.7"
11
11
  },
12
12
  "plugins": [
13
13
  {
14
14
  "name": "gogcli-mcp",
15
15
  "displayName": "gogcli",
16
16
  "source": "./",
17
- "description": "Google Sheets (and more) for Claude via gogcli \u2014 read, write, and manage spreadsheets",
18
- "version": "2.0.3",
17
+ "description": "Google Sheets (and more) for Claude via gogcli read, write, and manage spreadsheets",
18
+ "version": "2.0.7",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "gogcli-mcp",
3
3
  "displayName": "gogcli",
4
- "version": "2.0.3",
5
- "description": "Google Sheets (and more) for Claude via gogcli \u2014 read, write, and manage spreadsheets",
4
+ "version": "2.0.7",
5
+ "description": "Google Sheets (and more) for Claude via gogcli read, write, and manage spreadsheets",
6
6
  "author": {
7
7
  "name": "Chris Hall",
8
8
  "email": "chris.c.hall@gmail.com"
package/dist/index.js CHANGED
@@ -30864,6 +30864,11 @@ var EMPTY_COMPLETION_RESULT = {
30864
30864
  // src/runner.ts
30865
30865
  import { spawn } from "node:child_process";
30866
30866
  var TIMEOUT_MS = 3e4;
30867
+ function envOrUndefined(key) {
30868
+ const value = process.env[key];
30869
+ if (!value || value.startsWith("${")) return void 0;
30870
+ return value;
30871
+ }
30867
30872
  function formatTimeout(ms) {
30868
30873
  const seconds = Math.round(ms / 1e3);
30869
30874
  if (seconds >= 60) {
@@ -30874,7 +30879,7 @@ function formatTimeout(ms) {
30874
30879
  }
30875
30880
  async function run(args, options = {}) {
30876
30881
  const { account, spawner = spawn, interactive = false, timeout } = options;
30877
- const effectiveAccount = account ?? process.env.GOG_ACCOUNT;
30882
+ const effectiveAccount = account ?? envOrUndefined("GOG_ACCOUNT");
30878
30883
  const fullArgs = ["--json", "--color=never"];
30879
30884
  if (!interactive) {
30880
30885
  fullArgs.push("--no-input");
@@ -30886,7 +30891,7 @@ async function run(args, options = {}) {
30886
30891
  const effectiveTimeout = timeout ?? TIMEOUT_MS;
30887
30892
  return new Promise((resolve, reject) => {
30888
30893
  const { GOG_ACCESS_TOKEN: _, ...cleanEnv } = process.env;
30889
- const child = spawner(process.env.GOG_PATH ?? "gog", fullArgs, { env: cleanEnv });
30894
+ const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env: cleanEnv });
30890
30895
  const stdoutChunks = [];
30891
30896
  const stderrChunks = [];
30892
30897
  let settled = false;
@@ -32118,7 +32123,7 @@ function registerTasksTools(server2) {
32118
32123
  }
32119
32124
 
32120
32125
  // src/server.ts
32121
- var VERSION = true ? "2.0.5" : "0.0.0";
32126
+ var VERSION = true ? "2.0.7" : "0.0.0";
32122
32127
  function createServer(options) {
32123
32128
  return new McpServer({
32124
32129
  name: options?.name ?? "gogcli",
package/dist/lib.js CHANGED
@@ -30771,6 +30771,11 @@ var EMPTY_COMPLETION_RESULT = {
30771
30771
  // src/runner.ts
30772
30772
  import { spawn } from "node:child_process";
30773
30773
  var TIMEOUT_MS = 3e4;
30774
+ function envOrUndefined(key) {
30775
+ const value = process.env[key];
30776
+ if (!value || value.startsWith("${")) return void 0;
30777
+ return value;
30778
+ }
30774
30779
  function formatTimeout(ms) {
30775
30780
  const seconds = Math.round(ms / 1e3);
30776
30781
  if (seconds >= 60) {
@@ -30781,7 +30786,7 @@ function formatTimeout(ms) {
30781
30786
  }
30782
30787
  async function run(args, options = {}) {
30783
30788
  const { account, spawner = spawn, interactive = false, timeout } = options;
30784
- const effectiveAccount = account ?? process.env.GOG_ACCOUNT;
30789
+ const effectiveAccount = account ?? envOrUndefined("GOG_ACCOUNT");
30785
30790
  const fullArgs = ["--json", "--color=never"];
30786
30791
  if (!interactive) {
30787
30792
  fullArgs.push("--no-input");
@@ -30793,7 +30798,7 @@ async function run(args, options = {}) {
30793
30798
  const effectiveTimeout = timeout ?? TIMEOUT_MS;
30794
30799
  return new Promise((resolve, reject) => {
30795
30800
  const { GOG_ACCESS_TOKEN: _, ...cleanEnv } = process.env;
30796
- const child = spawner(process.env.GOG_PATH ?? "gog", fullArgs, { env: cleanEnv });
30801
+ const child = spawner(envOrUndefined("GOG_PATH") ?? "gog", fullArgs, { env: cleanEnv });
30797
30802
  const stdoutChunks = [];
30798
30803
  const stderrChunks = [];
30799
30804
  let settled = false;
@@ -32025,7 +32030,7 @@ function registerTasksTools(server) {
32025
32030
  }
32026
32031
 
32027
32032
  // src/server.ts
32028
- var VERSION = true ? "2.0.5" : "0.0.0";
32033
+ var VERSION = true ? "2.0.7" : "0.0.0";
32029
32034
  function createServer(options) {
32030
32035
  return new McpServer({
32031
32036
  name: options?.name ?? "gogcli",
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",
6
+ "version": "2.0.7",
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.6",
3
+ "version": "2.0.7",
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>",
package/server.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.chrischall/gogcli-mcp",
4
- "description": "Google Sheets (and more) for Claude via gogcli \u2014 read, write, and manage spreadsheets",
4
+ "description": "Google Sheets (and more) for Claude via gogcli read, write, and manage spreadsheets",
5
5
  "repository": {
6
6
  "url": "https://github.com/chrischall/gogcli-mcp",
7
7
  "source": "github",
8
8
  "subfolder": "packages/gogcli-mcp"
9
9
  },
10
- "version": "2.0.3",
10
+ "version": "2.0.7",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "gogcli-mcp",
15
- "version": "2.0.3",
15
+ "version": "2.0.7",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
package/src/runner.ts CHANGED
@@ -16,6 +16,16 @@ export interface RunOptions {
16
16
 
17
17
  const TIMEOUT_MS = 30_000;
18
18
 
19
+ // Treat unresolved .mcpb placeholders ("${user_config.gog_path}") and empty
20
+ // strings the same as an unset env var. When an optional .mcpb user_config
21
+ // field is left blank, some clients pass the literal placeholder text through
22
+ // to the spawned server instead of substituting "" or omitting the key.
23
+ function envOrUndefined(key: string): string | undefined {
24
+ const value = process.env[key];
25
+ if (!value || value.startsWith('${')) return undefined;
26
+ return value;
27
+ }
28
+
19
29
  function formatTimeout(ms: number): string {
20
30
  const seconds = Math.round(ms / 1000);
21
31
  if (seconds >= 60) {
@@ -28,7 +38,7 @@ function formatTimeout(ms: number): string {
28
38
  export async function run(args: string[], options: RunOptions = {}): Promise<string> {
29
39
  const { account, spawner = spawn as unknown as Spawner, interactive = false, timeout } = options;
30
40
 
31
- const effectiveAccount = account ?? process.env.GOG_ACCOUNT;
41
+ const effectiveAccount = account ?? envOrUndefined('GOG_ACCOUNT');
32
42
 
33
43
  const fullArgs = ['--json', '--color=never'];
34
44
  if (!interactive) {
@@ -45,10 +55,7 @@ export async function run(args: string[], options: RunOptions = {}): Promise<str
45
55
  // Strip GOG_ACCESS_TOKEN so gogcli uses stored refresh tokens instead of
46
56
  // a potentially stale direct access token passed through MCP env config.
47
57
  const { GOG_ACCESS_TOKEN: _, ...cleanEnv } = process.env;
48
- // Use `||` (not `??`) so an empty-string GOG_PATH common when the .mcpb
49
- // user_config "gog_path" is left blank and substituted as "" — falls back
50
- // to PATH lookup instead of trying to spawn an empty executable name.
51
- const child = spawner(process.env.GOG_PATH || 'gog', fullArgs, { env: cleanEnv });
58
+ const child = spawner(envOrUndefined('GOG_PATH') ?? 'gog', fullArgs, { env: cleanEnv });
52
59
  const stdoutChunks: Buffer[] = [];
53
60
  const stderrChunks: Buffer[] = [];
54
61
  let settled = false;
@@ -143,6 +143,39 @@ describe('run', () => {
143
143
  }
144
144
  });
145
145
 
146
+ it('falls back to "gog" on PATH when GOG_PATH is an unresolved .mcpb placeholder', async () => {
147
+ const spawner = makeSpawner(0, '{}');
148
+ const originalEnv = process.env.GOG_PATH;
149
+ process.env.GOG_PATH = '${user_config.gog_path}';
150
+ try {
151
+ await run(['sheets', 'metadata', 'id1'], { spawner });
152
+ expect(spawner).toHaveBeenCalledWith('gog', expect.any(Array), expect.any(Object));
153
+ } finally {
154
+ if (originalEnv === undefined) {
155
+ delete process.env.GOG_PATH;
156
+ } else {
157
+ process.env.GOG_PATH = originalEnv;
158
+ }
159
+ }
160
+ });
161
+
162
+ it('omits --account when GOG_ACCOUNT is an unresolved .mcpb placeholder', async () => {
163
+ const spawner = makeSpawner(0, '{}');
164
+ const originalEnv = process.env.GOG_ACCOUNT;
165
+ process.env.GOG_ACCOUNT = '${user_config.gog_account}';
166
+ try {
167
+ await run(['sheets', 'metadata', 'id1'], { spawner });
168
+ const callArgs = (spawner as ReturnType<typeof vi.fn>).mock.calls[0][1] as string[];
169
+ expect(callArgs).not.toContain('--account');
170
+ } finally {
171
+ if (originalEnv === undefined) {
172
+ delete process.env.GOG_ACCOUNT;
173
+ } else {
174
+ process.env.GOG_ACCOUNT = originalEnv;
175
+ }
176
+ }
177
+ });
178
+
146
179
  it('returns stdout on exit code 0', async () => {
147
180
  const spawner = makeSpawner(0, '{"values":[["hello"]]}');
148
181
  const result = await run(['sheets', 'get', 'id1', 'A1'], { spawner });
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/lib.d.ts DELETED
@@ -1,6 +0,0 @@
1
- export { createBaseServer, VERSION } from './server.js';
2
- export { run } from './runner.js';
3
- export type { RunOptions, Spawner } from './runner.js';
4
- export { accountParam, runOrDiagnose, toText, toError } from './tools/utils.js';
5
- export type { ToolResult } from './tools/utils.js';
6
- //# sourceMappingURL=lib.d.ts.map
package/dist/lib.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/runner.d.ts DELETED
@@ -1,12 +0,0 @@
1
- import type { ChildProcess } from 'node:child_process';
2
- export type Spawner = (command: string, args: string[], options: {
3
- env: NodeJS.ProcessEnv;
4
- }) => ChildProcess;
5
- export interface RunOptions {
6
- account?: string;
7
- spawner?: Spawner;
8
- interactive?: boolean;
9
- timeout?: number;
10
- }
11
- export declare function run(args: string[], options?: RunOptions): Promise<string>;
12
- //# sourceMappingURL=runner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChC,YAAY,CAAC;AAElB,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DnF"}
package/dist/server.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare const VERSION: string;
3
- export declare function createBaseServer(options?: {
4
- name?: string;
5
- version?: string;
6
- }): McpServer;
7
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE,eAAO,MAAM,OAAO,QAAmE,CAAC;AAExF,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAgBzF"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerAuthTools(server: McpServer): void;
3
- //# sourceMappingURL=auth.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwEzD"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerCalendarTools(server: McpServer): void;
3
- //# sourceMappingURL=calendar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/tools/calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2H7D"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerContactsTools(server: McpServer): void;
3
- //# sourceMappingURL=contacts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/tools/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkE7D"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerDocsTools(server: McpServer): void;
3
- //# sourceMappingURL=docs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/tools/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoGzD"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerDriveTools(server: McpServer): void;
3
- //# sourceMappingURL=drive.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../src/tools/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgH1D"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerGmailTools(server: McpServer): void;
3
- //# sourceMappingURL=gmail.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gmail.d.ts","sourceRoot":"","sources":["../../src/tools/gmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D1D"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerSheetsTools(server: McpServer): void;
3
- //# sourceMappingURL=sheets.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sheets.d.ts","sourceRoot":"","sources":["../../src/tools/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuG3D"}
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerTasksTools(server: McpServer): void;
3
- //# sourceMappingURL=tasks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsF1D"}
@@ -1,14 +0,0 @@
1
- import { z } from 'zod';
2
- export type ToolResult = {
3
- content: [{
4
- type: 'text';
5
- text: string;
6
- }];
7
- };
8
- export declare const accountParam: z.ZodOptional<z.ZodString>;
9
- export declare function toText(output: string): ToolResult;
10
- export declare function toError(err: unknown): ToolResult;
11
- export declare function runOrDiagnose(args: string[], options: {
12
- account?: string;
13
- }): Promise<ToolResult>;
14
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAEvE,eAAO,MAAM,YAAY,4BAExB,CAAC;AAEF,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAEjD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAEhD;AAQD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,UAAU,CAAC,CAerB"}