@atomicmail/mcp 0.1.0 → 0.2.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 (49) hide show
  1. package/README.md +45 -145
  2. package/esm/lib/src/agent-auth-http.d.ts +26 -0
  3. package/esm/lib/src/agent-auth-http.d.ts.map +1 -0
  4. package/esm/lib/src/agent-auth-http.js +76 -0
  5. package/esm/{mcp/src/credentials.d.ts → lib/src/agent-credentials-store.d.ts} +3 -2
  6. package/esm/lib/src/agent-credentials-store.d.ts.map +1 -0
  7. package/esm/{mcp/src/credentials.js → lib/src/agent-credentials-store.js} +19 -16
  8. package/esm/lib/src/agent-help-content.d.ts +4 -0
  9. package/esm/lib/src/agent-help-content.d.ts.map +1 -0
  10. package/esm/lib/src/agent-help-content.js +236 -0
  11. package/esm/lib/src/agent-jmap.d.ts +49 -0
  12. package/esm/lib/src/agent-jmap.d.ts.map +1 -0
  13. package/esm/lib/src/agent-jmap.js +130 -0
  14. package/esm/lib/src/agent-jwt.d.ts +14 -0
  15. package/esm/lib/src/agent-jwt.d.ts.map +1 -0
  16. package/esm/lib/src/agent-jwt.js +29 -0
  17. package/esm/lib/src/agent-pow.d.ts +5 -0
  18. package/esm/lib/src/agent-pow.d.ts.map +1 -0
  19. package/esm/lib/src/agent-pow.js +49 -0
  20. package/esm/lib/src/agent-resolve-config.d.ts +24 -0
  21. package/esm/lib/src/agent-resolve-config.d.ts.map +1 -0
  22. package/esm/lib/src/agent-resolve-config.js +70 -0
  23. package/esm/lib/src/agent-session.d.ts +62 -0
  24. package/esm/lib/src/agent-session.d.ts.map +1 -0
  25. package/esm/lib/src/agent-session.js +206 -0
  26. package/esm/lib/src/agent-vars.d.ts +23 -0
  27. package/esm/lib/src/agent-vars.d.ts.map +1 -0
  28. package/esm/lib/src/agent-vars.js +65 -0
  29. package/esm/mcp/src/main.js +31 -61
  30. package/esm/mcp/src/tools/help.d.ts +3 -0
  31. package/esm/mcp/src/tools/help.d.ts.map +1 -0
  32. package/esm/mcp/src/tools/help.js +22 -0
  33. package/esm/mcp/src/tools/jmap.d.ts +2 -2
  34. package/esm/mcp/src/tools/jmap.d.ts.map +1 -1
  35. package/esm/mcp/src/tools/jmap.js +53 -140
  36. package/esm/mcp/src/tools/register.d.ts +2 -2
  37. package/esm/mcp/src/tools/register.d.ts.map +1 -1
  38. package/esm/mcp/src/tools/register.js +9 -45
  39. package/package.json +1 -1
  40. package/esm/mcp/src/auth-session.d.ts +0 -88
  41. package/esm/mcp/src/auth-session.d.ts.map +0 -1
  42. package/esm/mcp/src/auth-session.js +0 -378
  43. package/esm/mcp/src/credentials.d.ts.map +0 -1
  44. package/esm/mcp/src/docs-content.d.ts +0 -4
  45. package/esm/mcp/src/docs-content.d.ts.map +0 -1
  46. package/esm/mcp/src/docs-content.js +0 -405
  47. package/esm/mcp/src/tools/docs.d.ts +0 -3
  48. package/esm/mcp/src/tools/docs.d.ts.map +0 -1
  49. package/esm/mcp/src/tools/docs.js +0 -22
@@ -1,405 +0,0 @@
1
- // Static documentation strings served by the get_docs tool.
2
- // Kept in one file so future edits don't require touching tool wiring.
3
- export const TOPICS = {
4
- overview: `\
5
- # AtomicMail — Overview
6
-
7
- AtomicMail is an email service provider (ESP) designed for AI agents. It
8
- gives you a programmable mailbox you can manage entirely over JMAP (JSON
9
- Meta Application Protocol) — no IMAP, no SMTP knowledge needed.
10
-
11
- ## MCP Tools
12
-
13
- This MCP server exposes four tools:
14
-
15
- 1. **register** — Create a new account (PoW signup). Persists credentials
16
- to disk; returns the API key once.
17
- 2. **jmap_session** — Fetch the JMAP session object to discover your
18
- accountId.
19
- 3. **jmap_request** — Send any JMAP method-call batch. Auth is automatic.
20
- Accepts inline 'methodCalls' or a saved 'opsFile'.
21
- 4. **get_docs** — You're reading this! Pass a topic to drill in.
22
-
23
- ## Typical Workflow
24
-
25
- 1. If you don't have an API key, call \`register\` with a username.
26
- 2. Call \`jmap_session\` to learn your accountId and INBOX id.
27
- 3. Use \`jmap_request\` to read, send, and manage email.
28
-
29
- Available doc topics: overview, auth, jmap_cheatsheet, tools, installation,
30
- presets, troubleshooting.`,
31
- installation: `\
32
- # AtomicMail MCP — Installation
33
-
34
- The MCP server ships as a single npm-published binary (built from Deno
35
- sources via dnt) and runs unchanged on Node, Bun, and Deno.
36
-
37
- ## Quick start
38
-
39
- The simplest way to use it from any MCP host is via npx:
40
-
41
- \`\`\`json
42
- {
43
- "mcpServers": {
44
- "atomicmail": {
45
- "command": "npx",
46
- "args": ["-y", "@atomicmail/mcp"],
47
- "env": {
48
- "ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
49
- "ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
50
- }
51
- }
52
- }
53
- }
54
- \`\`\`
55
-
56
- Replace \`npx\` with \`bunx\` for Bun, or use \`deno run -A npm:@atomicmail/mcp\`
57
- for Deno.
58
-
59
- ## Cursor
60
-
61
- In \`~/.cursor/mcp.json\` (or per-project \`.cursor/mcp.json\`):
62
-
63
- \`\`\`json
64
- {
65
- "mcpServers": {
66
- "atomicmail": {
67
- "command": "npx",
68
- "args": ["-y", "@atomicmail/mcp"],
69
- "env": {
70
- "ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
71
- "ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
72
- }
73
- }
74
- }
75
- }
76
- \`\`\`
77
-
78
- ## Claude Desktop
79
-
80
- In \`claude_desktop_config.json\`:
81
-
82
- \`\`\`json
83
- {
84
- "mcpServers": {
85
- "atomicmail": {
86
- "command": "npx",
87
- "args": ["-y", "@atomicmail/mcp"],
88
- "env": {
89
- "ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
90
- "ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
91
- }
92
- }
93
- }
94
- }
95
- \`\`\`
96
-
97
- ## Sharing credentials with the skill CLI
98
-
99
- If you already use \`atomic-mail-signup\` from \`@atomic-mail/agent-skill\`,
100
- the MCP can pick up its credentials.json/session.jwt/capability.jwt with
101
- zero extra env vars beyond \`ATOMIC_MAIL_CREDENTIALS_DIR\`:
102
-
103
- \`\`\`json
104
- {
105
- "mcpServers": {
106
- "atomicmail": {
107
- "command": "npx",
108
- "args": ["-y", "@atomicmail/mcp"],
109
- "env": {
110
- "ATOMIC_MAIL_CREDENTIALS_DIR": "/Users/me/.atomicmail"
111
- }
112
- }
113
- }
114
- }
115
- \`\`\`
116
-
117
- The MCP defaults the credential directory to \`~/.atomicmail/\` if no env
118
- var is set, so even \`{}\` may suffice on a machine where you've already
119
- run \`atomic-mail-signup\`.
120
-
121
- ## From source (development)
122
-
123
- \`\`\`
124
- git clone https://github.com/atomic-mail/agentic-mail
125
- cd services/mcp-server-local
126
-
127
- # Run directly with Deno
128
- deno task start
129
-
130
- # Or build the npm package and run with Node
131
- deno task build:npm
132
- node npm/esm/main.js
133
- \`\`\`
134
-
135
- See README.md in the package root for more.`,
136
- auth: `\
137
- # AtomicMail — Auth Flow
138
-
139
- Auth is fully automatic inside this MCP server. You don't need to do
140
- anything unless you're registering for the first time.
141
-
142
- ## How it works internally
143
-
144
- 1. **Challenge** — MCP server requests a challenge from the auth service.
145
- 2. **Proof-of-Work** — MCP server computes a scrypt hash that satisfies the
146
- difficulty requirement. ~64 attempts on average (< 1 second).
147
- 3. **Session JWT** — Server validates the PoW and returns a session token
148
- (valid for 4 hours). On signup, it also returns a one-time API key.
149
- 4. **Capability JWT** — Before each JMAP call, the MCP server exchanges the
150
- session JWT for a short-lived capability token (2 min TTL) that the API
151
- service accepts.
152
-
153
- The MCP server decodes JWT \`exp\` claims and rotates session/capability
154
- JWTs as they approach expiry, persisting the new tokens to disk so a
155
- restarted process (or a concurrent atomic-mail-jmap CLI invocation) sees
156
- the latest values.
157
-
158
- ## Credential files
159
-
160
- All three files live in the credential directory (default
161
- \`~/.atomicmail/\`, override with \`ATOMIC_MAIL_CREDENTIALS_DIR\`). They are
162
- written with mode 0600 so other local users cannot read them.
163
-
164
- credentials.json { apiKey, inboxId, authUrl, apiUrl, scryptSalt }
165
- session.jwt 4-hour TTL
166
- capability.jwt 2-minute TTL
167
-
168
- ## Environment Variables
169
-
170
- | Variable | Required | Description |
171
- |--------------------------------|----------|-----------------------------------|
172
- | ATOMIC_MAIL_AUTH_URL | Yes* | Auth service URL |
173
- | ATOMIC_MAIL_API_URL | Yes* | API/JMAP service URL |
174
- | ATOMIC_MAIL_SCRYPT_SALT | No | Optional PoW salt override (defaults match auth-service) |
175
- | ATOMIC_MAIL_API_KEY | No | Existing API key (skip signup) |
176
- | ATOMIC_MAIL_CREDENTIALS_DIR | No | Override default credential dir |
177
-
178
- * "Yes" means at least one source — env var OR credentials.json — must
179
- provide authUrl and apiUrl. Env vars override credentials.json on a per-field
180
- basis. PoW salt defaults to the built-in deployment constant when unset.`,
181
- jmap_cheatsheet: `\
182
- # JMAP Cheatsheet for AtomicMail
183
-
184
- JMAP (RFC 8620 + RFC 8621) is a JSON-over-HTTP protocol for email. Every
185
- request is a batch of method calls. AtomicMail supports:
186
-
187
- ## Capabilities (pass in "using")
188
- - urn:ietf:params:jmap:core
189
- - urn:ietf:params:jmap:mail
190
- - urn:ietf:params:jmap:submission
191
-
192
- ## Common Method Calls
193
-
194
- ### List mailboxes
195
- \`\`\`json
196
- ["Mailbox/get", {"accountId": "ACCOUNT_ID"}, "m0"]
197
- \`\`\`
198
-
199
- ### List identities (for sending)
200
- \`\`\`json
201
- ["Identity/get", {"accountId": "ACCOUNT_ID"}, "i0"]
202
- \`\`\`
203
-
204
- ### Query last 100 emails in INBOX (newest first)
205
- \`\`\`json
206
- ["Email/query", {
207
- "accountId": "ACCOUNT_ID",
208
- "filter": {"inMailbox": "INBOX_ID"},
209
- "sort": [{"property": "receivedAt", "isAscending": false}],
210
- "limit": 100
211
- }, "q0"]
212
- \`\`\`
213
-
214
- ### Fetch email details (back-reference from query)
215
- \`\`\`json
216
- ["Email/get", {
217
- "accountId": "ACCOUNT_ID",
218
- "#ids": {"resultOf": "q0", "name": "Email/query", "path": "/ids"},
219
- "properties": ["subject", "from", "to", "receivedAt", "bodyValues"],
220
- "fetchAllBodyValues": true
221
- }, "g0"]
222
- \`\`\`
223
-
224
- ### Send an email (create draft + submit, destroy on success)
225
- \`\`\`json
226
- ["Email/set", {
227
- "accountId": "ACCOUNT_ID",
228
- "create": {
229
- "draft": {
230
- "mailboxIds": {"INBOX_ID": true},
231
- "keywords": {"$draft": true},
232
- "from": [{"email": "you@atomicmail.io"}],
233
- "to": [{"email": "recipient@example.com"}],
234
- "subject": "Hello",
235
- "bodyValues": {"body": {"value": "Message body", "charset": "utf-8"}},
236
- "textBody": [{"partId": "body", "type": "text/plain"}]
237
- }
238
- }
239
- }, "c0"],
240
- ["EmailSubmission/set", {
241
- "accountId": "ACCOUNT_ID",
242
- "onSuccessDestroyEmail": ["#sub"],
243
- "create": {
244
- "sub": {
245
- "emailId": "#draft",
246
- "identityId": "IDENTITY_ID",
247
- "envelope": {
248
- "mailFrom": {"email": "you@atomicmail.io"},
249
- "rcptTo": [{"email": "recipient@example.com"}]
250
- }
251
- }
252
- }
253
- }, "c1"]
254
- \`\`\`
255
-
256
- ## Tips
257
-
258
- - Always call \`jmap_session\` first to discover accountId and the INBOX id.
259
- - Back-references (\`#ids\`, \`#draft\`) chain calls in a single batch.
260
- - Add \`urn:ietf:params:jmap:submission\` to \`using\` when sending email.
261
- - Save reusable batches as preset files — see the \`presets\` topic.`,
262
- tools: `\
263
- # AtomicMail MCP — Tool Reference
264
-
265
- ## register
266
- **Input:** { username: string }
267
- **Returns:** Account info + API key (also persisted to credentials.json).
268
- Creates a new account. Performs Proof-of-Work automatically. Refuses to
269
- run if an API key is already configured.
270
-
271
- ## jmap_session
272
- **Input:** (none)
273
- **Returns:** JMAP session JSON with accountId, capabilities, and URLs.
274
- Call this first to discover your accountId and mailbox structure.
275
-
276
- ## jmap_request
277
- **Input:** { using?: string[], methodCalls?: array, opsFile?: string }
278
- **Returns:** JMAP response JSON with methodResponses.
279
- Sends a batch of JMAP method calls. Auth is automatic.
280
-
281
- • methodCalls — inline JMAP batch.
282
- • opsFile — path to a saved JSON preset (relative paths resolve
283
- against the credential directory).
284
- • using — capability URNs. Defaults to core + mail. Add
285
- "urn:ietf:params:jmap:submission" when sending.
286
-
287
- Exactly one of methodCalls or opsFile must be provided.
288
-
289
- ## get_docs
290
- **Input:** { topic?: string }
291
- **Returns:** Documentation text.
292
- Topics: overview, installation, auth, jmap_cheatsheet, tools, presets,
293
- troubleshooting.`,
294
- presets: `\
295
- # AtomicMail MCP — JMAP Presets
296
-
297
- The \`opsFile\` parameter on \`jmap_request\` lets you save reusable JMAP
298
- batches as JSON files on disk, then reference them by path. This mirrors
299
- the \`atomic-mail-jmap --ops-file\` flag from the skill CLI, so the MCP
300
- server and the skill CLI both consume the same preset format from the
301
- same directory.
302
-
303
- ## Where presets live
304
-
305
- Relative paths passed to \`opsFile\` resolve against the credential
306
- directory (default \`~/.atomicmail/\`, override with
307
- \`ATOMIC_MAIL_CREDENTIALS_DIR\`). Absolute paths are taken as-is.
308
-
309
- So \`opsFile: "fetch_last_100.json"\` reads from
310
- \`~/.atomicmail/fetch_last_100.json\`.
311
-
312
- ## Preset file shape
313
-
314
- Two equivalent shapes are accepted:
315
-
316
- 1. A bare \`methodCalls\` array:
317
-
318
- \`\`\`json
319
- [
320
- ["Email/query", {
321
- "accountId": "ACC",
322
- "filter": {"inMailbox": "INBOX"},
323
- "sort": [{"property": "receivedAt", "isAscending": false}],
324
- "limit": 100
325
- }, "q0"]
326
- ]
327
- \`\`\`
328
-
329
- 2. A full envelope:
330
-
331
- \`\`\`json
332
- {
333
- "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
334
- "methodCalls": [
335
- ["Email/query", { "...": "..." }, "q0"]
336
- ]
337
- }
338
- \`\`\`
339
-
340
- If the file already specifies \`using\`, that wins over the inline
341
- \`using\` parameter; otherwise the request defaults (\`core + mail\`) or
342
- the explicit \`using\` argument is used.
343
-
344
- ## Suggested presets to keep
345
-
346
- - \`fetch_last_100.json\` — newest 100 emails in INBOX.
347
- - \`unread_inbox.json\` — query \`{filter: {inMailbox: ..., notKeyword: "$seen"}}\`.
348
- - \`my_identities.json\` — \`Identity/get\` for sending.
349
- - \`mailboxes.json\` — \`Mailbox/get\` to keep a fresh map of folders.
350
-
351
- A typical agent workflow: bootstrap presets once via \`atomic-mail-signup\`
352
- + a few file writes, then drive everything through \`opsFile\` + a small
353
- amount of inline parameter substitution.`,
354
- troubleshooting: `\
355
- # AtomicMail MCP — Troubleshooting
356
-
357
- ## "Missing required configuration: ATOMIC_MAIL_AUTH_URL, ..."
358
-
359
- The server could not resolve authUrl and apiUrl from either env vars or
360
- \`credentials.json\` in the credential directory.
361
- Either set the env vars in your MCP host config, or run
362
- \`atomic-mail-signup\` once to populate \`credentials.json\`.
363
-
364
- ## "No API key configured — call the 'register' tool"
365
-
366
- The server started fine but no API key was found. Either:
367
- - Call the \`register\` tool to create a new account, or
368
- - Set \`ATOMIC_MAIL_API_KEY\` in your MCP env, or
369
- - Place an existing \`credentials.json\` (from another machine, or
370
- from \`atomic-mail-signup\`) into the credential directory.
371
-
372
- ## "auth-service /api/v1/session returned 401"
373
-
374
- Usually means the API key is invalid for the configured auth service,
375
- or (if you set \`ATOMIC_MAIL_SCRYPT_SALT\`) the override does not match the
376
- server build. Verify authUrl and apiUrl match the deployment you signed up at.
377
-
378
- ## "Capability JWT missing inboxId claim"
379
-
380
- The auth service returned a capability JWT without the inboxId claim. This
381
- indicates a server bug — please open an issue with the auth-service
382
- deployment version.
383
-
384
- ## I changed the PoW salt override — what now?
385
-
386
- The PoW salt is normally fixed per server release. If you set
387
- \`ATOMIC_MAIL_SCRYPT_SALT\` or stored a custom \`scryptSalt\` in
388
- credentials.json, it must match the auth-service build you are talking to.
389
-
390
- ## "Could not read opsFile '/path/to/x.json'"
391
-
392
- The opsFile path could not be opened. Relative paths resolve against the
393
- credential directory — for absolute control, pass an absolute path. The
394
- file must contain valid JSON (either a methodCalls array or a full
395
- envelope). See the \`presets\` topic.`,
396
- };
397
- export const TOPIC_LIST = Object.keys(TOPICS);
398
- export function getDocs(topic) {
399
- if (!topic) {
400
- return TOPICS["overview"];
401
- }
402
- const key = topic.toLowerCase().replace(/[\s-]/g, "_");
403
- return (TOPICS[key] ??
404
- `Unknown topic "${topic}". Available topics: ${TOPIC_LIST.join(", ")}`);
405
- }
@@ -1,3 +0,0 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
2
- export declare function registerDocsTool(server: McpServer): void;
3
- //# sourceMappingURL=docs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../../src/mcp/src/tools/docs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AAGtE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2BxD"}
@@ -1,22 +0,0 @@
1
- import { z } from "zod";
2
- import { getDocs, TOPIC_LIST } from "../docs-content.js";
3
- export function registerDocsTool(server) {
4
- server.registerTool("get_docs", {
5
- title: "AtomicMail documentation",
6
- description: `Get documentation about AtomicMail and this MCP server. ` +
7
- `Available topics: ${TOPIC_LIST.join(", ")}. ` +
8
- `Call with no topic for the overview.`,
9
- inputSchema: z.object({
10
- topic: z
11
- .string()
12
- .optional()
13
- .describe(`Documentation topic. One of: ${TOPIC_LIST.join(", ")}. Omit for overview.`),
14
- }),
15
- annotations: {
16
- readOnlyHint: true,
17
- idempotentHint: true,
18
- },
19
- }, ({ topic }) => ({
20
- content: [{ type: "text", text: getDocs(topic) }],
21
- }));
22
- }