mcp-google-multi 6.0.0-alpha.37 → 6.0.0-alpha.38
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/doctor.js
CHANGED
|
@@ -7,6 +7,7 @@ import { peekMasterKeyProvenance, deleteMasterKeyMaterial } from './master-key.j
|
|
|
7
7
|
import { hasToken } from './token-store.js';
|
|
8
8
|
import { configDir, loadConfigFile } from './config-file.js';
|
|
9
9
|
import { envValueSource } from './env-load.js';
|
|
10
|
+
import { reauthHint } from './reauth-hint.js';
|
|
10
11
|
import { describeMetricsDir, resolveUsageMetrics, sourceLabel } from './usage-metrics.js';
|
|
11
12
|
import { probeApiEnablement } from './api-probe.js';
|
|
12
13
|
import { safeMessage, stringifyEnvelope } from './tools/_errors.js';
|
|
@@ -181,7 +182,7 @@ function sectionsTokensAndScopes(deps, aliases) {
|
|
|
181
182
|
if (scopeVerdict === 'ok')
|
|
182
183
|
scopeVerdict = 'warn';
|
|
183
184
|
scopeLines.push(`${alias}: ${r.callable.length} callable, ${r.requestable.length} requested-not-granted`);
|
|
184
|
-
scopeHint = `Re-auth to grant missing scopes
|
|
185
|
+
scopeHint = `Re-auth to grant missing scopes. ${reauthHint(alias)}`;
|
|
185
186
|
}
|
|
186
187
|
else {
|
|
187
188
|
scopeLines.push(`${alias}: ${r.callable.length} callable, all profile scopes granted`);
|
package/dist/http-transport.d.ts
CHANGED
package/dist/http-transport.js
CHANGED
|
@@ -149,6 +149,15 @@ export class HttpTransportHost {
|
|
|
149
149
|
this.log(`${auth.status} auth_failed path=/mcp`);
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
|
+
// Thread the verified subject to tool handlers: the Node transport forwards
|
|
153
|
+
// req.auth verbatim as ctx.http.authInfo. Token/clientId stay empty — the
|
|
154
|
+
// bearer value must not re-enter the dispatch path via handler context.
|
|
155
|
+
req.auth = {
|
|
156
|
+
token: '',
|
|
157
|
+
clientId: '',
|
|
158
|
+
scopes: ['mcp:use'],
|
|
159
|
+
extra: { sub: auth.sub ?? 'owner' },
|
|
160
|
+
};
|
|
152
161
|
let body;
|
|
153
162
|
try {
|
|
154
163
|
body = await this.readJson(req);
|
package/dist/oauth-as.js
CHANGED
|
@@ -385,8 +385,8 @@ export function buildAuthServer(config, deps = {}) {
|
|
|
385
385
|
if (!form.code_verifier || pkceS256(form.code_verifier) !== code.code_challenge) {
|
|
386
386
|
return json(res, 400, { error: 'invalid_grant', message: 'PKCE verification failed' });
|
|
387
387
|
}
|
|
388
|
-
const access = await signAccessToken({ base, secret, iat: nowSec(), ttlSec: accessTtl, sub:
|
|
389
|
-
const refreshToken = refresh.issue(now(),
|
|
388
|
+
const access = await signAccessToken({ base, secret, iat: nowSec(), ttlSec: accessTtl, sub: code.sub });
|
|
389
|
+
const refreshToken = refresh.issue(now(), code.sub);
|
|
390
390
|
log('token issued grant=authorization_code');
|
|
391
391
|
return json(res, 200, { access_token: access, token_type: 'Bearer', expires_in: accessTtl, refresh_token: refreshToken, scope: 'mcp:use' });
|
|
392
392
|
}
|
|
@@ -394,7 +394,7 @@ export function buildAuthServer(config, deps = {}) {
|
|
|
394
394
|
const next = refresh.rotate(form.refresh_token ?? '', now());
|
|
395
395
|
if (!next)
|
|
396
396
|
return json(res, 400, { error: 'invalid_grant', message: 'unknown or rotated refresh token' });
|
|
397
|
-
const access = await signAccessToken({ base, secret, iat: nowSec(), ttlSec: accessTtl, sub:
|
|
397
|
+
const access = await signAccessToken({ base, secret, iat: nowSec(), ttlSec: accessTtl, sub: next.sub });
|
|
398
398
|
log('token issued grant=refresh_token');
|
|
399
399
|
return json(res, 200, { access_token: access, token_type: 'Bearer', expires_in: accessTtl, refresh_token: next.token, scope: 'mcp:use' });
|
|
400
400
|
}
|
|
@@ -446,8 +446,8 @@ export function buildAuthServer(config, deps = {}) {
|
|
|
446
446
|
return { ok: false, status: 401, headers: { 'WWW-Authenticate': wwwAuth }, body: JSON.stringify({ error: 'E_MCP_TOKEN_INVALID', message: 'missing bearer token' }) };
|
|
447
447
|
}
|
|
448
448
|
try {
|
|
449
|
-
await verifyAccessToken(header.slice(7), base, secret);
|
|
450
|
-
return { ok: true };
|
|
449
|
+
const claims = await verifyAccessToken(header.slice(7), base, secret);
|
|
450
|
+
return { ok: true, sub: claims.sub };
|
|
451
451
|
}
|
|
452
452
|
catch {
|
|
453
453
|
return { ok: false, status: 401, headers: { 'WWW-Authenticate': wwwAuth }, body: JSON.stringify({ error: 'E_MCP_TOKEN_INVALID', message: 'invalid or expired token' }) };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ADMIN_SCOPES, BUNDLE_CATALOG } from './scope-catalog.js';
|
|
2
2
|
import { BASE_SCOPES, resolveScopesForAccount } from './auth.js';
|
|
3
3
|
import { readToken } from './token-store.js';
|
|
4
|
+
import { reauthHint } from './reauth-hint.js';
|
|
4
5
|
// Reverse index scope -> bundles offering it, narrowest bundle first (fewest
|
|
5
6
|
// scopes) so the remediation names the smallest grant. BASE_SCOPES map to the
|
|
6
7
|
// pseudo-bundle "base" (outside a profile only via includesBase:false).
|
|
@@ -74,7 +75,7 @@ export function scopeHint(scope, c, alias) {
|
|
|
74
75
|
case 'requestable_not_granted':
|
|
75
76
|
return {
|
|
76
77
|
hint: `Scope ${scope} is in ${alias}'s profile but not granted (you unchecked it at consent). ` +
|
|
77
|
-
|
|
78
|
+
reauthHint(alias),
|
|
78
79
|
retriable: true,
|
|
79
80
|
};
|
|
80
81
|
case 'not_requestable':
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { reauthHint } from '../reauth-hint.js';
|
|
1
2
|
import * as fs from 'node:fs';
|
|
2
3
|
import { getAccountSet, refreshAccountSetIfStale } from '../accounts.js';
|
|
3
4
|
import { buildScopesReport } from '../scope-observability.js';
|
|
@@ -35,7 +36,7 @@ export function deriveAccountHealth(alias, deps = DEFAULT_DEPS) {
|
|
|
35
36
|
status: 'missing',
|
|
36
37
|
hint: legacy
|
|
37
38
|
? 'Plaintext token.json found — run: npx mcp-google-multi migrate-tokens'
|
|
38
|
-
:
|
|
39
|
+
: reauthHint(alias),
|
|
39
40
|
},
|
|
40
41
|
scopes: noScopes,
|
|
41
42
|
};
|
|
@@ -69,7 +70,7 @@ export function deriveAccountHealth(alias, deps = DEFAULT_DEPS) {
|
|
|
69
70
|
status,
|
|
70
71
|
expiryDate: expiry !== undefined ? new Date(expiry).toISOString() : undefined,
|
|
71
72
|
hint: status === 'needs_reauth'
|
|
72
|
-
?
|
|
73
|
+
? reauthHint(alias)
|
|
73
74
|
: missing.length > 0
|
|
74
75
|
? 'Re-auth to grant the missing scopes'
|
|
75
76
|
: undefined,
|
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.38",
|
|
4
4
|
"mcpName": "io.github.bakissation/mcp-google-multi",
|
|
5
5
|
"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.",
|
|
6
6
|
"type": "module",
|