@atomicmail/mcp 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -187
- package/esm/_dnt.polyfills.d.ts +101 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +127 -0
- package/esm/lib/agent/auth/agent-auth-http.d.ts +26 -0
- package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-auth-http.js +76 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts +14 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-jwt.js +29 -0
- package/esm/lib/agent/auth/agent-pow.d.ts +5 -0
- package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-pow.js +49 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts +4 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-help-content.js +244 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts +49 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-jmap.js +174 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts +23 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-vars.js +65 -0
- package/esm/{mcp/src/credentials.d.ts → lib/agent/session/agent-credentials-store.d.ts} +3 -2
- package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
- package/esm/{mcp/src/credentials.js → lib/agent/session/agent-credentials-store.js} +19 -16
- package/esm/lib/agent/session/agent-resolve-config.d.ts +24 -0
- package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-resolve-config.js +70 -0
- package/esm/lib/agent/session/agent-session.d.ts +62 -0
- package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-session.js +206 -0
- package/esm/lib/core/consts.d.ts.map +1 -0
- package/esm/lib/core/types.d.ts +2 -0
- package/esm/lib/core/types.d.ts.map +1 -0
- package/esm/lib/core/types.js +1 -0
- package/esm/lib/core/utils.d.ts +10 -0
- package/esm/lib/core/utils.d.ts.map +1 -0
- package/esm/lib/core/utils.js +28 -0
- package/esm/lib/mod.d.ts +14 -0
- package/esm/lib/mod.d.ts.map +1 -0
- package/esm/lib/mod.js +13 -0
- package/esm/lib/network/auth-client.d.ts +57 -0
- package/esm/lib/network/auth-client.d.ts.map +1 -0
- package/esm/lib/network/auth-client.js +188 -0
- package/esm/mcp/main.d.ts +3 -0
- package/esm/mcp/main.d.ts.map +1 -0
- package/esm/mcp/main.js +86 -0
- package/esm/mcp/tools/help.d.ts +3 -0
- package/esm/mcp/tools/help.d.ts.map +1 -0
- package/esm/mcp/tools/help.js +22 -0
- package/esm/mcp/{src/tools → tools}/jmap.d.ts +2 -2
- package/esm/mcp/tools/jmap.d.ts.map +1 -0
- package/esm/mcp/tools/jmap.js +115 -0
- package/esm/mcp/{src/tools → tools}/register.d.ts +2 -2
- package/esm/mcp/tools/register.d.ts.map +1 -0
- package/esm/mcp/tools/register.js +43 -0
- package/package.json +5 -5
- package/presets/list_inbox.json +39 -0
- package/presets/reply.json +75 -0
- package/presets/send_mail.json +42 -0
- package/esm/lib/src/consts.d.ts.map +0 -1
- package/esm/mcp/src/auth-session.d.ts +0 -88
- package/esm/mcp/src/auth-session.d.ts.map +0 -1
- package/esm/mcp/src/auth-session.js +0 -378
- package/esm/mcp/src/credentials.d.ts.map +0 -1
- package/esm/mcp/src/docs-content.d.ts +0 -4
- package/esm/mcp/src/docs-content.d.ts.map +0 -1
- package/esm/mcp/src/docs-content.js +0 -405
- package/esm/mcp/src/main.d.ts +0 -3
- package/esm/mcp/src/main.d.ts.map +0 -1
- package/esm/mcp/src/main.js +0 -116
- package/esm/mcp/src/tools/docs.d.ts +0 -3
- package/esm/mcp/src/tools/docs.d.ts.map +0 -1
- package/esm/mcp/src/tools/docs.js +0 -22
- package/esm/mcp/src/tools/jmap.d.ts.map +0 -1
- package/esm/mcp/src/tools/jmap.js +0 -202
- package/esm/mcp/src/tools/register.d.ts.map +0 -1
- package/esm/mcp/src/tools/register.js +0 -79
- /package/esm/lib/{src → core}/consts.d.ts +0 -0
- /package/esm/lib/{src → core}/consts.js +0 -0
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { isAbsolute, resolve as resolvePath } from "node:path";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
const DEFAULT_USING = [
|
|
5
|
-
"urn:ietf:params:jmap:core",
|
|
6
|
-
"urn:ietf:params:jmap:mail",
|
|
7
|
-
];
|
|
8
|
-
function parseEnvelope(raw, defaultUsing, source) {
|
|
9
|
-
let value;
|
|
10
|
-
try {
|
|
11
|
-
value = JSON.parse(raw);
|
|
12
|
-
}
|
|
13
|
-
catch (err) {
|
|
14
|
-
throw new Error(`${source} is not valid JSON: ${err.message}`);
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
return { using: defaultUsing, methodCalls: value };
|
|
18
|
-
}
|
|
19
|
-
if (value !== null &&
|
|
20
|
-
typeof value === "object" &&
|
|
21
|
-
Array.isArray(value.methodCalls)) {
|
|
22
|
-
const obj = value;
|
|
23
|
-
const using = Array.isArray(obj.using)
|
|
24
|
-
? obj.using.filter((u) => typeof u === "string")
|
|
25
|
-
: defaultUsing;
|
|
26
|
-
return { using, methodCalls: obj.methodCalls };
|
|
27
|
-
}
|
|
28
|
-
throw new Error(`${source} must be a methodCalls array, e.g. ` +
|
|
29
|
-
'[["Mailbox/get",{...},"m0"]], or an object with a methodCalls array.');
|
|
30
|
-
}
|
|
31
|
-
export function registerJmapTool(server, session) {
|
|
32
|
-
const apiUrl = session.apiUrl;
|
|
33
|
-
server.registerTool("jmap_request", {
|
|
34
|
-
title: "Send a JMAP request",
|
|
35
|
-
description: "Send a JMAP request to your AtomicMail inbox. Auth (session and " +
|
|
36
|
-
"capability JWT rotation) is handled automatically — just provide " +
|
|
37
|
-
"the JMAP method calls.\n\n" +
|
|
38
|
-
"Provide exactly one request body:\n" +
|
|
39
|
-
" • methodCalls — inline JMAP batch, an array of " +
|
|
40
|
-
"[methodName, args, callId] entries.\n" +
|
|
41
|
-
" • opsFile — path to a saved JSON preset. Relative paths " +
|
|
42
|
-
"resolve against the credential directory (the same directory " +
|
|
43
|
-
"the skill's --ops-file flag uses), so common requests can be " +
|
|
44
|
-
"saved once and reused.\n\n" +
|
|
45
|
-
"Tip: call jmap_session first to discover your accountId.\n\n" +
|
|
46
|
-
"Examples:\n" +
|
|
47
|
-
' methodCalls: [["Mailbox/get", {"accountId": "..."}, "m0"]]\n' +
|
|
48
|
-
' methodCalls: [["Email/query", {"accountId": "...", "filter": {"inMailbox": "..."}}, "q0"]]\n' +
|
|
49
|
-
" opsFile: fetch_last_100.json",
|
|
50
|
-
inputSchema: z.object({
|
|
51
|
-
using: z
|
|
52
|
-
.array(z.string())
|
|
53
|
-
.default(DEFAULT_USING)
|
|
54
|
-
.describe("JMAP capability URNs. Defaults to core + mail. Add " +
|
|
55
|
-
'"urn:ietf:params:jmap:submission" when sending email. ' +
|
|
56
|
-
"Ignored if the file/inline body already sets a 'using' field."),
|
|
57
|
-
methodCalls: z
|
|
58
|
-
.array(z.json())
|
|
59
|
-
.optional()
|
|
60
|
-
.describe("Inline JMAP method calls array. Each entry is " +
|
|
61
|
-
'[methodName, args, callId], e.g. ["Mailbox/get", {"accountId": "abc"}, "m0"]. ' +
|
|
62
|
-
"Mutually exclusive with opsFile."),
|
|
63
|
-
opsFile: z
|
|
64
|
-
.string()
|
|
65
|
-
.optional()
|
|
66
|
-
.describe("Path to a saved JMAP preset file. Relative paths resolve " +
|
|
67
|
-
"against the credential directory. The file may contain " +
|
|
68
|
-
"either a methodCalls array or a full {using, methodCalls} " +
|
|
69
|
-
"envelope. Mutually exclusive with methodCalls."),
|
|
70
|
-
}),
|
|
71
|
-
}, async ({ using, methodCalls, opsFile }) => {
|
|
72
|
-
try {
|
|
73
|
-
if (methodCalls && opsFile) {
|
|
74
|
-
return {
|
|
75
|
-
content: [
|
|
76
|
-
{
|
|
77
|
-
type: "text",
|
|
78
|
-
text: "methodCalls and opsFile are mutually exclusive — provide one.",
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
isError: true,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
let envelope;
|
|
85
|
-
if (opsFile) {
|
|
86
|
-
const filePath = isAbsolute(opsFile)
|
|
87
|
-
? opsFile
|
|
88
|
-
: resolvePath(session.credentialDir, opsFile);
|
|
89
|
-
let raw;
|
|
90
|
-
try {
|
|
91
|
-
raw = await readFile(filePath, "utf-8");
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
return {
|
|
95
|
-
content: [
|
|
96
|
-
{
|
|
97
|
-
type: "text",
|
|
98
|
-
text: `Could not read opsFile '${filePath}': ${err.message}`,
|
|
99
|
-
},
|
|
100
|
-
],
|
|
101
|
-
isError: true,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
envelope = parseEnvelope(raw, using, `opsFile '${filePath}'`);
|
|
105
|
-
}
|
|
106
|
-
else if (methodCalls) {
|
|
107
|
-
envelope = { using, methodCalls };
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
return {
|
|
111
|
-
content: [
|
|
112
|
-
{
|
|
113
|
-
type: "text",
|
|
114
|
-
text: "Provide either methodCalls or opsFile.",
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
isError: true,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
const capabilityJWT = await session.getCapabilityToken();
|
|
121
|
-
const res = await fetch(`${apiUrl}/jmap/`, {
|
|
122
|
-
method: "POST",
|
|
123
|
-
headers: {
|
|
124
|
-
"Content-Type": "application/json",
|
|
125
|
-
Authorization: `Bearer ${capabilityJWT}`,
|
|
126
|
-
},
|
|
127
|
-
body: JSON.stringify(envelope),
|
|
128
|
-
});
|
|
129
|
-
const text = await res.text();
|
|
130
|
-
if (!res.ok) {
|
|
131
|
-
return {
|
|
132
|
-
content: [
|
|
133
|
-
{
|
|
134
|
-
type: "text",
|
|
135
|
-
text: `JMAP request failed (HTTP ${res.status}): ${text}`,
|
|
136
|
-
},
|
|
137
|
-
],
|
|
138
|
-
isError: true,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
return {
|
|
142
|
-
content: [{ type: "text", text }],
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
return {
|
|
147
|
-
content: [
|
|
148
|
-
{
|
|
149
|
-
type: "text",
|
|
150
|
-
text: `JMAP request error: ${error instanceof Error ? error.message : String(error)}`,
|
|
151
|
-
},
|
|
152
|
-
],
|
|
153
|
-
isError: true,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
server.registerTool("jmap_session", {
|
|
158
|
-
title: "Get JMAP session",
|
|
159
|
-
description: "Fetch the JMAP session object via GET /.well-known/jmap. Returns " +
|
|
160
|
-
"your accountId, capabilities, and mailbox discovery URLs. Call " +
|
|
161
|
-
"this first to learn your accountId before issuing jmap_request " +
|
|
162
|
-
"method calls.",
|
|
163
|
-
inputSchema: {},
|
|
164
|
-
annotations: {
|
|
165
|
-
readOnlyHint: true,
|
|
166
|
-
idempotentHint: true,
|
|
167
|
-
},
|
|
168
|
-
}, async () => {
|
|
169
|
-
try {
|
|
170
|
-
const capabilityJWT = await session.getCapabilityToken();
|
|
171
|
-
const res = await fetch(`${apiUrl}/.well-known/jmap`, {
|
|
172
|
-
headers: { Authorization: `Bearer ${capabilityJWT}` },
|
|
173
|
-
});
|
|
174
|
-
const text = await res.text();
|
|
175
|
-
if (!res.ok) {
|
|
176
|
-
return {
|
|
177
|
-
content: [
|
|
178
|
-
{
|
|
179
|
-
type: "text",
|
|
180
|
-
text: `Session fetch failed (HTTP ${res.status}): ${text}`,
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
isError: true,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
return {
|
|
187
|
-
content: [{ type: "text", text }],
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
return {
|
|
192
|
-
content: [
|
|
193
|
-
{
|
|
194
|
-
type: "text",
|
|
195
|
-
text: `Session fetch error: ${error instanceof Error ? error.message : String(error)}`,
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
|
-
isError: true,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/mcp/src/tools/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,GACnB,IAAI,CAuFN"}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export function registerRegisterTool(server, session) {
|
|
3
|
-
server.registerTool("register", {
|
|
4
|
-
title: "Register a new AtomicMail inbox",
|
|
5
|
-
description: "Create a new AtomicMail account. Performs a Proof-of-Work signup, " +
|
|
6
|
-
"fetches the first session and capability JWTs, and writes " +
|
|
7
|
-
"credentials.json + session.jwt + capability.jwt into the " +
|
|
8
|
-
"configured credential directory. After this returns, the agent " +
|
|
9
|
-
"can immediately call jmap_session and jmap_request without any " +
|
|
10
|
-
"further setup. Idempotent guard: if an API key is already " +
|
|
11
|
-
"configured, this tool will refuse to register a second account.",
|
|
12
|
-
inputSchema: z.object({
|
|
13
|
-
username: z
|
|
14
|
-
.string()
|
|
15
|
-
.min(1)
|
|
16
|
-
.describe("Desired username for the new inbox. Becomes the local-part of your email address."),
|
|
17
|
-
}),
|
|
18
|
-
annotations: {
|
|
19
|
-
idempotentHint: false,
|
|
20
|
-
destructiveHint: false,
|
|
21
|
-
},
|
|
22
|
-
}, async ({ username }) => {
|
|
23
|
-
try {
|
|
24
|
-
if (session.hasApiKey) {
|
|
25
|
-
return {
|
|
26
|
-
content: [
|
|
27
|
-
{
|
|
28
|
-
type: "text",
|
|
29
|
-
text: "An API key is already configured for this MCP server. " +
|
|
30
|
-
"Refusing to register a second account. Use jmap_request " +
|
|
31
|
-
"to interact with your existing inbox, or remove " +
|
|
32
|
-
"credentials.json (and unset ATOMIC_MAIL_API_KEY) before " +
|
|
33
|
-
"registering a new one.",
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const { apiKey, inboxId } = await session.signup(username);
|
|
39
|
-
return {
|
|
40
|
-
content: [
|
|
41
|
-
{
|
|
42
|
-
type: "text",
|
|
43
|
-
text: [
|
|
44
|
-
`Account created successfully for "${username}".`,
|
|
45
|
-
"",
|
|
46
|
-
`Inbox ID: ${inboxId}`,
|
|
47
|
-
`API Key: ${apiKey}`,
|
|
48
|
-
"",
|
|
49
|
-
"Credentials persisted to:",
|
|
50
|
-
` ${session.files.credentialsFile}`,
|
|
51
|
-
` ${session.files.sessionFile}`,
|
|
52
|
-
` ${session.files.capabilityFile}`,
|
|
53
|
-
"",
|
|
54
|
-
"IMPORTANT: The API key is stored in credentials.json above. " +
|
|
55
|
-
"Treat that file as a secret (mode 0600). To re-use this " +
|
|
56
|
-
"account from another machine or a fresh MCP host, copy " +
|
|
57
|
-
"credentials.json over, or set ATOMIC_MAIL_API_KEY in the " +
|
|
58
|
-
"new environment.",
|
|
59
|
-
"",
|
|
60
|
-
"You are now logged in. Call jmap_session next to discover " +
|
|
61
|
-
"your accountId, then use jmap_request for all email operations.",
|
|
62
|
-
].join("\n"),
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
return {
|
|
69
|
-
content: [
|
|
70
|
-
{
|
|
71
|
-
type: "text",
|
|
72
|
-
text: `Registration failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
isError: true,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}
|
|
File without changes
|
|
File without changes
|