mcp-google-multi 5.4.1-alpha.2 → 6.0.0-alpha.2
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/README.md +21 -16
- package/dist/accounts.d.ts +44 -5
- package/dist/accounts.js +267 -25
- package/dist/auth.d.ts +11 -4
- package/dist/auth.js +85 -78
- package/dist/client-config.d.ts +90 -0
- package/dist/client-config.js +282 -0
- package/dist/client.js +10 -4
- package/dist/config-file.d.ts +38 -0
- package/dist/config-file.js +117 -0
- package/dist/discover.js +57 -3
- package/dist/doctor.d.ts +86 -0
- package/dist/doctor.js +384 -0
- package/dist/env-load.d.ts +11 -0
- package/dist/env-load.js +52 -0
- package/dist/executor.d.ts +2 -0
- package/dist/executor.js +2 -1
- package/dist/fanout.js +8 -5
- package/dist/fs-atomic.d.ts +3 -0
- package/dist/fs-atomic.js +123 -0
- package/dist/http-config.d.ts +35 -0
- package/dist/http-config.js +113 -0
- package/dist/http-transport.d.ts +59 -0
- package/dist/http-transport.js +269 -0
- package/dist/identity.d.ts +24 -0
- package/dist/identity.js +19 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +199 -18
- package/dist/master-key.d.ts +53 -0
- package/dist/master-key.js +242 -0
- package/dist/mcp-token.d.ts +81 -0
- package/dist/mcp-token.js +176 -0
- package/dist/migrate-config.d.ts +7 -0
- package/dist/migrate-config.js +103 -0
- package/dist/migrate-tokens.js +4 -3
- package/dist/net-tuning.d.ts +8 -0
- package/dist/net-tuning.js +25 -0
- package/dist/oauth-as.d.ts +52 -0
- package/dist/oauth-as.js +457 -0
- package/dist/oauth-consent.d.ts +28 -0
- package/dist/oauth-consent.js +109 -0
- package/dist/open-url.d.ts +1 -0
- package/dist/open-url.js +30 -0
- package/dist/reauth-hint.d.ts +2 -0
- package/dist/reauth-hint.js +15 -0
- package/dist/registry-transfer.d.ts +41 -0
- package/dist/registry-transfer.js +219 -0
- package/dist/registry.d.ts +27 -1
- package/dist/registry.js +117 -6
- package/dist/scope-catalog.d.ts +19 -0
- package/dist/scope-catalog.js +182 -0
- package/dist/scope-observability.d.ts +78 -0
- package/dist/scope-observability.js +192 -0
- package/dist/services.js +1 -1
- package/dist/setup-prompt.d.ts +9 -0
- package/dist/setup-prompt.js +59 -0
- package/dist/ssrf-guard.d.ts +48 -0
- package/dist/ssrf-guard.js +242 -0
- package/dist/token-store.js +23 -125
- package/dist/tools/_errors.d.ts +8 -2
- package/dist/tools/_errors.js +97 -6
- package/dist/tools/account-wizard.d.ts +33 -0
- package/dist/tools/account-wizard.js +284 -0
- package/dist/tools/accounts-tool.d.ts +8 -5
- package/dist/tools/accounts-tool.js +38 -15
- package/dist/tools/admin.js +2 -2
- package/dist/tools/calendar.js +2 -2
- package/dist/tools/chat.js +2 -2
- package/dist/tools/contacts.d.ts +40 -0
- package/dist/tools/contacts.js +135 -2
- package/dist/tools/docs.d.ts +3 -0
- package/dist/tools/docs.js +60 -9
- package/dist/tools/drive.d.ts +3 -0
- package/dist/tools/drive.js +60 -8
- package/dist/tools/forms.js +4 -2
- package/dist/tools/generated/_shared.d.ts +1 -3
- package/dist/tools/generated/_shared.js +3 -3
- package/dist/tools/generated/admin.js +175 -132
- package/dist/tools/generated/appsmarket.js +6 -2
- package/dist/tools/generated/calendar.js +45 -27
- package/dist/tools/generated/chat.js +81 -47
- package/dist/tools/generated/classroom.js +131 -104
- package/dist/tools/generated/cloudidentity.js +73 -61
- package/dist/tools/generated/cloudsearch.js +59 -49
- package/dist/tools/generated/contacts.js +22 -14
- package/dist/tools/generated/drive.js +51 -35
- package/dist/tools/generated/driveactivity.js +5 -1
- package/dist/tools/generated/drivelabels.js +30 -25
- package/dist/tools/generated/forms.js +7 -3
- package/dist/tools/generated/gmail.js +73 -58
- package/dist/tools/generated/groupsmigration.js +5 -1
- package/dist/tools/generated/groupssettings.js +7 -3
- package/dist/tools/generated/keep.js +12 -7
- package/dist/tools/generated/licensing.js +11 -7
- package/dist/tools/generated/meet.js +20 -13
- package/dist/tools/generated/postmaster.js +8 -4
- package/dist/tools/generated/reseller.js +22 -17
- package/dist/tools/generated/script.js +26 -16
- package/dist/tools/generated/sheets.js +11 -7
- package/dist/tools/generated/tasks.js +6 -2
- package/dist/tools/generated/vault.js +38 -33
- package/dist/tools/generated/workspaceevents.js +12 -7
- package/dist/tools/gmail-mime.d.ts +38 -8
- package/dist/tools/gmail-mime.js +75 -71
- package/dist/tools/gmail.d.ts +31 -0
- package/dist/tools/gmail.js +483 -99
- package/dist/tools/google-api.js +7 -4
- package/dist/tools/meet.js +2 -2
- package/dist/tools/searchconsole.js +2 -2
- package/dist/tools/sheets.js +6 -2
- package/dist/tools/slides.js +4 -2
- package/dist/tools/tasks.js +2 -2
- package/dist/types.d.ts +1 -1
- package/dist/write-control.d.ts +24 -1
- package/dist/write-control.js +26 -1
- package/package.json +26 -7
package/dist/tools/docs.js
CHANGED
|
@@ -1,11 +1,54 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceBoolean, coerceJson } from './_coerce.js';
|
|
3
3
|
import { docs as docsClient } from '@googleapis/docs';
|
|
4
|
-
import {
|
|
4
|
+
import { accountAliasSchema } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError } from './_errors.js';
|
|
7
7
|
import { capText } from '../trim.js';
|
|
8
|
-
const accountEnum =
|
|
8
|
+
const accountEnum = accountAliasSchema.optional();
|
|
9
|
+
// A single very large insertText has been observed to apply only partially while
|
|
10
|
+
// the request still returns success, silently dropping the tail. Split a large
|
|
11
|
+
// insert into bounded pieces sent as sequential insertText requests in one atomic
|
|
12
|
+
// batchUpdate: small inserts keep the exact single-request path, and a large one
|
|
13
|
+
// can no longer be silently truncated. Docs indices are UTF-16 code units (= JS
|
|
14
|
+
// string length), so index math advances by `.length`; never split a surrogate pair.
|
|
15
|
+
export const DOCS_INSERT_CHUNK = 5000;
|
|
16
|
+
export function splitInsertText(text, maxLen = DOCS_INSERT_CHUNK) {
|
|
17
|
+
if (text.length === 0)
|
|
18
|
+
return [];
|
|
19
|
+
if (text.length <= maxLen)
|
|
20
|
+
return [text];
|
|
21
|
+
const chunks = [];
|
|
22
|
+
let i = 0;
|
|
23
|
+
while (i < text.length) {
|
|
24
|
+
let end = Math.min(i + maxLen, text.length);
|
|
25
|
+
if (end < text.length) {
|
|
26
|
+
const code = text.charCodeAt(end - 1);
|
|
27
|
+
if (code >= 0xd800 && code <= 0xdbff)
|
|
28
|
+
end -= 1; // keep a surrogate pair together
|
|
29
|
+
}
|
|
30
|
+
chunks.push(text.slice(i, end));
|
|
31
|
+
i = end;
|
|
32
|
+
}
|
|
33
|
+
return chunks;
|
|
34
|
+
}
|
|
35
|
+
// Sequential insertText requests: appends chain at end-of-segment; index inserts
|
|
36
|
+
// advance the cursor by each prior chunk's length so the pieces stay contiguous.
|
|
37
|
+
export function buildInsertRequests(text, index) {
|
|
38
|
+
const chunks = splitInsertText(text);
|
|
39
|
+
const requests = [];
|
|
40
|
+
let cursor = index;
|
|
41
|
+
for (const chunk of chunks) {
|
|
42
|
+
if (cursor === undefined) {
|
|
43
|
+
requests.push({ insertText: { text: chunk, endOfSegmentLocation: { segmentId: '' } } });
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
requests.push({ insertText: { text: chunk, location: { index: cursor } } });
|
|
47
|
+
cursor += chunk.length;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return requests;
|
|
51
|
+
}
|
|
9
52
|
function extractPlainText(body) {
|
|
10
53
|
return extractPlainTextInRange(body, 0, Infinity);
|
|
11
54
|
}
|
|
@@ -304,21 +347,23 @@ export function registerDocsTools(server) {
|
|
|
304
347
|
try {
|
|
305
348
|
const auth = await getClient(account);
|
|
306
349
|
const docs = docsClient({ version: 'v1', auth });
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
350
|
+
const requests = buildInsertRequests(text, index);
|
|
351
|
+
if (requests.length === 0) {
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
354
|
+
documentId, insertedAt: index ?? 'end', inserted: 0,
|
|
355
|
+
}, null, 2) }],
|
|
356
|
+
};
|
|
313
357
|
}
|
|
314
358
|
const res = await docs.documents.batchUpdate({
|
|
315
359
|
documentId,
|
|
316
|
-
requestBody: { requests
|
|
360
|
+
requestBody: { requests },
|
|
317
361
|
});
|
|
318
362
|
return {
|
|
319
363
|
content: [{ type: 'text', text: JSON.stringify({
|
|
320
364
|
documentId: res.data.documentId,
|
|
321
365
|
insertedAt: index ?? 'end',
|
|
366
|
+
inserted: text.length,
|
|
322
367
|
}, null, 2) }],
|
|
323
368
|
};
|
|
324
369
|
}
|
|
@@ -327,6 +372,8 @@ export function registerDocsTools(server) {
|
|
|
327
372
|
}
|
|
328
373
|
});
|
|
329
374
|
server.registerTool('docs_replace_text', {
|
|
375
|
+
// Insert/append-capable or non-convergent: a retry duplicates content.
|
|
376
|
+
annotations: { idempotentHint: false },
|
|
330
377
|
description: 'Find and replace all occurrences of text in a document',
|
|
331
378
|
inputSchema: {
|
|
332
379
|
account: accountEnum.describe('Google account alias'),
|
|
@@ -978,6 +1025,8 @@ export function registerDocsTools(server) {
|
|
|
978
1025
|
});
|
|
979
1026
|
// ─── Table mutations (one tool with operation discriminator) ───────────
|
|
980
1027
|
server.registerTool('docs_modify_table', {
|
|
1028
|
+
// Insert/append-capable or non-convergent: a retry duplicates content.
|
|
1029
|
+
annotations: { idempotentHint: false },
|
|
981
1030
|
description: 'Mutate a table by operation: insertRow, insertColumn, deleteRow, deleteColumn, mergeCells, unmergeCells. Locate the cell with tableStartIndex (the table\'s start index in the doc) plus rowIndex/columnIndex (0-based).',
|
|
982
1031
|
inputSchema: {
|
|
983
1032
|
account: accountEnum.describe('Google account alias'),
|
|
@@ -1156,6 +1205,8 @@ export function registerDocsTools(server) {
|
|
|
1156
1205
|
});
|
|
1157
1206
|
// ─── Batch update escape hatch ─────────────────────────────────────────
|
|
1158
1207
|
server.registerTool('docs_batch_update', {
|
|
1208
|
+
// Insert/append-capable or non-convergent: a retry duplicates content.
|
|
1209
|
+
annotations: { idempotentHint: false },
|
|
1159
1210
|
description: 'Generic documents.batchUpdate pass-through. Accepts the full Request union (40 types). See https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request',
|
|
1160
1211
|
inputSchema: {
|
|
1161
1212
|
account: accountEnum.describe('Google account alias'),
|
package/dist/tools/drive.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
2
|
export declare function prepareLocalDest(savePath: string, filename: string): string;
|
|
3
|
+
export declare const DRIVE_QUERY_HINT: string;
|
|
4
|
+
export declare function normalizeDriveQuery(raw: string): string;
|
|
5
|
+
export declare function isDriveInvalidQuery(error: any): boolean;
|
|
3
6
|
export declare function resolveShareNotification(opts: {
|
|
4
7
|
type: string;
|
|
5
8
|
role: string;
|
package/dist/tools/drive.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceArray, coerceBoolean } from './_coerce.js';
|
|
3
3
|
import { drive as driveClient } from '@googleapis/drive';
|
|
4
|
-
import {
|
|
4
|
+
import { accountAliasSchema, getAccountSet } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError } from './_errors.js';
|
|
7
7
|
import { isAllowed, writeDisabledResult } from '../write-control.js';
|
|
@@ -12,7 +12,10 @@ import * as os from 'os';
|
|
|
12
12
|
import * as crypto from 'crypto';
|
|
13
13
|
import { pipeline } from 'node:stream/promises';
|
|
14
14
|
import mime from 'mime-types';
|
|
15
|
-
const accountEnum =
|
|
15
|
+
const accountEnum = accountAliasSchema.optional();
|
|
16
|
+
// drive_transfer's two-account form is the sanctioned schema exception and
|
|
17
|
+
// stays REQUIRED: omission must fail at the schema, not as a runtime riddle.
|
|
18
|
+
const requiredAccountEnum = accountAliasSchema;
|
|
16
19
|
const MAX_FILE_SIZE = 2 * 1024 * 1024; // 2MB
|
|
17
20
|
const FALLBACK_MAX_BYTES = 1024 * 1024 * 1024; // 1GB
|
|
18
21
|
const GOOGLE_WORKSPACE_TYPES = new Set([
|
|
@@ -34,6 +37,41 @@ export function prepareLocalDest(savePath, filename) {
|
|
|
34
37
|
fs.mkdirSync(savePath, { recursive: true });
|
|
35
38
|
return dest;
|
|
36
39
|
}
|
|
40
|
+
export const DRIVE_QUERY_HINT = "Drive search syntax: a plain keyword is treated as a full-text search, but a " +
|
|
41
|
+
"structured query needs an operator, e.g. \"name contains 'report'\", " +
|
|
42
|
+
"\"mimeType = 'application/pdf'\", or \"'me' in owners\". " +
|
|
43
|
+
'Reference: https://developers.google.com/drive/api/guides/search-files';
|
|
44
|
+
// A bare keyword is not valid Drive `q` syntax (Google 400s "Invalid Value"), yet
|
|
45
|
+
// it is the natural thing to pass to a "search" tool, so wrap it as a full-text
|
|
46
|
+
// match. A query already carrying a comparison operator or a quoted literal is a
|
|
47
|
+
// structured query and is passed through untouched.
|
|
48
|
+
export function normalizeDriveQuery(raw) {
|
|
49
|
+
const q = raw.trim();
|
|
50
|
+
if (q === '')
|
|
51
|
+
return q;
|
|
52
|
+
// Structured iff it carries a comparison operator or the membership form
|
|
53
|
+
// "<value> in (parents|owners|writers|readers)". A bare apostrophe does NOT
|
|
54
|
+
// count (names like O'Brien are keywords, not query syntax).
|
|
55
|
+
const hasComparison = /(\bcontains\b|!=|<=|>=|[=<>])/i.test(q);
|
|
56
|
+
const hasMembership = /\bin\s+(parents|owners|writers|readers)\b/i.test(q);
|
|
57
|
+
if (hasComparison || hasMembership)
|
|
58
|
+
return q;
|
|
59
|
+
const escaped = q.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
60
|
+
return `fullText contains '${escaped}'`;
|
|
61
|
+
}
|
|
62
|
+
// Drive rejects a malformed query with HTTP 400 / reason "invalid" and the opaque
|
|
63
|
+
// message "Invalid Value"; detect that so drive_search returns query-syntax help
|
|
64
|
+
// instead of a generic upstream_error.
|
|
65
|
+
export function isDriveInvalidQuery(error) {
|
|
66
|
+
const raw = error?.code ?? error?.status ?? error?.response?.status;
|
|
67
|
+
const status = typeof raw === 'string' ? Number(raw) : raw;
|
|
68
|
+
if (status !== 400)
|
|
69
|
+
return false;
|
|
70
|
+
const reason = error?.errors?.[0]?.reason ??
|
|
71
|
+
error?.response?.data?.error?.errors?.[0]?.reason;
|
|
72
|
+
const message = error?.response?.data?.error?.message ?? error?.message ?? '';
|
|
73
|
+
return reason === 'invalid' || reason === 'invalidQuery' || /invalid value/i.test(String(message));
|
|
74
|
+
}
|
|
37
75
|
// sendNotificationEmail is only valid for user/group permissions, and Google forbids
|
|
38
76
|
// disabling it on an ownership transfer. Returns undefined to omit the param entirely.
|
|
39
77
|
export function resolveShareNotification(opts) {
|
|
@@ -46,10 +84,10 @@ export function resolveShareNotification(opts) {
|
|
|
46
84
|
export function registerDriveTools(server) {
|
|
47
85
|
// ─── Read / search / list ──────────────────────────────────────────────
|
|
48
86
|
server.registerTool('drive_search', {
|
|
49
|
-
description: 'Search files in a Google Drive account',
|
|
87
|
+
description: 'Search files in a Google Drive account. A plain keyword is treated as a full-text search; pass Drive query syntax for a structured search.',
|
|
50
88
|
inputSchema: {
|
|
51
89
|
account: accountEnum.describe('Google account alias'),
|
|
52
|
-
query: z.string().describe('
|
|
90
|
+
query: z.string().describe('A plain keyword (full-text search) or Drive query syntax, e.g. "name contains \'MoU\'"'),
|
|
53
91
|
maxResults: z.number().min(1).max(100).default(20).optional()
|
|
54
92
|
.describe('Max results to return (default: 20)'),
|
|
55
93
|
driveId: z.string().optional().describe('Optional shared drive ID'),
|
|
@@ -59,7 +97,7 @@ export function registerDriveTools(server) {
|
|
|
59
97
|
const auth = await getClient(account);
|
|
60
98
|
const drive = driveClient({ version: 'v3', auth });
|
|
61
99
|
const params = {
|
|
62
|
-
q: query,
|
|
100
|
+
q: normalizeDriveQuery(query),
|
|
63
101
|
pageSize: maxResults ?? 20,
|
|
64
102
|
fields: 'files(id,name,mimeType,modifiedTime,webViewLink,size,parents,driveId)',
|
|
65
103
|
supportsAllDrives: true,
|
|
@@ -75,10 +113,24 @@ export function registerDriveTools(server) {
|
|
|
75
113
|
};
|
|
76
114
|
}
|
|
77
115
|
catch (error) {
|
|
116
|
+
if (isDriveInvalidQuery(error)) {
|
|
117
|
+
const message = error?.response?.data?.error?.message ?? error?.message ?? 'Invalid Value';
|
|
118
|
+
return {
|
|
119
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
120
|
+
error: 'invalid_query',
|
|
121
|
+
message,
|
|
122
|
+
hint: DRIVE_QUERY_HINT,
|
|
123
|
+
retriable: false,
|
|
124
|
+
account,
|
|
125
|
+
}) }],
|
|
126
|
+
isError: true,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
78
129
|
return handleDriveError(error, account);
|
|
79
130
|
}
|
|
80
131
|
});
|
|
81
132
|
server.registerTool('drive_read', {
|
|
133
|
+
_meta: { 'anthropic/maxResultSizeChars': 100_000 },
|
|
82
134
|
description: 'Read the content of a Google Drive file (returns up to maxChars characters per call; non-Google-native files over 2MB return too_large)',
|
|
83
135
|
inputSchema: {
|
|
84
136
|
account: accountEnum.describe('Google account alias'),
|
|
@@ -1095,8 +1147,8 @@ export function registerDriveTools(server) {
|
|
|
1095
1147
|
'revision history, and permissions do not transfer. move=true trashes the source after a ' +
|
|
1096
1148
|
'successful copy and requires deletes to be allowed by write-control.',
|
|
1097
1149
|
inputSchema: {
|
|
1098
|
-
fromAccount:
|
|
1099
|
-
toAccount:
|
|
1150
|
+
fromAccount: requiredAccountEnum.describe('Source account alias'),
|
|
1151
|
+
toAccount: requiredAccountEnum.describe('Target account alias'),
|
|
1100
1152
|
fileId: z.string().describe('File ID in the source account (folders are not supported)'),
|
|
1101
1153
|
parentFolderId: z.string().optional().describe('Target folder ID (default: target My Drive root)'),
|
|
1102
1154
|
newName: z.string().optional().describe('Rename the copy (default: keep the source name)'),
|
|
@@ -1150,7 +1202,7 @@ export function registerDriveTools(server) {
|
|
|
1150
1202
|
};
|
|
1151
1203
|
}
|
|
1152
1204
|
const intendedName = newName ?? meta.data.name ?? 'transferred-file';
|
|
1153
|
-
const targetEmail =
|
|
1205
|
+
const targetEmail = getAccountSet().configs[toAccount].email;
|
|
1154
1206
|
const finish = async (data, strategy, flags) => {
|
|
1155
1207
|
let moveFailed = false;
|
|
1156
1208
|
let moveSkipped = false;
|
package/dist/tools/forms.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { forms as formsClient } from '@googleapis/forms';
|
|
3
|
-
import {
|
|
3
|
+
import { accountAliasSchema } from '../accounts.js';
|
|
4
4
|
import { getClient } from '../client.js';
|
|
5
5
|
import { handleGoogleApiError } from './_errors.js';
|
|
6
6
|
import { coerceArray, coerceBoolean, coerceJson } from './_coerce.js';
|
|
7
|
-
const accountEnum =
|
|
7
|
+
const accountEnum = accountAliasSchema.optional();
|
|
8
8
|
export function registerFormsTools(server) {
|
|
9
9
|
server.registerTool('forms_get', {
|
|
10
10
|
description: 'Get a Google Form (definition: questions, sections, settings). Requires forms.body scope.',
|
|
@@ -119,6 +119,8 @@ export function registerFormsTools(server) {
|
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
server.registerTool('forms_batch_update', {
|
|
122
|
+
// Insert/append-capable or non-convergent: a retry duplicates content.
|
|
123
|
+
annotations: { idempotentHint: false },
|
|
122
124
|
description: 'Generic forms.batchUpdate pass-through: add/edit/delete questions, update form info and settings. See https://developers.google.com/workspace/forms/api/reference/rest/v1/forms/request',
|
|
123
125
|
inputSchema: {
|
|
124
126
|
account: accountEnum.describe('Google account alias'),
|
|
@@ -15,7 +15,5 @@ export interface GeneratedToolDef {
|
|
|
15
15
|
hasBody: boolean;
|
|
16
16
|
shape: z.ZodRawShape;
|
|
17
17
|
}
|
|
18
|
-
export declare function accountField(): z.
|
|
19
|
-
[x: string]: string;
|
|
20
|
-
}>;
|
|
18
|
+
export declare function accountField(): z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
|
|
21
19
|
export declare function registerGeneratedTool(registry: ToolRegistry, def: GeneratedToolDef, deps?: ExecuteDeps): void;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ACCOUNTS } from '../../accounts.js';
|
|
1
|
+
import { accountAliasSchema } from '../../accounts.js';
|
|
3
2
|
import { executeApiMethod } from '../../executor.js';
|
|
4
3
|
export function accountField() {
|
|
5
|
-
return
|
|
4
|
+
return accountAliasSchema.optional().describe('Google account alias (omit for the default account)');
|
|
6
5
|
}
|
|
7
6
|
export function registerGeneratedTool(registry, def, deps = {}) {
|
|
8
7
|
// Widened locally: `cud` is a registry extension the SDK config type doesn't
|
|
@@ -13,6 +12,7 @@ export function registerGeneratedTool(registry, def, deps = {}) {
|
|
|
13
12
|
inputSchema: def.shape,
|
|
14
13
|
cud: def.cud,
|
|
15
14
|
annotations: { openWorldHint: true },
|
|
15
|
+
requiredScopes: def.method.scopes,
|
|
16
16
|
}, async (args) => {
|
|
17
17
|
const pathParams = {};
|
|
18
18
|
const queryParams = {};
|