@mcp-z/mcp-gmail 1.0.0
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/LICENSE +21 -0
- package/README.md +167 -0
- package/bin/server.js +5 -0
- package/dist/cjs/constants.d.cts +11 -0
- package/dist/cjs/constants.d.ts +11 -0
- package/dist/cjs/constants.js +39 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/email/composition/rfc822-builder.d.cts +11 -0
- package/dist/cjs/email/composition/rfc822-builder.d.ts +11 -0
- package/dist/cjs/email/composition/rfc822-builder.js +24 -0
- package/dist/cjs/email/composition/rfc822-builder.js.map +1 -0
- package/dist/cjs/email/messages/fetch-message.d.cts +24 -0
- package/dist/cjs/email/messages/fetch-message.d.ts +24 -0
- package/dist/cjs/email/messages/fetch-message.js +367 -0
- package/dist/cjs/email/messages/fetch-message.js.map +1 -0
- package/dist/cjs/email/messages/messages.d.cts +7 -0
- package/dist/cjs/email/messages/messages.d.ts +7 -0
- package/dist/cjs/email/messages/messages.js +146 -0
- package/dist/cjs/email/messages/messages.js.map +1 -0
- package/dist/cjs/email/parsing/header-parsing.d.cts +1 -0
- package/dist/cjs/email/parsing/header-parsing.d.ts +1 -0
- package/dist/cjs/email/parsing/header-parsing.js +20 -0
- package/dist/cjs/email/parsing/header-parsing.js.map +1 -0
- package/dist/cjs/email/parsing/headers-utils.d.cts +5 -0
- package/dist/cjs/email/parsing/headers-utils.d.ts +5 -0
- package/dist/cjs/email/parsing/headers-utils.js +46 -0
- package/dist/cjs/email/parsing/headers-utils.js.map +1 -0
- package/dist/cjs/email/parsing/html-processing.d.cts +8 -0
- package/dist/cjs/email/parsing/html-processing.d.ts +8 -0
- package/dist/cjs/email/parsing/html-processing.js +72 -0
- package/dist/cjs/email/parsing/html-processing.js.map +1 -0
- package/dist/cjs/email/parsing/message-extraction.d.cts +2 -0
- package/dist/cjs/email/parsing/message-extraction.d.ts +2 -0
- package/dist/cjs/email/parsing/message-extraction.js +25 -0
- package/dist/cjs/email/parsing/message-extraction.js.map +1 -0
- package/dist/cjs/email/querying/execute-query.d.cts +17 -0
- package/dist/cjs/email/querying/execute-query.d.ts +17 -0
- package/dist/cjs/email/querying/execute-query.js +265 -0
- package/dist/cjs/email/querying/execute-query.js.map +1 -0
- package/dist/cjs/email/querying/pagination.d.cts +27 -0
- package/dist/cjs/email/querying/pagination.d.ts +27 -0
- package/dist/cjs/email/querying/pagination.js +533 -0
- package/dist/cjs/email/querying/pagination.js.map +1 -0
- package/dist/cjs/email/querying/query-builder.d.cts +47 -0
- package/dist/cjs/email/querying/query-builder.d.ts +47 -0
- package/dist/cjs/email/querying/query-builder.js +387 -0
- package/dist/cjs/email/querying/query-builder.js.map +1 -0
- package/dist/cjs/email/querying/search-execution.d.cts +29 -0
- package/dist/cjs/email/querying/search-execution.d.ts +29 -0
- package/dist/cjs/email/querying/search-execution.js +190 -0
- package/dist/cjs/email/querying/search-execution.js.map +1 -0
- package/dist/cjs/index.d.cts +8 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.js +314 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/labels/gmail-labels.d.cts +2 -0
- package/dist/cjs/labels/gmail-labels.d.ts +2 -0
- package/dist/cjs/labels/gmail-labels.js +206 -0
- package/dist/cjs/labels/gmail-labels.js.map +1 -0
- package/dist/cjs/lib/base64-encoding.d.cts +2 -0
- package/dist/cjs/lib/base64-encoding.d.ts +2 -0
- package/dist/cjs/lib/base64-encoding.js +32 -0
- package/dist/cjs/lib/base64-encoding.js.map +1 -0
- package/dist/cjs/lib/create-store.d.cts +2 -0
- package/dist/cjs/lib/create-store.d.ts +2 -0
- package/dist/cjs/lib/create-store.js +166 -0
- package/dist/cjs/lib/create-store.js.map +1 -0
- package/dist/cjs/lib/date-conversion.d.cts +1 -0
- package/dist/cjs/lib/date-conversion.d.ts +1 -0
- package/dist/cjs/lib/date-conversion.js +16 -0
- package/dist/cjs/lib/date-conversion.js.map +1 -0
- package/dist/cjs/lib/messages-to-row.d.cts +61 -0
- package/dist/cjs/lib/messages-to-row.d.ts +61 -0
- package/dist/cjs/lib/messages-to-row.js +243 -0
- package/dist/cjs/lib/messages-to-row.js.map +1 -0
- package/dist/cjs/mcp/index.d.cts +3 -0
- package/dist/cjs/mcp/index.d.ts +3 -0
- package/dist/cjs/mcp/index.js +66 -0
- package/dist/cjs/mcp/index.js.map +1 -0
- package/dist/cjs/mcp/prompts/draft-email.d.cts +30 -0
- package/dist/cjs/mcp/prompts/draft-email.d.ts +30 -0
- package/dist/cjs/mcp/prompts/draft-email.js +184 -0
- package/dist/cjs/mcp/prompts/draft-email.js.map +1 -0
- package/dist/cjs/mcp/prompts/index.d.cts +2 -0
- package/dist/cjs/mcp/prompts/index.d.ts +2 -0
- package/dist/cjs/mcp/prompts/index.js +26 -0
- package/dist/cjs/mcp/prompts/index.js.map +1 -0
- package/dist/cjs/mcp/prompts/query-syntax.d.cts +19 -0
- package/dist/cjs/mcp/prompts/query-syntax.d.ts +19 -0
- package/dist/cjs/mcp/prompts/query-syntax.js +169 -0
- package/dist/cjs/mcp/prompts/query-syntax.js.map +1 -0
- package/dist/cjs/mcp/resources/email.d.cts +11 -0
- package/dist/cjs/mcp/resources/email.d.ts +11 -0
- package/dist/cjs/mcp/resources/email.js +256 -0
- package/dist/cjs/mcp/resources/email.js.map +1 -0
- package/dist/cjs/mcp/resources/index.d.cts +1 -0
- package/dist/cjs/mcp/resources/index.d.ts +1 -0
- package/dist/cjs/mcp/resources/index.js +17 -0
- package/dist/cjs/mcp/resources/index.js.map +1 -0
- package/dist/cjs/mcp/tools/categories-list.d.cts +58 -0
- package/dist/cjs/mcp/tools/categories-list.d.ts +58 -0
- package/dist/cjs/mcp/tools/categories-list.js +298 -0
- package/dist/cjs/mcp/tools/categories-list.js.map +1 -0
- package/dist/cjs/mcp/tools/index.d.cts +11 -0
- package/dist/cjs/mcp/tools/index.d.ts +11 -0
- package/dist/cjs/mcp/tools/index.js +62 -0
- package/dist/cjs/mcp/tools/index.js.map +1 -0
- package/dist/cjs/mcp/tools/label-add.d.cts +61 -0
- package/dist/cjs/mcp/tools/label-add.d.ts +61 -0
- package/dist/cjs/mcp/tools/label-add.js +280 -0
- package/dist/cjs/mcp/tools/label-add.js.map +1 -0
- package/dist/cjs/mcp/tools/label-delete.d.cts +71 -0
- package/dist/cjs/mcp/tools/label-delete.d.ts +71 -0
- package/dist/cjs/mcp/tools/label-delete.js +476 -0
- package/dist/cjs/mcp/tools/label-delete.js.map +1 -0
- package/dist/cjs/mcp/tools/labels-list.d.cts +75 -0
- package/dist/cjs/mcp/tools/labels-list.d.ts +75 -0
- package/dist/cjs/mcp/tools/labels-list.js +298 -0
- package/dist/cjs/mcp/tools/labels-list.js.map +1 -0
- package/dist/cjs/mcp/tools/message-get.d.cts +146 -0
- package/dist/cjs/mcp/tools/message-get.d.ts +146 -0
- package/dist/cjs/mcp/tools/message-get.js +317 -0
- package/dist/cjs/mcp/tools/message-get.js.map +1 -0
- package/dist/cjs/mcp/tools/message-mark-read.d.cts +50 -0
- package/dist/cjs/mcp/tools/message-mark-read.d.ts +50 -0
- package/dist/cjs/mcp/tools/message-mark-read.js +254 -0
- package/dist/cjs/mcp/tools/message-mark-read.js.map +1 -0
- package/dist/cjs/mcp/tools/message-move-to-trash.d.cts +71 -0
- package/dist/cjs/mcp/tools/message-move-to-trash.d.ts +71 -0
- package/dist/cjs/mcp/tools/message-move-to-trash.js +450 -0
- package/dist/cjs/mcp/tools/message-move-to-trash.js.map +1 -0
- package/dist/cjs/mcp/tools/message-respond.d.cts +60 -0
- package/dist/cjs/mcp/tools/message-respond.d.ts +60 -0
- package/dist/cjs/mcp/tools/message-respond.js +367 -0
- package/dist/cjs/mcp/tools/message-respond.js.map +1 -0
- package/dist/cjs/mcp/tools/message-search.d.cts +182 -0
- package/dist/cjs/mcp/tools/message-search.d.ts +182 -0
- package/dist/cjs/mcp/tools/message-search.js +405 -0
- package/dist/cjs/mcp/tools/message-search.js.map +1 -0
- package/dist/cjs/mcp/tools/message-send.d.cts +87 -0
- package/dist/cjs/mcp/tools/message-send.d.ts +87 -0
- package/dist/cjs/mcp/tools/message-send.js +288 -0
- package/dist/cjs/mcp/tools/message-send.js.map +1 -0
- package/dist/cjs/mcp/tools/messages-export-csv.d.cts +84 -0
- package/dist/cjs/mcp/tools/messages-export-csv.d.ts +84 -0
- package/dist/cjs/mcp/tools/messages-export-csv.js +530 -0
- package/dist/cjs/mcp/tools/messages-export-csv.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/schemas/gmail-query-schema.d.cts +36 -0
- package/dist/cjs/schemas/gmail-query-schema.d.ts +36 -0
- package/dist/cjs/schemas/gmail-query-schema.js +117 -0
- package/dist/cjs/schemas/gmail-query-schema.js.map +1 -0
- package/dist/cjs/schemas/index.d.cts +1 -0
- package/dist/cjs/schemas/index.d.ts +1 -0
- package/dist/cjs/schemas/index.js +19 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/setup/config.d.cts +48 -0
- package/dist/cjs/setup/config.d.ts +48 -0
- package/dist/cjs/setup/config.js +217 -0
- package/dist/cjs/setup/config.js.map +1 -0
- package/dist/cjs/setup/http.d.cts +8 -0
- package/dist/cjs/setup/http.d.ts +8 -0
- package/dist/cjs/setup/http.js +267 -0
- package/dist/cjs/setup/http.js.map +1 -0
- package/dist/cjs/setup/index.d.cts +5 -0
- package/dist/cjs/setup/index.d.ts +5 -0
- package/dist/cjs/setup/index.js +46 -0
- package/dist/cjs/setup/index.js.map +1 -0
- package/dist/cjs/setup/oauth-google.d.cts +54 -0
- package/dist/cjs/setup/oauth-google.d.ts +54 -0
- package/dist/cjs/setup/oauth-google.js +332 -0
- package/dist/cjs/setup/oauth-google.js.map +1 -0
- package/dist/cjs/setup/runtime.d.cts +12 -0
- package/dist/cjs/setup/runtime.d.ts +12 -0
- package/dist/cjs/setup/runtime.js +489 -0
- package/dist/cjs/setup/runtime.js.map +1 -0
- package/dist/cjs/setup/stdio.d.cts +7 -0
- package/dist/cjs/setup/stdio.d.ts +7 -0
- package/dist/cjs/setup/stdio.js +239 -0
- package/dist/cjs/setup/stdio.js.map +1 -0
- package/dist/cjs/types.d.cts +54 -0
- package/dist/cjs/types.d.ts +54 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/constants.d.ts +11 -0
- package/dist/esm/constants.js +14 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/email/composition/rfc822-builder.d.ts +11 -0
- package/dist/esm/email/composition/rfc822-builder.js +13 -0
- package/dist/esm/email/composition/rfc822-builder.js.map +1 -0
- package/dist/esm/email/messages/fetch-message.d.ts +24 -0
- package/dist/esm/email/messages/fetch-message.js +123 -0
- package/dist/esm/email/messages/fetch-message.js.map +1 -0
- package/dist/esm/email/messages/messages.d.ts +7 -0
- package/dist/esm/email/messages/messages.js +91 -0
- package/dist/esm/email/messages/messages.js.map +1 -0
- package/dist/esm/email/parsing/header-parsing.d.ts +1 -0
- package/dist/esm/email/parsing/header-parsing.js +1 -0
- package/dist/esm/email/parsing/header-parsing.js.map +1 -0
- package/dist/esm/email/parsing/headers-utils.d.ts +5 -0
- package/dist/esm/email/parsing/headers-utils.js +25 -0
- package/dist/esm/email/parsing/headers-utils.js.map +1 -0
- package/dist/esm/email/parsing/html-processing.d.ts +8 -0
- package/dist/esm/email/parsing/html-processing.js +39 -0
- package/dist/esm/email/parsing/html-processing.js.map +1 -0
- package/dist/esm/email/parsing/message-extraction.d.ts +2 -0
- package/dist/esm/email/parsing/message-extraction.js +3 -0
- package/dist/esm/email/parsing/message-extraction.js.map +1 -0
- package/dist/esm/email/querying/execute-query.d.ts +17 -0
- package/dist/esm/email/querying/execute-query.js +45 -0
- package/dist/esm/email/querying/execute-query.js.map +1 -0
- package/dist/esm/email/querying/pagination.d.ts +27 -0
- package/dist/esm/email/querying/pagination.js +152 -0
- package/dist/esm/email/querying/pagination.js.map +1 -0
- package/dist/esm/email/querying/query-builder.d.ts +47 -0
- package/dist/esm/email/querying/query-builder.js +306 -0
- package/dist/esm/email/querying/query-builder.js.map +1 -0
- package/dist/esm/email/querying/search-execution.d.ts +29 -0
- package/dist/esm/email/querying/search-execution.js +35 -0
- package/dist/esm/email/querying/search-execution.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +34 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/labels/gmail-labels.d.ts +2 -0
- package/dist/esm/labels/gmail-labels.js +43 -0
- package/dist/esm/labels/gmail-labels.js.map +1 -0
- package/dist/esm/lib/base64-encoding.d.ts +2 -0
- package/dist/esm/lib/base64-encoding.js +13 -0
- package/dist/esm/lib/base64-encoding.js.map +1 -0
- package/dist/esm/lib/create-store.d.ts +2 -0
- package/dist/esm/lib/create-store.js +6 -0
- package/dist/esm/lib/create-store.js.map +1 -0
- package/dist/esm/lib/date-conversion.d.ts +1 -0
- package/dist/esm/lib/date-conversion.js +5 -0
- package/dist/esm/lib/date-conversion.js.map +1 -0
- package/dist/esm/lib/messages-to-row.d.ts +61 -0
- package/dist/esm/lib/messages-to-row.js +188 -0
- package/dist/esm/lib/messages-to-row.js.map +1 -0
- package/dist/esm/mcp/index.d.ts +3 -0
- package/dist/esm/mcp/index.js +6 -0
- package/dist/esm/mcp/index.js.map +1 -0
- package/dist/esm/mcp/prompts/draft-email.d.ts +30 -0
- package/dist/esm/mcp/prompts/draft-email.js +37 -0
- package/dist/esm/mcp/prompts/draft-email.js.map +1 -0
- package/dist/esm/mcp/prompts/index.d.ts +2 -0
- package/dist/esm/mcp/prompts/index.js +2 -0
- package/dist/esm/mcp/prompts/index.js.map +1 -0
- package/dist/esm/mcp/prompts/query-syntax.d.ts +19 -0
- package/dist/esm/mcp/prompts/query-syntax.js +74 -0
- package/dist/esm/mcp/prompts/query-syntax.js.map +1 -0
- package/dist/esm/mcp/resources/email.d.ts +11 -0
- package/dist/esm/mcp/resources/email.js +92 -0
- package/dist/esm/mcp/resources/email.js.map +1 -0
- package/dist/esm/mcp/resources/index.d.ts +1 -0
- package/dist/esm/mcp/resources/index.js +1 -0
- package/dist/esm/mcp/resources/index.js.map +1 -0
- package/dist/esm/mcp/tools/categories-list.d.ts +58 -0
- package/dist/esm/mcp/tools/categories-list.js +124 -0
- package/dist/esm/mcp/tools/categories-list.js.map +1 -0
- package/dist/esm/mcp/tools/index.d.ts +11 -0
- package/dist/esm/mcp/tools/index.js +11 -0
- package/dist/esm/mcp/tools/index.js.map +1 -0
- package/dist/esm/mcp/tools/label-add.d.ts +61 -0
- package/dist/esm/mcp/tools/label-add.js +101 -0
- package/dist/esm/mcp/tools/label-add.js.map +1 -0
- package/dist/esm/mcp/tools/label-delete.d.ts +71 -0
- package/dist/esm/mcp/tools/label-delete.js +186 -0
- package/dist/esm/mcp/tools/label-delete.js.map +1 -0
- package/dist/esm/mcp/tools/labels-list.d.ts +75 -0
- package/dist/esm/mcp/tools/labels-list.js +122 -0
- package/dist/esm/mcp/tools/labels-list.js.map +1 -0
- package/dist/esm/mcp/tools/message-get.d.ts +146 -0
- package/dist/esm/mcp/tools/message-get.js +145 -0
- package/dist/esm/mcp/tools/message-get.js.map +1 -0
- package/dist/esm/mcp/tools/message-mark-read.d.ts +50 -0
- package/dist/esm/mcp/tools/message-mark-read.js +80 -0
- package/dist/esm/mcp/tools/message-mark-read.js.map +1 -0
- package/dist/esm/mcp/tools/message-move-to-trash.d.ts +71 -0
- package/dist/esm/mcp/tools/message-move-to-trash.js +167 -0
- package/dist/esm/mcp/tools/message-move-to-trash.js.map +1 -0
- package/dist/esm/mcp/tools/message-respond.d.ts +60 -0
- package/dist/esm/mcp/tools/message-respond.js +152 -0
- package/dist/esm/mcp/tools/message-respond.js.map +1 -0
- package/dist/esm/mcp/tools/message-search.d.ts +182 -0
- package/dist/esm/mcp/tools/message-search.js +180 -0
- package/dist/esm/mcp/tools/message-search.js.map +1 -0
- package/dist/esm/mcp/tools/message-send.d.ts +87 -0
- package/dist/esm/mcp/tools/message-send.js +115 -0
- package/dist/esm/mcp/tools/message-send.js.map +1 -0
- package/dist/esm/mcp/tools/messages-export-csv.d.ts +84 -0
- package/dist/esm/mcp/tools/messages-export-csv.js +261 -0
- package/dist/esm/mcp/tools/messages-export-csv.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/schemas/gmail-query-schema.d.ts +36 -0
- package/dist/esm/schemas/gmail-query-schema.js +72 -0
- package/dist/esm/schemas/gmail-query-schema.js.map +1 -0
- package/dist/esm/schemas/index.d.ts +1 -0
- package/dist/esm/schemas/index.js +1 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/dist/esm/setup/config.d.ts +48 -0
- package/dist/esm/setup/config.js +175 -0
- package/dist/esm/setup/config.js.map +1 -0
- package/dist/esm/setup/http.d.ts +8 -0
- package/dist/esm/setup/http.js +61 -0
- package/dist/esm/setup/http.js.map +1 -0
- package/dist/esm/setup/index.d.ts +5 -0
- package/dist/esm/setup/index.js +5 -0
- package/dist/esm/setup/index.js.map +1 -0
- package/dist/esm/setup/oauth-google.d.ts +54 -0
- package/dist/esm/setup/oauth-google.js +142 -0
- package/dist/esm/setup/oauth-google.js.map +1 -0
- package/dist/esm/setup/runtime.d.ts +12 -0
- package/dist/esm/setup/runtime.js +115 -0
- package/dist/esm/setup/runtime.js.map +1 -0
- package/dist/esm/setup/stdio.d.ts +7 -0
- package/dist/esm/setup/stdio.js +38 -0
- package/dist/esm/setup/stdio.js.map +1 -0
- package/dist/esm/types.d.ts +54 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gmail category mappings - case insensitive input to exact system labels
|
|
3
|
+
*/ const GMAIL_CATEGORIES = {
|
|
4
|
+
primary: 'CATEGORY_PERSONAL',
|
|
5
|
+
social: 'CATEGORY_SOCIAL',
|
|
6
|
+
promotions: 'CATEGORY_PROMOTIONS',
|
|
7
|
+
updates: 'CATEGORY_UPDATES',
|
|
8
|
+
forums: 'CATEGORY_FORUMS'
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Validate and map category name to Gmail system label
|
|
12
|
+
* Throws error for invalid categories (fail fast principle)
|
|
13
|
+
*/ function mapCategoryToLabel(category) {
|
|
14
|
+
// Input validation - fail fast on invalid input
|
|
15
|
+
if (!category || typeof category !== 'string') {
|
|
16
|
+
throw new Error(`Invalid category: expected non-empty string, got ${typeof category}`);
|
|
17
|
+
}
|
|
18
|
+
const trimmed = category.trim();
|
|
19
|
+
if (trimmed === '') {
|
|
20
|
+
throw new Error('Invalid category: empty string after trimming');
|
|
21
|
+
}
|
|
22
|
+
// Fail fast on unknown categories
|
|
23
|
+
const normalizedCategory = trimmed.toLowerCase();
|
|
24
|
+
const systemLabel = GMAIL_CATEGORIES[normalizedCategory];
|
|
25
|
+
if (!systemLabel) {
|
|
26
|
+
throw new Error(`Invalid Gmail category: "${category}". Valid categories: ${Object.keys(GMAIL_CATEGORIES).join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
return systemLabel;
|
|
29
|
+
}
|
|
30
|
+
export function toGmailQuery(query, options = {}) {
|
|
31
|
+
const slashDates = options.dateSlash !== false;
|
|
32
|
+
const subjectIncludes = [];
|
|
33
|
+
const bodyIncludes = [];
|
|
34
|
+
const textIncludes = [];
|
|
35
|
+
const fromIncludes = [];
|
|
36
|
+
const toIncludes = [];
|
|
37
|
+
const ccIncludes = [];
|
|
38
|
+
const bccIncludes = [];
|
|
39
|
+
const categoriesIncludes = [];
|
|
40
|
+
const labelIncludes = [];
|
|
41
|
+
let hasAttachment;
|
|
42
|
+
function p(s) {
|
|
43
|
+
return `(${String(s !== null && s !== void 0 ? s : '')})`;
|
|
44
|
+
}
|
|
45
|
+
function fmt(d) {
|
|
46
|
+
const str = String(d !== null && d !== void 0 ? d : '');
|
|
47
|
+
return slashDates ? str.replace(/-/g, '/') : str;
|
|
48
|
+
}
|
|
49
|
+
function fv(field, raw) {
|
|
50
|
+
const rawVal = String(raw !== null && raw !== void 0 ? raw : '');
|
|
51
|
+
if (rawVal.trim() === '') {
|
|
52
|
+
throw new Error(`Invalid ${field} value: empty string`);
|
|
53
|
+
}
|
|
54
|
+
const v = quote(rawVal);
|
|
55
|
+
if (field === 'subject') subjectIncludes.push(rawVal);
|
|
56
|
+
if (field === 'body') bodyIncludes.push(rawVal);
|
|
57
|
+
if (field === 'text') {
|
|
58
|
+
textIncludes.push(rawVal);
|
|
59
|
+
bodyIncludes.push(rawVal);
|
|
60
|
+
}
|
|
61
|
+
if (field === 'from') fromIncludes.push(rawVal);
|
|
62
|
+
if (field === 'to') toIncludes.push(rawVal);
|
|
63
|
+
if (field === 'cc') ccIncludes.push(rawVal);
|
|
64
|
+
if (field === 'bcc') bccIncludes.push(rawVal);
|
|
65
|
+
if (field === 'categories') {
|
|
66
|
+
const systemLabel = mapCategoryToLabel(rawVal);
|
|
67
|
+
categoriesIncludes.push(rawVal);
|
|
68
|
+
return `label:${systemLabel}`;
|
|
69
|
+
}
|
|
70
|
+
if (field === 'label') {
|
|
71
|
+
// Direct passthrough to Gmail's label syntax (case-sensitive)
|
|
72
|
+
labelIncludes.push(rawVal);
|
|
73
|
+
return `label:${quote(rawVal)}`;
|
|
74
|
+
}
|
|
75
|
+
if (field === 'text' || field === 'body') return p(`subject:${v} OR ${v}`);
|
|
76
|
+
return `${field}:${v}`;
|
|
77
|
+
}
|
|
78
|
+
function chain(op, arr) {
|
|
79
|
+
if (arr.length === 0) throw new Error(`chain: empty array for ${op} operation`);
|
|
80
|
+
if (arr.length === 1) {
|
|
81
|
+
var _arr_;
|
|
82
|
+
const first = (_arr_ = arr[0]) !== null && _arr_ !== void 0 ? _arr_ : '';
|
|
83
|
+
return first;
|
|
84
|
+
}
|
|
85
|
+
return p(arr.join(` ${op} `));
|
|
86
|
+
}
|
|
87
|
+
function fieldExpr(field, op) {
|
|
88
|
+
if (op.$any) {
|
|
89
|
+
const results = op.$any.map((v)=>fv(field, String(v !== null && v !== void 0 ? v : '')));
|
|
90
|
+
return chain('OR', results);
|
|
91
|
+
}
|
|
92
|
+
if (op.$all) {
|
|
93
|
+
const results = op.$all.map((v)=>fv(field, String(v !== null && v !== void 0 ? v : '')));
|
|
94
|
+
return chain('AND', results);
|
|
95
|
+
}
|
|
96
|
+
if (op.$none) {
|
|
97
|
+
const results = op.$none.map((v)=>fv(field, String(v !== null && v !== void 0 ? v : '')));
|
|
98
|
+
return `NOT ${p(chain('OR', results))}`;
|
|
99
|
+
}
|
|
100
|
+
throw new Error(`Unknown field operator ${JSON.stringify(op)}`);
|
|
101
|
+
}
|
|
102
|
+
function dateExpr(d) {
|
|
103
|
+
var _parts_;
|
|
104
|
+
const parts = [];
|
|
105
|
+
if (d && typeof d === 'object' && '$gte' in d) {
|
|
106
|
+
parts.push(`after:${fmt(d.$gte)}`);
|
|
107
|
+
}
|
|
108
|
+
if (d && typeof d === 'object' && '$lt' in d) {
|
|
109
|
+
parts.push(`before:${fmt(d.$lt)}`);
|
|
110
|
+
}
|
|
111
|
+
return parts.length > 1 ? p(parts.join(' AND ')) : (_parts_ = parts[0]) !== null && _parts_ !== void 0 ? _parts_ : '';
|
|
112
|
+
}
|
|
113
|
+
function fieldKeys() {
|
|
114
|
+
return [
|
|
115
|
+
'from',
|
|
116
|
+
'to',
|
|
117
|
+
'cc',
|
|
118
|
+
'bcc',
|
|
119
|
+
'subject',
|
|
120
|
+
'text',
|
|
121
|
+
'body',
|
|
122
|
+
'categories',
|
|
123
|
+
'label'
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
function quote(s) {
|
|
127
|
+
const str = String(s !== null && s !== void 0 ? s : '');
|
|
128
|
+
return /[\s"()]/.test(str) ? `"${str.replace(/["\\]/g, (m)=>`\\${m}`)}"` : str;
|
|
129
|
+
}
|
|
130
|
+
function emit(n) {
|
|
131
|
+
if (!n || typeof n !== 'object') return '';
|
|
132
|
+
if ('$and' in n && Array.isArray(n.$and)) {
|
|
133
|
+
return p(n.$and.map(emit).join(' AND '));
|
|
134
|
+
}
|
|
135
|
+
if ('$or' in n && Array.isArray(n.$or)) {
|
|
136
|
+
return p(n.$or.map(emit).join(' OR '));
|
|
137
|
+
}
|
|
138
|
+
if ('$not' in n) {
|
|
139
|
+
return `NOT ${emit(n.$not)}`;
|
|
140
|
+
}
|
|
141
|
+
if ('hasAttachment' in n) {
|
|
142
|
+
hasAttachment = true;
|
|
143
|
+
return 'has:attachment';
|
|
144
|
+
}
|
|
145
|
+
if ('fuzzyPhrase' in n) {
|
|
146
|
+
// Gmail fuzzy phrase matching using quoted strings
|
|
147
|
+
// Example: { fuzzyPhrase: "quarterly report" } -> "quarterly report"
|
|
148
|
+
return quote(n.fuzzyPhrase);
|
|
149
|
+
}
|
|
150
|
+
if ('date' in n) {
|
|
151
|
+
return dateExpr(n.date);
|
|
152
|
+
}
|
|
153
|
+
// Handle empty objects
|
|
154
|
+
const keys = Object.keys(n);
|
|
155
|
+
if (keys.length === 0) return '';
|
|
156
|
+
if (keys.length === 1) {
|
|
157
|
+
var _keys_;
|
|
158
|
+
const k = String((_keys_ = keys[0]) !== null && _keys_ !== void 0 ? _keys_ : '');
|
|
159
|
+
if (fieldKeys().includes(k)) {
|
|
160
|
+
const op = n[k];
|
|
161
|
+
// Handle string-only category queries properly (C2 fix)
|
|
162
|
+
const normalizedOp = typeof op === 'string' ? {
|
|
163
|
+
$any: [
|
|
164
|
+
op
|
|
165
|
+
]
|
|
166
|
+
} : op !== null && op !== void 0 ? op : {};
|
|
167
|
+
return fieldExpr(k, normalizedOp);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
throw new Error(`Unknown node: ${JSON.stringify(n)}`);
|
|
171
|
+
}
|
|
172
|
+
function emitTop(n) {
|
|
173
|
+
if (!n || typeof n !== 'object') return '';
|
|
174
|
+
// Handle empty objects
|
|
175
|
+
if (Object.keys(n).length === 0) return '';
|
|
176
|
+
if ('$and' in n && Array.isArray(n.$and)) {
|
|
177
|
+
return n.$and.map(emit).join(' ');
|
|
178
|
+
}
|
|
179
|
+
if ('$or' in n && Array.isArray(n.$or)) {
|
|
180
|
+
return n.$or.map(emit).join(' OR ');
|
|
181
|
+
}
|
|
182
|
+
if ('$not' in n) {
|
|
183
|
+
return `NOT ${emit(n.$not)}`;
|
|
184
|
+
}
|
|
185
|
+
if ('hasAttachment' in n) {
|
|
186
|
+
hasAttachment = true;
|
|
187
|
+
return 'has:attachment';
|
|
188
|
+
}
|
|
189
|
+
if ('fuzzyPhrase' in n) {
|
|
190
|
+
// Gmail fuzzy phrase matching using quoted strings
|
|
191
|
+
return quote(n.fuzzyPhrase);
|
|
192
|
+
}
|
|
193
|
+
if ('date' in n) {
|
|
194
|
+
return dateExpr(n.date);
|
|
195
|
+
}
|
|
196
|
+
return emit(n);
|
|
197
|
+
}
|
|
198
|
+
const q = emitTop(query);
|
|
199
|
+
const filters = {};
|
|
200
|
+
if (subjectIncludes.length) filters.subjectIncludes = subjectIncludes;
|
|
201
|
+
if (bodyIncludes.length) filters.bodyIncludes = bodyIncludes;
|
|
202
|
+
if (textIncludes.length) filters.textIncludes = textIncludes;
|
|
203
|
+
if (fromIncludes.length) filters.fromIncludes = fromIncludes;
|
|
204
|
+
if (toIncludes.length) filters.toIncludes = toIncludes;
|
|
205
|
+
if (ccIncludes.length) filters.ccIncludes = ccIncludes;
|
|
206
|
+
if (bccIncludes.length) filters.bccIncludes = bccIncludes;
|
|
207
|
+
if (categoriesIncludes.length) filters.categoriesIncludes = categoriesIncludes;
|
|
208
|
+
if (labelIncludes.length) filters.labelIncludes = labelIncludes;
|
|
209
|
+
if (typeof hasAttachment === 'boolean') filters.hasAttachment = hasAttachment;
|
|
210
|
+
return {
|
|
211
|
+
q: q !== null && q !== void 0 ? q : '',
|
|
212
|
+
filters
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export function extractFiltersFromParsed(parsed) {
|
|
216
|
+
const filters = {
|
|
217
|
+
subjectIncludes: [],
|
|
218
|
+
bodyIncludes: [],
|
|
219
|
+
textIncludes: [],
|
|
220
|
+
categoriesIncludes: [],
|
|
221
|
+
labelIncludes: []
|
|
222
|
+
};
|
|
223
|
+
function walk(node) {
|
|
224
|
+
if (!node || typeof node !== 'object') return;
|
|
225
|
+
if ('$and' in node && Array.isArray(node.$and)) {
|
|
226
|
+
node.$and.forEach(walk);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if ('$or' in node && Array.isArray(node.$or)) {
|
|
230
|
+
node.$or.forEach(walk);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if ('$not' in node) {
|
|
234
|
+
walk(node.$not);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if ('hasAttachment' in node) {
|
|
238
|
+
filters.hasAttachment = node.hasAttachment === true;
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if ('date' in node) {
|
|
242
|
+
const dateObj = node.date;
|
|
243
|
+
if (dateObj && typeof dateObj === 'object') {
|
|
244
|
+
if ('$gte' in dateObj) {
|
|
245
|
+
filters.since = String(dateObj.$gte);
|
|
246
|
+
}
|
|
247
|
+
if ('$lt' in dateObj) {
|
|
248
|
+
filters.before = String(dateObj.$lt);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const keys = Object.keys(node || {});
|
|
254
|
+
for (const k of keys){
|
|
255
|
+
const v = node[k];
|
|
256
|
+
if (!v || typeof v !== 'object') continue;
|
|
257
|
+
if (k === 'subject') {
|
|
258
|
+
var _filters_subjectIncludes, _filters_subjectIncludes1, _filters_subjectIncludes2;
|
|
259
|
+
if ('$any' in v && Array.isArray(v.$any)) (_filters_subjectIncludes = filters.subjectIncludes) === null || _filters_subjectIncludes === void 0 ? void 0 : _filters_subjectIncludes.push(...v.$any);
|
|
260
|
+
if ('$all' in v && Array.isArray(v.$all)) (_filters_subjectIncludes1 = filters.subjectIncludes) === null || _filters_subjectIncludes1 === void 0 ? void 0 : _filters_subjectIncludes1.push(...v.$all);
|
|
261
|
+
if ('$none' in v && Array.isArray(v.$none)) (_filters_subjectIncludes2 = filters.subjectIncludes) === null || _filters_subjectIncludes2 === void 0 ? void 0 : _filters_subjectIncludes2.push(...v.$none);
|
|
262
|
+
} else if (k === 'body') {
|
|
263
|
+
var _filters_bodyIncludes, _filters_bodyIncludes1, _filters_bodyIncludes2;
|
|
264
|
+
if ('$any' in v && Array.isArray(v.$any)) (_filters_bodyIncludes = filters.bodyIncludes) === null || _filters_bodyIncludes === void 0 ? void 0 : _filters_bodyIncludes.push(...v.$any);
|
|
265
|
+
if ('$all' in v && Array.isArray(v.$all)) (_filters_bodyIncludes1 = filters.bodyIncludes) === null || _filters_bodyIncludes1 === void 0 ? void 0 : _filters_bodyIncludes1.push(...v.$all);
|
|
266
|
+
if ('$none' in v && Array.isArray(v.$none)) (_filters_bodyIncludes2 = filters.bodyIncludes) === null || _filters_bodyIncludes2 === void 0 ? void 0 : _filters_bodyIncludes2.push(...v.$none);
|
|
267
|
+
} else if (k === 'text') {
|
|
268
|
+
var _filters_textIncludes, _filters_textIncludes1, _filters_textIncludes2;
|
|
269
|
+
if ('$any' in v && Array.isArray(v.$any)) (_filters_textIncludes = filters.textIncludes) === null || _filters_textIncludes === void 0 ? void 0 : _filters_textIncludes.push(...v.$any);
|
|
270
|
+
if ('$all' in v && Array.isArray(v.$all)) (_filters_textIncludes1 = filters.textIncludes) === null || _filters_textIncludes1 === void 0 ? void 0 : _filters_textIncludes1.push(...v.$all);
|
|
271
|
+
if ('$none' in v && Array.isArray(v.$none)) (_filters_textIncludes2 = filters.textIncludes) === null || _filters_textIncludes2 === void 0 ? void 0 : _filters_textIncludes2.push(...v.$none);
|
|
272
|
+
} else if (k === 'categories') {
|
|
273
|
+
// Validate all categories (will throw on invalid)
|
|
274
|
+
if ('$any' in v && Array.isArray(v.$any)) {
|
|
275
|
+
var _filters_categoriesIncludes;
|
|
276
|
+
v.$any.forEach((cat)=>{
|
|
277
|
+
mapCategoryToLabel(String(cat));
|
|
278
|
+
});
|
|
279
|
+
(_filters_categoriesIncludes = filters.categoriesIncludes) === null || _filters_categoriesIncludes === void 0 ? void 0 : _filters_categoriesIncludes.push(...v.$any.map(String));
|
|
280
|
+
}
|
|
281
|
+
if ('$all' in v && Array.isArray(v.$all)) {
|
|
282
|
+
var _filters_categoriesIncludes1;
|
|
283
|
+
v.$all.forEach((cat)=>{
|
|
284
|
+
mapCategoryToLabel(String(cat));
|
|
285
|
+
});
|
|
286
|
+
(_filters_categoriesIncludes1 = filters.categoriesIncludes) === null || _filters_categoriesIncludes1 === void 0 ? void 0 : _filters_categoriesIncludes1.push(...v.$all.map(String));
|
|
287
|
+
}
|
|
288
|
+
if ('$none' in v && Array.isArray(v.$none)) {
|
|
289
|
+
var _filters_categoriesIncludes2;
|
|
290
|
+
v.$none.forEach((cat)=>{
|
|
291
|
+
mapCategoryToLabel(String(cat));
|
|
292
|
+
});
|
|
293
|
+
(_filters_categoriesIncludes2 = filters.categoriesIncludes) === null || _filters_categoriesIncludes2 === void 0 ? void 0 : _filters_categoriesIncludes2.push(...v.$none.map(String));
|
|
294
|
+
}
|
|
295
|
+
} else if (k === 'label') {
|
|
296
|
+
var _filters_labelIncludes, _filters_labelIncludes1, _filters_labelIncludes2;
|
|
297
|
+
// Direct passthrough for labels (case-sensitive)
|
|
298
|
+
if ('$any' in v && Array.isArray(v.$any)) (_filters_labelIncludes = filters.labelIncludes) === null || _filters_labelIncludes === void 0 ? void 0 : _filters_labelIncludes.push(...v.$any.map(String));
|
|
299
|
+
if ('$all' in v && Array.isArray(v.$all)) (_filters_labelIncludes1 = filters.labelIncludes) === null || _filters_labelIncludes1 === void 0 ? void 0 : _filters_labelIncludes1.push(...v.$all.map(String));
|
|
300
|
+
if ('$none' in v && Array.isArray(v.$none)) (_filters_labelIncludes2 = filters.labelIncludes) === null || _filters_labelIncludes2 === void 0 ? void 0 : _filters_labelIncludes2.push(...v.$none.map(String));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
walk(parsed);
|
|
305
|
+
return filters;
|
|
306
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/email/querying/query-builder.ts"],"sourcesContent":["import type { GmailQuery as QueryNode } from '../../schemas/gmail-query-schema.js';\n\n/**\n * Field operator interface for query filters\n */\nexport interface FieldOperator {\n $any?: string[];\n $all?: string[];\n $none?: string[];\n}\n\n/**\n * Field query interface with support for all email fields including categories and labels\n */\nexport interface FieldQuery {\n from?: FieldOperator | string;\n to?: FieldOperator | string;\n cc?: FieldOperator | string;\n bcc?: FieldOperator | string;\n subject?: FieldOperator | string;\n text?: FieldOperator | string;\n body?: FieldOperator | string;\n categories?: FieldOperator | string;\n label?: FieldOperator | string;\n}\n\n/**\n * Filter extraction result with all collected values from a query\n */\nexport interface Filters {\n subjectIncludes?: string[];\n bodyIncludes?: string[];\n textIncludes?: string[];\n fromIncludes?: string[];\n toIncludes?: string[];\n ccIncludes?: string[];\n bccIncludes?: string[];\n categoriesIncludes?: string[];\n labelIncludes?: string[];\n hasAttachment?: boolean;\n since?: string;\n before?: string;\n}\n\n/**\n * Gmail category mappings - case insensitive input to exact system labels\n */\nconst GMAIL_CATEGORIES = {\n primary: 'CATEGORY_PERSONAL',\n social: 'CATEGORY_SOCIAL',\n promotions: 'CATEGORY_PROMOTIONS',\n updates: 'CATEGORY_UPDATES',\n forums: 'CATEGORY_FORUMS',\n} as const;\n\n/**\n * Validate and map category name to Gmail system label\n * Throws error for invalid categories (fail fast principle)\n */\nfunction mapCategoryToLabel(category: string): string {\n // Input validation - fail fast on invalid input\n if (!category || typeof category !== 'string') {\n throw new Error(`Invalid category: expected non-empty string, got ${typeof category}`);\n }\n\n const trimmed = category.trim();\n if (trimmed === '') {\n throw new Error('Invalid category: empty string after trimming');\n }\n\n // Fail fast on unknown categories\n const normalizedCategory = trimmed.toLowerCase();\n const systemLabel = GMAIL_CATEGORIES[normalizedCategory as keyof typeof GMAIL_CATEGORIES];\n\n if (!systemLabel) {\n throw new Error(`Invalid Gmail category: \"${category}\". Valid categories: ${Object.keys(GMAIL_CATEGORIES).join(', ')}`);\n }\n\n return systemLabel;\n}\n\nexport function toGmailQuery(query: QueryNode, options: { dateSlash?: boolean } = {}) {\n const slashDates = options.dateSlash !== false;\n const subjectIncludes: string[] = [];\n const bodyIncludes: string[] = [];\n const textIncludes: string[] = [];\n const fromIncludes: string[] = [];\n const toIncludes: string[] = [];\n const ccIncludes: string[] = [];\n const bccIncludes: string[] = [];\n const categoriesIncludes: string[] = [];\n const labelIncludes: string[] = [];\n let hasAttachment: boolean | undefined;\n\n function p(s: unknown) {\n return `(${String(s ?? '')})`;\n }\n function fmt(d: unknown) {\n const str = String(d ?? '');\n return slashDates ? str.replace(/-/g, '/') : str;\n }\n\n function fv(field: string, raw?: unknown) {\n const rawVal = String(raw ?? '');\n if (rawVal.trim() === '') {\n throw new Error(`Invalid ${field} value: empty string`);\n }\n const v = quote(rawVal);\n if (field === 'subject') subjectIncludes.push(rawVal);\n if (field === 'body') bodyIncludes.push(rawVal);\n if (field === 'text') {\n textIncludes.push(rawVal);\n bodyIncludes.push(rawVal);\n }\n if (field === 'from') fromIncludes.push(rawVal);\n if (field === 'to') toIncludes.push(rawVal);\n if (field === 'cc') ccIncludes.push(rawVal);\n if (field === 'bcc') bccIncludes.push(rawVal);\n if (field === 'categories') {\n const systemLabel = mapCategoryToLabel(rawVal);\n categoriesIncludes.push(rawVal);\n return `label:${systemLabel}`;\n }\n if (field === 'label') {\n // Direct passthrough to Gmail's label syntax (case-sensitive)\n labelIncludes.push(rawVal);\n return `label:${quote(rawVal)}`;\n }\n if (field === 'text' || field === 'body') return p(`subject:${v} OR ${v}`);\n return `${field}:${v}`;\n }\n\n function chain(op: 'AND' | 'OR', arr: string[]) {\n if (arr.length === 0) throw new Error(`chain: empty array for ${op} operation`);\n if (arr.length === 1) {\n const first = arr[0] ?? '';\n return first;\n }\n return p(arr.join(` ${op} `));\n }\n\n function fieldExpr(field: string, op: FieldOperator) {\n if (op.$any) {\n const results = op.$any.map((v: string) => fv(field, String(v ?? '')));\n return chain('OR', results);\n }\n if (op.$all) {\n const results = op.$all.map((v: string) => fv(field, String(v ?? '')));\n return chain('AND', results);\n }\n if (op.$none) {\n const results = op.$none.map((v: string) => fv(field, String(v ?? '')));\n return `NOT ${p(chain('OR', results))}`;\n }\n throw new Error(`Unknown field operator ${JSON.stringify(op)}`);\n }\n\n function dateExpr(d: unknown) {\n const parts: string[] = [];\n if (d && typeof d === 'object' && '$gte' in d) {\n parts.push(`after:${fmt(d.$gte)}`);\n }\n if (d && typeof d === 'object' && '$lt' in d) {\n parts.push(`before:${fmt(d.$lt)}`);\n }\n return parts.length > 1 ? p(parts.join(' AND ')) : (parts[0] ?? '');\n }\n\n function fieldKeys() {\n return ['from', 'to', 'cc', 'bcc', 'subject', 'text', 'body', 'categories', 'label'];\n }\n\n function quote(s?: unknown) {\n const str = String(s ?? '');\n return /[\\s\"()]/.test(str) ? `\"${str.replace(/[\"\\\\]/g, (m) => `\\\\${m}`)}\"` : str;\n }\n\n function emit(n: unknown): string {\n if (!n || typeof n !== 'object') return '';\n\n if ('$and' in n && Array.isArray(n.$and)) {\n return p(n.$and.map(emit).join(' AND '));\n }\n if ('$or' in n && Array.isArray(n.$or)) {\n return p(n.$or.map(emit).join(' OR '));\n }\n if ('$not' in n) {\n return `NOT ${emit(n.$not)}`;\n }\n if ('hasAttachment' in n) {\n hasAttachment = true;\n return 'has:attachment';\n }\n if ('fuzzyPhrase' in n) {\n // Gmail fuzzy phrase matching using quoted strings\n // Example: { fuzzyPhrase: \"quarterly report\" } -> \"quarterly report\"\n return quote(n.fuzzyPhrase);\n }\n if ('date' in n) {\n return dateExpr(n.date);\n }\n\n // Handle empty objects\n const keys = Object.keys(n);\n if (keys.length === 0) return '';\n\n if (keys.length === 1) {\n const k = String(keys[0] ?? '');\n if (fieldKeys().includes(k)) {\n const op = (n as Record<string, unknown>)[k];\n // Handle string-only category queries properly (C2 fix)\n const normalizedOp: FieldOperator = typeof op === 'string' ? { $any: [op] } : (op ?? {});\n return fieldExpr(k, normalizedOp);\n }\n }\n throw new Error(`Unknown node: ${JSON.stringify(n)}`);\n }\n\n function emitTop(n: unknown): string {\n if (!n || typeof n !== 'object') return '';\n\n // Handle empty objects\n if (Object.keys(n).length === 0) return '';\n\n if ('$and' in n && Array.isArray(n.$and)) {\n return n.$and.map(emit).join(' ');\n }\n if ('$or' in n && Array.isArray(n.$or)) {\n return n.$or.map(emit).join(' OR ');\n }\n if ('$not' in n) {\n return `NOT ${emit(n.$not)}`;\n }\n if ('hasAttachment' in n) {\n hasAttachment = true;\n return 'has:attachment';\n }\n if ('fuzzyPhrase' in n) {\n // Gmail fuzzy phrase matching using quoted strings\n return quote(n.fuzzyPhrase);\n }\n if ('date' in n) {\n return dateExpr(n.date);\n }\n return emit(n);\n }\n\n const q = emitTop(query);\n const filters: Record<string, unknown> = {};\n if (subjectIncludes.length) filters.subjectIncludes = subjectIncludes;\n if (bodyIncludes.length) filters.bodyIncludes = bodyIncludes;\n if (textIncludes.length) filters.textIncludes = textIncludes;\n if (fromIncludes.length) filters.fromIncludes = fromIncludes;\n if (toIncludes.length) filters.toIncludes = toIncludes;\n if (ccIncludes.length) filters.ccIncludes = ccIncludes;\n if (bccIncludes.length) filters.bccIncludes = bccIncludes;\n if (categoriesIncludes.length) filters.categoriesIncludes = categoriesIncludes;\n if (labelIncludes.length) filters.labelIncludes = labelIncludes;\n if (typeof hasAttachment === 'boolean') filters.hasAttachment = hasAttachment;\n return { q: q ?? '', filters };\n}\n\nexport function extractFiltersFromParsed(parsed: QueryNode): Filters {\n const filters: Filters = {\n subjectIncludes: [],\n bodyIncludes: [],\n textIncludes: [],\n categoriesIncludes: [],\n labelIncludes: [],\n };\n\n function walk(node: unknown): void {\n if (!node || typeof node !== 'object') return;\n\n if ('$and' in node && Array.isArray(node.$and)) {\n node.$and.forEach(walk);\n return;\n }\n if ('$or' in node && Array.isArray(node.$or)) {\n node.$or.forEach(walk);\n return;\n }\n if ('$not' in node) {\n walk(node.$not);\n return;\n }\n if ('hasAttachment' in node) {\n filters.hasAttachment = node.hasAttachment === true;\n return;\n }\n if ('date' in node) {\n const dateObj = node.date;\n if (dateObj && typeof dateObj === 'object') {\n if ('$gte' in dateObj) {\n filters.since = String(dateObj.$gte);\n }\n if ('$lt' in dateObj) {\n filters.before = String(dateObj.$lt);\n }\n }\n return;\n }\n\n const keys = Object.keys(node || {});\n for (const k of keys) {\n const v = (node as Record<string, unknown>)[k];\n if (!v || typeof v !== 'object') continue;\n\n if (k === 'subject') {\n if ('$any' in v && Array.isArray(v.$any)) filters.subjectIncludes?.push(...v.$any);\n if ('$all' in v && Array.isArray(v.$all)) filters.subjectIncludes?.push(...v.$all);\n if ('$none' in v && Array.isArray(v.$none)) filters.subjectIncludes?.push(...v.$none);\n } else if (k === 'body') {\n if ('$any' in v && Array.isArray(v.$any)) filters.bodyIncludes?.push(...v.$any);\n if ('$all' in v && Array.isArray(v.$all)) filters.bodyIncludes?.push(...v.$all);\n if ('$none' in v && Array.isArray(v.$none)) filters.bodyIncludes?.push(...v.$none);\n } else if (k === 'text') {\n if ('$any' in v && Array.isArray(v.$any)) filters.textIncludes?.push(...v.$any);\n if ('$all' in v && Array.isArray(v.$all)) filters.textIncludes?.push(...v.$all);\n if ('$none' in v && Array.isArray(v.$none)) filters.textIncludes?.push(...v.$none);\n } else if (k === 'categories') {\n // Validate all categories (will throw on invalid)\n if ('$any' in v && Array.isArray(v.$any)) {\n v.$any.forEach((cat: unknown) => {\n mapCategoryToLabel(String(cat));\n });\n filters.categoriesIncludes?.push(...v.$any.map(String));\n }\n if ('$all' in v && Array.isArray(v.$all)) {\n v.$all.forEach((cat: unknown) => {\n mapCategoryToLabel(String(cat));\n });\n filters.categoriesIncludes?.push(...v.$all.map(String));\n }\n if ('$none' in v && Array.isArray(v.$none)) {\n v.$none.forEach((cat: unknown) => {\n mapCategoryToLabel(String(cat));\n });\n filters.categoriesIncludes?.push(...v.$none.map(String));\n }\n } else if (k === 'label') {\n // Direct passthrough for labels (case-sensitive)\n if ('$any' in v && Array.isArray(v.$any)) filters.labelIncludes?.push(...v.$any.map(String));\n if ('$all' in v && Array.isArray(v.$all)) filters.labelIncludes?.push(...v.$all.map(String));\n if ('$none' in v && Array.isArray(v.$none)) filters.labelIncludes?.push(...v.$none.map(String));\n }\n }\n }\n walk(parsed);\n return filters;\n}\n"],"names":["GMAIL_CATEGORIES","primary","social","promotions","updates","forums","mapCategoryToLabel","category","Error","trimmed","trim","normalizedCategory","toLowerCase","systemLabel","Object","keys","join","toGmailQuery","query","options","slashDates","dateSlash","subjectIncludes","bodyIncludes","textIncludes","fromIncludes","toIncludes","ccIncludes","bccIncludes","categoriesIncludes","labelIncludes","hasAttachment","p","s","String","fmt","d","str","replace","fv","field","raw","rawVal","v","quote","push","chain","op","arr","length","first","fieldExpr","$any","results","map","$all","$none","JSON","stringify","dateExpr","parts","$gte","$lt","fieldKeys","test","m","emit","n","Array","isArray","$and","$or","$not","fuzzyPhrase","date","k","includes","normalizedOp","emitTop","q","filters","extractFiltersFromParsed","parsed","walk","node","forEach","dateObj","since","before","cat"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { gmail_v1 } from 'googleapis';
|
|
2
|
+
import type { GmailQuery as QueryNode } from '../../schemas/gmail-query-schema.js';
|
|
3
|
+
import type { Logger } from '../../types.js';
|
|
4
|
+
export interface GmailSearchOptions {
|
|
5
|
+
readonly query?: QueryNode;
|
|
6
|
+
readonly pageSize?: number;
|
|
7
|
+
readonly includeBody?: boolean;
|
|
8
|
+
readonly pageToken: string | undefined;
|
|
9
|
+
readonly logger: Logger;
|
|
10
|
+
}
|
|
11
|
+
export interface GmailEmailSummary {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly provider: 'gmail';
|
|
14
|
+
readonly threadId?: string;
|
|
15
|
+
readonly date?: string;
|
|
16
|
+
readonly from?: string;
|
|
17
|
+
readonly fromName?: string;
|
|
18
|
+
readonly to?: string;
|
|
19
|
+
readonly cc?: string;
|
|
20
|
+
readonly bcc?: string;
|
|
21
|
+
readonly subject?: string;
|
|
22
|
+
readonly snippet?: string;
|
|
23
|
+
readonly body?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface GmailSearchResult {
|
|
26
|
+
readonly messages: gmail_v1.Schema$Message[];
|
|
27
|
+
readonly nextPageToken: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
export declare function searchMessages(gmail: gmail_v1.Gmail, opts: GmailSearchOptions): Promise<GmailSearchResult>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { fetchMessagesPage } from './pagination.js';
|
|
2
|
+
import { toGmailQuery } from './query-builder.js';
|
|
3
|
+
function buildGmailQ(query) {
|
|
4
|
+
var _ref;
|
|
5
|
+
if (!query) return '';
|
|
6
|
+
const emitted = toGmailQuery(query);
|
|
7
|
+
return (_ref = emitted === null || emitted === void 0 ? void 0 : emitted.q) !== null && _ref !== void 0 ? _ref : '';
|
|
8
|
+
}
|
|
9
|
+
export async function searchMessages(gmail, opts) {
|
|
10
|
+
const { query, pageSize = 50, includeBody = false, pageToken, logger } = opts;
|
|
11
|
+
const gmailQ = buildGmailQ(query);
|
|
12
|
+
const metadataHeaders = [
|
|
13
|
+
'Date',
|
|
14
|
+
'Subject',
|
|
15
|
+
'From',
|
|
16
|
+
'To',
|
|
17
|
+
'Cc',
|
|
18
|
+
'Bcc'
|
|
19
|
+
];
|
|
20
|
+
// Always fetch metadata headers - body is additional content, not a replacement for headers
|
|
21
|
+
const pageParams = {
|
|
22
|
+
gmailQ,
|
|
23
|
+
pageSize,
|
|
24
|
+
body: includeBody,
|
|
25
|
+
metadataHeaders,
|
|
26
|
+
pageToken,
|
|
27
|
+
logger
|
|
28
|
+
};
|
|
29
|
+
const result = await fetchMessagesPage(gmail, pageParams);
|
|
30
|
+
// Return raw Gmail messages - transformation happens in caller
|
|
31
|
+
return {
|
|
32
|
+
messages: result.messages,
|
|
33
|
+
nextPageToken: result.nextPageToken
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/email/querying/search-execution.ts"],"sourcesContent":["import type { gmail_v1 } from 'googleapis';\nimport type { GmailQuery as QueryNode } from '../../schemas/gmail-query-schema.js';\nimport type { Logger } from '../../types.js';\nimport { type FetchMessagesPageParams, fetchMessagesPage } from './pagination.js';\nimport { toGmailQuery } from './query-builder.js';\n\nexport interface GmailSearchOptions {\n readonly query?: QueryNode;\n readonly pageSize?: number;\n readonly includeBody?: boolean;\n readonly pageToken: string | undefined; // For pagination support - explicit undefined allowed\n readonly logger: Logger;\n}\n\nexport interface GmailEmailSummary {\n readonly id: string;\n readonly provider: 'gmail';\n readonly threadId?: string;\n readonly date?: string;\n readonly from?: string;\n readonly fromName?: string;\n readonly to?: string;\n readonly cc?: string;\n readonly bcc?: string;\n readonly subject?: string;\n readonly snippet?: string;\n readonly body?: string;\n}\n\nfunction buildGmailQ(query: QueryNode | undefined): string {\n if (!query) return '';\n const emitted = toGmailQuery(query);\n return emitted?.q ?? '';\n}\n\nexport interface GmailSearchResult {\n readonly messages: gmail_v1.Schema$Message[]; // Raw Gmail API messages for transformation by caller\n readonly nextPageToken: string | undefined;\n}\n\nexport async function searchMessages(gmail: gmail_v1.Gmail, opts: GmailSearchOptions): Promise<GmailSearchResult> {\n const { query, pageSize = 50, includeBody = false, pageToken, logger } = opts;\n const gmailQ = buildGmailQ(query);\n const metadataHeaders = ['Date', 'Subject', 'From', 'To', 'Cc', 'Bcc'];\n // Always fetch metadata headers - body is additional content, not a replacement for headers\n const pageParams: FetchMessagesPageParams = {\n gmailQ,\n pageSize,\n body: includeBody,\n metadataHeaders,\n pageToken,\n logger,\n };\n const result = await fetchMessagesPage(gmail, pageParams);\n\n // Return raw Gmail messages - transformation happens in caller\n return {\n messages: result.messages,\n nextPageToken: result.nextPageToken,\n };\n}\n"],"names":["fetchMessagesPage","toGmailQuery","buildGmailQ","query","emitted","q","searchMessages","gmail","opts","pageSize","includeBody","pageToken","logger","gmailQ","metadataHeaders","pageParams","body","result","messages","nextPageToken"],"mappings":"AAGA,SAAuCA,iBAAiB,QAAQ,kBAAkB;AAClF,SAASC,YAAY,QAAQ,qBAAqB;AAyBlD,SAASC,YAAYC,KAA4B;;IAC/C,IAAI,CAACA,OAAO,OAAO;IACnB,MAAMC,UAAUH,aAAaE;IAC7B,eAAOC,oBAAAA,8BAAAA,QAASC,CAAC,uCAAI;AACvB;AAOA,OAAO,eAAeC,eAAeC,KAAqB,EAAEC,IAAwB;IAClF,MAAM,EAAEL,KAAK,EAAEM,WAAW,EAAE,EAAEC,cAAc,KAAK,EAAEC,SAAS,EAAEC,MAAM,EAAE,GAAGJ;IACzE,MAAMK,SAASX,YAAYC;IAC3B,MAAMW,kBAAkB;QAAC;QAAQ;QAAW;QAAQ;QAAM;QAAM;KAAM;IACtE,4FAA4F;IAC5F,MAAMC,aAAsC;QAC1CF;QACAJ;QACAO,MAAMN;QACNI;QACAH;QACAC;IACF;IACA,MAAMK,SAAS,MAAMjB,kBAAkBO,OAAOQ;IAE9C,+DAA+D;IAC/D,OAAO;QACLG,UAAUD,OAAOC,QAAQ;QACzBC,eAAeF,OAAOE,aAAa;IACrC;AACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ServerConfig } from './types.js';
|
|
2
|
+
export { GOOGLE_SCOPE } from './constants.js';
|
|
3
|
+
export * as mcp from './mcp/index.js';
|
|
4
|
+
export * as schemas from './schemas/index.js';
|
|
5
|
+
export * as setup from './setup/index.js';
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export declare function startServer(config: ServerConfig): Promise<void>;
|
|
8
|
+
export default function main(): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createConfig, handleVersionHelp } from './setup/config.js';
|
|
2
|
+
import { createHTTPServer } from './setup/http.js';
|
|
3
|
+
import { createStdioServer } from './setup/stdio.js';
|
|
4
|
+
export { GOOGLE_SCOPE } from './constants.js';
|
|
5
|
+
import * as _mcp from './mcp/index.js';
|
|
6
|
+
export { _mcp as mcp };
|
|
7
|
+
import * as _schemas from './schemas/index.js';
|
|
8
|
+
export { _schemas as schemas };
|
|
9
|
+
import * as _setup from './setup/index.js';
|
|
10
|
+
export { _setup as setup };
|
|
11
|
+
export * from './types.js';
|
|
12
|
+
export async function startServer(config) {
|
|
13
|
+
const { logger, close } = config.transport.type === 'stdio' ? await createStdioServer(config) : await createHTTPServer(config);
|
|
14
|
+
process.on('SIGINT', async ()=>{
|
|
15
|
+
await close();
|
|
16
|
+
process.exit(0);
|
|
17
|
+
});
|
|
18
|
+
logger.info(`Server started with ${config.transport.type} transport`);
|
|
19
|
+
await new Promise(()=>{});
|
|
20
|
+
}
|
|
21
|
+
export default async function main() {
|
|
22
|
+
// Check for help/version flags FIRST, before config parsing
|
|
23
|
+
const versionHelpResult = handleVersionHelp(process.argv);
|
|
24
|
+
if (versionHelpResult.handled) {
|
|
25
|
+
console.log(versionHelpResult.output);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
// Only parse config if no help/version flags
|
|
29
|
+
const config = createConfig();
|
|
30
|
+
await startServer(config);
|
|
31
|
+
}
|
|
32
|
+
if (process.argv[1] === new URL(import.meta.url).pathname) {
|
|
33
|
+
main();
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/index.ts"],"sourcesContent":["import { createConfig, handleVersionHelp } from './setup/config.js';\nimport { createHTTPServer } from './setup/http.js';\nimport { createStdioServer } from './setup/stdio.js';\nimport type { ServerConfig } from './types.js';\n\nexport { GOOGLE_SCOPE } from './constants.ts';\nexport * as mcp from './mcp/index.js';\nexport * as schemas from './schemas/index.js';\nexport * as setup from './setup/index.js';\nexport * from './types.js';\n\nexport async function startServer(config: ServerConfig): Promise<void> {\n const { logger, close } = config.transport.type === 'stdio' ? await createStdioServer(config) : await createHTTPServer(config);\n\n process.on('SIGINT', async () => {\n await close();\n process.exit(0);\n });\n\n logger.info(`Server started with ${config.transport.type} transport`);\n await new Promise(() => {});\n}\n\nexport default async function main(): Promise<void> {\n // Check for help/version flags FIRST, before config parsing\n const versionHelpResult = handleVersionHelp(process.argv);\n if (versionHelpResult.handled) {\n console.log(versionHelpResult.output);\n process.exit(0);\n }\n\n // Only parse config if no help/version flags\n const config = createConfig();\n await startServer(config);\n}\n\nif (process.argv[1] === new URL(import.meta.url).pathname) {\n main();\n}\n"],"names":["createConfig","handleVersionHelp","createHTTPServer","createStdioServer","GOOGLE_SCOPE","mcp","schemas","setup","startServer","config","logger","close","transport","type","process","on","exit","info","Promise","main","versionHelpResult","argv","handled","console","log","output","URL","url","pathname"],"mappings":"AAAA,SAASA,YAAY,EAAEC,iBAAiB,QAAQ,oBAAoB;AACpE,SAASC,gBAAgB,QAAQ,kBAAkB;AACnD,SAASC,iBAAiB,QAAQ,mBAAmB;AAGrD,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,sBAAqB,iBAAiB;AAAtC,SAAO,QAAKC,GAAG,GAAuB;AACtC,0BAAyB,qBAAqB;AAA9C,SAAO,YAAKC,OAAO,GAA2B;AAC9C,wBAAuB,mBAAmB;AAA1C,SAAO,UAAKC,KAAK,GAAyB;AAC1C,cAAc,aAAa;AAE3B,OAAO,eAAeC,YAAYC,MAAoB;IACpD,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGF,OAAOG,SAAS,CAACC,IAAI,KAAK,UAAU,MAAMV,kBAAkBM,UAAU,MAAMP,iBAAiBO;IAEvHK,QAAQC,EAAE,CAAC,UAAU;QACnB,MAAMJ;QACNG,QAAQE,IAAI,CAAC;IACf;IAEAN,OAAOO,IAAI,CAAC,CAAC,oBAAoB,EAAER,OAAOG,SAAS,CAACC,IAAI,CAAC,UAAU,CAAC;IACpE,MAAM,IAAIK,QAAQ,KAAO;AAC3B;AAEA,eAAe,eAAeC;IAC5B,4DAA4D;IAC5D,MAAMC,oBAAoBnB,kBAAkBa,QAAQO,IAAI;IACxD,IAAID,kBAAkBE,OAAO,EAAE;QAC7BC,QAAQC,GAAG,CAACJ,kBAAkBK,MAAM;QACpCX,QAAQE,IAAI,CAAC;IACf;IAEA,6CAA6C;IAC7C,MAAMP,SAAST;IACf,MAAMQ,YAAYC;AACpB;AAEA,IAAIK,QAAQO,IAAI,CAAC,EAAE,KAAK,IAAIK,IAAI,YAAYC,GAAG,EAAEC,QAAQ,EAAE;IACzDT;AACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export async function ensureLabelId(gmail, userId, labelName) {
|
|
2
|
+
var _listed_data, _created_data;
|
|
3
|
+
// Built-in system labels: pass through by name
|
|
4
|
+
const builtInLabels = {
|
|
5
|
+
INBOX: 'INBOX',
|
|
6
|
+
SPAM: 'SPAM',
|
|
7
|
+
TRASH: 'TRASH',
|
|
8
|
+
UNREAD: 'UNREAD',
|
|
9
|
+
STARRED: 'STARRED',
|
|
10
|
+
IMPORTANT: 'IMPORTANT',
|
|
11
|
+
SENT: 'SENT',
|
|
12
|
+
DRAFT: 'DRAFT',
|
|
13
|
+
CATEGORY_PERSONAL: 'CATEGORY_PERSONAL',
|
|
14
|
+
CATEGORY_SOCIAL: 'CATEGORY_SOCIAL',
|
|
15
|
+
CATEGORY_PROMOTIONS: 'CATEGORY_PROMOTIONS',
|
|
16
|
+
CATEGORY_UPDATES: 'CATEGORY_UPDATES',
|
|
17
|
+
CATEGORY_FORUMS: 'CATEGORY_FORUMS'
|
|
18
|
+
};
|
|
19
|
+
const upper = labelName.toUpperCase();
|
|
20
|
+
if (builtInLabels[upper]) return builtInLabels[upper];
|
|
21
|
+
// Try to find an existing user label by name
|
|
22
|
+
const listed = await gmail.users.labels.list({
|
|
23
|
+
userId
|
|
24
|
+
});
|
|
25
|
+
const labels = Array.isArray(listed === null || listed === void 0 ? void 0 : (_listed_data = listed.data) === null || _listed_data === void 0 ? void 0 : _listed_data.labels) ? listed.data.labels : [];
|
|
26
|
+
const existing = labels.find((l)=>{
|
|
27
|
+
const label = l;
|
|
28
|
+
return (label === null || label === void 0 ? void 0 : label.name) === labelName;
|
|
29
|
+
});
|
|
30
|
+
const existingTyped = existing;
|
|
31
|
+
if (existingTyped === null || existingTyped === void 0 ? void 0 : existingTyped.id) return String(existingTyped.id);
|
|
32
|
+
// Create the label if it doesn't exist
|
|
33
|
+
const created = await gmail.users.labels.create({
|
|
34
|
+
userId,
|
|
35
|
+
requestBody: {
|
|
36
|
+
name: labelName,
|
|
37
|
+
labelListVisibility: 'labelShow',
|
|
38
|
+
messageListVisibility: 'show'
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
if (!(created === null || created === void 0 ? void 0 : (_created_data = created.data) === null || _created_data === void 0 ? void 0 : _created_data.id)) throw new Error('Failed to create label');
|
|
42
|
+
return created.data.id;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/labels/gmail-labels.ts"],"sourcesContent":["import type { gmail_v1 } from 'googleapis';\n\nexport async function ensureLabelId(gmail: gmail_v1.Gmail, userId: string, labelName: string): Promise<string> {\n // Built-in system labels: pass through by name\n const builtInLabels: Record<string, string> = {\n INBOX: 'INBOX',\n SPAM: 'SPAM',\n TRASH: 'TRASH',\n UNREAD: 'UNREAD',\n STARRED: 'STARRED',\n IMPORTANT: 'IMPORTANT',\n SENT: 'SENT',\n DRAFT: 'DRAFT',\n CATEGORY_PERSONAL: 'CATEGORY_PERSONAL',\n CATEGORY_SOCIAL: 'CATEGORY_SOCIAL',\n CATEGORY_PROMOTIONS: 'CATEGORY_PROMOTIONS',\n CATEGORY_UPDATES: 'CATEGORY_UPDATES',\n CATEGORY_FORUMS: 'CATEGORY_FORUMS',\n };\n\n const upper = labelName.toUpperCase();\n if (builtInLabels[upper]) return builtInLabels[upper];\n\n // Try to find an existing user label by name\n const listed = await gmail.users.labels.list({ userId });\n const labels = Array.isArray(listed?.data?.labels) ? listed.data.labels : [];\n const existing = labels.find((l: unknown) => {\n const label = l as { name?: unknown; id?: unknown };\n return label?.name === labelName;\n });\n const existingTyped = existing as { id?: unknown } | undefined;\n if (existingTyped?.id) return String(existingTyped.id);\n\n // Create the label if it doesn't exist\n const created = await gmail.users.labels.create({\n userId,\n requestBody: {\n name: labelName,\n labelListVisibility: 'labelShow',\n messageListVisibility: 'show',\n },\n });\n if (!created?.data?.id) throw new Error('Failed to create label');\n return created.data.id as string;\n}\n"],"names":["ensureLabelId","gmail","userId","labelName","listed","created","builtInLabels","INBOX","SPAM","TRASH","UNREAD","STARRED","IMPORTANT","SENT","DRAFT","CATEGORY_PERSONAL","CATEGORY_SOCIAL","CATEGORY_PROMOTIONS","CATEGORY_UPDATES","CATEGORY_FORUMS","upper","toUpperCase","users","labels","list","Array","isArray","data","existing","find","l","label","name","existingTyped","id","String","create","requestBody","labelListVisibility","messageListVisibility","Error"],"mappings":"AAEA,OAAO,eAAeA,cAAcC,KAAqB,EAAEC,MAAc,EAAEC,SAAiB;QAuB7DC,cAiBxBC;IAvCL,+CAA+C;IAC/C,MAAMC,gBAAwC;QAC5CC,OAAO;QACPC,MAAM;QACNC,OAAO;QACPC,QAAQ;QACRC,SAAS;QACTC,WAAW;QACXC,MAAM;QACNC,OAAO;QACPC,mBAAmB;QACnBC,iBAAiB;QACjBC,qBAAqB;QACrBC,kBAAkB;QAClBC,iBAAiB;IACnB;IAEA,MAAMC,QAAQjB,UAAUkB,WAAW;IACnC,IAAIf,aAAa,CAACc,MAAM,EAAE,OAAOd,aAAa,CAACc,MAAM;IAErD,6CAA6C;IAC7C,MAAMhB,SAAS,MAAMH,MAAMqB,KAAK,CAACC,MAAM,CAACC,IAAI,CAAC;QAAEtB;IAAO;IACtD,MAAMqB,SAASE,MAAMC,OAAO,CAACtB,mBAAAA,8BAAAA,eAAAA,OAAQuB,IAAI,cAAZvB,mCAAAA,aAAcmB,MAAM,IAAInB,OAAOuB,IAAI,CAACJ,MAAM,GAAG,EAAE;IAC5E,MAAMK,WAAWL,OAAOM,IAAI,CAAC,CAACC;QAC5B,MAAMC,QAAQD;QACd,OAAOC,CAAAA,kBAAAA,4BAAAA,MAAOC,IAAI,MAAK7B;IACzB;IACA,MAAM8B,gBAAgBL;IACtB,IAAIK,0BAAAA,oCAAAA,cAAeC,EAAE,EAAE,OAAOC,OAAOF,cAAcC,EAAE;IAErD,uCAAuC;IACvC,MAAM7B,UAAU,MAAMJ,MAAMqB,KAAK,CAACC,MAAM,CAACa,MAAM,CAAC;QAC9ClC;QACAmC,aAAa;YACXL,MAAM7B;YACNmC,qBAAqB;YACrBC,uBAAuB;QACzB;IACF;IACA,IAAI,EAAClC,oBAAAA,+BAAAA,gBAAAA,QAASsB,IAAI,cAAbtB,oCAAAA,cAAe6B,EAAE,GAAE,MAAM,IAAIM,MAAM;IACxC,OAAOnC,QAAQsB,IAAI,CAACO,EAAE;AACxB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { safeBase64UrlDecode } from '@mcp-z/email';
|
|
2
|
+
export function safeBase64Decode(raw) {
|
|
3
|
+
if (!raw) return '';
|
|
4
|
+
try {
|
|
5
|
+
return safeBase64UrlDecode(raw);
|
|
6
|
+
} catch {
|
|
7
|
+
// Fallback to original input if decoding fails
|
|
8
|
+
return String(raw);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function b64url(input) {
|
|
12
|
+
return Buffer.from(input).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/lib/base64-encoding.ts"],"sourcesContent":["import { safeBase64UrlDecode } from '@mcp-z/email';\n\nexport function safeBase64Decode(raw?: string): string {\n if (!raw) return '';\n try {\n return safeBase64UrlDecode(raw);\n } catch {\n // Fallback to original input if decoding fails\n return String(raw);\n }\n}\n\nexport function b64url(input: string): string {\n return Buffer.from(input).toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n"],"names":["safeBase64UrlDecode","safeBase64Decode","raw","String","b64url","input","Buffer","from","toString","replace"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,eAAe;AAEnD,OAAO,SAASC,iBAAiBC,GAAY;IAC3C,IAAI,CAACA,KAAK,OAAO;IACjB,IAAI;QACF,OAAOF,oBAAoBE;IAC7B,EAAE,OAAM;QACN,+CAA+C;QAC/C,OAAOC,OAAOD;IAChB;AACF;AAEA,OAAO,SAASE,OAAOC,KAAa;IAClC,OAAOC,OAAOC,IAAI,CAACF,OAAOG,QAAQ,CAAC,UAAUC,OAAO,CAAC,OAAO,KAAKA,OAAO,CAAC,OAAO,KAAKA,OAAO,CAAC,OAAO;AACtG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/lib/create-store.ts"],"sourcesContent":["import type Keyv from 'keyv';\nimport keyvRegistry from 'keyv-registry';\n\nexport default async function createStore<T>(uri: string): Promise<Keyv<T>> {\n const store = await keyvRegistry<T>(uri);\n if (!store) throw new Error(`Failed to create store for URI: ${uri}`);\n return store;\n}\n"],"names":["keyvRegistry","createStore","uri","store","Error"],"mappings":"AACA,OAAOA,kBAAkB,gBAAgB;AAEzC,eAAe,eAAeC,YAAeC,GAAW;IACtD,MAAMC,QAAQ,MAAMH,aAAgBE;IACpC,IAAI,CAACC,OAAO,MAAM,IAAIC,MAAM,CAAC,gCAAgC,EAAEF,KAAK;IACpE,OAAOC;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toIsoUtc(dateStr?: string): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-gmail/src/lib/date-conversion.ts"],"sourcesContent":["export function toIsoUtc(dateStr?: string): string | undefined {\n if (!dateStr) return undefined;\n const d = new Date(dateStr);\n return Number.isNaN(d.getTime()) ? undefined : d.toISOString();\n}\n"],"names":["toIsoUtc","dateStr","undefined","d","Date","Number","isNaN","getTime","toISOString"],"mappings":"AAAA,OAAO,SAASA,SAASC,OAAgB;IACvC,IAAI,CAACA,SAAS,OAAOC;IACrB,MAAMC,IAAI,IAAIC,KAAKH;IACnB,OAAOI,OAAOC,KAAK,CAACH,EAAEI,OAAO,MAAML,YAAYC,EAAEK,WAAW;AAC9D"}
|