mcp-google-multi 5.4.1-alpha.2 → 6.0.0-alpha.2
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 +21 -16
- package/dist/accounts.d.ts +44 -5
- package/dist/accounts.js +267 -25
- package/dist/auth.d.ts +11 -4
- package/dist/auth.js +85 -78
- package/dist/client-config.d.ts +90 -0
- package/dist/client-config.js +282 -0
- package/dist/client.js +10 -4
- package/dist/config-file.d.ts +38 -0
- package/dist/config-file.js +117 -0
- package/dist/discover.js +57 -3
- package/dist/doctor.d.ts +86 -0
- package/dist/doctor.js +384 -0
- package/dist/env-load.d.ts +11 -0
- package/dist/env-load.js +52 -0
- package/dist/executor.d.ts +2 -0
- package/dist/executor.js +2 -1
- package/dist/fanout.js +8 -5
- package/dist/fs-atomic.d.ts +3 -0
- package/dist/fs-atomic.js +123 -0
- package/dist/http-config.d.ts +35 -0
- package/dist/http-config.js +113 -0
- package/dist/http-transport.d.ts +59 -0
- package/dist/http-transport.js +269 -0
- package/dist/identity.d.ts +24 -0
- package/dist/identity.js +19 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +199 -18
- package/dist/master-key.d.ts +53 -0
- package/dist/master-key.js +242 -0
- package/dist/mcp-token.d.ts +81 -0
- package/dist/mcp-token.js +176 -0
- package/dist/migrate-config.d.ts +7 -0
- package/dist/migrate-config.js +103 -0
- package/dist/migrate-tokens.js +4 -3
- package/dist/net-tuning.d.ts +8 -0
- package/dist/net-tuning.js +25 -0
- package/dist/oauth-as.d.ts +52 -0
- package/dist/oauth-as.js +457 -0
- package/dist/oauth-consent.d.ts +28 -0
- package/dist/oauth-consent.js +109 -0
- package/dist/open-url.d.ts +1 -0
- package/dist/open-url.js +30 -0
- package/dist/reauth-hint.d.ts +2 -0
- package/dist/reauth-hint.js +15 -0
- package/dist/registry-transfer.d.ts +41 -0
- package/dist/registry-transfer.js +219 -0
- package/dist/registry.d.ts +27 -1
- package/dist/registry.js +117 -6
- package/dist/scope-catalog.d.ts +19 -0
- package/dist/scope-catalog.js +182 -0
- package/dist/scope-observability.d.ts +78 -0
- package/dist/scope-observability.js +192 -0
- package/dist/services.js +1 -1
- package/dist/setup-prompt.d.ts +9 -0
- package/dist/setup-prompt.js +59 -0
- package/dist/ssrf-guard.d.ts +48 -0
- package/dist/ssrf-guard.js +242 -0
- package/dist/token-store.js +23 -125
- package/dist/tools/_errors.d.ts +8 -2
- package/dist/tools/_errors.js +97 -6
- package/dist/tools/account-wizard.d.ts +33 -0
- package/dist/tools/account-wizard.js +284 -0
- package/dist/tools/accounts-tool.d.ts +8 -5
- package/dist/tools/accounts-tool.js +38 -15
- package/dist/tools/admin.js +2 -2
- package/dist/tools/calendar.js +2 -2
- package/dist/tools/chat.js +2 -2
- package/dist/tools/contacts.d.ts +40 -0
- package/dist/tools/contacts.js +135 -2
- package/dist/tools/docs.d.ts +3 -0
- package/dist/tools/docs.js +60 -9
- package/dist/tools/drive.d.ts +3 -0
- package/dist/tools/drive.js +60 -8
- package/dist/tools/forms.js +4 -2
- package/dist/tools/generated/_shared.d.ts +1 -3
- package/dist/tools/generated/_shared.js +3 -3
- package/dist/tools/generated/admin.js +175 -132
- package/dist/tools/generated/appsmarket.js +6 -2
- package/dist/tools/generated/calendar.js +45 -27
- package/dist/tools/generated/chat.js +81 -47
- package/dist/tools/generated/classroom.js +131 -104
- package/dist/tools/generated/cloudidentity.js +73 -61
- package/dist/tools/generated/cloudsearch.js +59 -49
- package/dist/tools/generated/contacts.js +22 -14
- package/dist/tools/generated/drive.js +51 -35
- package/dist/tools/generated/driveactivity.js +5 -1
- package/dist/tools/generated/drivelabels.js +30 -25
- package/dist/tools/generated/forms.js +7 -3
- package/dist/tools/generated/gmail.js +73 -58
- package/dist/tools/generated/groupsmigration.js +5 -1
- package/dist/tools/generated/groupssettings.js +7 -3
- package/dist/tools/generated/keep.js +12 -7
- package/dist/tools/generated/licensing.js +11 -7
- package/dist/tools/generated/meet.js +20 -13
- package/dist/tools/generated/postmaster.js +8 -4
- package/dist/tools/generated/reseller.js +22 -17
- package/dist/tools/generated/script.js +26 -16
- package/dist/tools/generated/sheets.js +11 -7
- package/dist/tools/generated/tasks.js +6 -2
- package/dist/tools/generated/vault.js +38 -33
- package/dist/tools/generated/workspaceevents.js +12 -7
- package/dist/tools/gmail-mime.d.ts +38 -8
- package/dist/tools/gmail-mime.js +75 -71
- package/dist/tools/gmail.d.ts +31 -0
- package/dist/tools/gmail.js +483 -99
- package/dist/tools/google-api.js +7 -4
- package/dist/tools/meet.js +2 -2
- package/dist/tools/searchconsole.js +2 -2
- package/dist/tools/sheets.js +6 -2
- package/dist/tools/slides.js +4 -2
- package/dist/tools/tasks.js +2 -2
- package/dist/types.d.ts +1 -1
- package/dist/write-control.d.ts +24 -1
- package/dist/write-control.js +26 -1
- package/package.json +26 -7
package/dist/tools/gmail-mime.js
CHANGED
|
@@ -1,50 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// Chunk on codepoint boundaries: many MUAs decode each encoded-word separately, so a mid-UTF-8-sequence split renders U+FFFD.
|
|
15
|
-
const chunks = [];
|
|
16
|
-
let buffered = [];
|
|
17
|
-
for (const char of value) {
|
|
18
|
-
const charBytes = Array.from(Buffer.from(char, 'utf-8'));
|
|
19
|
-
if (buffered.length + charBytes.length > maxBytesPerChunk && buffered.length > 0) {
|
|
20
|
-
chunks.push(`${prefix}${Buffer.from(buffered).toString('base64')}${suffix}`);
|
|
21
|
-
buffered = [];
|
|
22
|
-
}
|
|
23
|
-
buffered.push(...charBytes);
|
|
24
|
-
}
|
|
25
|
-
if (buffered.length > 0) {
|
|
26
|
-
chunks.push(`${prefix}${Buffer.from(buffered).toString('base64')}${suffix}`);
|
|
27
|
-
}
|
|
28
|
-
return chunks.join('\r\n ');
|
|
29
|
-
}
|
|
30
|
-
/** Address-list headers (To/Cc/Bcc/From): RFC 2047 forbids encoded-words in the addr-spec, so only display names are encoded. */
|
|
31
|
-
export function encodeAddressHeader(value) {
|
|
32
|
-
if (value === '')
|
|
33
|
-
return '';
|
|
34
|
-
return value.split(',').map((part) => {
|
|
35
|
-
const trimmed = part.trim();
|
|
36
|
-
if (trimmed === '')
|
|
37
|
-
return '';
|
|
38
|
-
const m = trimmed.match(/^(.*?)<([^>]+)>$/);
|
|
39
|
-
if (m) {
|
|
40
|
-
const rawName = m[1].trim().replace(/^"(.*)"$/, '$1').trim();
|
|
41
|
-
const addr = m[2].trim();
|
|
42
|
-
if (rawName === '')
|
|
43
|
-
return `<${addr}>`;
|
|
44
|
-
return `${encodeHeaderValue(rawName)} <${addr}>`;
|
|
45
|
-
}
|
|
46
|
-
return trimmed;
|
|
47
|
-
}).filter(Boolean).join(', ');
|
|
1
|
+
import MailComposer from 'nodemailer/lib/mail-composer/index.js';
|
|
2
|
+
import MarkdownIt from 'markdown-it';
|
|
3
|
+
import TurndownService from 'turndown';
|
|
4
|
+
// @ts-expect-error turndown-plugin-gfm ships no type declarations
|
|
5
|
+
import { gfm } from 'turndown-plugin-gfm';
|
|
6
|
+
// D6 send: one symmetric text format. body is Markdown; text/plain = the
|
|
7
|
+
// source verbatim, text/html = this render. html:false ESCAPES raw HTML in
|
|
8
|
+
// the body (the XSS-safe default); allowRawHtml swaps to the html:true
|
|
9
|
+
// instance so an audited caller can pass literal HTML (e.g. inline color).
|
|
10
|
+
const mdSafe = new MarkdownIt({ html: false, linkify: true });
|
|
11
|
+
const mdRaw = new MarkdownIt({ html: true, linkify: true });
|
|
12
|
+
export function renderMarkdown(body, allowRawHtml = false) {
|
|
13
|
+
return (allowRawHtml ? mdRaw : mdSafe).render(body);
|
|
48
14
|
}
|
|
49
15
|
/** RFC 5322 §2.3 forbids bare CR or LF in bodies; normalize everything to CRLF. */
|
|
50
16
|
export function normalizeBodyLineEndings(body) {
|
|
@@ -121,6 +87,23 @@ export function htmlToText(html) {
|
|
|
121
87
|
.replace(/\n{3,}/g, '\n\n')
|
|
122
88
|
.trim();
|
|
123
89
|
}
|
|
90
|
+
// D6 read: HTML-only bodies convert to Markdown so the model reads structure
|
|
91
|
+
// (headings, links, lists, GFM tables), not a flat text dump. turndown's
|
|
92
|
+
// bundled @mixmark-io/domino fork does NOT execute scripts; remove() drops
|
|
93
|
+
// script/style/head entirely (turndown otherwise leaks their text content).
|
|
94
|
+
const turndownService = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced', bulletListMarker: '-' });
|
|
95
|
+
turndownService.use(gfm);
|
|
96
|
+
turndownService.remove(['script', 'style', 'head']);
|
|
97
|
+
/** Convert HTML to Markdown; on any turndown failure fall back to the
|
|
98
|
+
* plain-text extractor (caller then reports bodyFormat 'plain', not 'markdown'). */
|
|
99
|
+
export function htmlToMarkdown(html) {
|
|
100
|
+
try {
|
|
101
|
+
return { text: turndownService.turndown(html), ok: true };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return { text: htmlToText(html), ok: false };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
124
107
|
/** In-Reply-To/References need the parent's real RFC 5322 Message-ID header, not the Gmail API id;
|
|
125
108
|
* falls back to the API id so replies still thread inside Gmail. */
|
|
126
109
|
export function buildReplyHeaders(fallbackId, parentMessageIdHeader, parentReferences) {
|
|
@@ -133,30 +116,51 @@ export function buildReplyHeaders(fallbackId, parentMessageIdHeader, parentRefer
|
|
|
133
116
|
references: refs === '' ? parentId : `${refs} ${parentId}`,
|
|
134
117
|
};
|
|
135
118
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
119
|
+
/** Header-injection guard slug; caller maps to a validation_error envelope. */
|
|
120
|
+
export class HeaderInjectionError extends Error {
|
|
121
|
+
field;
|
|
122
|
+
constructor(field) {
|
|
123
|
+
super(`E_HEADER_INJECTION: "${field}" must not contain CR or LF (header injection).`);
|
|
124
|
+
this.field = field;
|
|
125
|
+
}
|
|
140
126
|
}
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
127
|
+
/**
|
|
128
|
+
* The single MIME-assembly seam for gmail_send and gmail_create_draft (A4).
|
|
129
|
+
* MailComposer owns header/RFC-2047/address encoding and boundary generation,
|
|
130
|
+
* which closes the CRLF header-injection hole in the old hand-rolled encoders.
|
|
131
|
+
* A deterministic pre-check rejects CR/LF in address/subject headers with a
|
|
132
|
+
* named error (belt-and-suspenders over MailComposer's own stripping).
|
|
133
|
+
*
|
|
134
|
+
* Bare-LF defense (Gmail's raw upload skips SMTP line-ending normalization):
|
|
135
|
+
* normalize text/html to CRLF, build with newline:"\r\n" and base64 CTE.
|
|
136
|
+
*/
|
|
137
|
+
export async function composeRaw(input) {
|
|
138
|
+
for (const field of ['from', 'to', 'cc', 'subject']) {
|
|
139
|
+
const v = input[field];
|
|
140
|
+
if (typeof v === 'string' && /[\r\n]/.test(v))
|
|
141
|
+
throw new HeaderInjectionError(field);
|
|
142
|
+
}
|
|
143
|
+
const options = {
|
|
144
|
+
from: input.from,
|
|
145
|
+
to: input.to,
|
|
146
|
+
cc: input.cc || undefined,
|
|
147
|
+
subject: input.subject,
|
|
148
|
+
text: normalizeBodyLineEndings(input.text),
|
|
149
|
+
html: input.html ? normalizeBodyLineEndings(input.html) : undefined,
|
|
150
|
+
inReplyTo: input.inReplyTo,
|
|
151
|
+
references: input.references,
|
|
152
|
+
attachments: input.attachments,
|
|
153
|
+
newline: '\r\n',
|
|
154
|
+
textEncoding: 'base64',
|
|
155
|
+
// This server reads any attachment file itself and passes a Buffer;
|
|
156
|
+
// MailComposer must never touch the filesystem or network (SSRF / local
|
|
157
|
+
// file-read defense-in-depth).
|
|
158
|
+
disableFileAccess: true,
|
|
159
|
+
disableUrlAccess: true,
|
|
161
160
|
};
|
|
161
|
+
const mail = new MailComposer(options);
|
|
162
|
+
const built = await new Promise((resolve, reject) => {
|
|
163
|
+
mail.compile().build((err, message) => (err ? reject(err) : resolve(message)));
|
|
164
|
+
});
|
|
165
|
+
return built.toString('base64url');
|
|
162
166
|
}
|
package/dist/tools/gmail.d.ts
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
|
+
import type { Account } from '../accounts.js';
|
|
3
|
+
import { type ComposeAttachment } from './gmail-mime.js';
|
|
2
4
|
import type { GmailMessageFull } from '../types.js';
|
|
5
|
+
/** Re: prefix unless the subject already carries one (case-insensitive, after
|
|
6
|
+
* trimming); never double-prefix. */
|
|
7
|
+
export declare function deriveReplySubject(sourceSubject: string): string;
|
|
8
|
+
interface ReplyDerivation {
|
|
9
|
+
inReplyTo: string;
|
|
10
|
+
references: string;
|
|
11
|
+
sourceFound: boolean;
|
|
12
|
+
to?: string;
|
|
13
|
+
cc?: string;
|
|
14
|
+
subject?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Fetch the reply source once and derive threading headers plus (auto-fill)
|
|
17
|
+
* to/cc/subject. On any fetch failure, degrade to the API id for threading and
|
|
18
|
+
* report sourceFound:false so the caller can decide (per A8 error dispositions). */
|
|
19
|
+
export declare function resolveReply(gmail: any, account: string, primaryEmail: string, replyToMessageId: string, replyAll: boolean): Promise<ReplyDerivation>;
|
|
20
|
+
export declare function readAttachments(raw: Array<{
|
|
21
|
+
path: string;
|
|
22
|
+
filename?: string;
|
|
23
|
+
contentType?: string;
|
|
24
|
+
}> | undefined, bodyBytes: number): Promise<ComposeAttachment[] | undefined>;
|
|
3
25
|
export declare function parseMessage(msg: any, bodyCap?: number, opts?: {
|
|
4
26
|
rawHtml?: boolean;
|
|
5
27
|
}): GmailMessageFull;
|
|
28
|
+
/**
|
|
29
|
+
* A9 gmail_read_batch core: fetch N ids with bounded parallelism, parse each,
|
|
30
|
+
* and bound the aggregate output. Order is preserved by input index. A per-id
|
|
31
|
+
* failure becomes a `{ id, error }` entry; an account-wide auth/scope failure
|
|
32
|
+
* is rethrown so the caller maps it to a whole-call isError. Returns the
|
|
33
|
+
* ordered per-id entries followed by a trailing counts summary.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readBatch(gmail: any, account: Account, ids: string[], full: boolean, rawHtml: boolean): Promise<any[]>;
|
|
6
36
|
export declare function registerGmailTools(server: ToolRegistry): void;
|
|
37
|
+
export {};
|