mcp-google-multi 6.0.0-beta.2 → 6.0.0-beta.3

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.
Files changed (165) hide show
  1. package/dist/accounts.d.ts +17 -1
  2. package/dist/accounts.js +52 -15
  3. package/dist/api-probe.d.ts +5 -0
  4. package/dist/api-probe.js +20 -15
  5. package/dist/arg-normalize.js +6 -5
  6. package/dist/arg-strict.d.ts +7 -0
  7. package/dist/arg-strict.js +34 -4
  8. package/dist/auth.d.ts +4 -3
  9. package/dist/auth.js +11 -13
  10. package/dist/boot-gates.d.ts +26 -0
  11. package/dist/boot-gates.js +38 -0
  12. package/dist/cimd-cache.d.ts +38 -0
  13. package/dist/cimd-cache.js +117 -0
  14. package/dist/client.d.ts +32 -2
  15. package/dist/client.js +0 -0
  16. package/dist/compose.d.ts +11 -0
  17. package/dist/compose.js +109 -0
  18. package/dist/config-file.d.ts +13 -0
  19. package/dist/config-file.js +37 -1
  20. package/dist/discover.js +3 -1
  21. package/dist/discovery-client.d.ts +3 -0
  22. package/dist/discovery-client.js +25 -2
  23. package/dist/doctor.d.ts +6 -2
  24. package/dist/doctor.js +119 -23
  25. package/dist/executor.d.ts +3 -0
  26. package/dist/executor.js +4 -2
  27. package/dist/fanout.d.ts +9 -1
  28. package/dist/fanout.js +44 -10
  29. package/dist/fs-atomic.d.ts +11 -0
  30. package/dist/fs-atomic.js +219 -28
  31. package/dist/hint-provider.d.ts +129 -0
  32. package/dist/hint-provider.js +64 -0
  33. package/dist/http-transport.d.ts +62 -4
  34. package/dist/http-transport.js +343 -24
  35. package/dist/identity.d.ts +4 -1
  36. package/dist/identity.js +25 -6
  37. package/dist/index.js +66 -138
  38. package/dist/master-key.js +13 -5
  39. package/dist/mcp-token.d.ts +136 -19
  40. package/dist/mcp-token.js +569 -72
  41. package/dist/migrate-config.js +2 -2
  42. package/dist/oauth-as.d.ts +103 -3
  43. package/dist/oauth-as.js +374 -79
  44. package/dist/oauth-consent.d.ts +10 -0
  45. package/dist/oauth-consent.js +16 -0
  46. package/dist/outbound-allowlist.js +5 -2
  47. package/dist/reauth-hint.d.ts +1 -1
  48. package/dist/reauth-hint.js +12 -8
  49. package/dist/registry-transfer.d.ts +5 -0
  50. package/dist/registry-transfer.js +65 -5
  51. package/dist/registry.d.ts +18 -1
  52. package/dist/registry.js +71 -15
  53. package/dist/scope-catalog.d.ts +11 -0
  54. package/dist/scope-catalog.js +23 -6
  55. package/dist/scope-observability.d.ts +8 -6
  56. package/dist/scope-observability.js +29 -13
  57. package/dist/services.d.ts +15 -10
  58. package/dist/services.js +59 -15
  59. package/dist/ssrf-guard.d.ts +23 -9
  60. package/dist/ssrf-guard.js +101 -62
  61. package/dist/tenant-purge.d.ts +26 -0
  62. package/dist/tenant-purge.js +67 -0
  63. package/dist/token-store.d.ts +20 -2
  64. package/dist/token-store.js +0 -0
  65. package/dist/tools/_errors.d.ts +3 -0
  66. package/dist/tools/_errors.js +53 -24
  67. package/dist/tools/_local-files.d.ts +9 -0
  68. package/dist/tools/_local-files.js +18 -0
  69. package/dist/tools/account-wizard.d.ts +10 -1
  70. package/dist/tools/account-wizard.js +74 -17
  71. package/dist/tools/accounts-tool.d.ts +7 -0
  72. package/dist/tools/accounts-tool.js +34 -18
  73. package/dist/tools/admin.d.ts +10 -1
  74. package/dist/tools/admin.js +15 -11
  75. package/dist/tools/analytics.d.ts +10 -1
  76. package/dist/tools/analytics.js +13 -8
  77. package/dist/tools/calendar.d.ts +2 -1
  78. package/dist/tools/calendar.js +18 -14
  79. package/dist/tools/chat.d.ts +10 -1
  80. package/dist/tools/chat.js +13 -8
  81. package/dist/tools/contacts.d.ts +2 -1
  82. package/dist/tools/contacts.js +17 -13
  83. package/dist/tools/docs.d.ts +2 -1
  84. package/dist/tools/docs.js +34 -30
  85. package/dist/tools/drive.d.ts +2 -1
  86. package/dist/tools/drive.js +65 -50
  87. package/dist/tools/forms.d.ts +10 -1
  88. package/dist/tools/forms.js +19 -12
  89. package/dist/tools/generated/_shared.d.ts +2 -1
  90. package/dist/tools/generated/_shared.js +7 -3
  91. package/dist/tools/generated/admin.d.ts +2 -1
  92. package/dist/tools/generated/admin.js +265 -265
  93. package/dist/tools/generated/analytics.d.ts +2 -1
  94. package/dist/tools/generated/analytics.js +125 -125
  95. package/dist/tools/generated/appsmarket.d.ts +2 -1
  96. package/dist/tools/generated/appsmarket.js +5 -5
  97. package/dist/tools/generated/calendar.d.ts +2 -1
  98. package/dist/tools/generated/calendar.js +55 -55
  99. package/dist/tools/generated/chat.d.ts +2 -1
  100. package/dist/tools/generated/chat.js +95 -95
  101. package/dist/tools/generated/classroom.d.ts +2 -1
  102. package/dist/tools/generated/classroom.js +209 -209
  103. package/dist/tools/generated/cloudidentity.d.ts +2 -1
  104. package/dist/tools/generated/cloudidentity.js +133 -133
  105. package/dist/tools/generated/cloudsearch.d.ts +2 -1
  106. package/dist/tools/generated/cloudsearch.js +99 -99
  107. package/dist/tools/generated/contacts.d.ts +2 -1
  108. package/dist/tools/generated/contacts.js +29 -29
  109. package/dist/tools/generated/drive.d.ts +2 -1
  110. package/dist/tools/generated/drive.js +71 -71
  111. package/dist/tools/generated/driveactivity.d.ts +2 -1
  112. package/dist/tools/generated/driveactivity.js +3 -3
  113. package/dist/tools/generated/drivelabels.d.ts +2 -1
  114. package/dist/tools/generated/drivelabels.js +53 -53
  115. package/dist/tools/generated/forms.d.ts +2 -1
  116. package/dist/tools/generated/forms.js +7 -7
  117. package/dist/tools/generated/gmail.d.ts +2 -1
  118. package/dist/tools/generated/gmail.js +117 -117
  119. package/dist/tools/generated/groupsmigration.d.ts +2 -1
  120. package/dist/tools/generated/groupsmigration.js +3 -3
  121. package/dist/tools/generated/groupssettings.d.ts +2 -1
  122. package/dist/tools/generated/groupssettings.js +7 -7
  123. package/dist/tools/generated/index.d.ts +2 -1
  124. package/dist/tools/generated/keep.d.ts +2 -1
  125. package/dist/tools/generated/keep.js +15 -15
  126. package/dist/tools/generated/licensing.d.ts +2 -1
  127. package/dist/tools/generated/licensing.js +15 -15
  128. package/dist/tools/generated/meet.d.ts +2 -1
  129. package/dist/tools/generated/meet.js +27 -27
  130. package/dist/tools/generated/postmaster.d.ts +2 -1
  131. package/dist/tools/generated/postmaster.js +9 -9
  132. package/dist/tools/generated/reseller.d.ts +2 -1
  133. package/dist/tools/generated/reseller.js +35 -35
  134. package/dist/tools/generated/script.d.ts +2 -1
  135. package/dist/tools/generated/script.js +33 -33
  136. package/dist/tools/generated/searchconsole.d.ts +2 -1
  137. package/dist/tools/generated/searchconsole.js +3 -3
  138. package/dist/tools/generated/sheets.d.ts +2 -1
  139. package/dist/tools/generated/sheets.js +15 -15
  140. package/dist/tools/generated/tasks.d.ts +2 -1
  141. package/dist/tools/generated/tasks.js +5 -5
  142. package/dist/tools/generated/vault.d.ts +2 -1
  143. package/dist/tools/generated/vault.js +67 -67
  144. package/dist/tools/generated/workspaceevents.d.ts +2 -1
  145. package/dist/tools/generated/workspaceevents.js +31 -31
  146. package/dist/tools/gmail.d.ts +2 -1
  147. package/dist/tools/gmail.js +45 -33
  148. package/dist/tools/google-api.d.ts +2 -3
  149. package/dist/tools/google-api.js +30 -16
  150. package/dist/tools/meet.d.ts +10 -1
  151. package/dist/tools/meet.js +13 -9
  152. package/dist/tools/searchconsole.d.ts +2 -1
  153. package/dist/tools/searchconsole.js +17 -13
  154. package/dist/tools/sheets.d.ts +2 -1
  155. package/dist/tools/sheets.js +36 -32
  156. package/dist/tools/slides.d.ts +10 -1
  157. package/dist/tools/slides.js +17 -10
  158. package/dist/tools/tasks.d.ts +2 -1
  159. package/dist/tools/tasks.js +19 -15
  160. package/dist/trim.d.ts +5 -0
  161. package/dist/trim.js +20 -0
  162. package/dist/usage-metrics.d.ts +23 -0
  163. package/dist/usage-metrics.js +65 -47
  164. package/dist/write-control.js +10 -2
  165. package/package.json +27 -1
@@ -1,5 +1,5 @@
1
1
  import { CONFIG_VERSION, configFilePath, loadConfigFile, mutateConfigFile } from './config-file.js';
2
- import { BUNDLE_CATALOG, closestBundle, resolveBundleAliases } from './scope-catalog.js';
2
+ import { closestBundle, isKnownBundle, resolveBundleAliases } from './scope-catalog.js';
3
3
  function parseCsv(value) {
4
4
  return (value ?? '').split(',').map((s) => s.trim()).filter(Boolean);
5
5
  }
@@ -47,7 +47,7 @@ export function runMigrateConfig(env = process.env) {
47
47
  process.exitCode = 1;
48
48
  return;
49
49
  }
50
- if (!(bundle in BUNDLE_CATALOG)) {
50
+ if (!isKnownBundle(bundle)) {
51
51
  const hint = closestBundle(bundle);
52
52
  console.error(`E_UNKNOWN_BUNDLE: unknown bundle "${bundle}" in GOOGLE_OPTIONAL_SCOPES${hint ? ` — did you mean "${hint}"?` : ''}. Nothing written.`);
53
53
  process.exitCode = 1;
@@ -6,6 +6,10 @@ export declare const DCR_MAX_REDIRECT_URIS = 10;
6
6
  export interface GoogleExchangeResult {
7
7
  tokens: Record<string, unknown>;
8
8
  email?: string;
9
+ /** Google's stable account id; unlike the address it is never reassigned. */
10
+ sub?: string;
11
+ /** Google Workspace hosted domain; absent for a consumer account. */
12
+ hd?: string;
9
13
  }
10
14
  export interface AuthServerConfig {
11
15
  base: string;
@@ -16,21 +20,72 @@ export interface AuthServerConfig {
16
20
  accessTtlSec?: number;
17
21
  masterKey: string;
18
22
  refreshStorePath: string;
23
+ /** `maxAgeSec` of the refresh store buildAuthServer creates: sessions end
24
+ * this long after their sign-in. Unset: unlimited. */
25
+ refreshMaxAgeSec?: number;
26
+ /** `idleSec` of that store: sessions end this long after their last
27
+ * refresh. Unset: unlimited. */
28
+ refreshIdleSec?: number;
29
+ /** `maxFamiliesPerSub` of that store: bounds how many live refresh-token
30
+ * families one subject may hold, dropping its least-recently-used one to
31
+ * make room. Unset: unlimited. */
32
+ refreshMaxFamiliesPerSub?: number;
33
+ /** Default true. The clientless `flow=alias_reauth` link names an alias with
34
+ * no tenant binding, so a multi-tenant deployment sets false: with several
35
+ * tenants an alias name alone is ambiguous and the branch becomes a
36
+ * cross-tenant re-auth vector. Server-minted alias_add flows are unaffected. */
37
+ legacyAliasReauth?: boolean;
19
38
  }
39
+ /** What /callback hands the alias_add binder once Google returned a verified
40
+ * identity for a server-minted link. */
41
+ export interface TenantAliasBind {
42
+ tenantId: string;
43
+ alias: string;
44
+ email: string;
45
+ bundles?: string[];
46
+ nonce?: string;
47
+ tokens: Record<string, unknown>;
48
+ sub?: string;
49
+ }
50
+ /** A binder's deliberate refusal (policy, not failure): /callback answers 403
51
+ * with this slug and message. The message reaches an unauthenticated browser. */
52
+ export interface AliasBindRefusal {
53
+ refused: {
54
+ slug: string;
55
+ message: string;
56
+ };
57
+ }
58
+ export interface GoogleIdentity {
59
+ email?: string;
60
+ sub?: string;
61
+ hd?: string;
62
+ }
63
+ /** Only trust the id_token identity when Google marks the email verified (#8).
64
+ * The token comes straight from Google's token endpoint, so its claims are
65
+ * read unsigned. A malformed sub or hd is dropped, never passed on. */
66
+ export declare function verifiedIdentityFromIdToken(idToken?: string | null): GoogleIdentity | undefined;
67
+ export declare function verifiedEmailFromIdToken(idToken?: string | null): string | undefined;
20
68
  export interface AuthServerDeps {
21
69
  fetchCimd?: (clientId: string) => Promise<Record<string, unknown>>;
22
70
  /** Exchange a Google auth code at `${base}/callback` for tokens (+ owner email). */
23
71
  exchangeCode?: (code: string, flow: StatePayload['flow']) => Promise<GoogleExchangeResult>;
24
72
  /** Build the Google authorization URL (redirect back to `${base}/callback`).
25
- * The impl chooses scope/prompt/login_hint from the flow: owner_gate =
26
- * `openid email` + select_account; alias_reauth = the alias's resource scopes
27
- * + consent. */
73
+ * The impl chooses scope/prompt from the flow: owner_gate = `openid email`
74
+ * + select_account; alias_reauth = the alias's resource scopes + select_account
75
+ * consent, and no login_hint (the link needs no authentication). */
28
76
  buildGoogleAuthUrl?: (opts: {
29
77
  flow: StatePayload['flow'];
30
78
  alias?: string;
31
79
  state: string;
80
+ bundles?: string[];
32
81
  }) => string;
33
82
  writeToken?: (alias: string, tokens: Record<string, unknown>) => void;
83
+ /** Scopes the alias asked for that `grantedScope` lacks, so the alias_reauth
84
+ * completion page can say what Google's granular consent left out. */
85
+ missingScopes?: (alias: string, grantedScope: string | undefined) => string[];
86
+ /** Whether a readable token is stored for the alias; a narrower re-auth
87
+ * grant keeps it rather than replace it. */
88
+ hasToken?: (alias: string) => boolean;
34
89
  registeredClients?: Map<string, {
35
90
  redirect_uris: string[];
36
91
  }>;
@@ -41,10 +96,55 @@ export interface AuthServerDeps {
41
96
  log?: (line: string) => void;
42
97
  /** The alias's configured Google email, for the alias_reauth identity binding. */
43
98
  aliasEmail?: (alias: string) => string | undefined;
99
+ /** Map a verified sign-in email to the subject its tokens are minted under.
100
+ * Default = the MCP_OWNER_EMAILS allowlist -> {sub:'owner'}; null = denied.
101
+ * The tenant resolver (invite claim / email->tenant lookup) plugs in here.
102
+ * `identity` carries Google's `sub` and `hd` when the exchange returned
103
+ * them, so a resolver can key on the stable account id rather than an
104
+ * address that can be reassigned. */
105
+ resolveSubject?: (email: string, identity?: {
106
+ sub?: string;
107
+ hd?: string;
108
+ }) => {
109
+ sub: string;
110
+ } | null | {
111
+ denied: {
112
+ description: string;
113
+ };
114
+ };
115
+ /** alias_add completion: persist the new alias's config row and tokens under
116
+ * its tenant. /callback awaits it only after a successful Google exchange.
117
+ * A returned refusal answers 403 with its slug; a throw or rejection answers
118
+ * 500 E_ALIAS_ADD_FAILED. */
119
+ bindTenantAlias?: (bind: TenantAliasBind) => void | AliasBindRefusal | Promise<void | AliasBindRefusal>;
120
+ /** False for a subject this host no longer serves (a multi-tenant host that
121
+ * removed or suspended it): /token then issues and rotates nothing for it
122
+ * (400 invalid_grant; a rotated sub's refresh tokens are dropped). A throw
123
+ * means the answer is unknown right now: 503 temporarily_unavailable, and
124
+ * the presented refresh token is not spent. Absent: every subject is active. */
125
+ subjectActive?: (sub: string) => boolean;
44
126
  }
45
127
  export interface AuthServer {
46
128
  routes: Record<string, RouteHandler>;
47
129
  authenticate: (req: IncomingMessage) => Promise<AuthOutcome>;
130
+ /** Mint a signed, single-use, TTL-bound clientless flow URL
131
+ * (`${base}/authorize?flow=...&state=<signed>`). The tenantId/bundles ride
132
+ * INSIDE the signed state, so nothing at /authorize or /callback trusts a
133
+ * caller-supplied identity. The URL works only on this AuthServer, and only
134
+ * until its process restarts: sign-in artifacts are signed with a key each
135
+ * buildAuthServer call generates. Inert unless something calls it. */
136
+ mintFlowState: (opts: {
137
+ flow: 'alias_add';
138
+ alias: string;
139
+ tenantId?: string;
140
+ bundles?: string[];
141
+ nonce?: string;
142
+ }) => Promise<string>;
143
+ /** The owner's re-auth link for `alias`: HMAC-signed, expiring, not single
144
+ * use (a chat client may prefetch it). /authorize refuses any alias_reauth
145
+ * request without a valid one, so an unauthenticated caller can neither
146
+ * start a re-auth nor learn which aliases exist or what they hold. */
147
+ reauthLink: (alias: string) => string;
48
148
  }
49
149
  /** C6: exact redirect_uri match, with RFC 8252 §7.3 port-agnostic loopback and
50
150
  * the fixed claude.ai callback. */