gogcli-mcp-contacts 2.23.1 → 2.24.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/dist/index.js +85 -40
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/src/tools/contacts-extra.ts +21 -13
package/dist/index.js
CHANGED
|
@@ -31542,6 +31542,26 @@ function normalizeTimestamps(text, tz = displayTimeZone(), naiveTz = naiveSource
|
|
|
31542
31542
|
return JSON.stringify(parsed, null, detectIndent(text));
|
|
31543
31543
|
}
|
|
31544
31544
|
|
|
31545
|
+
// ../gogcli-mcp/src/pagination.ts
|
|
31546
|
+
function detectIndent2(text) {
|
|
31547
|
+
const match = /\n(\s+)\S/.exec(text);
|
|
31548
|
+
return match ? match[1].replace(/\t/g, " ").length : 0;
|
|
31549
|
+
}
|
|
31550
|
+
function stripConsumedPageToken(text) {
|
|
31551
|
+
const trimmed = text.trim();
|
|
31552
|
+
if (trimmed === "" || !trimmed.startsWith("{")) return text;
|
|
31553
|
+
let parsed;
|
|
31554
|
+
try {
|
|
31555
|
+
parsed = JSON.parse(trimmed);
|
|
31556
|
+
} catch {
|
|
31557
|
+
return text;
|
|
31558
|
+
}
|
|
31559
|
+
const obj = parsed;
|
|
31560
|
+
if (obj.nextPageToken !== "") return text;
|
|
31561
|
+
delete obj.nextPageToken;
|
|
31562
|
+
return JSON.stringify(obj, null, detectIndent2(text));
|
|
31563
|
+
}
|
|
31564
|
+
|
|
31545
31565
|
// ../gogcli-mcp/src/tools/utils.ts
|
|
31546
31566
|
var accountParam = external_exports.string().optional().describe(
|
|
31547
31567
|
"Google account email to use, e.g. you@gmail.com \u2014 must be the full address, not a bare username. Overrides the GOG_ACCOUNT env var. Omit to use the single configured account."
|
|
@@ -31570,9 +31590,19 @@ var ids = {
|
|
|
31570
31590
|
// People API uses fully-qualified resource names ("people/c123") not bare IDs.
|
|
31571
31591
|
person: external_exports.string().describe("Person resource name (people/...) or email")
|
|
31572
31592
|
};
|
|
31593
|
+
var pageTokenParam = external_exports.string().optional().describe(
|
|
31594
|
+
"Cursor for the NEXT page. Pass back the nextPageToken from a previous response verbatim, keeping the query and max identical: call once, then call again with pageToken=<that value>. A response with NO nextPageToken is the last page."
|
|
31595
|
+
);
|
|
31596
|
+
var pageAliasParam = external_exports.string().optional().describe(
|
|
31597
|
+
"Deprecated alias for pageToken, accepted so existing callers keep working. Use pageToken \u2014 it matches the nextPageToken field in the response."
|
|
31598
|
+
);
|
|
31599
|
+
function resolvePageToken(p) {
|
|
31600
|
+
return p.pageToken ?? p.page;
|
|
31601
|
+
}
|
|
31573
31602
|
var paginationParams = {
|
|
31574
31603
|
max: external_exports.number().int().optional().describe("Max results"),
|
|
31575
|
-
|
|
31604
|
+
pageToken: pageTokenParam,
|
|
31605
|
+
page: pageAliasParam,
|
|
31576
31606
|
all: external_exports.boolean().optional().describe("Fetch all pages")
|
|
31577
31607
|
};
|
|
31578
31608
|
function registerRunTool(server, options) {
|
|
@@ -31647,7 +31677,7 @@ ${accounts || "(none)"}${hint}`);
|
|
|
31647
31677
|
async function runOrDiagnose(args, options) {
|
|
31648
31678
|
try {
|
|
31649
31679
|
const raw = await run(args, options);
|
|
31650
|
-
return rawTextResult(options.lossless ? raw : normalizeTimestamps(raw));
|
|
31680
|
+
return rawTextResult(options.lossless ? raw : stripConsumedPageToken(normalizeTimestamps(raw)));
|
|
31651
31681
|
} catch (err) {
|
|
31652
31682
|
return diagnose(err);
|
|
31653
31683
|
}
|
|
@@ -31697,6 +31727,7 @@ function formatAuthHealth(raw, now) {
|
|
|
31697
31727
|
// ../gogcli-mcp/src/tools/auth.ts
|
|
31698
31728
|
function registerAuthToolsWith(server, defaultServices) {
|
|
31699
31729
|
const servicesDescribe = `Services to authorize: "all" or comma-separated list (e.g. "sheets,gmail,calendar"). Default: "${defaultServices}". Prefer the narrowest set you need \u2014 requesting a service whose Google API is not enabled on the OAuth client's project makes Google reject the WHOLE request with invalid_scope.`;
|
|
31730
|
+
const extraScopesDescribe = "Additional raw OAuth scope URIs to request, comma-separated, on top of the ones `services` implies. Use for scopes no service covers \u2014 e.g. https://www.googleapis.com/auth/bigquery.readonly, required before gog_sheets_datasource_* can read BigQuery-backed Connected Sheets. Leave unset otherwise: an extra scope whose API is not enabled on the OAuth client project makes Google reject the WHOLE authorization with invalid_scope.";
|
|
31700
31731
|
server.registerTool("gog_auth_list", {
|
|
31701
31732
|
description: "List the Google accounts stored in gogcli, with their scopes. This reads local configuration only \u2014 it does not contact Google and does NOT tell you whether an account still works: a signed-out account whose refresh token expired or was revoked is listed here exactly like a healthy one, scopes and all. Use gog_auth_health to check whether an account can actually authenticate.",
|
|
31702
31733
|
annotations: { readOnlyHint: true },
|
|
@@ -31746,11 +31777,14 @@ function registerAuthToolsWith(server, defaultServices) {
|
|
|
31746
31777
|
annotations: { destructiveHint: true },
|
|
31747
31778
|
inputSchema: {
|
|
31748
31779
|
email: external_exports.string().describe("Google account email to authorize"),
|
|
31749
|
-
services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe)
|
|
31780
|
+
services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe),
|
|
31781
|
+
extraScopes: external_exports.string().optional().describe(extraScopesDescribe)
|
|
31750
31782
|
}
|
|
31751
|
-
}, async ({ email: email3, services = defaultServices }) => {
|
|
31783
|
+
}, async ({ email: email3, services = defaultServices, extraScopes }) => {
|
|
31752
31784
|
try {
|
|
31753
|
-
|
|
31785
|
+
const args = ["auth", "add", email3, "--services", services];
|
|
31786
|
+
if (extraScopes) args.push(`--extra-scopes=${extraScopes}`, "--force-consent");
|
|
31787
|
+
return rawTextResult(await run(args, {
|
|
31754
31788
|
interactive: true,
|
|
31755
31789
|
timeout: 3e5
|
|
31756
31790
|
}));
|
|
@@ -31762,14 +31796,14 @@ function registerAuthToolsWith(server, defaultServices) {
|
|
|
31762
31796
|
description: "Begin REMOTE/headless Google authorization (step 1 of 2). Returns a sign-in URL to open in any browser \u2014 no local server or terminal on the gogcli host is needed, so this works over the hosted connector where the interactive gog_auth_add cannot. Hand the URL to the user; after they sign in, the browser is redirected to a localhost URL that fails to load \u2014 that is expected. They copy that full redirected URL (from the address bar) and you pass it to gog_auth_add_complete. The link is valid for 10 minutes. If you pass a custom `services` here, pass the SAME value to gog_auth_add_complete or the second step will not match this one.",
|
|
31763
31797
|
inputSchema: {
|
|
31764
31798
|
email: external_exports.string().describe("Google account email to authorize"),
|
|
31765
|
-
services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe)
|
|
31799
|
+
services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe),
|
|
31800
|
+
extraScopes: external_exports.string().optional().describe(`${extraScopesDescribe} Pass the SAME value to gog_auth_add_complete.`)
|
|
31766
31801
|
}
|
|
31767
|
-
}, async ({ email: email3, services = defaultServices }) => {
|
|
31802
|
+
}, async ({ email: email3, services = defaultServices, extraScopes }) => {
|
|
31768
31803
|
try {
|
|
31769
|
-
|
|
31770
|
-
|
|
31771
|
-
|
|
31772
|
-
));
|
|
31804
|
+
const args = ["auth", "add", email3, "--remote", "--step", "1", "--services", services, "--force-consent"];
|
|
31805
|
+
if (extraScopes) args.push(`--extra-scopes=${extraScopes}`);
|
|
31806
|
+
return rawTextResult(await run(args, { redactMode: "tokens" }));
|
|
31773
31807
|
} catch (err) {
|
|
31774
31808
|
return errorResult(errorText(err));
|
|
31775
31809
|
}
|
|
@@ -31784,25 +31818,28 @@ function registerAuthToolsWith(server, defaultServices) {
|
|
|
31784
31818
|
),
|
|
31785
31819
|
services: external_exports.string().optional().default(defaultServices).describe(
|
|
31786
31820
|
`Services authorized \u2014 MUST match the value passed to gog_auth_add_url. Default: "${defaultServices}".`
|
|
31821
|
+
),
|
|
31822
|
+
extraScopes: external_exports.string().optional().describe(
|
|
31823
|
+
"Extra OAuth scope URIs \u2014 MUST match the value passed to gog_auth_add_url, for the same reason `services` must: the two steps have to describe the same grant."
|
|
31787
31824
|
)
|
|
31788
31825
|
}
|
|
31789
|
-
}, async ({ email: email3, redirectUrl, services = defaultServices }) => {
|
|
31826
|
+
}, async ({ email: email3, redirectUrl, services = defaultServices, extraScopes }) => {
|
|
31790
31827
|
try {
|
|
31791
|
-
|
|
31792
|
-
|
|
31793
|
-
|
|
31794
|
-
|
|
31795
|
-
|
|
31796
|
-
|
|
31797
|
-
|
|
31798
|
-
|
|
31799
|
-
|
|
31800
|
-
|
|
31801
|
-
|
|
31802
|
-
|
|
31803
|
-
|
|
31804
|
-
|
|
31805
|
-
));
|
|
31828
|
+
const args = [
|
|
31829
|
+
"auth",
|
|
31830
|
+
"add",
|
|
31831
|
+
email3,
|
|
31832
|
+
"--remote",
|
|
31833
|
+
"--step",
|
|
31834
|
+
"2",
|
|
31835
|
+
"--auth-url",
|
|
31836
|
+
redirectUrl,
|
|
31837
|
+
"--services",
|
|
31838
|
+
services,
|
|
31839
|
+
"--force-consent"
|
|
31840
|
+
];
|
|
31841
|
+
if (extraScopes) args.push(`--extra-scopes=${extraScopes}`);
|
|
31842
|
+
return rawTextResult(await run(args));
|
|
31806
31843
|
} catch (err) {
|
|
31807
31844
|
return errorResult(errorText(err));
|
|
31808
31845
|
}
|
|
@@ -31883,7 +31920,7 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
|
|
|
31883
31920
|
);
|
|
31884
31921
|
|
|
31885
31922
|
// ../gogcli-mcp/src/server.ts
|
|
31886
|
-
var VERSION = true ? "2.
|
|
31923
|
+
var VERSION = true ? "2.24.0" : "0.0.0";
|
|
31887
31924
|
|
|
31888
31925
|
// ../gogcli-mcp/src/auth-log.ts
|
|
31889
31926
|
var FAILURES = /* @__PURE__ */ new Set([
|
|
@@ -32396,14 +32433,16 @@ function registerExtraContactsTools(server) {
|
|
|
32396
32433
|
inputSchema: {
|
|
32397
32434
|
query: external_exports.string().describe("Search query (name, email, etc.)"),
|
|
32398
32435
|
max: external_exports.number().optional().describe("Max results (default: 50)"),
|
|
32399
|
-
|
|
32436
|
+
pageToken: pageTokenParam,
|
|
32437
|
+
page: pageAliasParam,
|
|
32400
32438
|
all: external_exports.boolean().optional().describe("Fetch all pages"),
|
|
32401
32439
|
account: accountParam
|
|
32402
32440
|
}
|
|
32403
|
-
}, async ({ query, max, page, all, account }) => {
|
|
32441
|
+
}, async ({ query, max, pageToken, page, all, account }) => {
|
|
32404
32442
|
const args = ["people", "search", query];
|
|
32405
32443
|
if (max !== void 0) args.push(`--max=${max}`);
|
|
32406
|
-
|
|
32444
|
+
const token = resolvePageToken({ pageToken, page });
|
|
32445
|
+
if (token) args.push(`--page=${token}`);
|
|
32407
32446
|
if (all) args.push("--all");
|
|
32408
32447
|
return runOrDiagnose(args, { account });
|
|
32409
32448
|
});
|
|
@@ -32472,17 +32511,19 @@ function registerExtraContactsTools(server) {
|
|
|
32472
32511
|
all: external_exports.boolean().optional().describe("Export all personal contacts"),
|
|
32473
32512
|
out: external_exports.string().optional().describe("Output path (.vcf), or - for stdout (default: stdout)"),
|
|
32474
32513
|
max: external_exports.number().optional().describe("Max results for query (1-30)"),
|
|
32475
|
-
|
|
32514
|
+
pageToken: pageTokenParam,
|
|
32515
|
+
page: pageAliasParam,
|
|
32476
32516
|
account: accountParam
|
|
32477
32517
|
}
|
|
32478
|
-
}, async ({ selector, query, all, out, max, page, account }) => {
|
|
32518
|
+
}, async ({ selector, query, all, out, max, pageToken, page, account }) => {
|
|
32479
32519
|
const args = ["contacts", "export"];
|
|
32480
32520
|
if (selector) args.push(selector);
|
|
32481
32521
|
if (query) args.push(`--query=${query}`);
|
|
32482
32522
|
if (all) args.push("--all");
|
|
32483
32523
|
if (out) args.push(`--out=${out}`);
|
|
32484
32524
|
if (max !== void 0) args.push(`--max=${max}`);
|
|
32485
|
-
|
|
32525
|
+
const token = resolvePageToken({ pageToken, page });
|
|
32526
|
+
if (token) args.push(`--page=${token}`);
|
|
32486
32527
|
return runOrDiagnose(args, { account });
|
|
32487
32528
|
});
|
|
32488
32529
|
server.registerTool("gog_contacts_dedupe", {
|
|
@@ -32511,14 +32552,16 @@ function registerExtraContactsTools(server) {
|
|
|
32511
32552
|
annotations: { readOnlyHint: true },
|
|
32512
32553
|
inputSchema: {
|
|
32513
32554
|
max: external_exports.number().optional().describe("Max results (default: 50)"),
|
|
32514
|
-
|
|
32555
|
+
pageToken: pageTokenParam,
|
|
32556
|
+
page: pageAliasParam,
|
|
32515
32557
|
all: external_exports.boolean().optional().describe("Fetch all pages"),
|
|
32516
32558
|
account: accountParam
|
|
32517
32559
|
}
|
|
32518
|
-
}, async ({ max, page, all, account }) => {
|
|
32560
|
+
}, async ({ max, pageToken, page, all, account }) => {
|
|
32519
32561
|
const args = ["contacts", "directory", "list"];
|
|
32520
32562
|
if (max !== void 0) args.push(`--max=${max}`);
|
|
32521
|
-
|
|
32563
|
+
const token = resolvePageToken({ pageToken, page });
|
|
32564
|
+
if (token) args.push(`--page=${token}`);
|
|
32522
32565
|
if (all) args.push("--all");
|
|
32523
32566
|
return runOrDiagnose(args, { account });
|
|
32524
32567
|
});
|
|
@@ -32527,14 +32570,16 @@ function registerExtraContactsTools(server) {
|
|
|
32527
32570
|
annotations: { readOnlyHint: true },
|
|
32528
32571
|
inputSchema: {
|
|
32529
32572
|
max: external_exports.number().optional().describe("Max results (default: 100)"),
|
|
32530
|
-
|
|
32573
|
+
pageToken: pageTokenParam,
|
|
32574
|
+
page: pageAliasParam,
|
|
32531
32575
|
all: external_exports.boolean().optional().describe("Fetch all pages"),
|
|
32532
32576
|
account: accountParam
|
|
32533
32577
|
}
|
|
32534
|
-
}, async ({ max, page, all, account }) => {
|
|
32578
|
+
}, async ({ max, pageToken, page, all, account }) => {
|
|
32535
32579
|
const args = ["contacts", "other", "list"];
|
|
32536
32580
|
if (max !== void 0) args.push(`--max=${max}`);
|
|
32537
|
-
|
|
32581
|
+
const token = resolvePageToken({ pageToken, page });
|
|
32582
|
+
if (token) args.push(`--page=${token}`);
|
|
32538
32583
|
if (all) args.push("--all");
|
|
32539
32584
|
return runOrDiagnose(args, { account });
|
|
32540
32585
|
});
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-contacts",
|
|
5
5
|
"display_name": "gogcli (Contacts)",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.24.0",
|
|
7
7
|
"description": "Extended Google Contacts for Claude via gogcli — auth + Contacts + Workspace directory (People API)",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-contacts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.24.0",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-contacts",
|
|
5
5
|
"description": "Extended Google Contacts + People MCP server via gogcli — auth + Contacts + Workspace directory (People API)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { accountParam, runOrDiagnose } from '../../../gogcli-mcp/src/lib.js';
|
|
3
|
+
import { accountParam, runOrDiagnose, pageTokenParam, pageAliasParam, resolvePageToken} from '../../../gogcli-mcp/src/lib.js';
|
|
4
4
|
|
|
5
5
|
// People is the richer API behind Google Contacts: Workspace directory
|
|
6
6
|
// search, profile fields, and relations.
|
|
@@ -32,14 +32,16 @@ export function registerExtraContactsTools(server: McpServer): void {
|
|
|
32
32
|
inputSchema: {
|
|
33
33
|
query: z.string().describe('Search query (name, email, etc.)'),
|
|
34
34
|
max: z.number().optional().describe('Max results (default: 50)'),
|
|
35
|
-
|
|
35
|
+
pageToken: pageTokenParam,
|
|
36
|
+
page: pageAliasParam,
|
|
36
37
|
all: z.boolean().optional().describe('Fetch all pages'),
|
|
37
38
|
account: accountParam,
|
|
38
39
|
},
|
|
39
|
-
}, async ({ query, max, page, all, account }) => {
|
|
40
|
+
}, async ({ query, max, pageToken, page, all, account }) => {
|
|
40
41
|
const args = ['people', 'search', query];
|
|
41
42
|
if (max !== undefined) args.push(`--max=${max}`);
|
|
42
|
-
|
|
43
|
+
const token = resolvePageToken({ pageToken, page });
|
|
44
|
+
if (token) args.push(`--page=${token}`);
|
|
43
45
|
if (all) args.push('--all');
|
|
44
46
|
return runOrDiagnose(args, { account });
|
|
45
47
|
});
|
|
@@ -112,17 +114,19 @@ export function registerExtraContactsTools(server: McpServer): void {
|
|
|
112
114
|
all: z.boolean().optional().describe('Export all personal contacts'),
|
|
113
115
|
out: z.string().optional().describe('Output path (.vcf), or - for stdout (default: stdout)'),
|
|
114
116
|
max: z.number().optional().describe('Max results for query (1-30)'),
|
|
115
|
-
|
|
117
|
+
pageToken: pageTokenParam,
|
|
118
|
+
page: pageAliasParam,
|
|
116
119
|
account: accountParam,
|
|
117
120
|
},
|
|
118
|
-
}, async ({ selector, query, all, out, max, page, account }) => {
|
|
121
|
+
}, async ({ selector, query, all, out, max, pageToken, page, account }) => {
|
|
119
122
|
const args = ['contacts', 'export'];
|
|
120
123
|
if (selector) args.push(selector);
|
|
121
124
|
if (query) args.push(`--query=${query}`);
|
|
122
125
|
if (all) args.push('--all');
|
|
123
126
|
if (out) args.push(`--out=${out}`);
|
|
124
127
|
if (max !== undefined) args.push(`--max=${max}`);
|
|
125
|
-
|
|
128
|
+
const token = resolvePageToken({ pageToken, page });
|
|
129
|
+
if (token) args.push(`--page=${token}`);
|
|
126
130
|
return runOrDiagnose(args, { account });
|
|
127
131
|
});
|
|
128
132
|
|
|
@@ -153,14 +157,16 @@ export function registerExtraContactsTools(server: McpServer): void {
|
|
|
153
157
|
annotations: { readOnlyHint: true },
|
|
154
158
|
inputSchema: {
|
|
155
159
|
max: z.number().optional().describe('Max results (default: 50)'),
|
|
156
|
-
|
|
160
|
+
pageToken: pageTokenParam,
|
|
161
|
+
page: pageAliasParam,
|
|
157
162
|
all: z.boolean().optional().describe('Fetch all pages'),
|
|
158
163
|
account: accountParam,
|
|
159
164
|
},
|
|
160
|
-
}, async ({ max, page, all, account }) => {
|
|
165
|
+
}, async ({ max, pageToken, page, all, account }) => {
|
|
161
166
|
const args = ['contacts', 'directory', 'list'];
|
|
162
167
|
if (max !== undefined) args.push(`--max=${max}`);
|
|
163
|
-
|
|
168
|
+
const token = resolvePageToken({ pageToken, page });
|
|
169
|
+
if (token) args.push(`--page=${token}`);
|
|
164
170
|
if (all) args.push('--all');
|
|
165
171
|
return runOrDiagnose(args, { account });
|
|
166
172
|
});
|
|
@@ -170,14 +176,16 @@ export function registerExtraContactsTools(server: McpServer): void {
|
|
|
170
176
|
annotations: { readOnlyHint: true },
|
|
171
177
|
inputSchema: {
|
|
172
178
|
max: z.number().optional().describe('Max results (default: 100)'),
|
|
173
|
-
|
|
179
|
+
pageToken: pageTokenParam,
|
|
180
|
+
page: pageAliasParam,
|
|
174
181
|
all: z.boolean().optional().describe('Fetch all pages'),
|
|
175
182
|
account: accountParam,
|
|
176
183
|
},
|
|
177
|
-
}, async ({ max, page, all, account }) => {
|
|
184
|
+
}, async ({ max, pageToken, page, all, account }) => {
|
|
178
185
|
const args = ['contacts', 'other', 'list'];
|
|
179
186
|
if (max !== undefined) args.push(`--max=${max}`);
|
|
180
|
-
|
|
187
|
+
const token = resolvePageToken({ pageToken, page });
|
|
188
|
+
if (token) args.push(`--page=${token}`);
|
|
181
189
|
if (all) args.push('--all');
|
|
182
190
|
return runOrDiagnose(args, { account });
|
|
183
191
|
});
|