@atomicmail/mcp
Advanced tools
| import { type JmapBlobUploadLimits } from "./agent-jmap-blob-limits.js"; | ||
| export type { JmapBlobUploadLimits } from "./agent-jmap-blob-limits.js"; | ||
| export declare const DEFAULT_JMAP_USING: readonly ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]; | ||
| export declare const BUNDLED_OPS_PRESET_NAMES: readonly ["list_inbox.json", "reply.json", "send_mail.json", "send_mail_attachment.json", "send_mail_blob_attachment.json"]; | ||
| export declare const JMAP_MAIL_URN: "urn:ietf:params:jmap:mail"; | ||
| export declare const JMAP_BLOB_URN: "urn:ietf:params:jmap:blob"; | ||
| export interface JmapEnvelope { | ||
| using: string[]; | ||
| methodCalls: unknown[]; | ||
| } | ||
| export declare function parseJmapEnvelope(raw: string, defaultUsing: string[], source: string): JmapEnvelope; | ||
| export declare function extractPrimaryMailAccountId(session: Record<string, unknown>): string; | ||
| export interface JmapBlobEndpoints { | ||
| uploadUrl: string; | ||
| downloadUrl: string; | ||
| } | ||
| export declare function extractBlobEndpoints(session: Record<string, unknown>): JmapBlobEndpoints; | ||
| export declare function extractJmapApiUrl(session: Record<string, unknown>): string; | ||
| export declare function extractBlobUploadLimits(session: Record<string, unknown>, accountId: string): JmapBlobUploadLimits | null; | ||
| export declare function fetchJmapWellKnown(apiUrl: string, capabilityJwt: string): Promise<Record<string, unknown>>; | ||
| /** Integration JMAP session port (KeyValue-backed AgentSession). */ | ||
| export interface IntegrationJmapSessionPort { | ||
| readonly apiUrl: string; | ||
| getJmapPostUrl(): Promise<string>; | ||
| getPrimaryMailAccountId(): Promise<string>; | ||
| getCapabilityToken(): Promise<string>; | ||
| readonly currentInboxId?: string; | ||
| readonly currentUploadUrl?: string; | ||
| readonly currentDownloadUrl?: string; | ||
| getBlobUploadLimitsForAccount(accountId: string): Promise<JmapBlobUploadLimits | null>; | ||
| } | ||
| export interface RunJmapRequestInput { | ||
| session: IntegrationJmapSessionPort; | ||
| opsJson: string; | ||
| defaultUsing: string[]; | ||
| sourceLabel: string; | ||
| dryRun?: boolean; | ||
| vars?: Record<string, string>; | ||
| } | ||
| export declare function runJmapRequest(input: RunJmapRequestInput): Promise<{ | ||
| ok: boolean; | ||
| status: number; | ||
| bodyText: string; | ||
| }>; | ||
| export declare function fetchInboxMailboxId(port: IntegrationJmapSessionPort): Promise<string>; | ||
| export declare function postJmap(jmapPostUrl: string, capabilityJwt: string, envelope: JmapEnvelope): Promise<{ | ||
| ok: boolean; | ||
| status: number; | ||
| bodyText: string; | ||
| }>; | ||
| export declare function attachJmapNextHints(bodyText: string): string; | ||
| //# sourceMappingURL=agent-jmap-run.d.ts.map |
| {"version":3,"file":"agent-jmap-run.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-jmap-run.ts"],"names":[],"mappings":"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"} |
| // JMAP execution for integration hosts (n8n bundle) — fetch-only, no node:fs. | ||
| import { JMAP_NEXT_HINTS } from "../../core/jmap-hints.js"; | ||
| import { inboxIdToMailboxEmail } from "../session/inbox-id-to-mailbox-email.js"; | ||
| import { assertBlobUploadEnvelopeWithinLimits, } from "./agent-jmap-blob-limits.js"; | ||
| import { ensureTextCharsetOnEmailSetBlobParts } from "./agent-jmap-email-charset.js"; | ||
| import { substituteVars } from "./agent-vars.js"; | ||
| export const DEFAULT_JMAP_USING = [ | ||
| "urn:ietf:params:jmap:core", | ||
| "urn:ietf:params:jmap:mail", | ||
| ]; | ||
| export const BUNDLED_OPS_PRESET_NAMES = [ | ||
| "list_inbox.json", | ||
| "reply.json", | ||
| "send_mail.json", | ||
| "send_mail_attachment.json", | ||
| "send_mail_blob_attachment.json", | ||
| ]; | ||
| export const JMAP_MAIL_URN = "urn:ietf:params:jmap:mail"; | ||
| export const JMAP_BLOB_URN = "urn:ietf:params:jmap:blob"; | ||
| export function parseJmapEnvelope(raw, defaultUsing, source) { | ||
| let value; | ||
| try { | ||
| value = JSON.parse(raw); | ||
| } | ||
| catch (err) { | ||
| throw new Error(`${source} is not valid JSON: ${err.message}`); | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return { using: [...defaultUsing], methodCalls: value }; | ||
| } | ||
| if (value !== null && | ||
| typeof value === "object" && | ||
| Array.isArray(value.methodCalls)) { | ||
| const obj = value; | ||
| const using = Array.isArray(obj.using) | ||
| ? obj.using.filter((u) => typeof u === "string") | ||
| : [...defaultUsing]; | ||
| return { using, methodCalls: obj.methodCalls }; | ||
| } | ||
| throw new Error(`${source} must be a methodCalls array, e.g. ` + | ||
| '[["Mailbox/get",{...},"m0"]], or an object with a methodCalls array.'); | ||
| } | ||
| export function extractPrimaryMailAccountId(session) { | ||
| const primary = session["primaryAccounts"]; | ||
| if (!primary || typeof primary !== "object") { | ||
| throw new Error("JMAP session missing primaryAccounts."); | ||
| } | ||
| const id = primary[JMAP_MAIL_URN]; | ||
| if (typeof id !== "string" || id.length === 0) { | ||
| throw new Error(`JMAP session missing primaryAccounts['${JMAP_MAIL_URN}'].`); | ||
| } | ||
| return id; | ||
| } | ||
| export function extractBlobEndpoints(session) { | ||
| const uploadUrl = session["uploadUrl"]; | ||
| const downloadUrl = session["downloadUrl"]; | ||
| if (typeof uploadUrl !== "string" || uploadUrl.length === 0) { | ||
| throw new Error("JMAP session missing uploadUrl."); | ||
| } | ||
| if (typeof downloadUrl !== "string" || downloadUrl.length === 0) { | ||
| throw new Error("JMAP session missing downloadUrl."); | ||
| } | ||
| return { uploadUrl, downloadUrl }; | ||
| } | ||
| export function extractJmapApiUrl(session) { | ||
| const u = session["apiUrl"]; | ||
| if (typeof u !== "string" || u.length === 0) { | ||
| throw new Error("JMAP session missing apiUrl."); | ||
| } | ||
| return u; | ||
| } | ||
| function asNonNegativeInt(v) { | ||
| if (typeof v !== "number" || !Number.isFinite(v)) | ||
| return undefined; | ||
| if (!Number.isInteger(v) || v < 0 || v > Number.MAX_SAFE_INTEGER) { | ||
| return undefined; | ||
| } | ||
| return v; | ||
| } | ||
| export function extractBlobUploadLimits(session, accountId) { | ||
| const accounts = session["accounts"]; | ||
| if (!accounts || typeof accounts !== "object") | ||
| return null; | ||
| const acc = accounts[accountId]; | ||
| if (!acc || typeof acc !== "object") | ||
| return null; | ||
| const caps = acc["accountCapabilities"]; | ||
| if (!caps || typeof caps !== "object") | ||
| return null; | ||
| const blob = caps[JMAP_BLOB_URN]; | ||
| if (!blob || typeof blob !== "object") | ||
| return null; | ||
| const b = blob; | ||
| let maxSizeBlobSet = null; | ||
| const rawMax = b["maxSizeBlobSet"]; | ||
| if (rawMax === null) { | ||
| maxSizeBlobSet = null; | ||
| } | ||
| else { | ||
| const n = asNonNegativeInt(rawMax); | ||
| maxSizeBlobSet = n === undefined ? null : n; | ||
| } | ||
| const maxDs = asNonNegativeInt(b["maxDataSources"]); | ||
| const out = { maxSizeBlobSet }; | ||
| if (maxDs !== undefined) { | ||
| out.maxDataSources = maxDs; | ||
| } | ||
| return out; | ||
| } | ||
| export async function fetchJmapWellKnown(apiUrl, capabilityJwt) { | ||
| const base = apiUrl.replace(/\/+$/, ""); | ||
| const res = await fetch(`${base}/.well-known/jmap`, { | ||
| headers: { Authorization: `Bearer ${capabilityJwt}` }, | ||
| }); | ||
| const text = await res.text(); | ||
| if (!res.ok) { | ||
| throw new Error(`JMAP session fetch failed (HTTP ${res.status}): ${text}`); | ||
| } | ||
| try { | ||
| return JSON.parse(text); | ||
| } | ||
| catch { | ||
| throw new Error("JMAP session response is not valid JSON."); | ||
| } | ||
| } | ||
| export async function runJmapRequest(input) { | ||
| const mergedVars = input.vars ?? {}; | ||
| const { text: raw } = await substituteVars({ | ||
| raw: input.opsJson, | ||
| vars: mergedVars, | ||
| autoResolvers: { | ||
| ACCOUNT_ID: () => input.session.getPrimaryMailAccountId(), | ||
| INBOX: async () => { | ||
| const rawInbox = input.session.currentInboxId; | ||
| if (!rawInbox) { | ||
| throw new Error("No inbox in session; run register first."); | ||
| } | ||
| return inboxIdToMailboxEmail(rawInbox); | ||
| }, | ||
| INBOX_MAILBOX_ID: () => fetchInboxMailboxId(input.session), | ||
| UPLOAD_URL: async () => { | ||
| if (input.session.currentUploadUrl) { | ||
| return input.session.currentUploadUrl; | ||
| } | ||
| throw new Error("JMAP session missing uploadUrl."); | ||
| }, | ||
| DOWNLOAD_URL: async () => { | ||
| if (input.session.currentDownloadUrl) { | ||
| return input.session.currentDownloadUrl; | ||
| } | ||
| throw new Error("JMAP session missing downloadUrl."); | ||
| }, | ||
| }, | ||
| }); | ||
| const envelope = parseJmapEnvelope(raw, input.defaultUsing, input.sourceLabel); | ||
| ensureTextCharsetOnEmailSetBlobParts(envelope); | ||
| await enforceJmapBlobUploadLimitsIfApplicable(input.session, envelope); | ||
| const jmapPostUrl = await input.session.getJmapPostUrl(); | ||
| if (input.dryRun) { | ||
| return { | ||
| ok: true, | ||
| status: 200, | ||
| bodyText: JSON.stringify({ dryRun: true, url: jmapPostUrl, envelope }, null, 2), | ||
| }; | ||
| } | ||
| const capabilityJwt = await input.session.getCapabilityToken(); | ||
| const { ok, status, bodyText } = await postJmap(jmapPostUrl, capabilityJwt, envelope); | ||
| if (!ok) { | ||
| return { ok, status, bodyText }; | ||
| } | ||
| return { ok, status, bodyText: attachJmapNextHints(bodyText) }; | ||
| } | ||
| export async function fetchInboxMailboxId(port) { | ||
| const accountId = await port.getPrimaryMailAccountId(); | ||
| const capabilityJwt = await port.getCapabilityToken(); | ||
| const envelope = { | ||
| using: ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], | ||
| methodCalls: [ | ||
| ["Mailbox/query", { accountId, filter: { role: "inbox" } }, "mq0"], | ||
| ], | ||
| }; | ||
| const jmapPostUrl = await port.getJmapPostUrl(); | ||
| const { ok, status, bodyText } = await postJmap(jmapPostUrl, capabilityJwt, envelope); | ||
| if (!ok) { | ||
| throw new Error(`Mailbox/query failed (HTTP ${status}): ${bodyText}`); | ||
| } | ||
| let parsed; | ||
| try { | ||
| parsed = JSON.parse(bodyText); | ||
| } | ||
| catch { | ||
| throw new Error("Mailbox/query response is not valid JSON."); | ||
| } | ||
| const responses = parsed | ||
| .methodResponses; | ||
| const first = responses?.[0]; | ||
| if (!Array.isArray(first) || first[0] === "error") { | ||
| throw new Error(`Mailbox/query failed: ${bodyText}`); | ||
| } | ||
| if (first[0] !== "Mailbox/query") { | ||
| throw new Error(`Mailbox/query failed: ${bodyText}`); | ||
| } | ||
| const payload = first[1]; | ||
| const id = payload.ids?.[0]; | ||
| if (typeof id !== "string" || id.length === 0) { | ||
| throw new Error("Mailbox/query returned no inbox mailbox id."); | ||
| } | ||
| return id; | ||
| } | ||
| function collectBlobUploadAccountIds(envelope) { | ||
| const ids = new Set(); | ||
| for (const call of envelope.methodCalls) { | ||
| if (!Array.isArray(call) || call[0] !== "Blob/upload") | ||
| continue; | ||
| const arg = call[1]; | ||
| if (!arg || typeof arg !== "object") | ||
| continue; | ||
| const aid = arg["accountId"]; | ||
| if (typeof aid === "string" && aid.length > 0) | ||
| ids.add(aid); | ||
| } | ||
| return [...ids]; | ||
| } | ||
| async function enforceJmapBlobUploadLimitsIfApplicable(session, envelope) { | ||
| if (!envelope.using.includes(JMAP_BLOB_URN)) | ||
| return; | ||
| const hasUpload = envelope.methodCalls.some((c) => Array.isArray(c) && c[0] === "Blob/upload"); | ||
| if (!hasUpload) | ||
| return; | ||
| const accountIds = collectBlobUploadAccountIds(envelope); | ||
| const limitsByAccount = new Map(); | ||
| for (const id of accountIds) { | ||
| limitsByAccount.set(id, await session.getBlobUploadLimitsForAccount(id)); | ||
| } | ||
| assertBlobUploadEnvelopeWithinLimits(envelope, limitsByAccount); | ||
| } | ||
| export async function postJmap(jmapPostUrl, capabilityJwt, envelope) { | ||
| const res = await fetch(jmapPostUrl, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| Authorization: `Bearer ${capabilityJwt}`, | ||
| }, | ||
| body: JSON.stringify(envelope), | ||
| }); | ||
| const bodyText = await res.text(); | ||
| return { ok: res.ok, status: res.status, bodyText }; | ||
| } | ||
| export function attachJmapNextHints(bodyText) { | ||
| try { | ||
| const obj = JSON.parse(bodyText); | ||
| if (obj && typeof obj === "object" && !Array.isArray(obj)) { | ||
| return JSON.stringify({ ...obj, _next: [...JMAP_NEXT_HINTS] }, null, 2); | ||
| } | ||
| } | ||
| catch { | ||
| // not JSON | ||
| } | ||
| return bodyText; | ||
| } |
| /** Static JMAP success hints (no shared/ filesystem reads). */ | ||
| export declare const JMAP_NEXT_HINTS: readonly ["Use jmap_request with Mailbox/get or Email/query to work with mail data.", "Use presets with $VAR placeholders — $ACCOUNT_ID, $INBOX, and $INBOX_MAILBOX_ID come from the session; pass others via vars / --vars.", "Call help for the JMAP cheatsheet and troubleshooting."]; | ||
| //# sourceMappingURL=jmap-hints.d.ts.map |
| {"version":3,"file":"jmap-hints.d.ts","sourceRoot":"","sources":["../../../src/lib/core/jmap-hints.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,eAAO,MAAM,eAAe,0RAIlB,CAAC"} |
| /** Static JMAP success hints (no shared/ filesystem reads). */ | ||
| export const JMAP_NEXT_HINTS = [ | ||
| "Use jmap_request with Mailbox/get or Email/query to work with mail data.", | ||
| "Use presets with $VAR placeholders — $ACCOUNT_ID, $INBOX, and $INBOX_MAILBOX_ID come from the session; pass others via vars / --vars.", | ||
| "Call help for the JMAP cheatsheet and troubleshooting.", | ||
| ]; |
| // Stateful PoW + capability JWT + optional cached JMAP session (accountId). | ||
| import { FilesystemCredentialStore, writeCredentials, writeJwtFile, } from "./agent-credentials-store.js"; | ||
| import { CAPABILITY_SAFETY_MARGIN_MS, decodeJwtPayload, isJwtExpired, SESSION_SAFETY_MARGIN_MS, } from "../auth/agent-jwt.js"; | ||
| import { extractBlobEndpoints, extractBlobUploadLimits, extractJmapApiUrl, extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap.js"; | ||
| import { extractBlobEndpoints, extractBlobUploadLimits, extractJmapApiUrl, extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap-run.js"; | ||
| import { fetchCapability, performPoWAndSession, } from "../auth/agent-auth-http.js"; | ||
@@ -6,0 +6,0 @@ function normalizeUsername(u) { |
@@ -1,2 +0,2 @@ | ||
| /** Subset of `process.env` read for `$INBOX` normalization (tests may pass a stub). */ | ||
| /** Optional inbox domain override for `$INBOX` normalization. */ | ||
| export type InboxEmailEnv = { | ||
@@ -3,0 +3,0 @@ ATOMIC_MAIL_INBOX_DOMAIN?: string; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"inbox-id-to-mailbox-email.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/inbox-id-to-mailbox-email.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAYlE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,aAAa,GAClB,MAAM,CAaR"} | ||
| {"version":3,"file":"inbox-id-to-mailbox-email.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/inbox-id-to-mailbox-email.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAYlE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,aAAa,GAClB,MAAM,CAWR"} |
@@ -1,2 +0,1 @@ | ||
| import process from "node:process"; | ||
| /** | ||
@@ -7,4 +6,4 @@ * Normalizes stored `inboxId` into an RFC5322 mailbox address for `$INBOX` | ||
| * Credentials may store only the local-part (`alice`); production mailboxes | ||
| * live at `alice@atomicmail.ai`. Custom stacks can set | ||
| * `ATOMIC_MAIL_INBOX_DOMAIN` (hostname only, optional leading `@` stripped). | ||
| * live at `alice@atomicmail.ai`. Pass `ATOMIC_MAIL_INBOX_DOMAIN` via `env` | ||
| * when not using the default domain. | ||
| */ | ||
@@ -18,5 +17,3 @@ const DEFAULT_INBOX_DOMAIN = "atomicmail.ai"; | ||
| return trimmed; | ||
| const raw = (env !== undefined | ||
| ? env.ATOMIC_MAIL_INBOX_DOMAIN | ||
| : process.env.ATOMIC_MAIL_INBOX_DOMAIN)?.trim(); | ||
| const raw = env?.ATOMIC_MAIL_INBOX_DOMAIN?.trim(); | ||
| const domain = raw && raw.length > 0 | ||
@@ -23,0 +20,0 @@ ? raw.replace(/^@+/, "") |
| /** Published @atomicmail/mcp version; set from release tag in CI. */ | ||
| export declare const ATOMICMAIL_MCP_VERSION = "0.3.17-rc2"; | ||
| export declare const ATOMICMAIL_MCP_VERSION = "0.3.17-rc3"; | ||
| //# sourceMappingURL=version.d.ts.map |
| /** Published @atomicmail/mcp version; set from release tag in CI. */ | ||
| export const ATOMICMAIL_MCP_VERSION = "0.3.17-rc2"; | ||
| export const ATOMICMAIL_MCP_VERSION = "0.3.17-rc3"; |
+1
-1
| { | ||
| "name": "@atomicmail/mcp", | ||
| "version": "0.3.17-rc2", | ||
| "version": "0.3.17-rc3", | ||
| "description": "Atomic Mail MCP server — local stdio proxy with PoW auth and JMAP, for AI agents.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
302333
5.27%171
3.64%5421
6.21%33
-2.94%11
22.22%