@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,113 @@
1
+ /** Input validation and sanitization utilities. */
2
+ /**
3
+ * Validate and sanitize an IMAP mailbox name.
4
+ * Rejects names containing IMAP wildcard characters (`*`, `%`) or empty strings.
5
+ * @param name - The mailbox name to validate.
6
+ * @returns The trimmed mailbox name.
7
+ */
8
+ export function sanitizeMailboxName(name) {
9
+ const trimmed = name.trim();
10
+ if (trimmed.length === 0) {
11
+ throw new Error('Mailbox name must not be empty');
12
+ }
13
+ if (trimmed.includes('*') || trimmed.includes('%')) {
14
+ throw new Error('Mailbox name must not contain IMAP wildcard characters (* or %)');
15
+ }
16
+ return trimmed;
17
+ }
18
+ /**
19
+ * Strip control characters from an IMAP search query.
20
+ * Removes ASCII 0-31 except tab (0x09) and newline (0x0A).
21
+ * @param query - The raw search query.
22
+ * @returns The sanitized query string.
23
+ */
24
+ export function sanitizeSearchQuery(query) {
25
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional — sanitize control chars from user input
26
+ const cleaned = query.replace(/[\x00-\x08\x0B-\x1F]/g, '').trim(); // eslint-disable-line no-control-regex
27
+ if (cleaned.length === 0) {
28
+ throw new Error('Search query must not be empty after sanitization');
29
+ }
30
+ return cleaned;
31
+ }
32
+ /**
33
+ * Validate a webhook URL.
34
+ * Ensures the URL uses http(s) and does not point to a private or loopback address.
35
+ * @param url - The webhook URL to validate.
36
+ */
37
+ export function validateWebhookUrl(url) {
38
+ let parsed;
39
+ try {
40
+ parsed = new URL(url);
41
+ }
42
+ catch {
43
+ throw new Error(`Invalid webhook URL: ${url}`);
44
+ }
45
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
46
+ throw new Error(`Webhook URL must use http or https protocol, got ${parsed.protocol}`);
47
+ }
48
+ const hostname = parsed.hostname.toLowerCase();
49
+ // new URL('https://[::1]') stores hostname as '[::1]'
50
+ const bare = hostname.replace(/^\[|\]$/g, '');
51
+ if (bare === 'localhost' || bare === '::1' || bare === '0.0.0.0') {
52
+ throw new Error(`Webhook URL must not point to a loopback or private address: ${bare}`);
53
+ }
54
+ const ipv4Match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(bare);
55
+ if (ipv4Match) {
56
+ const [, a, b] = ipv4Match.map(Number);
57
+ if (a === 127 || a === 10 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168)) {
58
+ throw new Error(`Webhook URL must not point to a loopback or private address: ${bare}`);
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Sanitize a value for use in a template.
64
+ * When `html` is true, HTML-special characters are escaped.
65
+ * @param value - The template variable value.
66
+ * @param html - Whether to apply HTML escaping.
67
+ * @returns The sanitized value.
68
+ */
69
+ export function sanitizeTemplateVariable(value, html) {
70
+ if (!html) {
71
+ return value;
72
+ }
73
+ return value
74
+ .replace(/&/g, '&amp;')
75
+ .replace(/</g, '&lt;')
76
+ .replace(/>/g, '&gt;')
77
+ .replace(/"/g, '&quot;')
78
+ .replace(/'/g, '&#39;');
79
+ }
80
+ /**
81
+ * Validate an email label name.
82
+ * Rejects labels with control characters or that exceed 200 characters.
83
+ * @param name - The label name to validate.
84
+ * @returns The trimmed label name.
85
+ */
86
+ export function validateLabelName(name) {
87
+ const trimmed = name.trim();
88
+ if (trimmed.length === 0) {
89
+ throw new Error('Label name must not be empty');
90
+ }
91
+ if (trimmed.length > 200) {
92
+ throw new Error('Label name must not exceed 200 characters');
93
+ }
94
+ /* eslint-disable no-control-regex */
95
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional — reject control chars in label names
96
+ if (/[\x00-\x1F]/.test(trimmed)) {
97
+ throw new Error('Label name must not contain control characters');
98
+ }
99
+ /* eslint-enable no-control-regex */
100
+ return trimmed;
101
+ }
102
+ /**
103
+ * Validate that an input string does not exceed a maximum length.
104
+ * @param input - The input string to check.
105
+ * @param maxLength - The maximum allowed length.
106
+ * @param fieldName - The field name for the error message.
107
+ */
108
+ export function validateInputLength(input, maxLength, fieldName) {
109
+ if (input.length > maxLength) {
110
+ throw new Error(`${fieldName} exceeds maximum length of ${maxLength} characters`);
111
+ }
112
+ }
113
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/safety/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * MCP Server factory.
3
+ *
4
+ * Creates and configures the McpServer instance with capabilities.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ export declare const PKG_NAME = "email-mcp";
8
+ export declare const PKG_VERSION: string;
9
+ export default function createServer(): McpServer;
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,WAAW,QAAc,CAAC;AAEvC,MAAM,CAAC,OAAO,UAAU,YAAY,IAAI,SAAS,CAehD"}
package/dist/server.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * MCP Server factory.
3
+ *
4
+ * Creates and configures the McpServer instance with capabilities.
5
+ */
6
+ import { createRequire } from 'node:module';
7
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ const esmRequire = createRequire(import.meta.url);
9
+ const pkg = esmRequire('../package.json');
10
+ export const PKG_NAME = 'email-mcp';
11
+ export const PKG_VERSION = pkg.version;
12
+ export default function createServer() {
13
+ return new McpServer({
14
+ name: PKG_NAME,
15
+ version: PKG_VERSION,
16
+ }, {
17
+ capabilities: {
18
+ tools: { listChanged: true },
19
+ prompts: { listChanged: true },
20
+ resources: { subscribe: true, listChanged: true },
21
+ logging: {},
22
+ },
23
+ });
24
+ }
25
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,GAAG,GAAG,UAAU,CAAC,iBAAiB,CAAwB,CAAC;AAEjE,MAAM,CAAC,MAAM,QAAQ,GAAG,WAAW,CAAC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC;AAEvC,MAAM,CAAC,OAAO,UAAU,YAAY;IAClC,OAAO,IAAI,SAAS,CAClB;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,WAAW;KACrB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;YAC5B,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;YAC9B,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;YACjD,OAAO,EAAE,EAAE;SACZ;KACF,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Calendar service — ICS/iCalendar parsing.
3
+ *
4
+ * Extracts structured calendar events from ICS content using node-ical.
5
+ */
6
+ import type { CalendarEvent } from '../types/index.js';
7
+ export default class CalendarService {
8
+ /**
9
+ * Parse ICS text content into structured CalendarEvent objects.
10
+ */
11
+ static parseIcs(content: string): CalendarEvent[];
12
+ /**
13
+ * Extract calendar events from raw email body parts.
14
+ * Accepts an array of ICS content strings (from inline text/calendar parts
15
+ * or downloaded .ics attachments).
16
+ */
17
+ extractFromParts(icsContents: string[]): CalendarEvent[];
18
+ private static parseOrganizer;
19
+ private static parseAttendees;
20
+ private static normalizeStatus;
21
+ }
22
+ //# sourceMappingURL=calendar.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.service.d.ts","sourceRoot":"","sources":["../../src/services/calendar.service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,mBAAmB,CAAC;AAIrE,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE;IA2CjD;;;;OAIG;IAEH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE;IAsBxD,OAAO,CAAC,MAAM,CAAC,cAAc;IAiB7B,OAAO,CAAC,MAAM,CAAC,cAAc;IAoB7B,OAAO,CAAC,MAAM,CAAC,eAAe;CAQ/B"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Calendar service — ICS/iCalendar parsing.
3
+ *
4
+ * Extracts structured calendar events from ICS content using node-ical.
5
+ */
6
+ import ical from 'node-ical';
7
+ export default class CalendarService {
8
+ /**
9
+ * Parse ICS text content into structured CalendarEvent objects.
10
+ */
11
+ static parseIcs(content) {
12
+ const parsed = ical.sync.parseICS(content);
13
+ const events = [];
14
+ // Extract the VCALENDAR METHOD if present
15
+ let calendarMethod;
16
+ Object.values(parsed).forEach((comp) => {
17
+ if (comp?.type === 'VCALENDAR') {
18
+ calendarMethod = comp.method;
19
+ }
20
+ });
21
+ Object.values(parsed).forEach((comp) => {
22
+ if (!comp || comp.type !== 'VEVENT')
23
+ return;
24
+ const event = comp;
25
+ const start = event.start;
26
+ const end = event.end;
27
+ const organizer = CalendarService.parseOrganizer(event.organizer);
28
+ const attendees = CalendarService.parseAttendees(event.attendee);
29
+ const rrule = event.rrule;
30
+ events.push({
31
+ uid: event.uid ?? '',
32
+ summary: event.summary ?? '(No title)',
33
+ description: event.description,
34
+ start: start ? start.toISOString() : '',
35
+ end: end ? end.toISOString() : '',
36
+ location: event.location,
37
+ organizer,
38
+ attendees,
39
+ status: CalendarService.normalizeStatus(event.status),
40
+ method: calendarMethod,
41
+ recurrence: rrule?.toString(),
42
+ });
43
+ });
44
+ // Sort by start time
45
+ events.sort((a, b) => a.start.localeCompare(b.start));
46
+ return events;
47
+ }
48
+ /**
49
+ * Extract calendar events from raw email body parts.
50
+ * Accepts an array of ICS content strings (from inline text/calendar parts
51
+ * or downloaded .ics attachments).
52
+ */
53
+ // eslint-disable-next-line class-methods-use-this
54
+ extractFromParts(icsContents) {
55
+ const allEvents = [];
56
+ const seenUids = new Set();
57
+ icsContents.forEach((content) => {
58
+ const events = CalendarService.parseIcs(content);
59
+ events.forEach((event) => {
60
+ if (!seenUids.has(event.uid)) {
61
+ seenUids.add(event.uid);
62
+ allEvents.push(event);
63
+ }
64
+ });
65
+ });
66
+ allEvents.sort((a, b) => a.start.localeCompare(b.start));
67
+ return allEvents;
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // Private helpers
71
+ // ---------------------------------------------------------------------------
72
+ static parseOrganizer(organizer) {
73
+ if (!organizer)
74
+ return undefined;
75
+ if (typeof organizer === 'string') {
76
+ const email = organizer.replace(/^mailto:/i, '');
77
+ return { address: email };
78
+ }
79
+ const org = organizer;
80
+ const val = org.val ?? '';
81
+ const email = val.replace(/^mailto:/i, '');
82
+ return {
83
+ name: org.params?.CN,
84
+ address: email,
85
+ };
86
+ }
87
+ static parseAttendees(attendees) {
88
+ if (!attendees)
89
+ return [];
90
+ const list = Array.isArray(attendees) ? attendees : [attendees];
91
+ return list
92
+ .map((att) => {
93
+ if (typeof att === 'string') {
94
+ return { address: att.replace(/^mailto:/i, '') };
95
+ }
96
+ const a = att;
97
+ const val = a.val ?? '';
98
+ const email = val.replace(/^mailto:/i, '');
99
+ return {
100
+ name: a.params?.CN,
101
+ address: email,
102
+ };
103
+ })
104
+ .filter((a) => a.address);
105
+ }
106
+ static normalizeStatus(status) {
107
+ const upper = (status ?? 'CONFIRMED').toUpperCase();
108
+ if (upper === 'TENTATIVE')
109
+ return 'TENTATIVE';
110
+ if (upper === 'CANCELLED')
111
+ return 'CANCELLED';
112
+ return 'CONFIRMED';
113
+ }
114
+ }
115
+ //# sourceMappingURL=calendar.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.service.js","sourceRoot":"","sources":["../../src/services/calendar.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Typed event bus for internal email events.
3
+ *
4
+ * Decouples the IMAP IDLE watcher from MCP notification hooks.
5
+ * Uses Node's built-in EventEmitter with typed event maps.
6
+ */
7
+ import { EventEmitter } from 'node:events';
8
+ import type { EmailMeta } from '../types/index.js';
9
+ export interface NewEmailEvent {
10
+ account: string;
11
+ mailbox: string;
12
+ emails: EmailMeta[];
13
+ }
14
+ export interface ExpungeEvent {
15
+ account: string;
16
+ mailbox: string;
17
+ count: number;
18
+ }
19
+ interface EmailEventMap {
20
+ 'email:new': [NewEmailEvent];
21
+ 'email:expunge': [ExpungeEvent];
22
+ }
23
+ export declare class EmailEventBus extends EventEmitter<EmailEventMap> {
24
+ }
25
+ /** Singleton event bus shared across the application. */
26
+ declare const eventBus: EmailEventBus;
27
+ export default eventBus;
28
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/services/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMnD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,UAAU,aAAa;IACrB,WAAW,EAAE,CAAC,aAAa,CAAC,CAAC;IAC7B,eAAe,EAAE,CAAC,YAAY,CAAC,CAAC;CACjC;AAMD,qBAAa,aAAc,SAAQ,YAAY,CAAC,aAAa,CAAC;CAAG;AAEjE,yDAAyD;AACzD,QAAA,MAAM,QAAQ,eAAsB,CAAC;AACrC,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Typed event bus for internal email events.
3
+ *
4
+ * Decouples the IMAP IDLE watcher from MCP notification hooks.
5
+ * Uses Node's built-in EventEmitter with typed event maps.
6
+ */
7
+ import { EventEmitter } from 'node:events';
8
+ // ---------------------------------------------------------------------------
9
+ // Typed EventBus
10
+ // ---------------------------------------------------------------------------
11
+ export class EmailEventBus extends EventEmitter {
12
+ }
13
+ /** Singleton event bus shared across the application. */
14
+ const eventBus = new EmailEventBus();
15
+ export default eventBus;
16
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/services/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA4B3C,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,OAAO,aAAc,SAAQ,YAA2B;CAAG;AAEjE,yDAAyD;AACzD,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;AACrC,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * AI Hooks Service — intelligent email triage via MCP sampling.
3
+ *
4
+ * Listens for new email events on the event bus and:
5
+ * - Matches static rules FIRST (fast, free, deterministic)
6
+ * - Falls through to AI triage via `sampling/createMessage` if no rule matched
7
+ * - Uses preset system prompts + custom instructions for AI triage
8
+ * - Auto-applies labels and flags based on AI response
9
+ * - Falls back to logging if sampling is unavailable
10
+ */
11
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
+ import type { EmailMeta, HookRule, HooksConfig } from '../types/index.js';
13
+ import type ImapService from './imap.service.js';
14
+ import NotifierService from './notifier.service.js';
15
+ interface TriageResult {
16
+ priority?: 'urgent' | 'high' | 'normal' | 'low';
17
+ labels?: string[];
18
+ flag?: boolean;
19
+ action?: string;
20
+ addToCalendar?: boolean;
21
+ }
22
+ interface BatchEmail {
23
+ account: string;
24
+ mailbox: string;
25
+ meta: EmailMeta;
26
+ }
27
+ interface RuleMatchResult {
28
+ matched: true;
29
+ rule: HookRule;
30
+ }
31
+ interface RuleNoMatch {
32
+ matched: false;
33
+ }
34
+ type StaticMatchOutcome = RuleMatchResult | RuleNoMatch;
35
+ export default class HooksService {
36
+ private config;
37
+ private imapService;
38
+ private lowLevelServer;
39
+ private samplingSupported;
40
+ private pendingEmails;
41
+ private batchTimer;
42
+ private rateCounter;
43
+ private rateResetTimer;
44
+ private readonly resolvedSystemPrompt;
45
+ private readonly notifier;
46
+ private readonly localCalendar;
47
+ private static readonly MAX_SAMPLING_PER_MIN;
48
+ constructor(config: HooksConfig, imapService: ImapService);
49
+ /** Returns the NotifierService instance for direct tool access. */
50
+ getNotifier(): NotifierService;
51
+ /** Returns the current hooks configuration. */
52
+ getHooksConfig(): HooksConfig;
53
+ /**
54
+ * Start listening for email events.
55
+ * Call after MCP server is connected so we can access the low-level server.
56
+ */
57
+ start(lowLevelServer: Server, clientCapabilities: {
58
+ sampling?: boolean;
59
+ }): void;
60
+ stop(): void;
61
+ private onNewEmail;
62
+ private flushBatch;
63
+ static matchStaticRules(email: BatchEmail, rules: HookRule[]): StaticMatchOutcome;
64
+ private static emailMatchesRule;
65
+ private applyStaticRule;
66
+ private sendResourceUpdates;
67
+ private notifyBatch;
68
+ private triageBatch;
69
+ private static formatEmailSummary;
70
+ private applyTriageResults;
71
+ private applySingleTriage;
72
+ private applyCalendarAction;
73
+ static parseTriageResponse(text: string, expectedCount: number): TriageResult[];
74
+ static sanitizeTriageResult(raw: unknown): TriageResult;
75
+ }
76
+ export {};
77
+ //# sourceMappingURL=hooks.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.service.d.ts","sourceRoot":"","sources":["../../src/services/hooks.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG1E,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAGjD,OAAO,eAAe,MAAM,uBAAuB,CAAC;AAQpD,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,KAAK,CAAC;CAChB;AAED,KAAK,kBAAkB,GAAG,eAAe,GAAG,WAAW,CAAC;AAgCxD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAc;IAEjC,OAAO,CAAC,cAAc,CAAuB;IAE7C,OAAO,CAAC,iBAAiB,CAAS;IAElC,OAAO,CAAC,aAAa,CAAoB;IAEzC,OAAO,CAAC,UAAU,CAA8C;IAEhE,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,cAAc,CAA+C;IAErE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAE9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAE3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;IAErD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAM;gBAEtC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW;IAWzD,mEAAmE;IACnE,WAAW,IAAI,eAAe;IAI9B,+CAA+C;IAC/C,cAAc,IAAI,WAAW;IAI7B;;;OAGG;IACH,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,kBAAkB,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAwB/E,IAAI,IAAI,IAAI;IAkBZ,OAAO,CAAC,UAAU;YAaJ,UAAU;IAyCxB,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,kBAAkB;IAKjF,OAAO,CAAC,MAAM,CAAC,gBAAgB;YA0BjB,eAAe;YA0Ef,mBAAmB;YAiBnB,WAAW;YAoBX,WAAW;IA4CzB,OAAO,CAAC,MAAM,CAAC,kBAAkB;YAkBnB,kBAAkB;YAKlB,iBAAiB;YAkEjB,mBAAmB;IAuGjC,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,YAAY,EAAE;IAiB/E,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY;CAexD"}