better-email-mcp 0.1.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 +123 -0
- package/dist/backends/imap.d.ts +46 -0
- package/dist/backends/imap.d.ts.map +1 -0
- package/dist/backends/imap.js +300 -0
- package/dist/backends/imap.js.map +1 -0
- package/dist/backends/jmap.d.ts +33 -0
- package/dist/backends/jmap.d.ts.map +1 -0
- package/dist/backends/jmap.js +374 -0
- package/dist/backends/jmap.js.map +1 -0
- package/dist/imap/client.d.ts +36 -0
- package/dist/imap/client.d.ts.map +1 -0
- package/dist/imap/client.js +212 -0
- package/dist/imap/client.js.map +1 -0
- package/dist/imap/parser.d.ts +73 -0
- package/dist/imap/parser.d.ts.map +1 -0
- package/dist/imap/parser.js +349 -0
- package/dist/imap/parser.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/smtp/client.d.ts +39 -0
- package/dist/smtp/client.d.ts.map +1 -0
- package/dist/smtp/client.js +241 -0
- package/dist/smtp/client.js.map +1 -0
- package/dist/tools/register.d.ts +4 -0
- package/dist/tools/register.d.ts.map +1 -0
- package/dist/tools/register.js +147 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal SMTP client using Node's built-in net/tls modules.
|
|
4
|
+
* Supports EHLO, AUTH PLAIN, STARTTLS, and message submission.
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.SmtpClient = exports.SmtpError = void 0;
|
|
41
|
+
const net = __importStar(require("net"));
|
|
42
|
+
const tls = __importStar(require("tls"));
|
|
43
|
+
class SmtpError extends Error {
|
|
44
|
+
code;
|
|
45
|
+
constructor(code, message) {
|
|
46
|
+
super(`SMTP error [${code}]: ${message}`);
|
|
47
|
+
this.code = code;
|
|
48
|
+
this.name = "SmtpError";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.SmtpError = SmtpError;
|
|
52
|
+
function validateAddress(address) {
|
|
53
|
+
if (/[\r\n\x00<>]/.test(address)) {
|
|
54
|
+
throw new SmtpError("invalid_address", "Email address contains illegal characters");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
class SmtpClient {
|
|
58
|
+
socket = null;
|
|
59
|
+
host = "";
|
|
60
|
+
buffer = "";
|
|
61
|
+
capabilities = [];
|
|
62
|
+
responseResolve = null;
|
|
63
|
+
responseReject = null;
|
|
64
|
+
responseLines = [];
|
|
65
|
+
async connect(config) {
|
|
66
|
+
this.host = config.host;
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
this.responseResolve = (resp) => {
|
|
69
|
+
if (resp.code === 220) {
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
reject(new SmtpError("greeting", `Server rejected connection: ${resp.lines.join(" ")}`));
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
this.responseReject = reject;
|
|
77
|
+
const onError = (err) => {
|
|
78
|
+
this.responseResolve = null;
|
|
79
|
+
this.responseReject = null;
|
|
80
|
+
reject(new SmtpError("connect", err.message));
|
|
81
|
+
};
|
|
82
|
+
if (config.tls) {
|
|
83
|
+
this.socket = tls.connect({ host: config.host, port: config.port }, () => {
|
|
84
|
+
// Connected, waiting for greeting
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.socket = net.connect({ host: config.host, port: config.port }, () => {
|
|
89
|
+
// Connected, waiting for greeting
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
this.socket.setEncoding("utf-8");
|
|
93
|
+
this.socket.on("data", (data) => this.onData(data));
|
|
94
|
+
this.socket.on("error", onError);
|
|
95
|
+
this.socket.on("close", () => {
|
|
96
|
+
if (this.responseReject) {
|
|
97
|
+
this.responseReject(new SmtpError("closed", "Connection closed unexpectedly"));
|
|
98
|
+
this.responseResolve = null;
|
|
99
|
+
this.responseReject = null;
|
|
100
|
+
}
|
|
101
|
+
this.socket = null;
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async ehlo(hostname) {
|
|
106
|
+
const resp = await this.sendCommand(`EHLO ${hostname}`, [250]);
|
|
107
|
+
this.capabilities = resp;
|
|
108
|
+
return resp;
|
|
109
|
+
}
|
|
110
|
+
async startTls() {
|
|
111
|
+
if (!this.socket) {
|
|
112
|
+
throw new SmtpError("disconnected", "Not connected");
|
|
113
|
+
}
|
|
114
|
+
const hasStartTls = this.capabilities.some((c) => c.toUpperCase() === "STARTTLS");
|
|
115
|
+
if (!hasStartTls) {
|
|
116
|
+
throw new SmtpError("starttls", "Server does not advertise STARTTLS");
|
|
117
|
+
}
|
|
118
|
+
await this.sendCommand("STARTTLS", [220]);
|
|
119
|
+
// Upgrade the socket to TLS
|
|
120
|
+
const rawSocket = this.socket;
|
|
121
|
+
rawSocket.removeAllListeners("data");
|
|
122
|
+
const tlsSocket = tls.connect({ socket: rawSocket, servername: this.host });
|
|
123
|
+
await new Promise((resolve, reject) => {
|
|
124
|
+
tlsSocket.once("secureConnect", resolve);
|
|
125
|
+
tlsSocket.once("error", reject);
|
|
126
|
+
});
|
|
127
|
+
this.socket = tlsSocket;
|
|
128
|
+
this.buffer = "";
|
|
129
|
+
this.socket.setEncoding("utf-8");
|
|
130
|
+
this.socket.on("data", (data) => this.onData(data));
|
|
131
|
+
}
|
|
132
|
+
async authPlain(user, password) {
|
|
133
|
+
const credentials = Buffer.from(`\0${user}\0${password}`).toString("base64");
|
|
134
|
+
await this.sendCommand(`AUTH PLAIN ${credentials}`, [235]);
|
|
135
|
+
}
|
|
136
|
+
async mailFrom(address) {
|
|
137
|
+
validateAddress(address);
|
|
138
|
+
await this.sendCommand(`MAIL FROM:<${address}>`, [250]);
|
|
139
|
+
}
|
|
140
|
+
async rcptTo(address) {
|
|
141
|
+
validateAddress(address);
|
|
142
|
+
await this.sendCommand(`RCPT TO:<${address}>`, [250]);
|
|
143
|
+
}
|
|
144
|
+
async data(content) {
|
|
145
|
+
await this.sendCommand("DATA", [354]);
|
|
146
|
+
// Normalize line endings to CRLF
|
|
147
|
+
let body = content.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n");
|
|
148
|
+
// Dot-stuffing: any line starting with "." gets an extra "." prepended (RFC 5321 §4.5.2)
|
|
149
|
+
body = body.replace(/\r\n\./g, "\r\n..");
|
|
150
|
+
// Also handle if the body itself starts with a dot
|
|
151
|
+
if (body.startsWith(".")) {
|
|
152
|
+
body = "." + body;
|
|
153
|
+
}
|
|
154
|
+
// Send body followed by terminating sequence
|
|
155
|
+
this.writeRaw(body + "\r\n.\r\n");
|
|
156
|
+
await this.readResponse([250]);
|
|
157
|
+
}
|
|
158
|
+
async quit() {
|
|
159
|
+
try {
|
|
160
|
+
await this.sendCommand("QUIT", [221]);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Ignore errors during quit
|
|
164
|
+
}
|
|
165
|
+
this.destroySocket();
|
|
166
|
+
}
|
|
167
|
+
disconnect() {
|
|
168
|
+
this.destroySocket();
|
|
169
|
+
}
|
|
170
|
+
// --- Private ---
|
|
171
|
+
async sendCommand(cmd, expectedCodes) {
|
|
172
|
+
if (!this.socket) {
|
|
173
|
+
throw new SmtpError("disconnected", "Not connected");
|
|
174
|
+
}
|
|
175
|
+
this.writeRaw(cmd + "\r\n");
|
|
176
|
+
return this.readResponse(expectedCodes);
|
|
177
|
+
}
|
|
178
|
+
readResponse(expectedCodes) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
this.responseLines = [];
|
|
181
|
+
this.responseResolve = (resp) => {
|
|
182
|
+
if (expectedCodes.includes(resp.code)) {
|
|
183
|
+
resolve(resp.lines);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
reject(new SmtpError(String(resp.code), resp.lines.join(" ") || `Unexpected response code ${resp.code}`));
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
this.responseReject = reject;
|
|
190
|
+
// Process any data already in the buffer
|
|
191
|
+
this.processBuffer();
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
writeRaw(data) {
|
|
195
|
+
if (!this.socket) {
|
|
196
|
+
throw new SmtpError("disconnected", "Not connected");
|
|
197
|
+
}
|
|
198
|
+
this.socket.write(data);
|
|
199
|
+
}
|
|
200
|
+
onData(data) {
|
|
201
|
+
this.buffer += data;
|
|
202
|
+
this.processBuffer();
|
|
203
|
+
}
|
|
204
|
+
processBuffer() {
|
|
205
|
+
while (this.buffer.length > 0) {
|
|
206
|
+
const crlfIdx = this.buffer.indexOf("\r\n");
|
|
207
|
+
if (crlfIdx === -1)
|
|
208
|
+
return;
|
|
209
|
+
const line = this.buffer.substring(0, crlfIdx);
|
|
210
|
+
this.buffer = this.buffer.substring(crlfIdx + 2);
|
|
211
|
+
this.handleLine(line);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
handleLine(line) {
|
|
215
|
+
// SMTP responses: "NNN-text" (continuation) or "NNN text" (final)
|
|
216
|
+
const match = line.match(/^(\d{3})([ -])(.*)/);
|
|
217
|
+
if (!match)
|
|
218
|
+
return;
|
|
219
|
+
const code = parseInt(match[1], 10);
|
|
220
|
+
const isContinuation = match[2] === "-";
|
|
221
|
+
const text = match[3];
|
|
222
|
+
this.responseLines.push(text);
|
|
223
|
+
if (!isContinuation && this.responseResolve) {
|
|
224
|
+
const resolve = this.responseResolve;
|
|
225
|
+
this.responseResolve = null;
|
|
226
|
+
this.responseReject = null;
|
|
227
|
+
resolve({ code, lines: this.responseLines });
|
|
228
|
+
this.responseLines = [];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
destroySocket() {
|
|
232
|
+
if (this.socket) {
|
|
233
|
+
this.socket.destroy();
|
|
234
|
+
this.socket = null;
|
|
235
|
+
}
|
|
236
|
+
this.responseResolve = null;
|
|
237
|
+
this.responseReject = null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
exports.SmtpClient = SmtpClient;
|
|
241
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/smtp/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAkC3C,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,YAAY,GACpB,IAAI,CAmJN"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerEmailTools = registerEmailTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
function errorResult(err) {
|
|
6
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
8
|
+
}
|
|
9
|
+
function jsonResult(data) {
|
|
10
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
11
|
+
}
|
|
12
|
+
function parseDisabledTools() {
|
|
13
|
+
const raw = process.env.DISABLED_TOOLS ?? "";
|
|
14
|
+
if (!raw.trim())
|
|
15
|
+
return new Set();
|
|
16
|
+
return new Set(raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean));
|
|
17
|
+
}
|
|
18
|
+
function toolEnabled(name, disabled) {
|
|
19
|
+
return !disabled.has(name.toLowerCase());
|
|
20
|
+
}
|
|
21
|
+
function parseEmailFormat() {
|
|
22
|
+
const raw = (process.env.EMAIL_FORMAT ?? "plain").trim().toLowerCase();
|
|
23
|
+
if (raw === "html")
|
|
24
|
+
return "html";
|
|
25
|
+
return "plain";
|
|
26
|
+
}
|
|
27
|
+
function registerEmailTools(server, backend) {
|
|
28
|
+
const disabled = parseDisabledTools();
|
|
29
|
+
if (toolEnabled("list_folders", disabled)) {
|
|
30
|
+
server.tool("list_folders", "List all email folders/mailboxes", {}, async () => {
|
|
31
|
+
try {
|
|
32
|
+
const folders = await backend.listFolders();
|
|
33
|
+
return jsonResult(folders);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
return errorResult(err);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (toolEnabled("list_messages", disabled)) {
|
|
41
|
+
server.tool("list_messages", "List recent email messages, optionally filtered by folder", {
|
|
42
|
+
folder: zod_1.z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe("Folder name to filter by (e.g. 'Inbox')"),
|
|
46
|
+
limit: zod_1.z
|
|
47
|
+
.number()
|
|
48
|
+
.int()
|
|
49
|
+
.min(1)
|
|
50
|
+
.max(100)
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("Max messages to return (default 25)"),
|
|
53
|
+
offset: zod_1.z
|
|
54
|
+
.number()
|
|
55
|
+
.int()
|
|
56
|
+
.min(0)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Number of messages to skip for pagination"),
|
|
59
|
+
}, async ({ folder, limit, offset }) => {
|
|
60
|
+
try {
|
|
61
|
+
const messages = await backend.listMessages({ folder, limit, offset });
|
|
62
|
+
return jsonResult(messages);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
return errorResult(err);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (toolEnabled("get_message", disabled)) {
|
|
70
|
+
server.tool("get_message", "Get a single email message by ID, including its full body text", {
|
|
71
|
+
id: zod_1.z.string().describe("The message ID"),
|
|
72
|
+
}, async ({ id }) => {
|
|
73
|
+
try {
|
|
74
|
+
const msg = await backend.getMessage(id);
|
|
75
|
+
if (!msg) {
|
|
76
|
+
return {
|
|
77
|
+
content: [{ type: "text", text: "Message not found" }],
|
|
78
|
+
isError: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return jsonResult(msg);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
return errorResult(err);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (toolEnabled("search_messages", disabled)) {
|
|
89
|
+
server.tool("search_messages", "Search email messages by text query", {
|
|
90
|
+
query: zod_1.z.string().describe("Search query text"),
|
|
91
|
+
folder: zod_1.z.string().optional().describe("Folder to search within"),
|
|
92
|
+
limit: zod_1.z
|
|
93
|
+
.number()
|
|
94
|
+
.int()
|
|
95
|
+
.min(1)
|
|
96
|
+
.max(100)
|
|
97
|
+
.optional()
|
|
98
|
+
.describe("Max results (default 25)"),
|
|
99
|
+
}, async ({ query, folder, limit }) => {
|
|
100
|
+
try {
|
|
101
|
+
const messages = await backend.searchMessages({ query, folder, limit });
|
|
102
|
+
return jsonResult(messages);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return errorResult(err);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (backend.sendMessage && toolEnabled("send_message", disabled)) {
|
|
110
|
+
const sendFn = backend.sendMessage.bind(backend);
|
|
111
|
+
const emailFormat = parseEmailFormat();
|
|
112
|
+
const sendParams = {
|
|
113
|
+
to: zod_1.z.array(zod_1.z.string()).describe("Recipient email addresses"),
|
|
114
|
+
cc: zod_1.z.array(zod_1.z.string()).optional().describe("CC recipient email addresses"),
|
|
115
|
+
bcc: zod_1.z.array(zod_1.z.string()).optional().describe("BCC recipient email addresses"),
|
|
116
|
+
subject: zod_1.z.string().describe("Email subject"),
|
|
117
|
+
textBody: zod_1.z.string().describe("Plain text body of the email"),
|
|
118
|
+
inReplyTo: zod_1.z
|
|
119
|
+
.string()
|
|
120
|
+
.optional()
|
|
121
|
+
.describe("Message ID to reply to, for threading"),
|
|
122
|
+
};
|
|
123
|
+
if (emailFormat === "html") {
|
|
124
|
+
sendParams.htmlBody = zod_1.z
|
|
125
|
+
.string()
|
|
126
|
+
.describe("HTML body of the email. The message is sent as multipart with both plain text and HTML.");
|
|
127
|
+
}
|
|
128
|
+
server.tool("send_message", "Send an email message", sendParams, async (args) => {
|
|
129
|
+
try {
|
|
130
|
+
const result = await sendFn({
|
|
131
|
+
to: args.to,
|
|
132
|
+
cc: args.cc,
|
|
133
|
+
bcc: args.bcc,
|
|
134
|
+
subject: args.subject,
|
|
135
|
+
textBody: args.textBody,
|
|
136
|
+
htmlBody: args.htmlBody,
|
|
137
|
+
inReplyTo: args.inReplyTo,
|
|
138
|
+
});
|
|
139
|
+
return jsonResult({ sent: true, id: result.id });
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
return errorResult(err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared interface that both IMAP and JMAP backends implement.
|
|
3
|
+
* The MCP tool layer depends only on this interface, never on a specific backend.
|
|
4
|
+
*/
|
|
5
|
+
export interface EmailMessage {
|
|
6
|
+
id: string;
|
|
7
|
+
subject: string;
|
|
8
|
+
from: string;
|
|
9
|
+
to: string[];
|
|
10
|
+
cc?: string[];
|
|
11
|
+
date: string;
|
|
12
|
+
snippet: string;
|
|
13
|
+
body?: string;
|
|
14
|
+
isRead: boolean;
|
|
15
|
+
folder: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ListMessagesOptions {
|
|
18
|
+
folder?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
offset?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface SearchOptions {
|
|
23
|
+
query: string;
|
|
24
|
+
folder?: string;
|
|
25
|
+
limit?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface SendMessageOptions {
|
|
28
|
+
to: string[];
|
|
29
|
+
cc?: string[];
|
|
30
|
+
bcc?: string[];
|
|
31
|
+
subject: string;
|
|
32
|
+
textBody: string;
|
|
33
|
+
htmlBody?: string;
|
|
34
|
+
inReplyTo?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface EmailBackend {
|
|
37
|
+
connect(): Promise<void>;
|
|
38
|
+
disconnect(): Promise<void>;
|
|
39
|
+
listFolders(): Promise<string[]>;
|
|
40
|
+
listMessages(options?: ListMessagesOptions): Promise<EmailMessage[]>;
|
|
41
|
+
getMessage(id: string): Promise<EmailMessage | null>;
|
|
42
|
+
searchMessages(options: SearchOptions): Promise<EmailMessage[]>;
|
|
43
|
+
sendMessage?(options: SendMessageOptions): Promise<{
|
|
44
|
+
id: string;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjC,YAAY,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACrE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACrD,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAChE,WAAW,CAAC,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared interface that both IMAP and JMAP backends implement.
|
|
4
|
+
* The MCP tool layer depends only on this interface, never on a specific backend.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-email-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for email access via IMAP and Fastmail JMAP",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"better-email-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsc --watch",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"test:watch": "jest --watch",
|
|
19
|
+
"lint": "eslint src/",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/samteezy/better-email-mcp"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"email",
|
|
30
|
+
"imap",
|
|
31
|
+
"jmap",
|
|
32
|
+
"fastmail"
|
|
33
|
+
],
|
|
34
|
+
"author": "",
|
|
35
|
+
"license": "ISC",
|
|
36
|
+
"type": "commonjs",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
39
|
+
"zod": "^4.3.6"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/jest": "^30.0.0",
|
|
43
|
+
"@types/node": "^25.5.0",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
45
|
+
"@typescript-eslint/parser": "^8.58.0",
|
|
46
|
+
"eslint": "^10.1.0",
|
|
47
|
+
"jest": "^30.3.0",
|
|
48
|
+
"ts-jest": "^29.4.9",
|
|
49
|
+
"typescript": "^6.0.2"
|
|
50
|
+
}
|
|
51
|
+
}
|