@adeu/mcp-server 1.18.4 → 1.19.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/README.md +16 -1
- package/dist/index.js +75 -28
- package/dist/index.js.map +1 -1
- package/dist/templates/email_ui.html +106 -3
- package/package.json +2 -2
- package/src/index.ts +11 -3
- package/src/templates/email_ui.html +106 -3
- package/src/tools/email.test.ts +281 -1
- package/src/tools/email.ts +112 -32
package/README.md
CHANGED
|
@@ -30,7 +30,9 @@ Add the following to your MCP configuration file (`claude_desktop_config.json`):
|
|
|
30
30
|
|
|
31
31
|
## Exposed Tools
|
|
32
32
|
|
|
33
|
-
Once connected, your AI agent will have access to the following tools
|
|
33
|
+
Once connected, your AI agent will have access to the following tools.
|
|
34
|
+
|
|
35
|
+
### Document tools
|
|
34
36
|
|
|
35
37
|
- `read_docx`: Reads a DOCX file and returns LLM-friendly text with inline CriticMarkup (`{++inserted++}`, `{--deleted--}`) for Tracked Changes and Comments. Supports pagination, structural outlining, and semantic appendix extraction.
|
|
36
38
|
- `process_document_batch`: Applies a batch of search-and-replace text modifications, table edits, and comment replies to a document. Translates the LLM's edits into perfectly formatted native Word Track Changes.
|
|
@@ -38,6 +40,19 @@ Once connected, your AI agent will have access to the following tools:
|
|
|
38
40
|
- `diff_docx_files`: Compares two DOCX files and returns a unified sub-word diff of their text content.
|
|
39
41
|
- `finalize_document`: Prepares a document for signature by applying native OOXML read-only locking and deep metadata sanitization.
|
|
40
42
|
|
|
43
|
+
### Email tools
|
|
44
|
+
|
|
45
|
+
These require an authenticated Adeu Cloud session (see Cloud tools below).
|
|
46
|
+
|
|
47
|
+
- `search_and_fetch_emails`: Searches the user's live email inbox via the Adeu Cloud backend and returns matching messages.
|
|
48
|
+
- `create_email_draft`: Creates an email draft in the user's native draft box (Outlook Drafts or Gmail Drafts).
|
|
49
|
+
- `list_available_mailboxes`: Lists all personal and shared/delegated mailboxes the authenticated user can access across every linked provider account, including each mailbox's address, display name, and auto-processing settings.
|
|
50
|
+
|
|
51
|
+
### Cloud tools
|
|
52
|
+
|
|
53
|
+
- `login_to_adeu_cloud`: Logs the user into Adeu Cloud, opening a browser window for SSO authentication.
|
|
54
|
+
- `logout_of_adeu_cloud`: Logs out of the Adeu Cloud backend.
|
|
55
|
+
|
|
41
56
|
## Documentation & Support
|
|
42
57
|
For full architectural details, prompt recommendations, and the project constitution, please visit the [main Adeu repository](https://github.com/dealfluence/adeu) or our [website](https://adeu.ai).
|
|
43
58
|
|
package/dist/index.js
CHANGED
|
@@ -542,10 +542,18 @@ import { join as join2 } from "path";
|
|
|
542
542
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
|
|
543
543
|
import { createHash } from "crypto";
|
|
544
544
|
var KNOWN_ERROR_HINTS = {
|
|
545
|
-
"Email not found.": "The email ID was not found. If this was a short ID (msg_*), it may have been evicted from the local cache or come from a different machine \u2014 re-run search_and_fetch_emails with filters to get a fresh ID. If it was an adeu_<numeric> or raw provider ID, verify it's correct.",
|
|
545
|
+
"Email not found.": "The email ID was not found. If this was a short ID (msg_*), it may have been evicted from the local cache or come from a different machine \u2014 re-run search_and_fetch_emails with filters to get a fresh ID. If it was an adeu_<numeric> or raw provider ID, verify it's correct. If the email lives in a shared or secondary mailbox, pass `mailbox_address` explicitly \u2014 provider IDs only resolve within the mailbox they came from.",
|
|
546
546
|
"Adeu email reference not found.": "The adeu_<id> reference doesn't resolve to any processed email for this user. Verify the ID, or re-run search_and_fetch_emails with filters to find the message.",
|
|
547
547
|
"Invalid adeu_ email ID format.": "The adeu_<id> reference is malformed. Expected format: adeu_<integer>."
|
|
548
548
|
};
|
|
549
|
+
function lookupErrorHint(detail) {
|
|
550
|
+
let hint = KNOWN_ERROR_HINTS[detail];
|
|
551
|
+
if (!hint && detail.startsWith("Mailbox '") && detail.endsWith("' not found.")) {
|
|
552
|
+
const mailbox = detail.slice("Mailbox '".length, -"' not found.".length);
|
|
553
|
+
hint = `The mailbox '${mailbox}' is not connected to your Adeu account. Call list_available_mailboxes to see valid mailbox addresses, then retry with one of those as \`mailbox_address\`.`;
|
|
554
|
+
}
|
|
555
|
+
return hint;
|
|
556
|
+
}
|
|
549
557
|
function formatBackendError(statusCode, responseBody) {
|
|
550
558
|
let detail = responseBody;
|
|
551
559
|
try {
|
|
@@ -555,12 +563,7 @@ function formatBackendError(statusCode, responseBody) {
|
|
|
555
563
|
}
|
|
556
564
|
} catch {
|
|
557
565
|
}
|
|
558
|
-
|
|
559
|
-
if (!hint && detail.startsWith("Mailbox '") && detail.endsWith("' not found.")) {
|
|
560
|
-
const mailbox = detail.slice("Mailbox '".length, -"' not found.".length);
|
|
561
|
-
hint = `The mailbox '${mailbox}' is not connected to your Adeu account. Call list_available_mailboxes to see valid mailbox addresses, then retry with one of those as \`mailbox_address\`.`;
|
|
562
|
-
}
|
|
563
|
-
const message = hint ?? detail;
|
|
566
|
+
const message = lookupErrorHint(detail) ?? detail;
|
|
564
567
|
return `Cloud search failed (HTTP ${statusCode}): ${message}`;
|
|
565
568
|
}
|
|
566
569
|
function isTimeoutError(err) {
|
|
@@ -576,6 +579,11 @@ function formatBytes(bytes) {
|
|
|
576
579
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
577
580
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
578
581
|
}
|
|
582
|
+
function cacheEntryParts(entry) {
|
|
583
|
+
if (!entry) return { id: null, mailbox: null };
|
|
584
|
+
if (typeof entry === "string") return { id: entry, mailbox: null };
|
|
585
|
+
return { id: entry.id ?? null, mailbox: entry.mailbox ?? null };
|
|
586
|
+
}
|
|
579
587
|
function loadIdCache() {
|
|
580
588
|
if (existsSync2(CACHE_FILE)) {
|
|
581
589
|
try {
|
|
@@ -599,11 +607,11 @@ function saveIdCache(cache) {
|
|
|
599
607
|
} catch {
|
|
600
608
|
}
|
|
601
609
|
}
|
|
602
|
-
function minifyEmailId(realId, cache) {
|
|
610
|
+
function minifyEmailId(realId, cache, mailboxAddress) {
|
|
603
611
|
if (!realId) return realId;
|
|
604
612
|
const hash = createHash("md5").update(realId).digest("hex").slice(0, 6);
|
|
605
613
|
const shortId = `msg_${hash}`;
|
|
606
|
-
cache[shortId] = realId;
|
|
614
|
+
cache[shortId] = { id: realId, mailbox: mailboxAddress ?? null };
|
|
607
615
|
return shortId;
|
|
608
616
|
}
|
|
609
617
|
var StaleShortIdError = class extends Error {
|
|
@@ -618,13 +626,17 @@ function resolveEmailId(shortId) {
|
|
|
618
626
|
if (!shortId) return shortId;
|
|
619
627
|
if (shortId.startsWith("adeu_")) return shortId;
|
|
620
628
|
const cache = loadIdCache();
|
|
621
|
-
const
|
|
622
|
-
if (
|
|
629
|
+
const { id } = cacheEntryParts(cache[shortId]);
|
|
630
|
+
if (id) return id;
|
|
623
631
|
if (shortId.startsWith("msg_")) {
|
|
624
632
|
throw new StaleShortIdError(shortId);
|
|
625
633
|
}
|
|
626
634
|
return shortId;
|
|
627
635
|
}
|
|
636
|
+
function resolveCachedMailbox(shortId) {
|
|
637
|
+
if (!shortId || !shortId.startsWith("msg_")) return null;
|
|
638
|
+
return cacheEntryParts(loadIdCache()[shortId]).mailbox;
|
|
639
|
+
}
|
|
628
640
|
var HTML_NAMED_ENTITIES = {
|
|
629
641
|
nbsp: " ",
|
|
630
642
|
amp: "&",
|
|
@@ -817,7 +829,8 @@ async function pollEmailTask(taskId, apiKey) {
|
|
|
817
829
|
}
|
|
818
830
|
if (status === "FAILED") {
|
|
819
831
|
const errorMsg = taskData.error || "Unknown internal error";
|
|
820
|
-
|
|
832
|
+
const hint = lookupErrorHint(errorMsg);
|
|
833
|
+
throw new Error(`Validation task failed on the server: ${hint ?? errorMsg}`);
|
|
821
834
|
}
|
|
822
835
|
await new Promise((resolve3) => setTimeout(resolve3, 5e3));
|
|
823
836
|
}
|
|
@@ -826,6 +839,7 @@ async function pollEmailTask(taskId, apiKey) {
|
|
|
826
839
|
async function search_and_fetch_emails(args2) {
|
|
827
840
|
const apiKey = await getCloudAuthToken();
|
|
828
841
|
const maxAttachmentSizeMb = typeof args2.max_attachment_size_mb === "number" && args2.max_attachment_size_mb > 0 ? args2.max_attachment_size_mb : 10;
|
|
842
|
+
let effectiveMailbox = args2.mailbox_address;
|
|
829
843
|
let data;
|
|
830
844
|
if (args2.task_id) {
|
|
831
845
|
const completedData = await pollEmailTask(args2.task_id, apiKey);
|
|
@@ -854,6 +868,10 @@ async function search_and_fetch_emails(args2) {
|
|
|
854
868
|
}
|
|
855
869
|
throw err;
|
|
856
870
|
}
|
|
871
|
+
if (args2.email_id && !effectiveMailbox) {
|
|
872
|
+
const cachedMailbox = resolveCachedMailbox(args2.email_id);
|
|
873
|
+
if (cachedMailbox) effectiveMailbox = cachedMailbox;
|
|
874
|
+
}
|
|
857
875
|
const payload = {
|
|
858
876
|
email_id: realEmailId,
|
|
859
877
|
sender: args2.sender,
|
|
@@ -865,7 +883,7 @@ async function search_and_fetch_emails(args2) {
|
|
|
865
883
|
folder: args2.folder,
|
|
866
884
|
limit: args2.limit ?? 10,
|
|
867
885
|
offset: args2.offset ?? 0,
|
|
868
|
-
mailbox_address:
|
|
886
|
+
mailbox_address: effectiveMailbox
|
|
869
887
|
};
|
|
870
888
|
Object.keys(payload).forEach(
|
|
871
889
|
(k) => payload[k] === void 0 && delete payload[k]
|
|
@@ -925,14 +943,17 @@ async function search_and_fetch_emails(args2) {
|
|
|
925
943
|
type: "text",
|
|
926
944
|
text: "No emails found matching your search criteria."
|
|
927
945
|
}
|
|
928
|
-
]
|
|
946
|
+
],
|
|
947
|
+
// Keep the UI channel populated (Python parity) — without it the
|
|
948
|
+
// widget's tool-result handler bails and the skeleton spins forever.
|
|
949
|
+
structuredContent: data
|
|
929
950
|
};
|
|
930
951
|
const lines = [
|
|
931
952
|
`Found ${previews.length} email(s). Here are the previews:`,
|
|
932
953
|
""
|
|
933
954
|
];
|
|
934
955
|
for (const p of previews) {
|
|
935
|
-
const shortId = minifyEmailId(p.id, cache);
|
|
956
|
+
const shortId = minifyEmailId(p.id, cache, effectiveMailbox);
|
|
936
957
|
const attFlag = p.has_attachments ? "\u{1F4CE} (Has Attachments)" : "";
|
|
937
958
|
const unreadFlag = p.is_read === false ? "\u{1F7E2} [UNREAD]" : "";
|
|
938
959
|
lines.push(
|
|
@@ -959,13 +980,28 @@ async function search_and_fetch_emails(args2) {
|
|
|
959
980
|
}
|
|
960
981
|
if (data.type === "full_email") {
|
|
961
982
|
const full = data.full_email || {};
|
|
962
|
-
const shortTargetId = minifyEmailId(
|
|
983
|
+
const shortTargetId = minifyEmailId(
|
|
984
|
+
full.id || "unknown_id",
|
|
985
|
+
cache,
|
|
986
|
+
effectiveMailbox
|
|
987
|
+
);
|
|
963
988
|
saveIdCache(cache);
|
|
964
989
|
const autoEscalated = !args2.email_id && (args2.sender !== void 0 || args2.subject !== void 0 || args2.has_attachments !== void 0 || args2.attachment_name !== void 0 || args2.is_unread !== void 0 || args2.days_ago !== void 0 || args2.folder !== void 0);
|
|
965
|
-
|
|
990
|
+
let baseDir = tmpdir();
|
|
991
|
+
let usedWorkingDirectory = false;
|
|
992
|
+
let dirFallbackNote = null;
|
|
993
|
+
if (args2.working_directory) {
|
|
994
|
+
try {
|
|
995
|
+
mkdirSync2(args2.working_directory, { recursive: true });
|
|
996
|
+
baseDir = args2.working_directory;
|
|
997
|
+
usedWorkingDirectory = true;
|
|
998
|
+
} catch (e) {
|
|
999
|
+
dirFallbackNote = `\u26A0\uFE0F **Attachment location notice**: the requested \`working_directory\` (\`${args2.working_directory}\`) did not exist and could not be created (${e.message}). Any attachments were saved to the system temp directory instead \u2014 use the exact paths listed below; do NOT re-run the search expecting a different location.`;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
966
1002
|
const saveDir = join2(
|
|
967
1003
|
baseDir,
|
|
968
|
-
|
|
1004
|
+
usedWorkingDirectory ? "adeu_attachments" : "adeu_downloads",
|
|
969
1005
|
shortTargetId
|
|
970
1006
|
);
|
|
971
1007
|
mkdirSync2(saveDir, { recursive: true });
|
|
@@ -1011,6 +1047,9 @@ async function search_and_fetch_emails(args2) {
|
|
|
1011
1047
|
"_(Search returned exactly one result; auto-fetched full email below.)_\n"
|
|
1012
1048
|
);
|
|
1013
1049
|
}
|
|
1050
|
+
if (dirFallbackNote) {
|
|
1051
|
+
lines.push(dirFallbackNote + "\n");
|
|
1052
|
+
}
|
|
1014
1053
|
lines.push(
|
|
1015
1054
|
`# Email Thread: ${full.subject}`,
|
|
1016
1055
|
"",
|
|
@@ -1076,7 +1115,7 @@ ${removeNestedQuotes(stripTags(histMsg.body_html || ""))}
|
|
|
1076
1115
|
);
|
|
1077
1116
|
if (hasAttachments) {
|
|
1078
1117
|
lines.push(
|
|
1079
|
-
"\n*You can now use tools like `read_docx`, `diff_docx_files`, or `finalize_document` on the local file paths listed under each message.*"
|
|
1118
|
+
"\n*You can now use tools like `read_docx`, `diff_docx_files`, or `finalize_document` on the local file paths listed under each message. These paths are on the user's machine \u2014 pass them directly to those tools; your own sandbox/shell may not see them, and that does NOT mean the download failed.*"
|
|
1080
1119
|
);
|
|
1081
1120
|
}
|
|
1082
1121
|
return {
|
|
@@ -1086,7 +1125,8 @@ ${removeNestedQuotes(stripTags(histMsg.body_html || ""))}
|
|
|
1086
1125
|
}
|
|
1087
1126
|
return {
|
|
1088
1127
|
isError: true,
|
|
1089
|
-
content: [{ type: "text", text: "Unknown response format from backend." }]
|
|
1128
|
+
content: [{ type: "text", text: "Unknown response format from backend." }],
|
|
1129
|
+
structuredContent: data
|
|
1090
1130
|
};
|
|
1091
1131
|
}
|
|
1092
1132
|
async function create_email_draft(args2) {
|
|
@@ -1115,8 +1155,13 @@ async function create_email_draft(args2) {
|
|
|
1115
1155
|
}
|
|
1116
1156
|
}
|
|
1117
1157
|
if (args2.subject) formData.append("subject", args2.subject);
|
|
1118
|
-
|
|
1119
|
-
|
|
1158
|
+
let draftMailbox = args2.mailbox_address;
|
|
1159
|
+
if (args2.reply_to_email_id && !draftMailbox) {
|
|
1160
|
+
const cachedMailbox = resolveCachedMailbox(args2.reply_to_email_id);
|
|
1161
|
+
if (cachedMailbox) draftMailbox = cachedMailbox;
|
|
1162
|
+
}
|
|
1163
|
+
if (draftMailbox) {
|
|
1164
|
+
formData.append("mailbox_address", draftMailbox);
|
|
1120
1165
|
}
|
|
1121
1166
|
if (args2.to_recipients) {
|
|
1122
1167
|
const recips = typeof args2.to_recipients === "string" ? JSON.parse(args2.to_recipients) : args2.to_recipients;
|
|
@@ -1289,8 +1334,8 @@ var READ_DOCX_TAIL = "Modes:\n- 'full' (default): paginated body content. Use pa
|
|
|
1289
1334
|
var PROCESS_BATCH_COMMON_DESC = "Applies a batch of edits and review actions to a DOCX.\n\nAll changes evaluate against the ORIGINAL document state \u2014 do not chain dependent edits within one batch (e.g. rename X to Y, then modify Y). Apply the rename first, then send a second batch.\n\n";
|
|
1290
1335
|
var PROCESS_BATCH_OPERATIONS_DESC = "Each item in `changes` must specify a `type`:\n1. 'modify': Search-and-replace. By default `target_text` must match uniquely (`match_mode`:'strict') \u2014 add surrounding context to disambiguate, or set `match_mode`:'first'/'all' to edit the first or every occurrence. Set `regex`:true to treat `target_text` as a regular expression (capture groups available in `new_text` as $1, $2\u2026). `new_text` supports Markdown: '# Heading 1' through '###### Heading 6', '**bold**', '_italic_', and '\\n\\n' to split into multiple paragraphs. Empty `new_text` deletes. Do NOT write CriticMarkup tags ({++, {--, {>>) manually \u2014 use the `comment` parameter for comments.\n \u2022 EMPTY/FORM TABLE CELLS: a blank cell has no text to match. `read_docx` renders each cell with a trailing `{#cell:<id>}` anchor \u2014 to fill a blank cell, set `target_text` to that exact anchor (e.g. '{#cell:0000005E}') and put the value in `new_text`. Do NOT try to match the pipe layout ('Date | | |'); the pipes are display separators, not editable text.\n2. 'accept' / 'reject': Finalize or revert a tracked change by `target_id` (e.g. 'Chg:12').\n3. 'reply': Reply to a comment by `target_id` (e.g. 'Com:5') with `text`.\n4. 'insert_row' / 'delete_row': Table edits. Disk mode only \u2014 not supported on Live Word canvas.\n\nID VOLATILITY: 'Chg:N' and 'Com:N' shift between document states. Always call `read_docx` immediately before any accept/reject/reply \u2014 do not reuse IDs from earlier in the conversation. The `{#cell:<id>}` anchors are stable (Word-assigned) and safe to reuse across reads.\n\n`author_name` is used for attribution on all tracked changes and comments, in both disk and Live Word modes.";
|
|
1291
1336
|
var DIFF_DOCX_DESC = "Compares two DOCX files and returns a compact `@@ Word Patch @@` diff \u2014 Adeu's token-level, sub-word patch format \u2014 of their text content. Useful for analyzing differences between versions before editing.";
|
|
1292
|
-
var gitSha = "
|
|
1293
|
-
var packageVersion = "1.
|
|
1337
|
+
var gitSha = "7506148";
|
|
1338
|
+
var packageVersion = "1.19.0";
|
|
1294
1339
|
var buildTag = ` [Adeu v${packageVersion}+${gitSha}]`;
|
|
1295
1340
|
var args = process.argv.slice(2);
|
|
1296
1341
|
var scopeIdx = args.indexOf("--scope");
|
|
@@ -1790,7 +1835,7 @@ if (!isDocxOnly) {
|
|
|
1790
1835
|
"search_and_fetch_emails",
|
|
1791
1836
|
{
|
|
1792
1837
|
title: "Search & Fetch Emails",
|
|
1793
|
-
description: "Searches the user's live email inbox via the Adeu cloud backend.\n\nTWO MODES:\n1. Search mode (no `email_id`): returns up to `limit` lightweight previews. Use filters (`sender`, `subject`, `is_unread`, `days_ago`, `folder`, `has_attachments`, `attachment_name`) to narrow down.\n2. Fetch mode (with `email_id`): returns the full email body, thread history, and downloads attachments under `max_attachment_size_mb` to the local disk.\n\nAUTO-ESCALATION: If a search returns exactly one preview, the backend automatically fetches the full email in the same call. Plan around the response shape \u2014 check the `type` field (`previews` vs `full_email`) before assuming.\n\nEMAIL ID FORMATS (`email_id` parameter accepts any of):\n- `msg_<6 chars>` \u2014 short ID returned by previews on THIS machine. NOT portable across machines or sessions; the local cache holds the most recent 1000. If you reference one that's been evicted, the tool returns a StaleShortIdError telling you to re-search
|
|
1838
|
+
description: "Searches the user's live email inbox via the Adeu cloud backend.\n\nTWO MODES:\n1. Search mode (no `email_id`): returns up to `limit` lightweight previews. Use filters (`sender`, `subject`, `is_unread`, `days_ago`, `folder`, `has_attachments`, `attachment_name`) to narrow down.\n2. Fetch mode (with `email_id`): returns the full email body, thread history, and downloads attachments under `max_attachment_size_mb` to the local disk.\n\nAUTO-ESCALATION: If a search returns exactly one preview, the backend automatically fetches the full email in the same call. Plan around the response shape \u2014 check the `type` field (`previews` vs `full_email`) before assuming.\n\nEMAIL ID FORMATS (`email_id` parameter accepts any of):\n- `msg_<6 chars>` \u2014 short ID returned by previews on THIS machine. NOT portable across machines or sessions; the local cache holds the most recent 1000. If you reference one that's been evicted, the tool returns a StaleShortIdError telling you to re-search. The mailbox used in the original search is remembered with the short ID and re-applied automatically when you fetch or reply without specifying `mailbox_address`.\n- `adeu_<numeric>` \u2014 server-side reference for emails Adeu has previously processed. Portable across machines and sessions for the same authenticated user.\n- Raw provider ID (Gmail/Outlook native ID) \u2014 works if you have it, but you usually won't.\n\nFOLDER DEFAULT: omitting `folder` searches the Inbox only (matching what the user sees in their mail client). Use `folder='sent'` for sent items, `folder='all'` to include Deleted Items, Drafts, and other folders.\n\nATTACHMENTS: attachments larger than `max_attachment_size_mb` (default 10) are listed in the response but NOT downloaded \u2014 raise the cap if you need them. Always set `working_directory` when calling from a project so attachments land alongside the user's other files; the directory is created automatically if it does not exist. This directory path refers to the user's native operating system, not the LLM's sandbox environment.",
|
|
1794
1839
|
inputSchema: z.object({
|
|
1795
1840
|
reasoning: z.string().describe(
|
|
1796
1841
|
"Why do I need to search or fetch these emails? State this reason before any other parameter."
|
|
@@ -1805,7 +1850,9 @@ if (!isDocxOnly) {
|
|
|
1805
1850
|
limit: z.coerce.number().default(10),
|
|
1806
1851
|
offset: z.coerce.number().default(0),
|
|
1807
1852
|
email_id: z.string().optional(),
|
|
1808
|
-
working_directory: z.string().optional()
|
|
1853
|
+
working_directory: z.string().optional().describe(
|
|
1854
|
+
"Optional. The current working directory of the project or task. If provided, attachments will be saved here under an 'adeu_attachments' subfolder; the directory is created automatically if it does not exist. If omitted, attachments are saved to the system temp directory."
|
|
1855
|
+
),
|
|
1809
1856
|
mailbox_address: z.string().optional().describe("Optional target mailbox email address to search within."),
|
|
1810
1857
|
task_id: z.string().optional().describe("If resuming a pending check, provide the task ID here."),
|
|
1811
1858
|
max_attachment_size_mb: z.coerce.number().optional().describe(
|
|
@@ -1971,8 +2018,8 @@ ${stats.skipped_details.join("\n")}`;
|
|
|
1971
2018
|
async function main() {
|
|
1972
2019
|
const transport = new StdioServerTransport();
|
|
1973
2020
|
await server.connect(transport);
|
|
1974
|
-
const gitSha2 = "
|
|
1975
|
-
const buildTs = "2026-07-
|
|
2021
|
+
const gitSha2 = "7506148";
|
|
2022
|
+
const buildTs = "2026-07-08T07:12:39.168Z";
|
|
1976
2023
|
console.error(
|
|
1977
2024
|
`Adeu MCP Server (Node.js Engine: ${identifyEngine()}) running on stdio build=${gitSha2}@${buildTs}`
|
|
1978
2025
|
);
|