mcp-google-multi 6.0.0-alpha.13 → 6.0.0-alpha.14
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/discovery-client.d.ts +1 -1
- package/dist/discovery-client.js +3 -3
- package/dist/tools/_errors.js +13 -0
- package/dist/tools/google-api.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mcp-google-multi
|
|
2
2
|
|
|
3
|
-
The most complete **local Google Workspace MCP server**: Gmail, Drive, Calendar, Sheets, Docs, Slides, Forms, Contacts, Tasks, Chat, Meet, Classroom, Vault, Admin and more — **every OAuth-reachable
|
|
3
|
+
The most complete **local Google Workspace MCP server**: Gmail, Drive, Calendar, Sheets, Docs, Slides, Forms, Contacts, Tasks, Chat, Meet, Analytics (GA4), Search Console, Classroom, Vault, Admin and more — **every OAuth-reachable API method** as a tool, across **multiple Google accounts** at once, from Claude Code or any MCP client.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/mcp-google-multi)
|
|
6
6
|
|
package/dist/discovery-client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import * as os from 'node:os';
|
|
4
|
-
export const
|
|
4
|
+
export const SUPPORTED_APIS = {
|
|
5
5
|
gmail: { id: 'gmail', version: 'v1' },
|
|
6
6
|
drive: { id: 'drive', version: 'v3' },
|
|
7
7
|
calendar: { id: 'calendar', version: 'v3' },
|
|
@@ -98,9 +98,9 @@ export async function loadMethodIndex(api, deps = {}) {
|
|
|
98
98
|
const cached = memoryCache.get(api);
|
|
99
99
|
if (cached && now() < cached.refreshAfter)
|
|
100
100
|
return cached.index;
|
|
101
|
-
const spec =
|
|
101
|
+
const spec = SUPPORTED_APIS[api];
|
|
102
102
|
if (!spec) {
|
|
103
|
-
throw new Error(`Unknown api "${api}". Known: ${Object.keys(
|
|
103
|
+
throw new Error(`Unknown api "${api}". Known: ${Object.keys(SUPPORTED_APIS).join(', ')}`);
|
|
104
104
|
}
|
|
105
105
|
const fetchFn = deps.fetchFn ?? ((url) => fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) }));
|
|
106
106
|
const cacheDir = deps.cacheDir ?? discoveryCacheDir();
|
package/dist/tools/_errors.js
CHANGED
|
@@ -129,6 +129,19 @@ export function mapGoogleError(error, account, forbiddenHint, scopeContext) {
|
|
|
129
129
|
}
|
|
130
130
|
if (status === 429) {
|
|
131
131
|
const retryAfter = error?.response?.headers?.['retry-after'];
|
|
132
|
+
// GA4 quota exhaustion ("Exhausted property tokens ...") is a per-property
|
|
133
|
+
// token bucket, not a transient rate spike: shrinking the request is the
|
|
134
|
+
// lever that helps, and a blind immediate retry only burns more tokens.
|
|
135
|
+
if (/property tokens/i.test(message)) {
|
|
136
|
+
return {
|
|
137
|
+
error: 'rate_limited',
|
|
138
|
+
message,
|
|
139
|
+
hint: 'GA4 quotas are per-property token buckets that refill over the hour/day. ' +
|
|
140
|
+
'Narrow the date range, request fewer dimensions/metrics/rows, and pass returnPropertyQuota to see the remaining tokens before retrying.',
|
|
141
|
+
retriable: true,
|
|
142
|
+
account,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
132
145
|
return {
|
|
133
146
|
error: 'rate_limited',
|
|
134
147
|
message,
|
package/dist/tools/google-api.js
CHANGED
|
@@ -6,7 +6,7 @@ import { coerceJson } from './_coerce.js';
|
|
|
6
6
|
import { getToolsets, toolsetEnabled } from '../toolsets.js';
|
|
7
7
|
import { editDistance } from '../scope-catalog.js';
|
|
8
8
|
import { executeApiMethod, jsonResult } from '../executor.js';
|
|
9
|
-
import {
|
|
9
|
+
import { SUPPORTED_APIS, cudFromMethod, loadMethodIndex, searchMethods, } from '../discovery-client.js';
|
|
10
10
|
const accountEnum = accountAliasSchema.optional();
|
|
11
11
|
// Policy/toolset namespace for each API alias must match the NAMED tools' service
|
|
12
12
|
// names, or user deny globs and GOOGLE_TOOLSETS silently miss escape-hatch calls.
|
|
@@ -61,7 +61,7 @@ export function registerEscapeTools(registry, policy, deps = {}) {
|
|
|
61
61
|
const apiEnabled = (alias) => {
|
|
62
62
|
return toolsetEnabled(toolsets, serviceForAlias(alias));
|
|
63
63
|
};
|
|
64
|
-
const enabledApis = Object.keys(
|
|
64
|
+
const enabledApis = Object.keys(SUPPORTED_APIS).filter(apiEnabled);
|
|
65
65
|
const apiList = enabledApis.join(', ');
|
|
66
66
|
const toolsetDisabled = (alias) => jsonResult({
|
|
67
67
|
error: 'toolset_disabled',
|
|
@@ -80,7 +80,7 @@ export function registerEscapeTools(registry, policy, deps = {}) {
|
|
|
80
80
|
},
|
|
81
81
|
annotations: { openWorldHint: true },
|
|
82
82
|
}, async ({ query, api, maxResults }) => {
|
|
83
|
-
if (api && !
|
|
83
|
+
if (api && !SUPPORTED_APIS[api]) {
|
|
84
84
|
return jsonResult({ error: 'unknown_api', message: `Unknown api "${api}".`, hint: `Known APIs: ${apiList}`, retriable: false }, true);
|
|
85
85
|
}
|
|
86
86
|
if (api && !apiEnabled(api))
|
|
@@ -129,7 +129,7 @@ export function registerEscapeTools(registry, policy, deps = {}) {
|
|
|
129
129
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
130
130
|
_meta: { 'anthropic/maxResultSizeChars': 100_000 },
|
|
131
131
|
}, async ({ account, api, methodId, pathParams, queryParams, body }) => {
|
|
132
|
-
if (!
|
|
132
|
+
if (!SUPPORTED_APIS[api]) {
|
|
133
133
|
return jsonResult({ error: 'unknown_api', message: `Unknown api "${api}".`, hint: `Known APIs: ${apiList}`, retriable: false, account }, true);
|
|
134
134
|
}
|
|
135
135
|
if (!apiEnabled(api))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-google-multi",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.14",
|
|
4
4
|
"description": "Local MCP server for Google Workspace (Gmail, Drive, Calendar, Sheets, Docs, Contacts, Tasks, Meet, Search Console, +Forms/Chat/Admin) across multiple accounts — OAuth-only, encrypted token storage, deny-by-default writes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|