🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@atomicmail/mcp

Package Overview
Dependencies
Maintainers
2
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@atomicmail/mcp - npm Package Compare versions

Comparing version
0.3.17-rc2
to
0.3.17-rc3
+52
esm/lib/agent/jmap/agent-jmap-run.d.ts
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.",
];
+1
-1
// 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";
{
"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": [