mcp-google-multi 5.3.0-beta.1 → 5.4.0-alpha.1
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 +1 -1
- package/dist/accounts.js +3 -8
- package/dist/auth.d.ts +1 -4
- package/dist/auth.js +6 -18
- package/dist/client.d.ts +2 -1
- package/dist/client.js +2 -2
- package/dist/executor.js +1 -5
- package/dist/services.js +2 -4
- package/dist/token-store.js +3 -8
- package/dist/tools/admin.d.ts +0 -6
- package/dist/tools/admin.js +8 -13
- package/dist/tools/calendar.js +12 -12
- package/dist/tools/chat.js +5 -5
- package/dist/tools/contacts.js +10 -10
- package/dist/tools/docs.js +28 -28
- package/dist/tools/drive.js +39 -41
- package/dist/tools/forms.js +8 -8
- package/dist/tools/gmail-mime.d.ts +7 -27
- package/dist/tools/gmail-mime.js +10 -36
- package/dist/tools/gmail.js +22 -22
- package/dist/tools/meet.js +6 -6
- package/dist/tools/searchconsole.js +12 -11
- package/dist/tools/sheets.js +30 -30
- package/dist/tools/slides.js +6 -6
- package/dist/tools/tasks.js +13 -13
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The most complete **local Google Workspace MCP server**: Gmail, Drive, Calendar,
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/mcp-google-multi)
|
|
6
6
|
|
|
7
|
-
- 🧰 **Exhaustive** —
|
|
7
|
+
- 🧰 **Exhaustive** — 872 tools across 28 services + an escape hatch for anything else → [COVERAGE.md](./COVERAGE.md)
|
|
8
8
|
- 🔑 **Multi-account** — drive any number of Google accounts by alias, or fan one call out across all of them
|
|
9
9
|
- 🔒 **Private by design** — your own OAuth app, tokens encrypted at rest (AES-256-GCM), writes deny-by-default, no telemetry, no metering — it talks only to Google
|
|
10
10
|
|
package/dist/accounts.js
CHANGED
|
@@ -3,20 +3,15 @@ import { fileURLToPath } from 'node:url';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// from .env after config() already ran).
|
|
6
|
+
// dotenv v17 prints a banner to stdout, corrupting the stdio JSON-RPC channel;
|
|
7
|
+
// DOTENV_CONFIG_QUIET cannot help, it would be read from .env after config() ran.
|
|
9
8
|
dotenv.config({ quiet: true });
|
|
10
9
|
dotenv.config({ path: path.resolve(__dirname, '..', '.env'), quiet: true });
|
|
11
10
|
const defaultTokenDir = path.join(process.env.XDG_CONFIG_HOME || path.join(homedir(), '.config'), 'mcp-google-multi', 'tokens');
|
|
12
11
|
const tokenDir = process.env.TOKEN_STORE_PATH
|
|
13
12
|
? path.resolve(process.env.TOKEN_STORE_PATH)
|
|
14
13
|
: defaultTokenDir;
|
|
15
|
-
/**
|
|
16
|
-
* Parse accounts from the GOOGLE_ACCOUNTS env var.
|
|
17
|
-
* Format: "alias1:email1,alias2:email2,..."
|
|
18
|
-
* Example: "work:me@company.com,personal:me@gmail.com"
|
|
19
|
-
*/
|
|
14
|
+
/** Format: GOOGLE_ACCOUNTS="alias1:email1,alias2:email2". */
|
|
20
15
|
function parseAccounts() {
|
|
21
16
|
const raw = process.env.GOOGLE_ACCOUNTS;
|
|
22
17
|
if (!raw || raw.trim() === '') {
|
package/dist/auth.d.ts
CHANGED
|
@@ -5,9 +5,6 @@ export declare const ADMIN_SCOPES: string[];
|
|
|
5
5
|
export declare function getOptionalBundles(): string[];
|
|
6
6
|
/** Account aliases granted ADMIN_SCOPES via GOOGLE_ADMIN_ACCOUNTS. */
|
|
7
7
|
export declare function getAdminAccounts(): string[];
|
|
8
|
-
/**
|
|
9
|
-
* Compose the scope list for a single account at consent time.
|
|
10
|
-
* Resolves env flags: GOOGLE_OPTIONAL_SCOPES (global) and GOOGLE_ADMIN_ACCOUNTS (per-account allowlist).
|
|
11
|
-
*/
|
|
8
|
+
/** Scopes are fixed at consent time: changing GOOGLE_OPTIONAL_SCOPES or GOOGLE_ADMIN_ACCOUNTS requires re-running auth. */
|
|
12
9
|
export declare function resolveScopesForAccount(alias: string): string[];
|
|
13
10
|
export declare function runAuthFlow(args: string[]): Promise<void>;
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OAuth2Client } from 'googleapis-common';
|
|
2
2
|
import http from 'node:http';
|
|
3
3
|
import { URL } from 'node:url';
|
|
4
4
|
import { randomBytes } from 'node:crypto';
|
|
@@ -6,14 +6,7 @@ import open from 'open';
|
|
|
6
6
|
import destroyer from 'server-destroy';
|
|
7
7
|
import { ACCOUNTS, ACCOUNT_CONFIG } from './accounts.js';
|
|
8
8
|
import { writeToken } from './token-store.js';
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// BASE: always granted. Existing v3 surface + Tasks + Meet (added in v4.0.0).
|
|
12
|
-
// OPTIONAL: per-account opt-in via env GOOGLE_OPTIONAL_SCOPES="slides,forms,chat".
|
|
13
|
-
// ADMIN: per-account opt-in via env GOOGLE_ADMIN_ACCOUNTS="alias1,alias2".
|
|
14
|
-
//
|
|
15
|
-
// Personal Gmail accounts will 403 on admin scopes — never grant by default.
|
|
16
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
9
|
+
// Personal (non-Workspace) accounts 403 on admin scopes; ADMIN_SCOPES stays per-account opt-in, never granted by default.
|
|
17
10
|
export const BASE_SCOPES = [
|
|
18
11
|
'https://www.googleapis.com/auth/gmail.modify',
|
|
19
12
|
'https://www.googleapis.com/auth/gmail.send',
|
|
@@ -39,10 +32,8 @@ export const OPTIONAL_SCOPE_BUNDLES = {
|
|
|
39
32
|
'https://www.googleapis.com/auth/chat.messages',
|
|
40
33
|
'https://www.googleapis.com/auth/chat.messages.create',
|
|
41
34
|
],
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
// work via gmail.modify). sharing is separate — it governs delegation,
|
|
45
|
-
// auto-forwarding and send-as, a different risk profile from e.g. filters.
|
|
35
|
+
// These extend the always-on gmail service: users.settings.* writes require these
|
|
36
|
+
// scopes (reads already work via gmail.modify); sharing is split out as riskier.
|
|
46
37
|
gmail_settings: [
|
|
47
38
|
'https://www.googleapis.com/auth/gmail.settings.basic',
|
|
48
39
|
],
|
|
@@ -104,10 +95,7 @@ export function getOptionalBundles() {
|
|
|
104
95
|
export function getAdminAccounts() {
|
|
105
96
|
return parseCsvEnv('GOOGLE_ADMIN_ACCOUNTS');
|
|
106
97
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Compose the scope list for a single account at consent time.
|
|
109
|
-
* Resolves env flags: GOOGLE_OPTIONAL_SCOPES (global) and GOOGLE_ADMIN_ACCOUNTS (per-account allowlist).
|
|
110
|
-
*/
|
|
98
|
+
/** Scopes are fixed at consent time: changing GOOGLE_OPTIONAL_SCOPES or GOOGLE_ADMIN_ACCOUNTS requires re-running auth. */
|
|
111
99
|
export function resolveScopesForAccount(alias) {
|
|
112
100
|
const scopes = [...BASE_SCOPES];
|
|
113
101
|
for (const bundle of getOptionalBundles()) {
|
|
@@ -141,7 +129,7 @@ export async function runAuthFlow(args) {
|
|
|
141
129
|
console.error('MASTER_KEY is not set. Generate one (openssl rand -base64 32) and add it to .env before authenticating.');
|
|
142
130
|
process.exit(1);
|
|
143
131
|
}
|
|
144
|
-
const oauth2Client = new
|
|
132
|
+
const oauth2Client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, 'http://localhost:4242/oauth2callback');
|
|
145
133
|
// CSRF protection for the OAuth callback (RFC 6749 §10.12).
|
|
146
134
|
const expectedState = randomBytes(32).toString('hex');
|
|
147
135
|
const authorizeUrl = oauth2Client.generateAuthUrl({
|
package/dist/client.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import { OAuth2Client } from 'googleapis-common';
|
|
1
2
|
import type { Account } from './accounts.js';
|
|
2
|
-
export declare function getClient(account: Account): Promise<
|
|
3
|
+
export declare function getClient(account: Account): Promise<OAuth2Client>;
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OAuth2Client } from 'googleapis-common';
|
|
2
2
|
import { ACCOUNT_CONFIG } from './accounts.js';
|
|
3
3
|
import { readToken, updateToken } from './token-store.js';
|
|
4
4
|
export async function getClient(account) {
|
|
@@ -7,7 +7,7 @@ export async function getClient(account) {
|
|
|
7
7
|
throw new Error('GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be set. ' +
|
|
8
8
|
'Check that .env exists in the project root or pass them as env vars.');
|
|
9
9
|
}
|
|
10
|
-
const oauth2Client = new
|
|
10
|
+
const oauth2Client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, 'http://localhost:4242/oauth2callback');
|
|
11
11
|
const tokenData = readToken(account);
|
|
12
12
|
if (!tokenData) {
|
|
13
13
|
throw new Error(`No token found for account "${account}" (${config.email}). ` +
|
package/dist/executor.js
CHANGED
|
@@ -20,11 +20,7 @@ export function buildQueryString(queryParams) {
|
|
|
20
20
|
}
|
|
21
21
|
return usp.toString();
|
|
22
22
|
}
|
|
23
|
-
// GET/HEAD
|
|
24
|
-
// declares a request schema, and undici/fetch throw ("Request with GET/HEAD method
|
|
25
|
-
// cannot have body") if one is attached. gaxios stringifies any object `data`
|
|
26
|
-
// without checking the verb, so a caller-supplied `{}` on a read would otherwise
|
|
27
|
-
// crash the request. Write verbs keep prior semantics: null/undefined -> no body.
|
|
23
|
+
// GET/HEAD bodies are stripped — undici rejects them and gaxios attaches `data` regardless of verb (docs/internals.md).
|
|
28
24
|
export function resolveRequestBody(httpMethod, body) {
|
|
29
25
|
const verb = httpMethod.toUpperCase();
|
|
30
26
|
if (verb === 'GET' || verb === 'HEAD')
|
package/dist/services.js
CHANGED
|
@@ -27,10 +27,8 @@ export const SERVICES = [
|
|
|
27
27
|
{ name: 'chat', register: registerChatTools, enabled: () => new Set(getOptionalBundles()).has('chat') },
|
|
28
28
|
{ name: 'admin', register: registerAdminTools, enabled: () => getAdminAccounts().length > 0 },
|
|
29
29
|
];
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
// buildRegistry. workspaceevents has no dedicated scope (subscriptions use the
|
|
33
|
-
// underlying resource scopes), so it registers ungated.
|
|
30
|
+
// Generated-only services with opt-in scopes; admin/forms/chat reuse their curated gate in buildRegistry,
|
|
31
|
+
// and workspaceevents is deliberately absent — no dedicated scope (subscriptions use resource scopes).
|
|
34
32
|
const bundleGate = (name) => ({
|
|
35
33
|
enabled: () => new Set(getOptionalBundles()).has(name),
|
|
36
34
|
hint: `add "${name}" to GOOGLE_OPTIONAL_SCOPES`,
|
package/dist/token-store.js
CHANGED
|
@@ -93,9 +93,8 @@ function withTokenLock(alias, fn) {
|
|
|
93
93
|
}
|
|
94
94
|
catch (ownerError) {
|
|
95
95
|
const code = ownerError.code;
|
|
96
|
-
// EPERM:
|
|
97
|
-
//
|
|
98
|
-
// break a lock we cannot verify.
|
|
96
|
+
// EPERM: PID exists but is not signalable (recycled by another user);
|
|
97
|
+
// treat as alive, never break a lock we cannot verify.
|
|
99
98
|
if (code === 'ESRCH')
|
|
100
99
|
ownerDead = true;
|
|
101
100
|
else if (code !== 'EPERM')
|
|
@@ -158,11 +157,7 @@ function writeTokenAtomic(alias, data) {
|
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
|
-
// Windows
|
|
162
|
-
// so replacing a token file that another process momentarily holds open — a
|
|
163
|
-
// concurrent readToken, antivirus, an indexer — fails with a transient
|
|
164
|
-
// EPERM/EACCES/EBUSY. Reads take no lock, so the token lock cannot prevent
|
|
165
|
-
// this; a short bounded retry absorbs it. POSIX rename never fails this way.
|
|
160
|
+
// Windows only: renaming over a momentarily-open file throws transient EPERM/EACCES/EBUSY (reads take no lock); see docs/internals.md.
|
|
166
161
|
function renameWithRetry(from, to) {
|
|
167
162
|
for (let attempt = 1;; attempt++) {
|
|
168
163
|
try {
|
package/dist/tools/admin.d.ts
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
|
-
/**
|
|
3
|
-
* Admin SDK tools require Workspace super-admin (or delegated admin) privileges on the target account.
|
|
4
|
-
* Personal `@gmail.com` accounts will 403 on every endpoint.
|
|
5
|
-
*
|
|
6
|
-
* Writes (e.g. admin_users_update) are gated by write-control like any CUD tool.
|
|
7
|
-
*/
|
|
8
2
|
export declare function registerAdminTools(server: ToolRegistry): void;
|
package/dist/tools/admin.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceBoolean } from './_coerce.js';
|
|
3
|
-
import {
|
|
3
|
+
import { admin as adminClient } from '@googleapis/admin';
|
|
4
4
|
import { ACCOUNTS } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError } from './_errors.js';
|
|
7
7
|
const accountEnum = z.enum(ACCOUNTS);
|
|
8
|
-
|
|
9
|
-
* Admin SDK tools require Workspace super-admin (or delegated admin) privileges on the target account.
|
|
10
|
-
* Personal `@gmail.com` accounts will 403 on every endpoint.
|
|
11
|
-
*
|
|
12
|
-
* Writes (e.g. admin_users_update) are gated by write-control like any CUD tool.
|
|
13
|
-
*/
|
|
8
|
+
// Admin SDK requires Workspace super-admin (or delegated admin) on the account — personal @gmail.com accounts 403 on every endpoint.
|
|
14
9
|
export function registerAdminTools(server) {
|
|
15
10
|
// ─── Reports / audit log ───────────────────────────────────────────────
|
|
16
11
|
server.registerTool('reports_activities_list', {
|
|
@@ -40,7 +35,7 @@ export function registerAdminTools(server) {
|
|
|
40
35
|
}, async ({ account, applicationName, userKey, startTime, endTime, eventName, actorIpAddress, filters, orgUnitID, groupIdFilter, customerId, maxResults, pageToken }) => {
|
|
41
36
|
try {
|
|
42
37
|
const auth = await getClient(account);
|
|
43
|
-
const reports =
|
|
38
|
+
const reports = adminClient({ version: 'reports_v1', auth });
|
|
44
39
|
const res = await reports.activities.list({
|
|
45
40
|
applicationName,
|
|
46
41
|
userKey: userKey ?? 'all',
|
|
@@ -80,7 +75,7 @@ export function registerAdminTools(server) {
|
|
|
80
75
|
}, async ({ account, customer, domain, query, maxResults, pageToken, orderBy, showDeleted, projection }) => {
|
|
81
76
|
try {
|
|
82
77
|
const auth = await getClient(account);
|
|
83
|
-
const directory =
|
|
78
|
+
const directory = adminClient({ version: 'directory_v1', auth });
|
|
84
79
|
const res = await directory.users.list({
|
|
85
80
|
customer: customer ?? 'my_customer',
|
|
86
81
|
domain,
|
|
@@ -109,7 +104,7 @@ export function registerAdminTools(server) {
|
|
|
109
104
|
}, async ({ account, userKey, projection }) => {
|
|
110
105
|
try {
|
|
111
106
|
const auth = await getClient(account);
|
|
112
|
-
const directory =
|
|
107
|
+
const directory = adminClient({ version: 'directory_v1', auth });
|
|
113
108
|
const res = await directory.users.get({
|
|
114
109
|
userKey,
|
|
115
110
|
projection: projection ?? 'basic',
|
|
@@ -137,7 +132,7 @@ export function registerAdminTools(server) {
|
|
|
137
132
|
}, async ({ account, userKey, givenName, familyName, suspended, password, changePasswordAtNextLogin, orgUnitPath }) => {
|
|
138
133
|
try {
|
|
139
134
|
const auth = await getClient(account);
|
|
140
|
-
const directory =
|
|
135
|
+
const directory = adminClient({ version: 'directory_v1', auth });
|
|
141
136
|
const requestBody = {};
|
|
142
137
|
if (givenName !== undefined || familyName !== undefined) {
|
|
143
138
|
requestBody.name = {};
|
|
@@ -181,7 +176,7 @@ export function registerAdminTools(server) {
|
|
|
181
176
|
}, async ({ account, customer, domain, userKey, query, maxResults, pageToken }) => {
|
|
182
177
|
try {
|
|
183
178
|
const auth = await getClient(account);
|
|
184
|
-
const directory =
|
|
179
|
+
const directory = adminClient({ version: 'directory_v1', auth });
|
|
185
180
|
const res = await directory.groups.list({
|
|
186
181
|
customer: customer ?? 'my_customer',
|
|
187
182
|
domain,
|
|
@@ -211,7 +206,7 @@ export function registerAdminTools(server) {
|
|
|
211
206
|
}, async ({ account, groupKey, roles, includeDerivedMembership, maxResults, pageToken }) => {
|
|
212
207
|
try {
|
|
213
208
|
const auth = await getClient(account);
|
|
214
|
-
const directory =
|
|
209
|
+
const directory = adminClient({ version: 'directory_v1', auth });
|
|
215
210
|
const res = await directory.members.list({
|
|
216
211
|
groupKey,
|
|
217
212
|
roles,
|
package/dist/tools/calendar.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceArray, coerceBoolean } from './_coerce.js';
|
|
3
|
-
import {
|
|
3
|
+
import { calendar as calendarClient } from '@googleapis/calendar';
|
|
4
4
|
import { ACCOUNTS } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError } from './_errors.js';
|
|
@@ -15,7 +15,7 @@ export function registerCalendarTools(server) {
|
|
|
15
15
|
}, async ({ account }) => {
|
|
16
16
|
try {
|
|
17
17
|
const auth = await getClient(account);
|
|
18
|
-
const cal =
|
|
18
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
19
19
|
const res = await cal.calendarList.list();
|
|
20
20
|
const calendars = (res.data.items ?? []).map((c) => ({
|
|
21
21
|
id: c.id,
|
|
@@ -50,7 +50,7 @@ export function registerCalendarTools(server) {
|
|
|
50
50
|
}, async ({ account, calendarId, query, timeMin, timeMax, maxResults }) => {
|
|
51
51
|
try {
|
|
52
52
|
const auth = await getClient(account);
|
|
53
|
-
const cal =
|
|
53
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
54
54
|
const params = {
|
|
55
55
|
calendarId: calendarId ?? 'primary',
|
|
56
56
|
maxResults: maxResults ?? 25,
|
|
@@ -87,7 +87,7 @@ export function registerCalendarTools(server) {
|
|
|
87
87
|
}, async ({ account, eventId, calendarId }) => {
|
|
88
88
|
try {
|
|
89
89
|
const auth = await getClient(account);
|
|
90
|
-
const cal =
|
|
90
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
91
91
|
const res = await cal.events.get({
|
|
92
92
|
calendarId: calendarId ?? 'primary',
|
|
93
93
|
eventId,
|
|
@@ -119,7 +119,7 @@ export function registerCalendarTools(server) {
|
|
|
119
119
|
}, async ({ account, summary, start, end, description, location, attendees, calendarId, allDay }) => {
|
|
120
120
|
try {
|
|
121
121
|
const auth = await getClient(account);
|
|
122
|
-
const cal =
|
|
122
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
123
123
|
const event = { summary };
|
|
124
124
|
if (allDay) {
|
|
125
125
|
event.start = { date: start };
|
|
@@ -169,7 +169,7 @@ export function registerCalendarTools(server) {
|
|
|
169
169
|
}, async ({ account, eventId, summary, start, end, description, location, attendees, calendarId }) => {
|
|
170
170
|
try {
|
|
171
171
|
const auth = await getClient(account);
|
|
172
|
-
const cal =
|
|
172
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
173
173
|
// Fetch the event first so a 404 surfaces before we attempt the patch.
|
|
174
174
|
await cal.events.get({
|
|
175
175
|
calendarId: calendarId ?? 'primary',
|
|
@@ -222,7 +222,7 @@ export function registerCalendarTools(server) {
|
|
|
222
222
|
}, async ({ account, eventId, calendarId }) => {
|
|
223
223
|
try {
|
|
224
224
|
const auth = await getClient(account);
|
|
225
|
-
const cal =
|
|
225
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
226
226
|
await cal.events.delete({
|
|
227
227
|
calendarId: calendarId ?? 'primary',
|
|
228
228
|
eventId,
|
|
@@ -247,7 +247,7 @@ export function registerCalendarTools(server) {
|
|
|
247
247
|
}, async ({ account, calendarId, text, sendNotifications }) => {
|
|
248
248
|
try {
|
|
249
249
|
const auth = await getClient(account);
|
|
250
|
-
const cal =
|
|
250
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
251
251
|
const res = await cal.events.quickAdd({
|
|
252
252
|
calendarId: calendarId ?? 'primary',
|
|
253
253
|
text,
|
|
@@ -273,7 +273,7 @@ export function registerCalendarTools(server) {
|
|
|
273
273
|
}, async ({ account, calendarId, eventId, destinationCalendarId, sendNotifications }) => {
|
|
274
274
|
try {
|
|
275
275
|
const auth = await getClient(account);
|
|
276
|
-
const cal =
|
|
276
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
277
277
|
const res = await cal.events.move({
|
|
278
278
|
calendarId,
|
|
279
279
|
eventId,
|
|
@@ -303,7 +303,7 @@ export function registerCalendarTools(server) {
|
|
|
303
303
|
}, async ({ account, calendarId, eventId, timeMin, timeMax, maxResults }) => {
|
|
304
304
|
try {
|
|
305
305
|
const auth = await getClient(account);
|
|
306
|
-
const cal =
|
|
306
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
307
307
|
const res = await cal.events.instances({
|
|
308
308
|
calendarId: calendarId ?? 'primary',
|
|
309
309
|
eventId,
|
|
@@ -332,7 +332,7 @@ export function registerCalendarTools(server) {
|
|
|
332
332
|
}, async ({ account, calendarIds, timeMin, timeMax, timeZone }) => {
|
|
333
333
|
try {
|
|
334
334
|
const auth = await getClient(account);
|
|
335
|
-
const cal =
|
|
335
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
336
336
|
const res = await cal.freebusy.query({
|
|
337
337
|
requestBody: {
|
|
338
338
|
timeMin,
|
|
@@ -360,7 +360,7 @@ export function registerCalendarTools(server) {
|
|
|
360
360
|
}, async ({ account, summary, description, timeZone }) => {
|
|
361
361
|
try {
|
|
362
362
|
const auth = await getClient(account);
|
|
363
|
-
const cal =
|
|
363
|
+
const cal = calendarClient({ version: 'v3', auth });
|
|
364
364
|
const res = await cal.calendars.insert({
|
|
365
365
|
requestBody: {
|
|
366
366
|
summary,
|
package/dist/tools/chat.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceJson } from './_coerce.js';
|
|
3
|
-
import {
|
|
3
|
+
import { chat as chatClient } from '@googleapis/chat';
|
|
4
4
|
import { ACCOUNTS } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError } from './_errors.js';
|
|
@@ -17,7 +17,7 @@ export function registerChatTools(server) {
|
|
|
17
17
|
}, async ({ account, pageSize, pageToken, filter }) => {
|
|
18
18
|
try {
|
|
19
19
|
const auth = await getClient(account);
|
|
20
|
-
const chat =
|
|
20
|
+
const chat = chatClient({ version: 'v1', auth });
|
|
21
21
|
const res = await chat.spaces.list({
|
|
22
22
|
pageSize: pageSize ?? 100,
|
|
23
23
|
pageToken,
|
|
@@ -40,7 +40,7 @@ export function registerChatTools(server) {
|
|
|
40
40
|
}, async ({ account, name }) => {
|
|
41
41
|
try {
|
|
42
42
|
const auth = await getClient(account);
|
|
43
|
-
const chat =
|
|
43
|
+
const chat = chatClient({ version: 'v1', auth });
|
|
44
44
|
const res = await chat.spaces.get({ name });
|
|
45
45
|
return {
|
|
46
46
|
content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }],
|
|
@@ -66,7 +66,7 @@ export function registerChatTools(server) {
|
|
|
66
66
|
return { content: [{ type: 'text', text: JSON.stringify({ error: 'Either text or cardsV2 must be provided' }) }], isError: true };
|
|
67
67
|
}
|
|
68
68
|
const auth = await getClient(account);
|
|
69
|
-
const chat =
|
|
69
|
+
const chat = chatClient({ version: 'v1', auth });
|
|
70
70
|
const requestBody = {};
|
|
71
71
|
if (text)
|
|
72
72
|
requestBody.text = text;
|
|
@@ -100,7 +100,7 @@ export function registerChatTools(server) {
|
|
|
100
100
|
}, async ({ account, parent, pageSize, pageToken, filter, orderBy }) => {
|
|
101
101
|
try {
|
|
102
102
|
const auth = await getClient(account);
|
|
103
|
-
const chat =
|
|
103
|
+
const chat = chatClient({ version: 'v1', auth });
|
|
104
104
|
const res = await chat.spaces.messages.list({
|
|
105
105
|
parent,
|
|
106
106
|
pageSize: pageSize ?? 100,
|
package/dist/tools/contacts.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { people as peopleClient } from '@googleapis/people';
|
|
3
3
|
import { ACCOUNTS } from '../accounts.js';
|
|
4
4
|
import { getClient } from '../client.js';
|
|
5
5
|
import { handleGoogleApiError } from './_errors.js';
|
|
@@ -43,7 +43,7 @@ export function registerContactsTools(server) {
|
|
|
43
43
|
}, async ({ account, query, pageSize }) => {
|
|
44
44
|
try {
|
|
45
45
|
const auth = await getClient(account);
|
|
46
|
-
const people =
|
|
46
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
47
47
|
// Warmup request required by the People API
|
|
48
48
|
await people.people.searchContacts({
|
|
49
49
|
query: '',
|
|
@@ -72,7 +72,7 @@ export function registerContactsTools(server) {
|
|
|
72
72
|
}, async ({ account, resourceName }) => {
|
|
73
73
|
try {
|
|
74
74
|
const auth = await getClient(account);
|
|
75
|
-
const people =
|
|
75
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
76
76
|
const res = await people.people.get({
|
|
77
77
|
resourceName,
|
|
78
78
|
personFields: PERSON_FIELDS,
|
|
@@ -103,7 +103,7 @@ export function registerContactsTools(server) {
|
|
|
103
103
|
}, async ({ account, pageSize, pageToken, sortOrder }) => {
|
|
104
104
|
try {
|
|
105
105
|
const auth = await getClient(account);
|
|
106
|
-
const people =
|
|
106
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
107
107
|
const res = await people.people.connections.list({
|
|
108
108
|
resourceName: 'people/me',
|
|
109
109
|
personFields: PERSON_FIELDS,
|
|
@@ -142,7 +142,7 @@ export function registerContactsTools(server) {
|
|
|
142
142
|
}, async ({ account, givenName, familyName, email, emailType, phone, phoneType, organization, jobTitle }) => {
|
|
143
143
|
try {
|
|
144
144
|
const auth = await getClient(account);
|
|
145
|
-
const people =
|
|
145
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
146
146
|
const requestBody = {
|
|
147
147
|
names: [{ givenName, familyName: familyName ?? '' }],
|
|
148
148
|
};
|
|
@@ -189,7 +189,7 @@ export function registerContactsTools(server) {
|
|
|
189
189
|
}, async ({ account, resourceName, givenName, familyName, email, emailType, phone, phoneType, organization, jobTitle }) => {
|
|
190
190
|
try {
|
|
191
191
|
const auth = await getClient(account);
|
|
192
|
-
const people =
|
|
192
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
193
193
|
// Fetch current contact to get etag
|
|
194
194
|
const current = await people.people.get({
|
|
195
195
|
resourceName,
|
|
@@ -251,7 +251,7 @@ export function registerContactsTools(server) {
|
|
|
251
251
|
}, async ({ account, resourceName }) => {
|
|
252
252
|
try {
|
|
253
253
|
const auth = await getClient(account);
|
|
254
|
-
const people =
|
|
254
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
255
255
|
await people.people.deleteContact({ resourceName });
|
|
256
256
|
return {
|
|
257
257
|
content: [{ type: 'text', text: JSON.stringify({
|
|
@@ -273,7 +273,7 @@ export function registerContactsTools(server) {
|
|
|
273
273
|
}, async ({ account, pageSize }) => {
|
|
274
274
|
try {
|
|
275
275
|
const auth = await getClient(account);
|
|
276
|
-
const people =
|
|
276
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
277
277
|
const res = await people.contactGroups.list({
|
|
278
278
|
pageSize: pageSize ?? 100,
|
|
279
279
|
groupFields: 'name,groupType,memberCount',
|
|
@@ -303,7 +303,7 @@ export function registerContactsTools(server) {
|
|
|
303
303
|
}, async ({ account, groupResourceName, maxMembers }) => {
|
|
304
304
|
try {
|
|
305
305
|
const auth = await getClient(account);
|
|
306
|
-
const people =
|
|
306
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
307
307
|
const groupRes = await people.contactGroups.get({
|
|
308
308
|
resourceName: groupResourceName,
|
|
309
309
|
maxMembers: maxMembers ?? 100,
|
|
@@ -344,7 +344,7 @@ export function registerContactsTools(server) {
|
|
|
344
344
|
}, async ({ account, name }) => {
|
|
345
345
|
try {
|
|
346
346
|
const auth = await getClient(account);
|
|
347
|
-
const people =
|
|
347
|
+
const people = peopleClient({ version: 'v1', auth });
|
|
348
348
|
const res = await people.contactGroups.create({
|
|
349
349
|
requestBody: {
|
|
350
350
|
contactGroup: { name },
|