@diskd-ai/email-mcp 0.3.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.
Files changed (295) hide show
  1. package/LICENSE +155 -0
  2. package/README.md +820 -0
  3. package/dist/cli/account-commands.d.ts +10 -0
  4. package/dist/cli/account-commands.d.ts.map +1 -0
  5. package/dist/cli/account-commands.js +703 -0
  6. package/dist/cli/account-commands.js.map +1 -0
  7. package/dist/cli/config-commands.d.ts +9 -0
  8. package/dist/cli/config-commands.d.ts.map +1 -0
  9. package/dist/cli/config-commands.js +156 -0
  10. package/dist/cli/config-commands.js.map +1 -0
  11. package/dist/cli/guard.d.ts +11 -0
  12. package/dist/cli/guard.d.ts.map +1 -0
  13. package/dist/cli/guard.js +18 -0
  14. package/dist/cli/guard.js.map +1 -0
  15. package/dist/cli/install-commands.d.ts +12 -0
  16. package/dist/cli/install-commands.d.ts.map +1 -0
  17. package/dist/cli/install-commands.js +320 -0
  18. package/dist/cli/install-commands.js.map +1 -0
  19. package/dist/cli/notify.d.ts +8 -0
  20. package/dist/cli/notify.d.ts.map +1 -0
  21. package/dist/cli/notify.js +143 -0
  22. package/dist/cli/notify.js.map +1 -0
  23. package/dist/cli/providers.d.ts +13 -0
  24. package/dist/cli/providers.d.ts.map +1 -0
  25. package/dist/cli/providers.js +180 -0
  26. package/dist/cli/providers.js.map +1 -0
  27. package/dist/cli/scheduler.d.ts +8 -0
  28. package/dist/cli/scheduler.d.ts.map +1 -0
  29. package/dist/cli/scheduler.js +268 -0
  30. package/dist/cli/scheduler.js.map +1 -0
  31. package/dist/cli/setup.d.ts +12 -0
  32. package/dist/cli/setup.d.ts.map +1 -0
  33. package/dist/cli/setup.js +15 -0
  34. package/dist/cli/setup.js.map +1 -0
  35. package/dist/cli/test.d.ts +7 -0
  36. package/dist/cli/test.d.ts.map +1 -0
  37. package/dist/cli/test.js +67 -0
  38. package/dist/cli/test.js.map +1 -0
  39. package/dist/config/loader.d.ts +34 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +339 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/schema.d.ts +351 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +165 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/config/xdg.d.ts +27 -0
  48. package/dist/config/xdg.d.ts.map +1 -0
  49. package/dist/config/xdg.js +30 -0
  50. package/dist/config/xdg.js.map +1 -0
  51. package/dist/connections/manager.d.ts +42 -0
  52. package/dist/connections/manager.d.ts.map +1 -0
  53. package/dist/connections/manager.js +266 -0
  54. package/dist/connections/manager.js.map +1 -0
  55. package/dist/connections/types.d.ts +13 -0
  56. package/dist/connections/types.d.ts.map +1 -0
  57. package/dist/connections/types.js +2 -0
  58. package/dist/connections/types.js.map +1 -0
  59. package/dist/logging.d.ts +46 -0
  60. package/dist/logging.d.ts.map +1 -0
  61. package/dist/logging.js +63 -0
  62. package/dist/logging.js.map +1 -0
  63. package/dist/main.d.ts +13 -0
  64. package/dist/main.d.ts.map +1 -0
  65. package/dist/main.js +206 -0
  66. package/dist/main.js.map +1 -0
  67. package/dist/prompts/actions.prompt.d.ts +9 -0
  68. package/dist/prompts/actions.prompt.d.ts.map +1 -0
  69. package/dist/prompts/actions.prompt.js +64 -0
  70. package/dist/prompts/actions.prompt.js.map +1 -0
  71. package/dist/prompts/calendar.prompt.d.ts +9 -0
  72. package/dist/prompts/calendar.prompt.d.ts.map +1 -0
  73. package/dist/prompts/calendar.prompt.js +55 -0
  74. package/dist/prompts/calendar.prompt.js.map +1 -0
  75. package/dist/prompts/cleanup.prompt.d.ts +9 -0
  76. package/dist/prompts/cleanup.prompt.d.ts.map +1 -0
  77. package/dist/prompts/cleanup.prompt.js +78 -0
  78. package/dist/prompts/cleanup.prompt.js.map +1 -0
  79. package/dist/prompts/compose.prompt.d.ts +8 -0
  80. package/dist/prompts/compose.prompt.d.ts.map +1 -0
  81. package/dist/prompts/compose.prompt.js +116 -0
  82. package/dist/prompts/compose.prompt.js.map +1 -0
  83. package/dist/prompts/register.d.ts +8 -0
  84. package/dist/prompts/register.d.ts.map +1 -0
  85. package/dist/prompts/register.js +20 -0
  86. package/dist/prompts/register.js.map +1 -0
  87. package/dist/prompts/thread.prompt.d.ts +9 -0
  88. package/dist/prompts/thread.prompt.d.ts.map +1 -0
  89. package/dist/prompts/thread.prompt.js +58 -0
  90. package/dist/prompts/thread.prompt.js.map +1 -0
  91. package/dist/prompts/triage.prompt.d.ts +9 -0
  92. package/dist/prompts/triage.prompt.d.ts.map +1 -0
  93. package/dist/prompts/triage.prompt.js +64 -0
  94. package/dist/prompts/triage.prompt.js.map +1 -0
  95. package/dist/resources/accounts.resource.d.ts +9 -0
  96. package/dist/resources/accounts.resource.d.ts.map +1 -0
  97. package/dist/resources/accounts.resource.js +26 -0
  98. package/dist/resources/accounts.resource.js.map +1 -0
  99. package/dist/resources/mailboxes.resource.d.ts +10 -0
  100. package/dist/resources/mailboxes.resource.d.ts.map +1 -0
  101. package/dist/resources/mailboxes.resource.js +33 -0
  102. package/dist/resources/mailboxes.resource.js.map +1 -0
  103. package/dist/resources/register.d.ts +12 -0
  104. package/dist/resources/register.d.ts.map +1 -0
  105. package/dist/resources/register.js +20 -0
  106. package/dist/resources/register.js.map +1 -0
  107. package/dist/resources/scheduled.resource.d.ts +9 -0
  108. package/dist/resources/scheduled.resource.d.ts.map +1 -0
  109. package/dist/resources/scheduled.resource.js +31 -0
  110. package/dist/resources/scheduled.resource.js.map +1 -0
  111. package/dist/resources/stats.resource.d.ts +10 -0
  112. package/dist/resources/stats.resource.d.ts.map +1 -0
  113. package/dist/resources/stats.resource.js +45 -0
  114. package/dist/resources/stats.resource.js.map +1 -0
  115. package/dist/resources/templates.resource.d.ts +9 -0
  116. package/dist/resources/templates.resource.d.ts.map +1 -0
  117. package/dist/resources/templates.resource.js +34 -0
  118. package/dist/resources/templates.resource.js.map +1 -0
  119. package/dist/resources/unread.resource.d.ts +11 -0
  120. package/dist/resources/unread.resource.d.ts.map +1 -0
  121. package/dist/resources/unread.resource.js +46 -0
  122. package/dist/resources/unread.resource.js.map +1 -0
  123. package/dist/safety/audit.d.ts +17 -0
  124. package/dist/safety/audit.d.ts.map +1 -0
  125. package/dist/safety/audit.js +50 -0
  126. package/dist/safety/audit.js.map +1 -0
  127. package/dist/safety/rate-limiter.d.ts +22 -0
  128. package/dist/safety/rate-limiter.d.ts.map +1 -0
  129. package/dist/safety/rate-limiter.js +52 -0
  130. package/dist/safety/rate-limiter.js.map +1 -0
  131. package/dist/safety/validation.d.ts +44 -0
  132. package/dist/safety/validation.d.ts.map +1 -0
  133. package/dist/safety/validation.js +113 -0
  134. package/dist/safety/validation.js.map +1 -0
  135. package/dist/server.d.ts +10 -0
  136. package/dist/server.d.ts.map +1 -0
  137. package/dist/server.js +25 -0
  138. package/dist/server.js.map +1 -0
  139. package/dist/services/calendar.service.d.ts +22 -0
  140. package/dist/services/calendar.service.d.ts.map +1 -0
  141. package/dist/services/calendar.service.js +115 -0
  142. package/dist/services/calendar.service.js.map +1 -0
  143. package/dist/services/event-bus.d.ts +28 -0
  144. package/dist/services/event-bus.d.ts.map +1 -0
  145. package/dist/services/event-bus.js +16 -0
  146. package/dist/services/event-bus.js.map +1 -0
  147. package/dist/services/hooks.service.d.ts +77 -0
  148. package/dist/services/hooks.service.d.ts.map +1 -0
  149. package/dist/services/hooks.service.js +498 -0
  150. package/dist/services/hooks.service.js.map +1 -0
  151. package/dist/services/imap.service.d.ts +133 -0
  152. package/dist/services/imap.service.d.ts.map +1 -0
  153. package/dist/services/imap.service.js +1393 -0
  154. package/dist/services/imap.service.js.map +1 -0
  155. package/dist/services/label-strategy.d.ts +20 -0
  156. package/dist/services/label-strategy.d.ts.map +1 -0
  157. package/dist/services/label-strategy.js +237 -0
  158. package/dist/services/label-strategy.js.map +1 -0
  159. package/dist/services/local-calendar.service.d.ts +126 -0
  160. package/dist/services/local-calendar.service.d.ts.map +1 -0
  161. package/dist/services/local-calendar.service.js +428 -0
  162. package/dist/services/local-calendar.service.js.map +1 -0
  163. package/dist/services/notifier.service.d.ts +69 -0
  164. package/dist/services/notifier.service.d.ts.map +1 -0
  165. package/dist/services/notifier.service.js +319 -0
  166. package/dist/services/notifier.service.js.map +1 -0
  167. package/dist/services/oauth.service.d.ts +47 -0
  168. package/dist/services/oauth.service.d.ts.map +1 -0
  169. package/dist/services/oauth.service.js +140 -0
  170. package/dist/services/oauth.service.js.map +1 -0
  171. package/dist/services/presets.d.ts +36 -0
  172. package/dist/services/presets.d.ts.map +1 -0
  173. package/dist/services/presets.js +173 -0
  174. package/dist/services/presets.js.map +1 -0
  175. package/dist/services/reminders.service.d.ts +63 -0
  176. package/dist/services/reminders.service.d.ts.map +1 -0
  177. package/dist/services/reminders.service.js +281 -0
  178. package/dist/services/reminders.service.js.map +1 -0
  179. package/dist/services/scheduler.service.d.ts +42 -0
  180. package/dist/services/scheduler.service.d.ts.map +1 -0
  181. package/dist/services/scheduler.service.js +260 -0
  182. package/dist/services/scheduler.service.js.map +1 -0
  183. package/dist/services/smtp.service.d.ts +40 -0
  184. package/dist/services/smtp.service.d.ts.map +1 -0
  185. package/dist/services/smtp.service.js +151 -0
  186. package/dist/services/smtp.service.js.map +1 -0
  187. package/dist/services/template.service.d.ts +33 -0
  188. package/dist/services/template.service.d.ts.map +1 -0
  189. package/dist/services/template.service.js +123 -0
  190. package/dist/services/template.service.js.map +1 -0
  191. package/dist/services/watcher.service.d.ts +36 -0
  192. package/dist/services/watcher.service.d.ts.map +1 -0
  193. package/dist/services/watcher.service.js +241 -0
  194. package/dist/services/watcher.service.js.map +1 -0
  195. package/dist/tools/accounts.tool.d.ts +7 -0
  196. package/dist/tools/accounts.tool.d.ts.map +1 -0
  197. package/dist/tools/accounts.tool.js +29 -0
  198. package/dist/tools/accounts.tool.js.map +1 -0
  199. package/dist/tools/analytics.tool.d.ts +9 -0
  200. package/dist/tools/analytics.tool.d.ts.map +1 -0
  201. package/dist/tools/analytics.tool.js +27 -0
  202. package/dist/tools/analytics.tool.js.map +1 -0
  203. package/dist/tools/attachments.tool.d.ts +7 -0
  204. package/dist/tools/attachments.tool.d.ts.map +1 -0
  205. package/dist/tools/attachments.tool.js +45 -0
  206. package/dist/tools/attachments.tool.js.map +1 -0
  207. package/dist/tools/bulk.tool.d.ts +7 -0
  208. package/dist/tools/bulk.tool.d.ts.map +1 -0
  209. package/dist/tools/bulk.tool.js +75 -0
  210. package/dist/tools/bulk.tool.js.map +1 -0
  211. package/dist/tools/calendar.tool.d.ts +19 -0
  212. package/dist/tools/calendar.tool.d.ts.map +1 -0
  213. package/dist/tools/calendar.tool.js +538 -0
  214. package/dist/tools/calendar.tool.js.map +1 -0
  215. package/dist/tools/contacts.tool.d.ts +7 -0
  216. package/dist/tools/contacts.tool.d.ts.map +1 -0
  217. package/dist/tools/contacts.tool.js +44 -0
  218. package/dist/tools/contacts.tool.js.map +1 -0
  219. package/dist/tools/drafts.tool.d.ts +8 -0
  220. package/dist/tools/drafts.tool.d.ts.map +1 -0
  221. package/dist/tools/drafts.tool.js +92 -0
  222. package/dist/tools/drafts.tool.js.map +1 -0
  223. package/dist/tools/emails.tool.d.ts +7 -0
  224. package/dist/tools/emails.tool.d.ts.map +1 -0
  225. package/dist/tools/emails.tool.js +400 -0
  226. package/dist/tools/emails.tool.js.map +1 -0
  227. package/dist/tools/folders.tool.d.ts +7 -0
  228. package/dist/tools/folders.tool.d.ts.map +1 -0
  229. package/dist/tools/folders.tool.js +111 -0
  230. package/dist/tools/folders.tool.js.map +1 -0
  231. package/dist/tools/health.tool.d.ts +10 -0
  232. package/dist/tools/health.tool.d.ts.map +1 -0
  233. package/dist/tools/health.tool.js +78 -0
  234. package/dist/tools/health.tool.js.map +1 -0
  235. package/dist/tools/label.tool.d.ts +11 -0
  236. package/dist/tools/label.tool.d.ts.map +1 -0
  237. package/dist/tools/label.tool.js +165 -0
  238. package/dist/tools/label.tool.js.map +1 -0
  239. package/dist/tools/locate.tool.d.ts +11 -0
  240. package/dist/tools/locate.tool.d.ts.map +1 -0
  241. package/dist/tools/locate.tool.js +59 -0
  242. package/dist/tools/locate.tool.js.map +1 -0
  243. package/dist/tools/mailboxes.tool.d.ts +7 -0
  244. package/dist/tools/mailboxes.tool.d.ts.map +1 -0
  245. package/dist/tools/mailboxes.tool.js +38 -0
  246. package/dist/tools/mailboxes.tool.js.map +1 -0
  247. package/dist/tools/manage.tool.d.ts +7 -0
  248. package/dist/tools/manage.tool.d.ts.map +1 -0
  249. package/dist/tools/manage.tool.js +125 -0
  250. package/dist/tools/manage.tool.js.map +1 -0
  251. package/dist/tools/register.d.ts +20 -0
  252. package/dist/tools/register.d.ts.map +1 -0
  253. package/dist/tools/register.js +53 -0
  254. package/dist/tools/register.js.map +1 -0
  255. package/dist/tools/scheduler.tool.d.ts +9 -0
  256. package/dist/tools/scheduler.tool.d.ts.map +1 -0
  257. package/dist/tools/scheduler.tool.js +104 -0
  258. package/dist/tools/scheduler.tool.js.map +1 -0
  259. package/dist/tools/send.tool.d.ts +7 -0
  260. package/dist/tools/send.tool.d.ts.map +1 -0
  261. package/dist/tools/send.tool.js +123 -0
  262. package/dist/tools/send.tool.js.map +1 -0
  263. package/dist/tools/templates.tool.d.ts +12 -0
  264. package/dist/tools/templates.tool.d.ts.map +1 -0
  265. package/dist/tools/templates.tool.js +140 -0
  266. package/dist/tools/templates.tool.js.map +1 -0
  267. package/dist/tools/thread.tool.d.ts +10 -0
  268. package/dist/tools/thread.tool.d.ts.map +1 -0
  269. package/dist/tools/thread.tool.js +146 -0
  270. package/dist/tools/thread.tool.js.map +1 -0
  271. package/dist/tools/watcher.tool.d.ts +9 -0
  272. package/dist/tools/watcher.tool.d.ts.map +1 -0
  273. package/dist/tools/watcher.tool.js +282 -0
  274. package/dist/tools/watcher.tool.js.map +1 -0
  275. package/dist/types/index.d.ts +271 -0
  276. package/dist/types/index.d.ts.map +1 -0
  277. package/dist/types/index.js +5 -0
  278. package/dist/types/index.js.map +1 -0
  279. package/dist/utils/calendar-notes.d.ts +31 -0
  280. package/dist/utils/calendar-notes.d.ts.map +1 -0
  281. package/dist/utils/calendar-notes.js +99 -0
  282. package/dist/utils/calendar-notes.js.map +1 -0
  283. package/dist/utils/calendar-state.d.ts +27 -0
  284. package/dist/utils/calendar-state.d.ts.map +1 -0
  285. package/dist/utils/calendar-state.js +85 -0
  286. package/dist/utils/calendar-state.js.map +1 -0
  287. package/dist/utils/conference-details.d.ts +12 -0
  288. package/dist/utils/conference-details.d.ts.map +1 -0
  289. package/dist/utils/conference-details.js +71 -0
  290. package/dist/utils/conference-details.js.map +1 -0
  291. package/dist/utils/meeting-url.d.ts +10 -0
  292. package/dist/utils/meeting-url.d.ts.map +1 -0
  293. package/dist/utils/meeting-url.js +30 -0
  294. package/dist/utils/meeting-url.js.map +1 -0
  295. package/package.json +108 -0
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Connection manager for lazy-persistent IMAP and SMTP connections.
3
+ *
4
+ * - Creates connections on first use per account
5
+ * - Reuses open connections across tool calls
6
+ * - Auto-reconnects on failure
7
+ * - Graceful shutdown closes all connections
8
+ */
9
+ import { ImapFlow } from 'imapflow';
10
+ import nodemailer from 'nodemailer';
11
+ import { mcpLog } from '../logging.js';
12
+ export default class ConnectionManager {
13
+ imapClients = new Map();
14
+ smtpTransports = new Map();
15
+ accounts = new Map();
16
+ oauthService;
17
+ constructor(accounts, oauthService) {
18
+ accounts.forEach((account) => {
19
+ this.accounts.set(account.name, account);
20
+ });
21
+ this.oauthService = oauthService;
22
+ }
23
+ // -------------------------------------------------------------------------
24
+ // Account lookup
25
+ // -------------------------------------------------------------------------
26
+ getAccount(name) {
27
+ const account = this.accounts.get(name);
28
+ if (!account) {
29
+ throw new Error(`Account "${name}" not found. Available: ${[...this.accounts.keys()].join(', ')}`);
30
+ }
31
+ return account;
32
+ }
33
+ getAccountNames() {
34
+ return [...this.accounts.keys()];
35
+ }
36
+ // -------------------------------------------------------------------------
37
+ // IMAP
38
+ // -------------------------------------------------------------------------
39
+ async getImapClient(accountName) {
40
+ const existing = this.imapClients.get(accountName);
41
+ if (existing?.usable) {
42
+ return existing;
43
+ }
44
+ // Clean up stale connection
45
+ if (existing) {
46
+ this.imapClients.delete(accountName);
47
+ try {
48
+ existing.close();
49
+ }
50
+ catch {
51
+ /* ignore */
52
+ }
53
+ }
54
+ const account = this.getAccount(accountName);
55
+ // Build auth config based on auth type
56
+ let auth;
57
+ if (account.oauth2 && this.oauthService) {
58
+ const accessToken = await this.oauthService.getAccessToken(account.oauth2);
59
+ auth = { user: account.username, accessToken };
60
+ }
61
+ else {
62
+ auth = { user: account.username, pass: account.password };
63
+ }
64
+ const client = new ImapFlow({
65
+ host: account.imap.host,
66
+ port: account.imap.port,
67
+ secure: account.imap.tls,
68
+ tls: {
69
+ rejectUnauthorized: account.imap.verifySsl,
70
+ },
71
+ auth,
72
+ logger: false,
73
+ });
74
+ await client.connect();
75
+ await mcpLog('info', 'imap', `Connected to ${account.imap.host}:${account.imap.port} for "${accountName}"`);
76
+ this.imapClients.set(accountName, client);
77
+ return client;
78
+ }
79
+ // -------------------------------------------------------------------------
80
+ // SMTP
81
+ // -------------------------------------------------------------------------
82
+ static buildSmtpTransportOptions(account, auth) {
83
+ const pool = account.smtp.pool ?? {
84
+ enabled: true,
85
+ maxConnections: 1,
86
+ maxMessages: 100,
87
+ };
88
+ return {
89
+ host: account.smtp.host,
90
+ port: account.smtp.port,
91
+ secure: account.smtp.tls,
92
+ requireTLS: account.smtp.starttls,
93
+ ignoreTLS: !account.smtp.tls && !account.smtp.starttls,
94
+ tls: {
95
+ rejectUnauthorized: account.smtp.verifySsl,
96
+ },
97
+ auth,
98
+ pool: pool.enabled,
99
+ ...(pool.enabled
100
+ ? {
101
+ maxConnections: pool.maxConnections,
102
+ maxMessages: pool.maxMessages,
103
+ }
104
+ : {}),
105
+ };
106
+ }
107
+ async getSmtpTransport(accountName, options) {
108
+ const verify = options?.verify ?? false;
109
+ const existing = this.smtpTransports.get(accountName);
110
+ if (existing) {
111
+ if (!verify) {
112
+ return existing;
113
+ }
114
+ try {
115
+ await existing.verify();
116
+ return existing;
117
+ }
118
+ catch {
119
+ this.smtpTransports.delete(accountName);
120
+ try {
121
+ existing.close();
122
+ }
123
+ catch {
124
+ /* ignore */
125
+ }
126
+ }
127
+ }
128
+ const account = this.getAccount(accountName);
129
+ // Build auth config based on auth type
130
+ let auth;
131
+ if (account.oauth2 && this.oauthService) {
132
+ const accessToken = await this.oauthService.getAccessToken(account.oauth2);
133
+ auth = { type: 'OAuth2', user: account.username, accessToken };
134
+ }
135
+ else {
136
+ auth = { user: account.username, pass: account.password };
137
+ }
138
+ const transport = nodemailer.createTransport(ConnectionManager.buildSmtpTransportOptions(account, auth));
139
+ await transport.verify();
140
+ await mcpLog('info', 'smtp', `Connected to ${account.smtp.host}:${account.smtp.port} for "${accountName}"`);
141
+ this.smtpTransports.set(accountName, transport);
142
+ return transport;
143
+ }
144
+ async verifySmtpTransport(accountName) {
145
+ await this.getSmtpTransport(accountName, { verify: true });
146
+ }
147
+ // -------------------------------------------------------------------------
148
+ // Test connections (for setup wizard / test command)
149
+ // -------------------------------------------------------------------------
150
+ static async testImap(account, oauthService) {
151
+ let client;
152
+ try {
153
+ let auth;
154
+ if (account.oauth2 && oauthService) {
155
+ const accessToken = await oauthService.getAccessToken(account.oauth2);
156
+ auth = { user: account.username, accessToken };
157
+ }
158
+ else {
159
+ auth = { user: account.username, pass: account.password };
160
+ }
161
+ client = new ImapFlow({
162
+ host: account.imap.host,
163
+ port: account.imap.port,
164
+ secure: account.imap.tls,
165
+ tls: {
166
+ rejectUnauthorized: account.imap.verifySsl,
167
+ },
168
+ auth,
169
+ logger: false,
170
+ });
171
+ await client.connect();
172
+ const mailboxes = await client.list();
173
+ let messageCount = 0;
174
+ try {
175
+ const inbox = await client.status('INBOX', {
176
+ messages: true,
177
+ unseen: true,
178
+ });
179
+ messageCount = inbox.messages ?? 0;
180
+ }
181
+ catch {
182
+ // INBOX may not exist (e.g. Google Workspace uses "All Mail")
183
+ if (mailboxes.length > 0) {
184
+ try {
185
+ const first = await client.status(mailboxes[0].path, {
186
+ messages: true,
187
+ });
188
+ messageCount = first.messages ?? 0;
189
+ }
190
+ catch {
191
+ /* ignore — connection still works */
192
+ }
193
+ }
194
+ }
195
+ return {
196
+ success: true,
197
+ details: {
198
+ messages: messageCount,
199
+ folders: mailboxes.length,
200
+ },
201
+ };
202
+ }
203
+ catch (err) {
204
+ return {
205
+ success: false,
206
+ error: err instanceof Error ? err.message : String(err),
207
+ };
208
+ }
209
+ finally {
210
+ if (client) {
211
+ try {
212
+ await client.logout();
213
+ }
214
+ catch {
215
+ /* ignore */
216
+ }
217
+ }
218
+ }
219
+ }
220
+ static async testSmtp(account, oauthService) {
221
+ let transport;
222
+ try {
223
+ let auth;
224
+ if (account.oauth2 && oauthService) {
225
+ const accessToken = await oauthService.getAccessToken(account.oauth2);
226
+ auth = { type: 'OAuth2', user: account.username, accessToken };
227
+ }
228
+ else {
229
+ auth = { user: account.username, pass: account.password };
230
+ }
231
+ transport = nodemailer.createTransport(ConnectionManager.buildSmtpTransportOptions(account, auth));
232
+ await transport.verify();
233
+ return { success: true };
234
+ }
235
+ catch (err) {
236
+ return {
237
+ success: false,
238
+ error: err instanceof Error ? err.message : String(err),
239
+ };
240
+ }
241
+ finally {
242
+ transport?.close();
243
+ }
244
+ }
245
+ // -------------------------------------------------------------------------
246
+ // Shutdown
247
+ // -------------------------------------------------------------------------
248
+ async closeAll() {
249
+ await mcpLog('info', 'connections', 'Closing all connections');
250
+ const closeOps = [];
251
+ Array.from(this.imapClients.entries()).forEach(([name, client]) => {
252
+ closeOps.push(client
253
+ .logout()
254
+ .catch(() => { })
255
+ .then(() => {
256
+ this.imapClients.delete(name);
257
+ }));
258
+ });
259
+ Array.from(this.smtpTransports.entries()).forEach(([name, transport]) => {
260
+ transport.close();
261
+ this.smtpTransports.delete(name);
262
+ });
263
+ await Promise.allSettled(closeOps);
264
+ }
265
+ }
266
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/connections/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ImapFlow } from 'imapflow';
2
+ import type { Transporter } from 'nodemailer';
3
+ import type { AccountConfig } from '../types/index.js';
4
+ export interface IConnectionManager {
5
+ getAccount: (name: string) => AccountConfig;
6
+ getAccountNames: () => string[];
7
+ getImapClient: (accountName: string) => Promise<ImapFlow>;
8
+ getSmtpTransport: (accountName: string, options?: {
9
+ verify?: boolean;
10
+ }) => Promise<Transporter>;
11
+ closeAll: () => Promise<void>;
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/connections/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,CAAC;IAC5C,eAAe,EAAE,MAAM,MAAM,EAAE,CAAC;IAChC,aAAa,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,gBAAgB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAChG,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/connections/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * MCP protocol logging bridge.
3
+ *
4
+ * Forwards structured log messages to the connected MCP client
5
+ * via the logging notification channel declared in server capabilities.
6
+ *
7
+ * Messages are silently dropped until `markInitialized()` is called,
8
+ * which should happen only after the MCP `initialized` handshake
9
+ * completes. This prevents pre-handshake notifications from being
10
+ * written to stdout and breaking clients.
11
+ *
12
+ * Usage:
13
+ * bindServer(server) — call once after creating the McpServer
14
+ * markInitialized() — call from the `oninitialized` callback
15
+ * mcpLog("info", …) — fire-and-forget from anywhere
16
+ */
17
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
18
+ type LogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';
19
+ /**
20
+ * Bind an McpServer instance so subsequent `mcpLog()` calls
21
+ * are forwarded to the connected client.
22
+ */
23
+ export declare function bindServer(server: McpServer): void;
24
+ /**
25
+ * Mark the server as fully initialized (handshake complete).
26
+ *
27
+ * Call this from the `server.server.oninitialized` callback so that
28
+ * `mcpLog()` starts forwarding messages to the client.
29
+ */
30
+ export declare function markInitialized(): void;
31
+ /**
32
+ * Reset module state. **Test-only** — never call in production.
33
+ * @internal
34
+ */
35
+ export declare function __resetForTesting(): void;
36
+ /**
37
+ * Emit a structured log message over the MCP logging channel.
38
+ *
39
+ * Safe to call at any point — silently dropped when:
40
+ * • the server hasn't been bound yet
41
+ * • the transport isn't connected
42
+ * • the MCP handshake hasn't completed (`markInitialized()` not called)
43
+ */
44
+ export declare function mcpLog(level: LogLevel, logger: string, data: unknown): Promise<void>;
45
+ export {};
46
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,OAAO,GACP,WAAW,CAAC;AAOhB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED;;;GAGG;AAEH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAO1F"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * MCP protocol logging bridge.
3
+ *
4
+ * Forwards structured log messages to the connected MCP client
5
+ * via the logging notification channel declared in server capabilities.
6
+ *
7
+ * Messages are silently dropped until `markInitialized()` is called,
8
+ * which should happen only after the MCP `initialized` handshake
9
+ * completes. This prevents pre-handshake notifications from being
10
+ * written to stdout and breaking clients.
11
+ *
12
+ * Usage:
13
+ * bindServer(server) — call once after creating the McpServer
14
+ * markInitialized() — call from the `oninitialized` callback
15
+ * mcpLog("info", …) — fire-and-forget from anywhere
16
+ */
17
+ let mcpServerRef = null;
18
+ /** `true` only after the client has completed the MCP `initialized` handshake. */
19
+ let initialized = false;
20
+ /**
21
+ * Bind an McpServer instance so subsequent `mcpLog()` calls
22
+ * are forwarded to the connected client.
23
+ */
24
+ export function bindServer(server) {
25
+ mcpServerRef = server;
26
+ }
27
+ /**
28
+ * Mark the server as fully initialized (handshake complete).
29
+ *
30
+ * Call this from the `server.server.oninitialized` callback so that
31
+ * `mcpLog()` starts forwarding messages to the client.
32
+ */
33
+ export function markInitialized() {
34
+ initialized = true;
35
+ }
36
+ /**
37
+ * Reset module state. **Test-only** — never call in production.
38
+ * @internal
39
+ */
40
+ // eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle
41
+ export function __resetForTesting() {
42
+ mcpServerRef = null;
43
+ initialized = false;
44
+ }
45
+ /**
46
+ * Emit a structured log message over the MCP logging channel.
47
+ *
48
+ * Safe to call at any point — silently dropped when:
49
+ * • the server hasn't been bound yet
50
+ * • the transport isn't connected
51
+ * • the MCP handshake hasn't completed (`markInitialized()` not called)
52
+ */
53
+ export async function mcpLog(level, logger, data) {
54
+ if (!initialized || !mcpServerRef?.isConnected())
55
+ return;
56
+ try {
57
+ await mcpServerRef.sendLoggingMessage({ level, logger, data });
58
+ }
59
+ catch {
60
+ // Never let a logging failure break tool execution
61
+ }
62
+ }
63
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,IAAI,YAAY,GAAqB,IAAI,CAAC;AAE1C,kFAAkF;AAClF,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe;IAC7B,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,sFAAsF;AACtF,MAAM,UAAU,iBAAiB;IAC/B,YAAY,GAAG,IAAI,CAAC;IACpB,WAAW,GAAG,KAAK,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAe,EAAE,MAAc,EAAE,IAAa;IACzE,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE;QAAE,OAAO;IACzD,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;AACH,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Email MCP Server — Main entry point.
4
+ *
5
+ * Subcommands:
6
+ * stdio Run as MCP server over stdio (default)
7
+ * setup Interactive account setup wizard
8
+ * test Test IMAP/SMTP connections
9
+ * config Config management (show, path, init)
10
+ * scheduler Email scheduling management
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
package/dist/main.js ADDED
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Email MCP Server — Main entry point.
4
+ *
5
+ * Subcommands:
6
+ * stdio Run as MCP server over stdio (default)
7
+ * setup Interactive account setup wizard
8
+ * test Test IMAP/SMTP connections
9
+ * config Config management (show, path, init)
10
+ * scheduler Email scheduling management
11
+ */
12
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
+ import { loadConfig } from './config/loader.js';
14
+ import ConnectionManager from './connections/manager.js';
15
+ import { bindServer, markInitialized, mcpLog } from './logging.js';
16
+ import registerAllPrompts from './prompts/register.js';
17
+ import registerAllResources from './resources/register.js';
18
+ import RateLimiter from './safety/rate-limiter.js';
19
+ import createServer, { PKG_VERSION } from './server.js';
20
+ import CalendarService from './services/calendar.service.js';
21
+ import HooksService from './services/hooks.service.js';
22
+ import ImapService from './services/imap.service.js';
23
+ import LocalCalendarService from './services/local-calendar.service.js';
24
+ import OAuthService from './services/oauth.service.js';
25
+ import RemindersService from './services/reminders.service.js';
26
+ import SchedulerService from './services/scheduler.service.js';
27
+ import SmtpService from './services/smtp.service.js';
28
+ import TemplateService from './services/template.service.js';
29
+ import WatcherService from './services/watcher.service.js';
30
+ import registerAllTools from './tools/register.js';
31
+ const HELP = `
32
+ email-mcp — Email MCP Server (IMAP + SMTP)
33
+
34
+ Usage:
35
+ email-mcp [command]
36
+
37
+ Commands:
38
+ stdio Run as MCP server over stdio (default)
39
+ account Account management (list, add, edit, delete)
40
+ setup Alias for 'account add'
41
+ test Test connections for all or a specific account
42
+ install Register/unregister with MCP clients (Claude, Cursor, …)
43
+ config Config management (show, edit, path, init)
44
+ scheduler Email scheduling management (check, list, install, uninstall, status)
45
+ notify Test and diagnose desktop notifications
46
+ help Show this help message
47
+
48
+ Examples:
49
+ email-mcp # Start MCP server
50
+ email-mcp account list # List configured accounts
51
+ email-mcp account add # Add a new email account
52
+ email-mcp account edit personal # Edit an account
53
+ email-mcp account delete work # Delete an account
54
+ email-mcp setup # Alias for account add
55
+ email-mcp test # Test all accounts
56
+ email-mcp test personal # Test specific account
57
+ email-mcp install # Register with detected MCP clients
58
+ email-mcp install status # Show client registration status
59
+ email-mcp install remove # Unregister from MCP clients
60
+ email-mcp config show # Show config (passwords masked)
61
+ email-mcp config edit # Edit global settings
62
+ email-mcp config path # Print config file path
63
+ email-mcp config init # Create template config
64
+ email-mcp scheduler check # Send overdue scheduled emails
65
+ email-mcp scheduler install # Install OS periodic check
66
+ email-mcp notify test # Send a test notification
67
+ email-mcp notify status # Check notification platform support
68
+ `.trim();
69
+ async function runServer() {
70
+ const config = await loadConfig();
71
+ const oauthService = new OAuthService();
72
+ const connections = new ConnectionManager(config.accounts, oauthService);
73
+ const rateLimiter = new RateLimiter(config.settings.rateLimit);
74
+ const imapService = new ImapService(connections);
75
+ const smtpService = new SmtpService(connections, rateLimiter, imapService);
76
+ const templateService = new TemplateService();
77
+ const calendarService = new CalendarService();
78
+ const localCalendarService = new LocalCalendarService();
79
+ const remindersService = new RemindersService();
80
+ const schedulerService = new SchedulerService(smtpService, imapService);
81
+ const watcherService = new WatcherService(config.settings.watcher, config.accounts);
82
+ const hooksService = new HooksService(config.settings.hooks, imapService);
83
+ const server = createServer();
84
+ bindServer(server);
85
+ registerAllTools(server, connections, imapService, smtpService, config, templateService, calendarService, localCalendarService, remindersService, schedulerService, watcherService, hooksService);
86
+ registerAllResources(server, connections, imapService, templateService, schedulerService);
87
+ registerAllPrompts(server);
88
+ const transport = new StdioServerTransport();
89
+ await server.connect(transport);
90
+ // --- Post-handshake initialization ----------------------------------------
91
+ // Everything below is deferred until the client completes the MCP
92
+ // `initialize` / `initialized` handshake. This prevents notifications
93
+ // from being written to stdout before the client is ready, which would
94
+ // crash clients like Vibe, and ensures `getClientCapabilities()` returns
95
+ // the real capabilities (including `sampling` support).
96
+ // --------------------------------------------------------------------------
97
+ let schedulerInterval;
98
+ const lowLevelServer = server.server;
99
+ lowLevelServer.oninitialized = () => {
100
+ markInitialized();
101
+ // eslint-disable-next-line no-void
102
+ void (async () => {
103
+ try {
104
+ const clientCaps = lowLevelServer.getClientCapabilities?.() ?? {};
105
+ hooksService.start(lowLevelServer, { sampling: clientCaps.sampling != null });
106
+ await watcherService.start();
107
+ await mcpLog('info', 'server', 'Email MCP server started');
108
+ // Check for overdue scheduled emails on startup
109
+ try {
110
+ const result = await schedulerService.checkAndSend();
111
+ if (result.sent > 0) {
112
+ await mcpLog('info', 'scheduler', `Sent ${result.sent} overdue email(s) on startup`);
113
+ }
114
+ }
115
+ catch {
116
+ // Non-fatal: scheduler check failure shouldn't prevent server start
117
+ }
118
+ // Periodic scheduler check every 60 seconds
119
+ schedulerInterval = setInterval(async () => {
120
+ try {
121
+ await schedulerService.checkAndSend();
122
+ }
123
+ catch {
124
+ // Silent — don't spam logs
125
+ }
126
+ }, 60_000);
127
+ }
128
+ catch (err) {
129
+ // Log to stderr — mcpLog may not be safe if init itself errored
130
+ process.stderr.write(`[email-mcp] post-init error: ${err instanceof Error ? err.message : String(err)}\n`);
131
+ }
132
+ })();
133
+ };
134
+ // Graceful shutdown
135
+ const shutdown = async () => {
136
+ if (schedulerInterval)
137
+ clearInterval(schedulerInterval);
138
+ hooksService.stop();
139
+ await watcherService.stop();
140
+ await connections.closeAll();
141
+ await server.close();
142
+ };
143
+ process.on('SIGINT', shutdown);
144
+ process.on('SIGTERM', shutdown);
145
+ }
146
+ async function main() {
147
+ const command = process.argv[2] ?? 'stdio';
148
+ switch (command) {
149
+ case 'stdio':
150
+ await runServer();
151
+ break;
152
+ case 'setup': {
153
+ const { default: runSetup } = await import('./cli/setup.js');
154
+ await runSetup();
155
+ break;
156
+ }
157
+ case 'account': {
158
+ const { default: runAccountCommand } = await import('./cli/account-commands.js');
159
+ await runAccountCommand(process.argv[3], process.argv[4]);
160
+ break;
161
+ }
162
+ case 'test': {
163
+ const { default: runTest } = await import('./cli/test.js');
164
+ await runTest(process.argv[3]);
165
+ break;
166
+ }
167
+ case 'config': {
168
+ const { default: runConfigCommand } = await import('./cli/config-commands.js');
169
+ await runConfigCommand(process.argv[3]);
170
+ break;
171
+ }
172
+ case 'install': {
173
+ const { default: runInstallCommand } = await import('./cli/install-commands.js');
174
+ await runInstallCommand(process.argv[3]);
175
+ break;
176
+ }
177
+ case 'scheduler': {
178
+ const { default: runSchedulerCommand } = await import('./cli/scheduler.js');
179
+ await runSchedulerCommand(process.argv[3]);
180
+ break;
181
+ }
182
+ case 'notify': {
183
+ const { default: runNotifyCommand } = await import('./cli/notify.js');
184
+ await runNotifyCommand(process.argv[3]);
185
+ break;
186
+ }
187
+ case '--version':
188
+ case '-v':
189
+ console.log(PKG_VERSION);
190
+ break;
191
+ case 'help':
192
+ case '--help':
193
+ case '-h':
194
+ console.log(HELP);
195
+ break;
196
+ default:
197
+ console.error(`Unknown command: ${command}\n`);
198
+ console.log(HELP);
199
+ throw new Error(`Unknown command: ${command}`);
200
+ }
201
+ }
202
+ main().catch((err) => {
203
+ console.error('Fatal error:', err instanceof Error ? err.message : String(err));
204
+ process.exitCode = 1;
205
+ });
206
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}