read-email-mcp 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/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "read-email-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Read-only MCP server that mirrors any IMAP mailbox into a local SQLite copy for browsing and searching email.",
5
+ "license": "MIT",
6
+ "author": "KelpHect",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/KelpHect/read-email-mcp.git"
10
+ },
11
+ "homepage": "https://github.com/KelpHect/read-email-mcp#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/KelpHect/read-email-mcp/issues"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "imap",
19
+ "email",
20
+ "sqlite",
21
+ "read-email"
22
+ ],
23
+ "type": "module",
24
+ "bin": {
25
+ "read-email-mcp": "dist/index.js"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "docs",
30
+ "scripts",
31
+ "README.md",
32
+ "LICENSE"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "smoke:mcp": "node scripts/smoke-mcp.mjs",
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "vitest run",
39
+ "verify": "npm test && npm run typecheck && npm run build && npm run smoke:mcp"
40
+ },
41
+ "dependencies": {
42
+ "@modelcontextprotocol/sdk": "^1.29.0",
43
+ "better-sqlite3": "^12.4.6",
44
+ "imapflow": "^1.0.191",
45
+ "mailparser": "^3.7.5",
46
+ "zod": "^3.25.76"
47
+ },
48
+ "devDependencies": {
49
+ "@types/better-sqlite3": "^7.6.13",
50
+ "@types/mailparser": "^3.4.6",
51
+ "@types/node": "^24.10.1",
52
+ "typescript": "^5.9.3",
53
+ "vitest": "^4.0.14"
54
+ },
55
+ "engines": {
56
+ "node": ">=20"
57
+ }
58
+ }
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
5
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
6
+
7
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
8
+ const expectedTools = [
9
+ "browse_email_dates",
10
+ "get_email",
11
+ "get_raw_email",
12
+ "get_recent_emails",
13
+ "get_storage_stats",
14
+ "get_sync_status",
15
+ "get_thread",
16
+ "list_emails",
17
+ "list_mailboxes",
18
+ "optimize_email_store",
19
+ "search_emails",
20
+ "sync_email"
21
+ ];
22
+
23
+ const inheritedEnv = Object.fromEntries(Object.entries(process.env).filter(([, value]) => value !== undefined));
24
+ delete inheritedEnv.EMAIL;
25
+ delete inheritedEnv.PASSWORD;
26
+ delete inheritedEnv.IMAP_HOST;
27
+ delete inheritedEnv.IMAP_PORT;
28
+ delete inheritedEnv.IMAP_SECURE;
29
+ delete inheritedEnv.IMAP_USER;
30
+ const transport = new StdioClientTransport({
31
+ command: process.execPath,
32
+ args: [
33
+ path.join(root, "dist", "index.js"),
34
+ "--email",
35
+ "smoke@example.com",
36
+ "--password",
37
+ "dummy-password",
38
+ "--imap-host",
39
+ "imap.example.com"
40
+ ],
41
+ cwd: root,
42
+ env: inheritedEnv,
43
+ stderr: "pipe"
44
+ });
45
+
46
+ const stderr = [];
47
+ transport.stderr?.on("data", (chunk) => stderr.push(String(chunk)));
48
+
49
+ const client = new Client(
50
+ {
51
+ name: "read-email-mcp-smoke",
52
+ version: "1.0.0-rc.1"
53
+ },
54
+ {
55
+ capabilities: {}
56
+ }
57
+ );
58
+
59
+ try {
60
+ await client.connect(transport);
61
+ const result = await client.listTools();
62
+ const actualTools = result.tools.map((tool) => tool.name).sort();
63
+ const missing = expectedTools.filter((tool) => !actualTools.includes(tool));
64
+ const extra = actualTools.filter((tool) => !expectedTools.includes(tool));
65
+ const stderrText = stderr.join("").trim();
66
+
67
+ if (missing.length || extra.length) {
68
+ throw new Error(
69
+ `Tool list mismatch. Missing: ${missing.join(", ") || "none"}. Extra: ${extra.join(", ") || "none"}.`
70
+ );
71
+ }
72
+
73
+ if (stderrText) {
74
+ throw new Error(`Server wrote to stderr during smoke test: ${stderrText}`);
75
+ }
76
+
77
+ console.log(`MCP smoke passed: ${actualTools.length} tools exposed.`);
78
+ } finally {
79
+ await client.close();
80
+ }