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,4 +1,6 @@
1
1
  import type { ToolRegistry } from '../registry.js';
2
+ import type { Account } from '../accounts.js';
3
+ import { type CuratedToolDeps } from '../client.js';
2
4
  /** Accepts "213025502" or "properties/213025502"; rejects the identifiers
3
5
  * people paste by mistake (G-… measurement IDs, UA-… properties) with a
4
6
  * pointer to the right one. */
@@ -15,4 +17,11 @@ export declare function shapeAccountSummaries(data: any): Record<string, unknown
15
17
  /** Full metadata descriptions run to paragraphs; the first ~160 chars carry
16
18
  * the disambiguation the model needs without bloating a ~300-entry list. */
17
19
  export declare function shapeMetadata(data: any): Record<string, unknown>;
18
- export declare function registerAnalyticsTools(server: ToolRegistry): void;
20
+ export declare function registerAnalyticsTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
21
+ export declare function handleAnalyticsError(error: any, account: Account): {
22
+ content: {
23
+ type: "text";
24
+ text: string;
25
+ }[];
26
+ isError: true;
27
+ };
@@ -2,10 +2,9 @@ import { z } from 'zod';
2
2
  import { coerceArray, coerceBoolean, coerceJson } from './_coerce.js';
3
3
  import { analyticsdata as analyticsdataClient } from '@googleapis/analyticsdata';
4
4
  import { analyticsadmin as analyticsadminClient } from '@googleapis/analyticsadmin';
5
- import { accountAliasSchema } from '../accounts.js';
5
+ import { accountArgLive } from '../accounts.js';
6
6
  import { getClient } from '../client.js';
7
7
  import { handleGoogleApiError } from './_errors.js';
8
- const accountEnum = accountAliasSchema.optional();
9
8
  /** Accepts "213025502" or "properties/213025502"; rejects the identifiers
10
9
  * people paste by mistake (G-… measurement IDs, UA-… properties) with a
11
10
  * pointer to the right one. */
@@ -105,7 +104,12 @@ export function shapeMetadata(data) {
105
104
  const propertySchema = z
106
105
  .string()
107
106
  .describe('GA4 property: numeric ID like "213025502" or "properties/213025502" — NOT a "G-..." measurement ID and not "UA-...". Find yours with analytics_account_summaries.');
108
- export function registerAnalyticsTools(server) {
107
+ export function registerAnalyticsTools(server, deps = {}) {
108
+ // Per-registry, LIVE account enum + injectable client (S1.10): the
109
+ // schema follows the registry's account view at parse time, and the
110
+ // custody path is the context's, not the process global.
111
+ const accountEnum = accountArgLive(() => server.accountAliases()).optional();
112
+ const getClientFn = deps.getClientFn ?? getClient;
109
113
  server.registerTool('analytics_account_summaries', {
110
114
  description: 'List every Google Analytics (GA4) account and property this Google account can access, with their numeric property IDs. The starting point for any Analytics question ("what properties do I have?").',
111
115
  inputSchema: {
@@ -115,7 +119,7 @@ export function registerAnalyticsTools(server) {
115
119
  },
116
120
  }, async ({ account, pageSize, pageToken }) => {
117
121
  try {
118
- const auth = await getClient(account);
122
+ const auth = await getClientFn(account);
119
123
  const admin = analyticsadminClient({ version: 'v1beta', auth });
120
124
  const res = await admin.accountSummaries.list({ pageSize, pageToken });
121
125
  return {
@@ -159,7 +163,7 @@ export function registerAnalyticsTools(server) {
159
163
  if ('hint' in prop)
160
164
  return invalidProperty(prop.hint, account);
161
165
  try {
162
- const auth = await getClient(account);
166
+ const auth = await getClientFn(account);
163
167
  const dataApi = analyticsdataClient({ version: 'v1beta', auth });
164
168
  const requestBody = {
165
169
  dateRanges: [{ startDate, endDate }],
@@ -216,7 +220,7 @@ export function registerAnalyticsTools(server) {
216
220
  if ('hint' in prop)
217
221
  return invalidProperty(prop.hint, account);
218
222
  try {
219
- const auth = await getClient(account);
223
+ const auth = await getClientFn(account);
220
224
  const dataApi = analyticsdataClient({ version: 'v1beta', auth });
221
225
  const requestBody = { metrics: metrics.map((name) => ({ name })) };
222
226
  if (dimensions?.length)
@@ -251,7 +255,7 @@ export function registerAnalyticsTools(server) {
251
255
  if ('hint' in prop)
252
256
  return invalidProperty(prop.hint, account);
253
257
  try {
254
- const auth = await getClient(account);
258
+ const auth = await getClientFn(account);
255
259
  const dataApi = analyticsdataClient({ version: 'v1beta', auth });
256
260
  const res = await dataApi.properties.getMetadata({ name: `${prop.name}/metadata` });
257
261
  return {
@@ -274,11 +278,12 @@ function invalidProperty(hint, account) {
274
278
  isError: true,
275
279
  };
276
280
  }
277
- function handleAnalyticsError(error, account) {
281
+ export function handleAnalyticsError(error, account) {
278
282
  return handleGoogleApiError(error, account, {
279
283
  scope: 'Needs the "analytics" bundle on this account: add it to the scope profile, then re-auth.',
280
284
  // GA4 answers PERMISSION_DENIED for a property ACL too, and the old
281
285
  // combined hint sent those callers to re-auth a scope they already had.
282
286
  resource: 'The scope is not the problem: this Google account has no access to that GA4 property. Grant it in GA4 Admin > Property Access Management, or call analytics_account_summaries to see the properties it can read.',
287
+ bundle: 'analytics',
283
288
  });
284
289
  }
@@ -1,5 +1,6 @@
1
1
  import type { ToolRegistry } from '../registry.js';
2
- export declare function registerCalendarTools(server: ToolRegistry): void;
2
+ import { type CuratedToolDeps } from '../client.js';
3
+ export declare function registerCalendarTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
3
4
  /** Google disagrees with itself on a backwards window: events.list answers 200
4
5
  * with [], which reads as "nothing scheduled", while freebusy.query 400s on the
5
6
  * identical input. Decide locally so an empty list always means empty. Returns
@@ -1,13 +1,17 @@
1
1
  import { z } from 'zod';
2
2
  import { coerceArray, coerceBoolean } from './_coerce.js';
3
3
  import { calendar as calendarClient } from '@googleapis/calendar';
4
- import { accountAliasSchema } from '../accounts.js';
4
+ import { accountArgLive } from '../accounts.js';
5
5
  import { getClient } from '../client.js';
6
6
  import { checkOutbound } from '../outbound-allowlist.js';
7
7
  import { handleGoogleApiError, invalidParams } from './_errors.js';
8
8
  import { listResult, sliceClean } from '../trim.js';
9
- const accountEnum = accountAliasSchema.optional();
10
- export function registerCalendarTools(server) {
9
+ export function registerCalendarTools(server, deps = {}) {
10
+ // Per-registry, LIVE account enum + injectable client (S1.10): the
11
+ // schema follows the registry's account view at parse time, and the
12
+ // custody path is the context's, not the process global.
13
+ const accountEnum = accountArgLive(() => server.accountAliases()).optional();
14
+ const getClientFn = deps.getClientFn ?? getClient;
11
15
  server.registerTool('calendar_list_calendars', {
12
16
  description: 'List all calendars for a Google account',
13
17
  inputSchema: {
@@ -15,7 +19,7 @@ export function registerCalendarTools(server) {
15
19
  },
16
20
  }, async ({ account }) => {
17
21
  try {
18
- const auth = await getClient(account);
22
+ const auth = await getClientFn(account);
19
23
  const cal = calendarClient({ version: 'v3', auth });
20
24
  const res = await cal.calendarList.list();
21
25
  const calendars = (res.data.items ?? []).map((c) => ({
@@ -55,7 +59,7 @@ export function registerCalendarTools(server) {
55
59
  if (rangeError)
56
60
  return invalidParams(account, rangeError, TIME_RANGE_HINT);
57
61
  try {
58
- const auth = await getClient(account);
62
+ const auth = await getClientFn(account);
59
63
  const cal = calendarClient({ version: 'v3', auth });
60
64
  const params = {
61
65
  calendarId: calendarId ?? 'primary',
@@ -98,7 +102,7 @@ export function registerCalendarTools(server) {
98
102
  },
99
103
  }, async ({ account, eventId, calendarId }) => {
100
104
  try {
101
- const auth = await getClient(account);
105
+ const auth = await getClientFn(account);
102
106
  const cal = calendarClient({ version: 'v3', auth });
103
107
  const res = await cal.events.get({
104
108
  calendarId: calendarId ?? 'primary',
@@ -135,7 +139,7 @@ export function registerCalendarTools(server) {
135
139
  if (outbound)
136
140
  return outbound;
137
141
  }
138
- const auth = await getClient(account);
142
+ const auth = await getClientFn(account);
139
143
  const cal = calendarClient({ version: 'v3', auth });
140
144
  const event = { summary };
141
145
  if (allDay) {
@@ -190,7 +194,7 @@ export function registerCalendarTools(server) {
190
194
  if (outbound)
191
195
  return outbound;
192
196
  }
193
- const auth = await getClient(account);
197
+ const auth = await getClientFn(account);
194
198
  const cal = calendarClient({ version: 'v3', auth });
195
199
  // Fetch the event first so a 404 surfaces before we attempt the patch.
196
200
  await cal.events.get({
@@ -243,7 +247,7 @@ export function registerCalendarTools(server) {
243
247
  },
244
248
  }, async ({ account, eventId, calendarId }) => {
245
249
  try {
246
- const auth = await getClient(account);
250
+ const auth = await getClientFn(account);
247
251
  const cal = calendarClient({ version: 'v3', auth });
248
252
  await cal.events.delete({
249
253
  calendarId: calendarId ?? 'primary',
@@ -268,7 +272,7 @@ export function registerCalendarTools(server) {
268
272
  },
269
273
  }, async ({ account, calendarId, text, sendNotifications }) => {
270
274
  try {
271
- const auth = await getClient(account);
275
+ const auth = await getClientFn(account);
272
276
  const cal = calendarClient({ version: 'v3', auth });
273
277
  const res = await cal.events.quickAdd({
274
278
  calendarId: calendarId ?? 'primary',
@@ -294,7 +298,7 @@ export function registerCalendarTools(server) {
294
298
  },
295
299
  }, async ({ account, calendarId, eventId, destinationCalendarId, sendNotifications }) => {
296
300
  try {
297
- const auth = await getClient(account);
301
+ const auth = await getClientFn(account);
298
302
  const cal = calendarClient({ version: 'v3', auth });
299
303
  const res = await cal.events.move({
300
304
  calendarId,
@@ -329,7 +333,7 @@ export function registerCalendarTools(server) {
329
333
  if (rangeError)
330
334
  return invalidParams(account, rangeError, TIME_RANGE_HINT);
331
335
  try {
332
- const auth = await getClient(account);
336
+ const auth = await getClientFn(account);
333
337
  const cal = calendarClient({ version: 'v3', auth });
334
338
  const res = await cal.events.instances({
335
339
  calendarId: calendarId ?? 'primary',
@@ -367,7 +371,7 @@ export function registerCalendarTools(server) {
367
371
  const rangeError = timeRangeError(timeMin, timeMax);
368
372
  if (rangeError)
369
373
  return invalidParams(account, rangeError, TIME_RANGE_HINT);
370
- const auth = await getClient(account);
374
+ const auth = await getClientFn(account);
371
375
  const cal = calendarClient({ version: 'v3', auth });
372
376
  const res = await cal.freebusy.query({
373
377
  requestBody: {
@@ -399,7 +403,7 @@ export function registerCalendarTools(server) {
399
403
  },
400
404
  }, async ({ account, summary, description, timeZone }) => {
401
405
  try {
402
- const auth = await getClient(account);
406
+ const auth = await getClientFn(account);
403
407
  const cal = calendarClient({ version: 'v3', auth });
404
408
  const res = await cal.calendars.insert({
405
409
  requestBody: {
@@ -1,2 +1,11 @@
1
1
  import type { ToolRegistry } from '../registry.js';
2
- export declare function registerChatTools(server: ToolRegistry): void;
2
+ import type { Account } from '../accounts.js';
3
+ import { type CuratedToolDeps } from '../client.js';
4
+ export declare function registerChatTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
5
+ export declare function handleChatError(error: any, account: Account): {
6
+ content: {
7
+ type: "text";
8
+ text: string;
9
+ }[];
10
+ isError: true;
11
+ };
@@ -1,11 +1,15 @@
1
1
  import { z } from 'zod';
2
2
  import { coerceJson } from './_coerce.js';
3
3
  import { chat as chatClient } from '@googleapis/chat';
4
- import { accountAliasSchema } from '../accounts.js';
4
+ import { accountArgLive } from '../accounts.js';
5
5
  import { getClient } from '../client.js';
6
6
  import { handleGoogleApiError, invalidParams } from './_errors.js';
7
- const accountEnum = accountAliasSchema.optional();
8
- export function registerChatTools(server) {
7
+ export function registerChatTools(server, deps = {}) {
8
+ // Per-registry, LIVE account enum + injectable client (S1.10): the
9
+ // schema follows the registry's account view at parse time, and the
10
+ // custody path is the context's, not the process global.
11
+ const accountEnum = accountArgLive(() => server.accountAliases()).optional();
12
+ const getClientFn = deps.getClientFn ?? getClient;
9
13
  server.registerTool('chat_spaces_list', {
10
14
  description: 'List Google Chat spaces the user is a member of',
11
15
  inputSchema: {
@@ -16,7 +20,7 @@ export function registerChatTools(server) {
16
20
  },
17
21
  }, async ({ account, pageSize, pageToken, filter }) => {
18
22
  try {
19
- const auth = await getClient(account);
23
+ const auth = await getClientFn(account);
20
24
  const chat = chatClient({ version: 'v1', auth });
21
25
  const res = await chat.spaces.list({
22
26
  pageSize: pageSize ?? 100,
@@ -39,7 +43,7 @@ export function registerChatTools(server) {
39
43
  },
40
44
  }, async ({ account, name }) => {
41
45
  try {
42
- const auth = await getClient(account);
46
+ const auth = await getClientFn(account);
43
47
  const chat = chatClient({ version: 'v1', auth });
44
48
  const res = await chat.spaces.get({ name });
45
49
  return {
@@ -65,7 +69,7 @@ export function registerChatTools(server) {
65
69
  if (!text && (!cardsV2 || cardsV2.length === 0)) {
66
70
  return invalidParams(account, 'A message needs content: neither text nor cardsV2 was supplied.', 'Pass text for a plain message, or cardsV2 for a Card v2 payload. Both may be sent together.');
67
71
  }
68
- const auth = await getClient(account);
72
+ const auth = await getClientFn(account);
69
73
  const chat = chatClient({ version: 'v1', auth });
70
74
  const requestBody = {};
71
75
  if (text)
@@ -99,7 +103,7 @@ export function registerChatTools(server) {
99
103
  },
100
104
  }, async ({ account, parent, pageSize, pageToken, filter, orderBy }) => {
101
105
  try {
102
- const auth = await getClient(account);
106
+ const auth = await getClientFn(account);
103
107
  const chat = chatClient({ version: 'v1', auth });
104
108
  const res = await chat.spaces.messages.list({
105
109
  parent,
@@ -117,9 +121,10 @@ export function registerChatTools(server) {
117
121
  }
118
122
  });
119
123
  }
120
- function handleChatError(error, account) {
124
+ export function handleChatError(error, account) {
121
125
  return handleGoogleApiError(error, account, {
122
126
  scope: 'Chat tools require the optional "chat" scope bundle: add it to this account\'s scope profile, then re-auth.',
123
127
  resource: `Google Chat denied this space or message to "${account}". The scope is not the problem: check that the account is a member of the space, and that Chat is turned on for the Workspace.`,
128
+ bundle: 'chat',
124
129
  });
125
130
  }
@@ -1,4 +1,5 @@
1
1
  import type { ToolRegistry } from '../registry.js';
2
+ import { type CuratedToolDeps } from '../client.js';
2
3
  export interface ResolveCandidate {
3
4
  resourceName: string;
4
5
  displayName: string;
@@ -39,4 +40,4 @@ export declare function resolveContacts(candidates: ResolveCandidate[], name: st
39
40
  }[];
40
41
  resolved?: undefined;
41
42
  };
42
- export declare function registerContactsTools(server: ToolRegistry): void;
43
+ export declare function registerContactsTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
@@ -1,11 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { people as peopleClient } from '@googleapis/people';
3
- import { accountAliasSchema } from '../accounts.js';
3
+ import { accountArgLive } from '../accounts.js';
4
4
  import { getClient } from '../client.js';
5
5
  import { coerceBoolean } from './_coerce.js';
6
6
  import { handleGoogleApiError, invalidParams } from './_errors.js';
7
7
  import { listResult } from '../trim.js';
8
- const accountEnum = accountAliasSchema.optional();
9
8
  const PERSON_FIELDS = 'names,emailAddresses,phoneNumbers,organizations,addresses,photos,memberships';
10
9
  // people.getBatchGet rejects more than 200 resource names per call.
11
10
  const BATCH_GET_LIMIT = 200;
@@ -123,7 +122,12 @@ function dedupeCandidates(list) {
123
122
  }
124
123
  return [...byResource.values()];
125
124
  }
126
- export function registerContactsTools(server) {
125
+ export function registerContactsTools(server, deps = {}) {
126
+ // Per-registry, LIVE account enum + injectable client (S1.10): the
127
+ // schema follows the registry's account view at parse time, and the
128
+ // custody path is the context's, not the process global.
129
+ const accountEnum = accountArgLive(() => server.accountAliases()).optional();
130
+ const getClientFn = deps.getClientFn ?? getClient;
127
131
  server.registerTool('contacts_search', {
128
132
  description: 'Search contacts by name, email, phone, or organization',
129
133
  inputSchema: {
@@ -134,7 +138,7 @@ export function registerContactsTools(server) {
134
138
  },
135
139
  }, async ({ account, query, pageSize }) => {
136
140
  try {
137
- const auth = await getClient(account);
141
+ const auth = await getClientFn(account);
138
142
  const people = peopleClient({ version: 'v1', auth });
139
143
  // Warmup request required by the People API
140
144
  await people.people.searchContacts({
@@ -174,7 +178,7 @@ export function registerContactsTools(server) {
174
178
  },
175
179
  }, async ({ account, name, maxCandidates, includeOtherContacts }) => {
176
180
  try {
177
- const auth = await getClient(account);
181
+ const auth = await getClientFn(account);
178
182
  const people = peopleClient({ version: 'v1', auth });
179
183
  // Warmup request required by the People API before searchContacts returns hits.
180
184
  await people.people.searchContacts({ query: '', readMask: 'names' });
@@ -213,7 +217,7 @@ export function registerContactsTools(server) {
213
217
  },
214
218
  }, async ({ account, resourceName }) => {
215
219
  try {
216
- const auth = await getClient(account);
220
+ const auth = await getClientFn(account);
217
221
  const people = peopleClient({ version: 'v1', auth });
218
222
  const res = await people.people.get({
219
223
  resourceName,
@@ -244,7 +248,7 @@ export function registerContactsTools(server) {
244
248
  },
245
249
  }, async ({ account, pageSize, pageToken, sortOrder }) => {
246
250
  try {
247
- const auth = await getClient(account);
251
+ const auth = await getClientFn(account);
248
252
  const people = peopleClient({ version: 'v1', auth });
249
253
  const res = await people.people.connections.list({
250
254
  resourceName: 'people/me',
@@ -283,7 +287,7 @@ export function registerContactsTools(server) {
283
287
  },
284
288
  }, async ({ account, givenName, familyName, email, emailType, phone, phoneType, organization, jobTitle }) => {
285
289
  try {
286
- const auth = await getClient(account);
290
+ const auth = await getClientFn(account);
287
291
  const people = peopleClient({ version: 'v1', auth });
288
292
  const requestBody = {
289
293
  names: [{ givenName, familyName: familyName ?? '' }],
@@ -330,7 +334,7 @@ export function registerContactsTools(server) {
330
334
  },
331
335
  }, async ({ account, resourceName, givenName, familyName, email, emailType, phone, phoneType, organization, jobTitle }) => {
332
336
  try {
333
- const auth = await getClient(account);
337
+ const auth = await getClientFn(account);
334
338
  const people = peopleClient({ version: 'v1', auth });
335
339
  // Fetch current contact to get etag
336
340
  const current = await people.people.get({
@@ -387,7 +391,7 @@ export function registerContactsTools(server) {
387
391
  },
388
392
  }, async ({ account, resourceName }) => {
389
393
  try {
390
- const auth = await getClient(account);
394
+ const auth = await getClientFn(account);
391
395
  const people = peopleClient({ version: 'v1', auth });
392
396
  await people.people.deleteContact({ resourceName });
393
397
  return {
@@ -409,7 +413,7 @@ export function registerContactsTools(server) {
409
413
  },
410
414
  }, async ({ account, pageSize }) => {
411
415
  try {
412
- const auth = await getClient(account);
416
+ const auth = await getClientFn(account);
413
417
  const people = peopleClient({ version: 'v1', auth });
414
418
  const res = await people.contactGroups.list({
415
419
  pageSize: pageSize ?? 100,
@@ -439,7 +443,7 @@ export function registerContactsTools(server) {
439
443
  },
440
444
  }, async ({ account, groupResourceName, maxMembers }) => {
441
445
  try {
442
- const auth = await getClient(account);
446
+ const auth = await getClientFn(account);
443
447
  const people = peopleClient({ version: 'v1', auth });
444
448
  const groupRes = await people.contactGroups.get({
445
449
  resourceName: groupResourceName,
@@ -503,7 +507,7 @@ export function registerContactsTools(server) {
503
507
  },
504
508
  }, async ({ account, name }) => {
505
509
  try {
506
- const auth = await getClient(account);
510
+ const auth = await getClientFn(account);
507
511
  const people = peopleClient({ version: 'v1', auth });
508
512
  const res = await people.contactGroups.create({
509
513
  requestBody: {
@@ -1,4 +1,5 @@
1
1
  import type { ToolRegistry } from '../registry.js';
2
+ import { type CuratedToolDeps } from '../client.js';
2
3
  export declare const DOCS_INSERT_CHUNK = 5000;
3
4
  export declare function splitInsertText(text: string, maxLen?: number): string[];
4
5
  export declare function buildInsertRequests(text: string, index?: number): any[];
@@ -24,7 +25,7 @@ export declare function listTabs(tabs: any[] | undefined): {
24
25
  tabId: string;
25
26
  title: string;
26
27
  }[];
27
- export declare function registerDocsTools(server: ToolRegistry): void;
28
+ export declare function registerDocsTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
28
29
  export declare function buildParagraphStyle(input: {
29
30
  namedStyleType?: string;
30
31
  alignment?: string;