hypermail-mcp 0.3.0 → 0.4.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/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/store/account-store.ts","../src/providers/outlook/index.ts","../src/providers/outlook/client.ts","../src/providers/outlook/auth.ts","../src/providers/imap/index.ts","../src/providers/registry.ts","../src/tools/index.ts","../src/html-to-markdown.ts","../src/version.ts","../src/cli.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\n\nimport { AccountStore } from \"./store/account-store.js\";\nimport { buildRegistry } from \"./providers/registry.js\";\nimport { registerTools } from \"./tools/index.js\";\nimport { VERSION } from \"./version.js\";\n\nexport interface ServerOptions {\n http?: boolean;\n port?: number;\n host?: string;\n dataDir?: string;\n readOnly?: boolean;\n /** When true, hide send_email and only expose draft_email. */\n draftOnly?: boolean;\n}\n\nexport async function startServer(opts: ServerOptions = {}): Promise<void> {\n const store = await AccountStore.open({ dataDir: opts.dataDir });\n const registry = buildRegistry({ store });\n\n const server = new McpServer(\n { name: \"hypermail-mcp\", version: VERSION },\n { capabilities: { tools: {}, logging: {} } },\n );\n\n registerTools(server, { store, registry, readOnly: !!opts.readOnly, draftOnly: !!opts.draftOnly });\n\n if (opts.http) {\n await startHttp(server, opts.host ?? \"127.0.0.1\", opts.port ?? 3000);\n } else {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\nasync function startHttp(server: McpServer, host: string, port: number): Promise<void> {\n // One transport per session, keyed by Mcp-Session-Id header.\n const sessions = new Map<string, StreamableHTTPServerTransport>();\n\n const http = createHttpServer(async (req: IncomingMessage, res: ServerResponse) => {\n try {\n if (!req.url || !req.url.startsWith(\"/mcp\")) {\n res.statusCode = 404;\n res.end(\"not found\");\n return;\n }\n const sessionId = (req.headers[\"mcp-session-id\"] as string | undefined) ?? undefined;\n let transport = sessionId ? sessions.get(sessionId) : undefined;\n\n if (!transport) {\n transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid: string) => {\n sessions.set(sid, transport!);\n },\n });\n transport.onclose = () => {\n if (transport!.sessionId) sessions.delete(transport!.sessionId);\n };\n await server.connect(transport);\n }\n\n // Buffer body for POST / DELETE\n let body: unknown = undefined;\n if (req.method === \"POST\" || req.method === \"DELETE\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n }\n await transport.handleRequest(req, res, body);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] http error:\", err);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(\"internal error\");\n }\n }\n });\n\n await new Promise<void>((resolve) => http.listen(port, host, resolve));\n // eslint-disable-next-line no-console\n console.error(`[hypermail-mcp] listening on http://${host}:${port}/mcp`);\n}\n","import {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n createHash,\n} from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * One stored account. `tokens` is provider-specific (e.g. serialized MSAL cache\n * for Outlook, host/port/password blob for IMAP) — the store is opaque to it.\n */\nexport interface AccountRecord {\n email: string;\n provider: \"outlook\" | \"imap\" | \"gmail\";\n displayName?: string;\n tokens: Record<string, unknown>;\n addedAt: string;\n /** HTML snippet — may contain formatting, images, links. Injected at end of outgoing emails. */\n signature?: string;\n /** Font/style preferences applied to outgoing HTML emails. */\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n}\n\ninterface StoreFile {\n version: 1;\n accounts: AccountRecord[];\n}\n\nexport interface OpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). Otherwise resolved\n * from `HYPERMAIL_MCP_KEY` env, then OS keychain, then auto-generated. */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"accounts.json.enc\";\nconst ALGO = \"aes-256-gcm\";\nconst KEY_LEN = 32;\n\nexport class AccountStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: StoreFile,\n ) {}\n\n static async open(opts: OpenOptions = {}): Promise<AccountStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: StoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, accounts: [] };\n } else {\n throw err;\n }\n }\n return new AccountStore(filePath, key, data);\n }\n\n listAccounts(): AccountRecord[] {\n // Return shallow clones without tokens leaking out unintentionally is the\n // caller's job; here we expose the full record for provider use.\n return this.data.accounts.map((a) => ({ ...a }));\n }\n\n getAccount(email: string): AccountRecord | undefined {\n const norm = email.trim().toLowerCase();\n const rec = this.data.accounts.find((a) => a.email.toLowerCase() === norm);\n return rec ? { ...rec } : undefined;\n }\n\n async upsertAccount(rec: AccountRecord): Promise<AccountRecord> {\n const norm = rec.email.trim().toLowerCase();\n const next: AccountRecord = { ...rec, email: norm };\n const idx = this.data.accounts.findIndex((a) => a.email.toLowerCase() === norm);\n if (idx >= 0) this.data.accounts[idx] = next;\n else this.data.accounts.push(next);\n await this.flush();\n return { ...next };\n }\n\n async removeAccount(email: string): Promise<boolean> {\n const norm = email.trim().toLowerCase();\n const before = this.data.accounts.length;\n this.data.accounts = this.data.accounts.filter((a) => a.email.toLowerCase() !== norm);\n if (this.data.accounts.length === before) return false;\n await this.flush();\n return true;\n }\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n const tmp = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, buf, { mode: 0o600 });\n await fs.rename(tmp, this.filePath);\n }\n}\n\n// ---------- encryption helpers ----------\n\nfunction encrypt(data: StoreFile, key: Buffer): Buffer {\n const iv = randomBytes(12);\n const cipher = createCipheriv(ALGO, key, iv);\n const plaintext = Buffer.from(JSON.stringify(data), \"utf8\");\n const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const tag = cipher.getAuthTag();\n // layout: [1-byte version=1][12 iv][16 tag][ct...]\n return Buffer.concat([Buffer.from([1]), iv, tag, ct]);\n}\n\nfunction decrypt(buf: Buffer, key: Buffer): StoreFile {\n if (buf.length < 1 + 12 + 16 + 1) throw new Error(\"accounts file truncated\");\n const v = buf[0];\n if (v !== 1) throw new Error(`unsupported accounts file version: ${v}`);\n const iv = buf.subarray(1, 13);\n const tag = buf.subarray(13, 29);\n const ct = buf.subarray(29);\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n const parsed = JSON.parse(pt.toString(\"utf8\")) as StoreFile;\n if (parsed.version !== 1 || !Array.isArray(parsed.accounts)) {\n throw new Error(\"accounts file is malformed\");\n }\n return parsed;\n}\n\n// ---------- key + path resolution ----------\n\nfunction resolveDataDir(explicit?: string): string {\n if (explicit && explicit.length > 0) return path.resolve(explicit);\n const env = process.env.HYPERMAIL_MCP_DATA_DIR;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(homedir(), \".hypermail-mcp\");\n}\n\nfunction parseEnvKey(raw: string): Buffer | undefined {\n const s = raw.trim();\n // hex (64 chars)\n if (/^[0-9a-fA-F]{64}$/.test(s)) return Buffer.from(s, \"hex\");\n // base64 — accept any length, then check\n try {\n const buf = Buffer.from(s, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n } catch {\n /* ignore */\n }\n // last-resort: derive 32 bytes via SHA-256 over the raw string. This lets\n // users pass any passphrase; not ideal but predictable.\n return createHash(\"sha256\").update(s, \"utf8\").digest();\n}\n\nasync function resolveKey(dataDir: string): Promise<Buffer> {\n const env = process.env.HYPERMAIL_MCP_KEY;\n if (env && env.length > 0) {\n const k = parseEnvKey(env);\n if (k) return k;\n }\n\n // Try OS keychain via keytar (optional dep).\n const fromKeytar = await tryKeytarGet();\n if (fromKeytar) return fromKeytar;\n\n // Local-dev fallback: persist a generated key to a 0600 file next to the\n // accounts blob so subsequent runs can decrypt. Hosted deployments should\n // always set HYPERMAIL_MCP_KEY explicitly.\n const keyFile = path.join(dataDir, \"master.key\");\n try {\n const existing = await fs.readFile(keyFile);\n if (existing.length === KEY_LEN) return existing;\n } catch {\n /* fall through to generate */\n }\n const gen = randomBytes(KEY_LEN);\n await fs.writeFile(keyFile, gen, { mode: 0o600 });\n await tryKeytarSet(gen);\n return gen;\n}\n\nasync function tryKeytarGet(): Promise<Buffer | undefined> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n const val = await mod.getPassword(\"hypermail-mcp\", \"master\");\n if (val) {\n const buf = Buffer.from(val, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n }\n } catch {\n /* keytar not installed or unsupported platform */\n }\n return undefined;\n}\n\nasync function tryKeytarSet(key: Buffer): Promise<void> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n await mod.setPassword(\"hypermail-mcp\", \"master\", key.toString(\"base64\"));\n } catch {\n /* ignore */\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport { ResponseType, type Client } from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n EmailFull,\n EmailProvider,\n EmailSummary,\n ListEmailsOptions,\n SearchEmailsOptions,\n SendInput,\n EmailAddress,\n} from \"../types.js\";\nimport { OutlookClientFactory } from \"./client.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type DeviceCodeBegin,\n type SerializedTokens,\n} from \"./auth.js\";\n\n// ---------- inline image conversion ----------\n\ninterface InlineAttachment {\n \"@odata.type\": string;\n name: string;\n contentType: string;\n contentId: string;\n contentBytes: string;\n isInline: boolean;\n}\n\n/**\n * Scans HTML for data:image/...;base64,... URIs, extracts the raw base64\n * data, assigns unique contentIds, and returns the transformed body\n * (with src=\"cid:...\" references) plus an array of inline fileAttachment\n * objects ready for the Graph API.\n *\n * Pass-through when there are no matches — returns the original body with\n * an empty attachments array.\n */\nexport function convertInlineImages(body: string): {\n body: string;\n attachments: InlineAttachment[];\n} {\n const attachments: InlineAttachment[] = [];\n // Match src=\"data:image/<subtype>;base64,<payload>\"\n // Supports png, jpg, jpeg, gif, svg+xml, webp, bmp, etc.\n const re = /src=\"data:image\\/([\\w+]+);base64,([^\"]+)\"/gi;\n\n const transformed = body.replace(re, (_fullMatch, mimeSubtype, b64) => {\n const contentId = `sig-img-${randomUUID()}`;\n const ext = mimeSubtype.toLowerCase().replace(/\\+/g, \"-\") === \"svg-xml\"\n ? \"svg\"\n : mimeSubtype.toLowerCase().replace(/\\+/g, \"-\");\n attachments.push({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name: `signature-image.${ext}`,\n contentType: `image/${mimeSubtype}`,\n contentId,\n contentBytes: b64,\n isInline: true,\n });\n return `src=\"cid:${contentId}\"`;\n });\n\n return { body: transformed, attachments };\n}\n\ninterface PendingFlow {\n begin: DeviceCodeBegin;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\nexport interface OutlookProviderOptions {\n store: AccountStore;\n}\n\nexport class OutlookProvider implements EmailProvider {\n readonly id = \"outlook\" as const;\n private readonly clients: OutlookClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n\n constructor(private readonly opts: OutlookProviderOptions) {\n this.clients = new OutlookClientFactory(opts.store);\n }\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode();\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n // Fire-and-forget: when the user finishes, persist and update flow.\n begin.result\n .then(async ({ tokens, account }) => {\n const email = (account.username || input.email || \"\").toLowerCase();\n if (!email) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Microsoft account\";\n return;\n }\n const rec: AccountRecord = {\n email,\n provider: \"outlook\",\n displayName: account.name ?? undefined,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(handle: string): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n // expire after 20 minutes regardless\n if (Date.now() - flow.startedAt > 20 * 60_000 && flow.settled === \"pending\") {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ---------- email ops ----------\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<EmailSummary[]> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const folder = opts.folder ?? \"inbox\";\n const filterParts: string[] = [];\n if (opts.unreadOnly) filterParts.push(\"isRead eq false\");\n\n let req = client\n .api(`/me/mailFolders/${encodeURIComponent(folder)}/messages`)\n .top(limit)\n .select([\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"))\n .orderby(\"receivedDateTime DESC\");\n\n if (filterParts.length > 0) req = req.filter(filterParts.join(\" and \"));\n\n const res = (await req.get()) as { value: GraphMessage[] };\n return res.value.map((m) => mapSummary(m, folder));\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n // $search requires the ConsistencyLevel: eventual header\n const res = (await client\n .api(\"/me/messages\")\n .header(\"ConsistencyLevel\", \"eventual\")\n .top(limit)\n .search(`\"${query.replace(/\"/g, '\\\\\"')}\"`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"),\n )\n .get()) as { value: GraphMessage[] };\n return res.value.map((m) => mapSummary(m));\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n const client = this.clients.get(account);\n const m = (await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"ccRecipients\",\n \"bccRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n \"body\",\n ].join(\",\"),\n )\n .get()) as GraphMessage;\n\n let attachments: EmailFull[\"attachments\"] = undefined;\n if (m.hasAttachments) {\n try {\n const attRes = (await client\n .api(`/me/messages/${encodeURIComponent(id)}/attachments`)\n .select(\"id,name,contentType,size\")\n .get()) as { value: GraphAttachment[] };\n attachments = attRes.value.map((a) => ({\n id: a.id,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n } catch {\n /* ignore attachment listing failure */\n }\n }\n\n const summary = mapSummary(m);\n const body = m.body;\n return {\n ...summary,\n cc: (m.ccRecipients ?? []).map(mapRecipient),\n bcc: (m.bccRecipients ?? []).map(mapRecipient),\n bodyText: body?.contentType === \"text\" ? body.content : undefined,\n bodyHtml: body?.contentType === \"html\" ? body.content : undefined,\n attachments,\n };\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n const client = this.clients.get(account);\n // First, get the attachment metadata to know the filename\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`)\n .select(\"name,contentType\")\n .get()) as { name: string; contentType?: string };\n\n // Download the raw content as ArrayBuffer\n const data = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}/$value`)\n .responseType(ResponseType.ARRAYBUFFER)\n .get()) as ArrayBuffer;\n\n // Write to temp file with original name\n const outPath = pathJoin(tmpdir(), att.name);\n writeFileSync(outPath, Buffer.from(data));\n\n return {\n name: att.name,\n contentType: att.contentType,\n path: outPath,\n };\n }\n\n // Shared helper — creates a draft from a reference message (forward or\n // reply), prepends our composed body before the existing content, and\n // attaches inline images. Returns the draft message ID.\n private async buildDraftFromReference(\n client: Client,\n createEndpoint: string,\n createPayload: Record<string, unknown>,\n converted: { body: string; attachments: InlineAttachment[] },\n ): Promise<string> {\n const draft: { id: string } = await client\n .api(createEndpoint)\n .post(createPayload);\n\n const draftMsg: { body?: { content?: string; contentType?: string } } =\n await client.api(`/me/messages/${draft.id}`).select(\"body\").get();\n\n const draftBody = draftMsg.body?.content ?? \"\";\n const draftContentType = draftMsg.body?.contentType ?? \"HTML\";\n const spacer = '<div style=\"line-height:12px\"><br></div>';\n const prepend = converted.body + spacer;\n const finalBody = draftBody.includes(\"<body\")\n ? draftBody.replace(/(<body[^>]*>)/i, `$1${prepend}`)\n : prepend + draftBody;\n\n await client.api(`/me/messages/${draft.id}`).patch({\n body: { contentType: draftContentType, content: finalBody },\n });\n\n for (const att of converted.attachments) {\n await client.api(`/me/messages/${draft.id}/attachments`).post(att);\n }\n\n return draft.id;\n }\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n\n if (msg.inReplyTo && msg.forwardMessageId) {\n throw new Error(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n\n // Convert data:image URIs to cid: references + inline attachments.\n const converted = convertInlineImages(msg.body);\n\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n {\n message: {\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n comment: \"\",\n },\n converted,\n );\n await client.api(`/me/messages/${draftId}/send`).post({});\n return { id: draftId };\n }\n\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client,\n createEndpoint,\n {},\n converted,\n );\n await client.api(`/me/messages/${draftId}/send`).post({});\n return { id: draftId };\n }\n\n // New email — use sendMail with inline attachments\n const payload: Record<string, unknown> = {\n message: {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n saveToSentItems: true,\n };\n if (converted.attachments.length > 0) {\n (payload.message as Record<string, unknown>).attachments =\n converted.attachments;\n }\n await client.api(\"/me/sendMail\").post(payload);\n // Graph's sendMail returns 202 with no body; we don't have an id back.\n return { id: \"\" };\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n\n if (msg.inReplyTo && msg.forwardMessageId) {\n throw new Error(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n\n const converted = convertInlineImages(msg.body);\n\n // Forward/reply drafts: same flow as sendEmail, but skip the final send.\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n {\n message: {\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n comment: \"\",\n },\n converted,\n );\n return { id: draftId };\n }\n\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client,\n createEndpoint,\n {},\n converted,\n );\n return { id: draftId };\n }\n\n // New email — create a draft message directly (POST /me/messages).\n // Graph creates drafts by default when posting to /me/messages.\n const draftPayload: Record<string, unknown> = {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n };\n if (converted.attachments.length > 0) {\n draftPayload.attachments = converted.attachments;\n }\n const draft: { id: string } = await client\n .api(\"/me/messages\")\n .post(draftPayload);\n return { id: draft.id };\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}/move`)\n .post({ destinationId });\n }\n}\n\n// ---------- mapping helpers ----------\n\ninterface GraphRecipient {\n emailAddress?: { name?: string; address?: string };\n}\ninterface GraphMessage {\n id: string;\n subject?: string;\n from?: GraphRecipient;\n toRecipients?: GraphRecipient[];\n ccRecipients?: GraphRecipient[];\n bccRecipients?: GraphRecipient[];\n receivedDateTime?: string;\n bodyPreview?: string;\n isRead?: boolean;\n hasAttachments?: boolean;\n body?: { contentType?: \"text\" | \"html\"; content?: string };\n}\ninterface GraphAttachment {\n id: string;\n name: string;\n contentType?: string;\n size?: number;\n}\n\nfunction mapRecipient(r: GraphRecipient): EmailAddress {\n return {\n name: r.emailAddress?.name,\n address: r.emailAddress?.address ?? \"\",\n };\n}\n\nfunction mapSummary(m: GraphMessage, folder?: string): EmailSummary {\n return {\n id: m.id,\n subject: m.subject ?? \"\",\n from: m.from ? mapRecipient(m.from) : undefined,\n to: (m.toRecipients ?? []).map(mapRecipient),\n receivedAt: m.receivedDateTime,\n preview: m.bodyPreview,\n isRead: m.isRead,\n hasAttachments: m.hasAttachments,\n folder,\n };\n}\n\nfunction toRecipient(a: EmailAddress): GraphRecipient {\n return { emailAddress: { name: a.name, address: a.address } };\n}\n\nfunction clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n","import \"isomorphic-fetch\";\nimport {\n Client,\n type AuthenticationProvider,\n} from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport { acquireAccessToken, type SerializedTokens } from \"./auth.js\";\n\n/**\n * Builds a Graph `Client` bound to a stored account. The client uses an\n * `AuthenticationProvider` that calls msal silently on every request, and\n * writes the (possibly-refreshed) cache back into the AccountStore.\n *\n * Clients are cached per email since the underlying SDK reuses connections.\n */\nexport class OutlookClientFactory {\n private readonly cache = new Map<string, Client>();\n\n constructor(private readonly store: AccountStore) {}\n\n get(account: AccountRecord): Client {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const store = this.store;\n const provider: AuthenticationProvider = {\n getAccessToken: async () => {\n const fresh = store.getAccount(account.email) ?? account;\n const tokens = fresh.tokens as unknown as SerializedTokens;\n const { accessToken, tokens: nextTokens } = await acquireAccessToken(tokens);\n // Persist refreshed cache opportunistically; failures here shouldn't\n // break the in-flight Graph call.\n if (nextTokens.msalCache !== tokens.msalCache) {\n store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n }\n return accessToken;\n },\n };\n\n const client = Client.initWithMiddleware({ authProvider: provider });\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import {\n PublicClientApplication,\n type Configuration,\n type AuthenticationResult,\n type AccountInfo,\n} from \"@azure/msal-node\";\n\n/**\n * Public client app id. Default is the well-known `ms-365` client id used by\n * the softeria/ms-365-mcp-server project — it's a public client registered\n * for personal MSA + multi-tenant work/school. Users can override via\n * MS_CLIENT_ID for their own Entra app registrations.\n */\nconst DEFAULT_CLIENT_ID = \"084a3e9f-a9f4-43f7-89f9-d229cf97853e\";\n// ^ Pre-registered public client app (same one used by softeria/ms-365-mcp-server).\n// Supports personal MSA + multi-tenant work/school via device-code flow.\n// Operators should set MS_CLIENT_ID to a client they control for production.\n\nconst DEFAULT_SCOPES = [\n \"offline_access\",\n \"User.Read\",\n \"Mail.ReadWrite\",\n \"Mail.Send\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the auth result once the user completes the flow. */\n result: Promise<{ tokens: SerializedTokens; account: AccountInfo }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedTokens {\n /** MSAL cache JSON, encrypted at rest by the account store. */\n msalCache: string;\n /** Home account id used to look up the account in the rehydrated cache. */\n homeAccountId: string;\n /** Tenant id captured at sign-in. */\n tenantId: string;\n /** Username captured at sign-in (typically the primary email). */\n username: string;\n scopes: string[];\n}\n\nfunction makeConfig(prevCacheJson?: string): Configuration {\n const clientId = process.env.MS_CLIENT_ID || DEFAULT_CLIENT_ID;\n const tenant = process.env.MS_TENANT_ID || \"common\";\n return {\n auth: {\n clientId,\n authority: `https://login.microsoftonline.com/${tenant}`,\n },\n cache: prevCacheJson\n ? {\n // msal-node supports an in-memory cache plugin; we hydrate manually\n // below via deserialize after construction.\n }\n : undefined,\n };\n}\n\nexport function buildPca(prevCacheJson?: string): PublicClientApplication {\n const pca = new PublicClientApplication(makeConfig(prevCacheJson));\n if (prevCacheJson) {\n pca.getTokenCache().deserialize(prevCacheJson);\n }\n return pca;\n}\n\n/**\n * Start a device-code flow. The returned `result` promise resolves once the\n * user has entered the code and consented; callers should poll it (or await it)\n * via `complete_add_account`.\n */\nexport function beginDeviceCode(scopes: string[] = DEFAULT_SCOPES): DeviceCodeBegin {\n const pca = buildPca();\n let resolve!: (v: { tokens: SerializedTokens; account: AccountInfo }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedTokens; account: AccountInfo }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // We capture the deviceCodeCallback synchronously to surface the user-facing\n // info back out via this object before awaiting the long-running poll.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = new Promise<void>((r) => {\n pca\n .acquireTokenByDeviceCode({\n scopes,\n deviceCodeCallback: (info) => {\n if (!info.userCode || !info.verificationUri) {\n // MSAL may fire the callback with an empty object if the\n // downstream HTTP request fails — reject so the caller\n // gets a clear error instead of silent empty strings.\n reject(\n new Error(\n \"Microsoft device-code endpoint returned no code. \" +\n \"Check MS_CLIENT_ID is a valid Azure Entra public-client application.\",\n ),\n );\n return;\n }\n userCode = info.userCode;\n verificationUri = info.verificationUri;\n message = info.message;\n if (info.expiresIn) {\n expiresAt = new Date(Date.now() + info.expiresIn * 1000).toISOString();\n }\n r();\n },\n })\n .then((authResult: AuthenticationResult | null) => {\n if (aborted) return;\n if (!authResult || !authResult.account) {\n reject(new Error(\"device-code flow returned no account\"));\n return;\n }\n const cache = pca.getTokenCache().serialize();\n const tokens: SerializedTokens = {\n msalCache: cache,\n homeAccountId: authResult.account.homeAccountId,\n tenantId: authResult.account.tenantId,\n username: authResult.account.username,\n scopes,\n };\n resolve({ tokens, account: authResult.account });\n })\n .catch((err) => {\n if (!aborted) reject(err);\n });\n });\n\n // Surface device-code info synchronously via a wrapper Promise:\n // we return the object but its strings are populated once `ready` settles.\n // To keep the API simple, we attach a getter that callers must `await` on.\n // Instead of getters, we wait for `ready` inside the begin helper:\n return {\n // these are placeholders until ready resolves\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n // hidden helper for the caller to await initial code\n // (typed via a cast below where used)\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted MSAL cache. Returns the (possibly-updated) cache so the caller\n * can write it back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedTokens,\n scopes: string[] = DEFAULT_SCOPES,\n): Promise<{ accessToken: string; tokens: SerializedTokens }> {\n const pca = buildPca(tokens.msalCache);\n const cache = pca.getTokenCache();\n const account =\n (await cache.getAccountByHomeId(tokens.homeAccountId)) ??\n (await cache.getAllAccounts()).find((a) => a.username === tokens.username);\n if (!account) {\n throw new Error(\"no MSAL account in cache — re-run add_account\");\n }\n const res = await pca.acquireTokenSilent({ account, scopes });\n if (!res?.accessToken) {\n throw new Error(\"acquireTokenSilent returned no access token\");\n }\n const next: SerializedTokens = {\n ...tokens,\n msalCache: cache.serialize(),\n scopes,\n };\n return { accessToken: res.accessToken, tokens: next };\n}\n","import type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n EmailFull,\n EmailProvider,\n EmailSummary,\n ListEmailsOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\n\nconst NOT_IMPLEMENTED =\n \"IMAP provider is not yet implemented in v1. Tracked at \" +\n \"src/providers/imap/index.ts — see src/providers/types.ts for the contract.\";\n\n/**\n * Placeholder IMAP provider — registered so the contract is locked in and\n * `add_account` returns a clear \"coming soon\" error instead of \"unknown provider\".\n *\n * v2 plan: use `imapflow` + `nodemailer` (for send). Tokens shape will be\n * `{ host, port, secure, user, password|appPassword }` encrypted at rest by\n * the AccountStore, identical to how Outlook's MSAL cache is stored.\n */\nexport class ImapProvider implements EmailProvider {\n readonly id = \"imap\" as const;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async addAccount(_input: AddAccountInput): Promise<AddAccountResult> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async completeAddAccount(_handle: string): Promise<CompleteAddAccountResult> {\n return { status: \"error\", error: NOT_IMPLEMENTED };\n }\n\n async listEmails(\n _account: AccountRecord,\n _opts: ListEmailsOptions,\n ): Promise<EmailSummary[]> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async searchEmails(\n _account: AccountRecord,\n _query: string,\n _opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async readEmail(_account: AccountRecord, _id: string): Promise<EmailFull> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async readAttachment(\n _account: AccountRecord,\n _messageId: string,\n _attachmentId: string,\n ): Promise<AttachmentContent> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async sendEmail(\n _account: AccountRecord,\n _msg: SendInput,\n ): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async saveDraft(\n _account: AccountRecord,\n _msg: SendInput,\n ): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async moveEmail(\n _account: AccountRecord,\n _id: string,\n _destinationId: string,\n ): Promise<void> {\n throw new Error(NOT_IMPLEMENTED);\n }\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { EmailProvider, ProviderId } from \"./types.js\";\nimport { OutlookProvider } from \"./outlook/index.js\";\nimport { ImapProvider } from \"./imap/index.js\";\n\nexport interface Registry {\n get(id: ProviderId): EmailProvider;\n resolveByEmail(email: string): { provider: EmailProvider; account: AccountRecord };\n list(): EmailProvider[];\n}\n\nexport interface BuildRegistryOptions {\n store: AccountStore;\n}\n\nexport function buildRegistry(opts: BuildRegistryOptions): Registry {\n const providers = new Map<ProviderId, EmailProvider>();\n providers.set(\"outlook\", new OutlookProvider({ store: opts.store }));\n providers.set(\"imap\", new ImapProvider());\n // gmail can be added later — registry will return a clear error if asked.\n\n function get(id: ProviderId): EmailProvider {\n const p = providers.get(id);\n if (!p) throw new Error(`unknown provider: ${id}`);\n return p;\n }\n\n function resolveByEmail(email: string): {\n provider: EmailProvider;\n account: AccountRecord;\n } {\n const account = opts.store.getAccount(email);\n if (!account) {\n throw new Error(\n `no account registered for \"${email}\". Call add_account first.`,\n );\n }\n return { provider: get(account.provider), account };\n }\n\n return {\n get,\n resolveByEmail,\n list: () => Array.from(providers.values()),\n };\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountRecord, AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailProvider, ProviderId, SendInput } from \"../providers/types.js\";\nimport { selectBody } from \"../html-to-markdown.js\";\n\nexport interface RegisterToolsOptions {\n store: AccountStore;\n registry: Registry;\n readOnly?: boolean;\n /** When true, send_email is not registered — only send_draft is available. */\n draftOnly?: boolean;\n}\n\n/** JSON-stringify a value into a single MCP text content block. */\nfunction ok(data: unknown, structuredContent?: Record<string, unknown>) {\n const result: { content: Array<{ type: \"text\"; text: string }>; structuredContent?: Record<string, unknown> } = {\n content: [\n { type: \"text\" as const, text: JSON.stringify(data, null, 2) },\n ],\n };\n if (structuredContent !== undefined) {\n result.structuredContent = structuredContent;\n }\n return result;\n}\nfunction fail(message: string) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: message }],\n };\n}\n\nconst emailAddrSchema = z.object({\n address: z.string().email(),\n name: z.string().optional(),\n});\n\n// ---------- shared output schemas ----------\n\nconst emailAddrOutputSchema = z.object({\n name: z.string().optional(),\n address: z.string(),\n});\n\nconst accountSummaryOutputSchema = z.object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n addedAt: z.string(),\n hasSignature: z.boolean(),\n hasStyle: z.boolean(),\n});\n\nconst emailSummaryOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n});\n\nconst attachmentMetaOutputSchema = z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n});\n\nconst styleOutputSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n});\n\nexport function registerTools(server: McpServer, opts: RegisterToolsOptions): void {\n const { store, registry, readOnly = false, draftOnly = false } = opts;\n\n // ---------- account management ----------\n\n const listAccountsOutputSchema = {\n accounts: z.array(accountSummaryOutputSchema),\n };\n\n server.registerTool(\n \"list_accounts\",\n {\n description:\n \"List all email accounts known to this server (no secrets). \" +\n \"Use the returned `email` value as the `account` argument to other tools.\",\n inputSchema: {},\n outputSchema: listAccountsOutputSchema,\n },\n async () => {\n const rows = store.listAccounts().map((a) => ({\n email: a.email,\n provider: a.provider,\n displayName: a.displayName,\n addedAt: a.addedAt,\n hasSignature: !!a.signature,\n hasStyle: !!(a.style && (a.style.fontFamily || a.style.fontSize || a.style.fontColor)),\n }));\n const data = { accounts: rows };\n return ok(data, data);\n },\n );\n\n const addAccountOutputSchema = z.discriminatedUnion(\"status\", [\n z.object({\n status: z.literal(\"pending\"),\n handle: z.string(),\n verification: z.object({\n userCode: z.string(),\n verificationUri: z.string(),\n expiresAt: z.string(),\n message: z.string(),\n }),\n }),\n z.object({\n status: z.literal(\"ready\"),\n account: z.object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n tokens: z.record(z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n }),\n }),\n ]);\n\n server.registerTool(\n \"add_account\",\n {\n description:\n \"Start adding an email account. For Outlook this returns a device code \" +\n \"the user must enter at the verification URL; then call `complete_add_account` \" +\n \"with the returned `handle` to finalize. Disabled in --read-only mode.\",\n inputSchema: {\n provider: z\n .enum([\"outlook\", \"imap\", \"gmail\"])\n .describe(\"Email backend. v1 only fully implements 'outlook'.\"),\n email: z\n .string()\n .email()\n .optional()\n .describe(\"Optional hint — the provider will verify it against the auth result.\"),\n config: z\n .record(z.unknown())\n .optional()\n .describe(\"Provider-specific config (e.g. IMAP host/port). Unused for Outlook.\"),\n },\n outputSchema: addAccountOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; add_account is disabled\");\n const provider = registry.get(args.provider as ProviderId);\n try {\n const res = await provider.addAccount({ email: args.email, config: args.config });\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const completeAddAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\", \"expired\", \"error\"]),\n account: z\n .object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n tokens: z.record(z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n })\n .optional(),\n error: z.string().optional(),\n });\n\n server.registerTool(\n \"complete_add_account\",\n {\n description:\n \"Poll/finalize a pending add_account flow. Returns `pending` until the user \" +\n \"completes the device-code step, then `ready` with the persisted account.\",\n inputSchema: {\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n handle: z.string().min(1),\n },\n outputSchema: completeAddAccountOutputSchema,\n },\n async (args) => {\n const provider = registry.get(args.provider as ProviderId);\n if (!provider.completeAddAccount) {\n return fail(`provider ${args.provider} has no async add-account flow`);\n }\n try {\n const res = await provider.completeAddAccount(args.handle);\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n // ---------- account settings ----------\n\n const accountSettingsOutputSchema = {\n signature: z.string().nullable(),\n style: styleOutputSchema.nullable(),\n };\n\n server.registerTool(\n \"get_account_settings\",\n {\n description:\n \"Get signature (HTML) and style preferences for an account.\",\n inputSchema: { account: z.string().email() },\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const acct = store.getAccount(args.account);\n if (!acct) return fail(`no account registered for \"${args.account}\"`);\n const data = { signature: acct.signature ?? null, style: acct.style ?? null };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n server.registerTool(\n \"set_account_settings\",\n {\n description:\n \"Set signature (HTML snippet) and/or style preferences for an account. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n signature: z\n .string()\n .optional()\n .describe(\"HTML snippet — may contain formatting, images, links. Pass null to clear.\"),\n style: z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n })\n .optional()\n .describe(\"Font preferences applied to outgoing HTML emails. Pass null to clear.\"),\n },\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; set_account_settings is disabled\");\n try {\n const acct = store.getAccount(args.account);\n if (!acct) return fail(`no account registered for \"${args.account}\"`);\n const updated = await store.upsertAccount({\n ...acct,\n signature: args.signature ?? acct.signature,\n style: args.style ?? acct.style,\n });\n const data = { signature: updated.signature ?? null, style: updated.style ?? null };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const removeAccountOutputSchema = {\n removed: z.boolean(),\n email: z.string(),\n };\n\n server.registerTool(\n \"remove_account\",\n {\n description: \"Forget an account and delete its stored tokens. Disabled in --read-only mode.\",\n inputSchema: { email: z.string().email() },\n outputSchema: removeAccountOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; remove_account is disabled\");\n const removed = await store.removeAccount(args.email);\n const data = { removed, email: args.email };\n return ok(data, data);\n },\n );\n\n // ---------- email ops ----------\n\n const emailListOutputSchema = {\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n };\n\n server.registerTool(\n \"list_emails\",\n {\n description:\n \"List recent emails in a folder of the given account. Pass the user's email \" +\n \"address as `account`; the server routes to the correct backend automatically.\",\n inputSchema: {\n account: z.string().email(),\n folder: z.string().default(\"inbox\").optional(),\n limit: z.number().int().positive().max(100).optional(),\n unreadOnly: z.boolean().optional(),\n },\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.listEmails(account, {\n folder: args.folder,\n limit: args.limit,\n unreadOnly: args.unreadOnly,\n });\n const data = { account: account.email, count: items.length, items };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n server.registerTool(\n \"search_emails\",\n {\n description:\n \"Search emails by free-text query (KQL on Outlook). Returns lightweight summaries.\",\n inputSchema: {\n account: z.string().email(),\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n },\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.searchEmails(account, args.query, {\n limit: args.limit,\n });\n const data = { account: account.email, count: items.length, items };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const readEmailOutputSchema = {\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n cc: z.array(emailAddrOutputSchema).optional(),\n bcc: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n attachments: z.array(attachmentMetaOutputSchema).optional(),\n body: z.string(),\n bodyFormat: z.enum([\"markdown\", \"html\", \"text\"]),\n };\n\n server.registerTool(\n \"read_email\",\n {\n description:\n \"Fetch a single email with full body and recipients by id. \" +\n \"Body is returned as `body` with `bodyFormat` indicating the format. \" +\n \"Default format is 'markdown' — HTML is automatically converted to save context tokens.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1),\n format: z\n .enum([\"markdown\", \"html\", \"text\"])\n .default(\"markdown\")\n .optional()\n .describe(\n \"Output body format. 'markdown' converts HTML to Markdown (default), \" +\n \"'html' returns the raw HTML, 'text' returns plain text.\",\n ),\n },\n outputSchema: readEmailOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const msg = await provider.readEmail(account, args.id);\n const format = args.format ?? \"markdown\";\n const body = selectBody(msg, format);\n const data = {\n id: msg.id,\n subject: msg.subject,\n from: msg.from,\n to: msg.to,\n cc: msg.cc,\n bcc: msg.bcc,\n receivedAt: msg.receivedAt,\n preview: msg.preview,\n isRead: msg.isRead,\n hasAttachments: msg.hasAttachments,\n folder: msg.folder,\n attachments: msg.attachments,\n body,\n bodyFormat: format,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const readAttachmentOutputSchema = {\n name: z.string(),\n contentType: z.string().optional(),\n path: z.string(),\n };\n\n server.registerTool(\n \"read_attachment\",\n {\n description:\n \"Download an email attachment to a temporary file and return its path. \" +\n \"Use messageId and attachmentId from a prior read_email call.\",\n inputSchema: {\n account: z.string().email(),\n messageId: z.string().min(1),\n attachmentId: z.string().min(1),\n },\n outputSchema: readAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.readAttachment(account, args.messageId, args.attachmentId);\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n // ---------- move / archive ----------\n\n {\n const schema = {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n };\n\n const archiveOutputSchema = {\n archived: z.literal(true),\n id: z.string(),\n };\n\n server.registerTool(\n \"archive_email\",\n {\n description:\n \"Move a message to the Archive folder. Disabled in --read-only mode.\",\n inputSchema: schema,\n outputSchema: archiveOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; archive_email is disabled\");\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, \"archive\");\n const data = { archived: true as const, id: args.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const trashOutputSchema = {\n trashed: z.literal(true),\n id: z.string(),\n };\n\n server.registerTool(\n \"trash_email\",\n {\n description:\n \"Move a message to the Deleted Items (trash) folder. Disabled in --read-only mode.\",\n inputSchema: schema,\n outputSchema: trashOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; trash_email is disabled\");\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, \"deleteditems\");\n const data = { trashed: true as const, id: args.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const moveEmailOutputSchema = {\n moved: z.literal(true),\n id: z.string(),\n destination: z.string(),\n };\n\n server.registerTool(\n \"move_email\",\n {\n description:\n \"Move a message to any folder by well-known name (e.g. 'inbox', 'drafts', \" +\n \"'junkemail', 'sentitems', 'outbox') or custom folder ID. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n destination: z\n .string()\n .min(1)\n .describe(\n \"Destination folder — a well-known folder name \" +\n \"('archive', 'deleteditems', 'inbox', 'drafts', 'junkemail', \" +\n \"'sentitems', 'outbox') or a raw folder ID.\",\n ),\n },\n outputSchema: moveEmailOutputSchema,\n },\n async (args) => {\n if (readOnly) return fail(\"server is in --read-only mode; move_email is disabled\");\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, args.destination);\n const data = { moved: true as const, id: args.id, destination: args.destination };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n\n const sendEmailSchema = z.object({\n account: z.string().email(),\n to: z.array(emailAddrSchema).min(1),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string(),\n body: z.string(),\n isHtml: z.boolean().optional(),\n include_signature: z\n .boolean()\n .describe(\n \"Whether to append the account's saved HTML signature to the email. \" +\n \"If true, don't include a signature in the body param to avoid double signature. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n inReplyTo: z\n .string()\n .optional()\n .describe(\n \"Message ID to reply to. When set, sends as a threaded reply \" +\n \"which includes the quoted thread history automatically.\",\n ),\n replyAll: z\n .boolean()\n .default(false)\n .optional()\n .describe(\n \"When true and `inReplyTo` is set, reply to all recipients \" +\n \"instead of just the sender.\",\n ),\n forwardMessageId: z\n .string()\n .optional()\n .describe(\n \"Message ID to forward. When set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"Mutually exclusive with `inReplyTo`.\",\n ),\n });\n\n type SendEmailArgs = z.infer<typeof sendEmailSchema>;\n\n async function handleSendOrDraft(\n args: SendEmailArgs,\n action: (\n provider: EmailProvider,\n account: AccountRecord,\n msg: SendInput,\n ) => Promise<{ id: string }>,\n resultKey: string,\n toolName: string,\n ) {\n if (readOnly) return fail(`server is in --read-only mode; ${toolName} is disabled`);\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n if (args.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n const composed = composeBody({\n body: args.body,\n isHtml: args.isHtml,\n signature: account.signature,\n style: account.style,\n includeSignature: args.include_signature,\n });\n if (args.inReplyTo && args.forwardMessageId) {\n return fail(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n const res = await action(provider, account, {\n to: args.to,\n cc: args.cc,\n bcc: args.bcc,\n subject: args.subject,\n body: composed.body,\n isHtml: composed.isHtml,\n inReplyTo: args.inReplyTo,\n replyAll: args.replyAll,\n forwardMessageId: args.forwardMessageId,\n });\n const result: Record<string, unknown> = { [resultKey]: true, ...res };\n // For draft_email, fetch the created draft back so the agent can\n // inspect the actual HTML content before deciding to send it.\n if (toolName === \"draft_email\" && res.id) {\n const draft = await provider.readEmail(account, res.id);\n result.draftHtml = draft.bodyHtml;\n }\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n }\n\n // ---------- send / draft ----------\n\n const sendEmailOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (!draftOnly) {\n server.registerTool(\n \"send_email\",\n {\n description:\n \"Send an email from the given account. Appends the \" +\n \"account's signature (HTML) and applies style preferences when \" +\n \"`include_signature` is true. Returns an error if \" +\n \"`include_signature` is true but no signature is configured. \" +\n \"When `inReplyTo` is set, sends as a reply (or reply-all) which \" +\n \"preserves thread history and conversation threading. \" +\n \"When `forwardMessageId` is set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"`inReplyTo` and `forwardMessageId` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: sendEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.sendEmail(a, m),\n \"sent\",\n \"send_email\",\n ),\n );\n }\n\n const draftEmailOutputSchema = {\n draft: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n server.registerTool(\n \"draft_email\",\n {\n description:\n \"Create a draft email from the given account without sending it. \" +\n \"Works identically to send_email — appends signature when \" +\n \"`include_signature` is true, applies style, and supports replies \" +\n \"and forwards — but saves the message to the Drafts folder \" +\n \"instead of sending. Returns the draft message ID and the draft's \" +\n \"HTML body content (`draftHtml`). Before sending the draft, \" +\n \"inspect `draftHtml` to verify the draft looks correct: no \" +\n \"duplicate signature blocks, no broken or missing inline images, \" +\n \"no malformed HTML, and no other formatting issues. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: draftEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.saveDraft(a, m),\n \"draft\",\n \"draft_email\",\n ),\n );\n}\n\n// ---------- body composition helpers ----------\n\ninterface ComposeBodyInput {\n body: string;\n isHtml?: boolean;\n signature?: string;\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n includeSignature: boolean;\n}\n\nexport function composeBody(input: ComposeBodyInput): { body: string; isHtml: boolean } {\n const { body, isHtml = false, signature, style, includeSignature } = input;\n const hasSignature = includeSignature && !!signature;\n const hasStyle = !!(style && (style.fontFamily || style.fontSize || style.fontColor));\n\n // Nothing to inject — pass through unchanged\n if (!hasSignature && !hasStyle) {\n return { body, isHtml };\n }\n\n // Need HTML for signature or style injection\n const styleAttr = hasStyle ? buildStyleAttr(style!) : \"\";\n\n if (isHtml) {\n let result = hasStyle ? `<div style=\"${styleAttr}\">${body}</div>` : body;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n }\n\n // Auto-upgrade plain text to HTML\n const escaped = escapeHtml(body);\n let result = `<div style=\"${styleAttr}\">${escaped}</div>`;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n}\n\nexport function buildStyleAttr(style: { fontFamily?: string; fontSize?: string; fontColor?: string }): string {\n const parts: string[] = [];\n if (style.fontFamily) parts.push(`font-family: ${style.fontFamily}`);\n if (style.fontSize) parts.push(`font-size: ${style.fontSize}`);\n if (style.fontColor) parts.push(`color: ${style.fontColor}`);\n return parts.join(\"; \");\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/\\n/g, \"<br>\");\n}\n\nfunction errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n","import TurndownService from \"turndown\";\n\nconst turndown = new TurndownService();\n\n/** Light wrapper — callers just pass HTML, get markdown back. */\nexport function htmlToMarkdown(html: string): string {\n return turndown.turndown(html);\n}\n\n/** Pick the right body for the requested format. */\nexport function selectBody(\n msg: { bodyHtml?: string; bodyText?: string },\n format: \"markdown\" | \"html\" | \"text\",\n): string {\n switch (format) {\n case \"markdown\": {\n if (msg.bodyHtml) return htmlToMarkdown(msg.bodyHtml);\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"html\": {\n if (msg.bodyHtml) return msg.bodyHtml;\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"text\": {\n if (msg.bodyText) return msg.bodyText;\n if (msg.bodyHtml) return msg.bodyHtml.replace(/<[^>]*>/g, \"\");\n return \"\";\n }\n }\n}\n","export const VERSION = \"0.3.0\";\n","import { startServer } from \"./server.js\";\n\ntype ParsedArgs = {\n http: boolean;\n port: number;\n host: string;\n dataDir?: string;\n readOnly: boolean;\n help: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {\n http: false,\n port: 3000,\n host: \"127.0.0.1\",\n readOnly: false,\n help: false,\n };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n switch (a) {\n case \"--http\":\n out.http = true;\n break;\n case \"--port\":\n out.port = Number(argv[++i] ?? \"3000\");\n break;\n case \"--host\":\n out.host = String(argv[++i] ?? \"127.0.0.1\");\n break;\n case \"--data-dir\":\n out.dataDir = String(argv[++i] ?? \"\");\n break;\n case \"--read-only\":\n out.readOnly = true;\n break;\n case \"-h\":\n case \"--help\":\n out.help = true;\n break;\n default:\n if (a && a.startsWith(\"--\")) {\n // ignore unknown flags rather than crashing — keeps the CLI forgiving\n // when embedded in MCP host configs.\n }\n }\n }\n return out;\n}\n\nfunction printHelp(): void {\n const msg = `hypermail-mcp — unified email MCP server\n\nUsage:\n hypermail-mcp [options]\n\nOptions:\n --http Run as Streamable HTTP server (default: stdio)\n --port <n> HTTP port (default: 3000)\n --host <addr> HTTP bind address (default: 127.0.0.1)\n --data-dir <path> Where to store the encrypted accounts file\n (default: $HYPERMAIL_MCP_DATA_DIR or ~/.hypermail-mcp)\n --read-only Disable tools that modify state (send_email, remove_account, add_account)\n -h, --help Show this help\n\nEnvironment:\n HYPERMAIL_MCP_DATA_DIR Same as --data-dir\n HYPERMAIL_MCP_KEY 32-byte key (base64 or hex) for at-rest encryption\n MS_CLIENT_ID Azure AD public client (application) ID\n MS_TENANT_ID Tenant (default: \"common\")\n`;\n process.stdout.write(msg);\n}\n\nasync function main(): Promise<void> {\n const opts = parseArgs(process.argv.slice(2));\n if (opts.help) {\n printHelp();\n return;\n }\n const draftOnly = process.env.HYPERMAIL_DRAFT_ONLY === \"true\";\n\n await startServer({\n http: opts.http,\n port: opts.port,\n host: opts.host,\n dataDir: opts.dataDir,\n readOnly: opts.readOnly,\n draftOnly,\n });\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] fatal:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":["randomUUID","result","randomUUID"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/store/account-store.ts","../src/providers/outlook/index.ts","../src/providers/outlook/client.ts","../src/providers/outlook/auth.ts","../src/providers/imap/index.ts","../src/providers/registry.ts","../src/tools/shared.ts","../src/tools/accounts.ts","../src/tools/browse.ts","../src/html-to-markdown.ts","../src/tools/folders.ts","../src/tools/organize.ts","../src/tools/compose.ts","../src/tools/index.ts","../src/version.ts","../src/config.ts","../src/cli.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\n\nimport { AccountStore } from \"./store/account-store.js\";\nimport { buildRegistry } from \"./providers/registry.js\";\nimport { registerTools } from \"./tools/index.js\";\nimport { VERSION } from \"./version.js\";\nimport type { AppConfig, ProvidersConfig, ResolvedTools } from \"./config.js\";\nimport { resolveTools } from \"./config.js\";\n\nexport interface ServerOptions {\n /** Fully resolved application config from hypermail-config.json. */\n config: AppConfig;\n}\n\nexport async function startServer(opts: ServerOptions): Promise<void> {\n const { config } = opts;\n const store = await AccountStore.open({ dataDir: config.dataDir });\n const registry = buildRegistry({ store, providers: config.providers });\n const tools: ResolvedTools = resolveTools(config);\n\n const server = new McpServer(\n { name: \"hypermail-mcp\", version: VERSION },\n { capabilities: { tools: {}, logging: {} } },\n );\n\n registerTools(server, { store, registry, tools });\n\n if (config.http.enabled) {\n await startHttp(server, config.http.host, config.http.port);\n } else {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\nasync function startHttp(server: McpServer, host: string, port: number): Promise<void> {\n // One transport per session, keyed by Mcp-Session-Id header.\n const sessions = new Map<string, StreamableHTTPServerTransport>();\n\n const http = createHttpServer(async (req: IncomingMessage, res: ServerResponse) => {\n try {\n if (!req.url || !req.url.startsWith(\"/mcp\")) {\n res.statusCode = 404;\n res.end(\"not found\");\n return;\n }\n const sessionId = (req.headers[\"mcp-session-id\"] as string | undefined) ?? undefined;\n let transport = sessionId ? sessions.get(sessionId) : undefined;\n\n if (!transport) {\n transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid: string) => {\n sessions.set(sid, transport!);\n },\n });\n transport.onclose = () => {\n if (transport!.sessionId) sessions.delete(transport!.sessionId);\n };\n await server.connect(transport);\n }\n\n // Buffer body for POST / DELETE\n let body: unknown = undefined;\n if (req.method === \"POST\" || req.method === \"DELETE\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n body = raw ? JSON.parse(raw) : undefined;\n }\n await transport.handleRequest(req, res, body);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] http error:\", err);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(\"internal error\");\n }\n }\n });\n\n await new Promise<void>((resolve) => http.listen(port, host, resolve));\n // eslint-disable-next-line no-console\n console.error(`[hypermail-mcp] listening on http://${host}:${port}/mcp`);\n}\n","import {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n createHash,\n} from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * One stored account. `tokens` is provider-specific (e.g. serialized MSAL cache\n * for Outlook, host/port/password blob for IMAP) — the store is opaque to it.\n */\nexport interface AccountRecord {\n email: string;\n provider: \"outlook\" | \"imap\" | \"gmail\";\n displayName?: string;\n tokens: Record<string, unknown>;\n addedAt: string;\n /** HTML snippet — may contain formatting, images, links. Injected at end of outgoing emails. */\n signature?: string;\n /** Font/style preferences applied to outgoing HTML emails. */\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n}\n\ninterface StoreFile {\n version: 1;\n accounts: AccountRecord[];\n}\n\nexport interface OpenOptions {\n dataDir?: string;\n /** Inject the encryption key directly (mostly for tests). Otherwise resolved\n * from `HYPERMAIL_MCP_KEY` env, then OS keychain, then auto-generated. */\n key?: Buffer;\n}\n\nconst FILE_NAME = \"accounts.json.enc\";\nconst ALGO = \"aes-256-gcm\";\nconst KEY_LEN = 32;\n\nexport class AccountStore {\n private constructor(\n private readonly filePath: string,\n private readonly key: Buffer,\n private data: StoreFile,\n ) {}\n\n static async open(opts: OpenOptions = {}): Promise<AccountStore> {\n const dataDir = resolveDataDir(opts.dataDir);\n await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });\n const filePath = path.join(dataDir, FILE_NAME);\n const key = opts.key ?? (await resolveKey(dataDir));\n\n let data: StoreFile;\n try {\n const buf = await fs.readFile(filePath);\n data = decrypt(buf, key);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n data = { version: 1, accounts: [] };\n } else {\n throw err;\n }\n }\n return new AccountStore(filePath, key, data);\n }\n\n listAccounts(): AccountRecord[] {\n // Return shallow clones without tokens leaking out unintentionally is the\n // caller's job; here we expose the full record for provider use.\n return this.data.accounts.map((a) => ({ ...a }));\n }\n\n getAccount(email: string): AccountRecord | undefined {\n const norm = email.trim().toLowerCase();\n const rec = this.data.accounts.find((a) => a.email.toLowerCase() === norm);\n return rec ? { ...rec } : undefined;\n }\n\n async upsertAccount(rec: AccountRecord): Promise<AccountRecord> {\n const norm = rec.email.trim().toLowerCase();\n const next: AccountRecord = { ...rec, email: norm };\n const idx = this.data.accounts.findIndex((a) => a.email.toLowerCase() === norm);\n if (idx >= 0) this.data.accounts[idx] = next;\n else this.data.accounts.push(next);\n await this.flush();\n return { ...next };\n }\n\n async removeAccount(email: string): Promise<boolean> {\n const norm = email.trim().toLowerCase();\n const before = this.data.accounts.length;\n this.data.accounts = this.data.accounts.filter((a) => a.email.toLowerCase() !== norm);\n if (this.data.accounts.length === before) return false;\n await this.flush();\n return true;\n }\n\n private async flush(): Promise<void> {\n const buf = encrypt(this.data, this.key);\n const tmp = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, buf, { mode: 0o600 });\n await fs.rename(tmp, this.filePath);\n }\n}\n\n// ---------- encryption helpers ----------\n\nfunction encrypt(data: StoreFile, key: Buffer): Buffer {\n const iv = randomBytes(12);\n const cipher = createCipheriv(ALGO, key, iv);\n const plaintext = Buffer.from(JSON.stringify(data), \"utf8\");\n const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const tag = cipher.getAuthTag();\n // layout: [1-byte version=1][12 iv][16 tag][ct...]\n return Buffer.concat([Buffer.from([1]), iv, tag, ct]);\n}\n\nfunction decrypt(buf: Buffer, key: Buffer): StoreFile {\n if (buf.length < 1 + 12 + 16 + 1) throw new Error(\"accounts file truncated\");\n const v = buf[0];\n if (v !== 1) throw new Error(`unsupported accounts file version: ${v}`);\n const iv = buf.subarray(1, 13);\n const tag = buf.subarray(13, 29);\n const ct = buf.subarray(29);\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n const parsed = JSON.parse(pt.toString(\"utf8\")) as StoreFile;\n if (parsed.version !== 1 || !Array.isArray(parsed.accounts)) {\n throw new Error(\"accounts file is malformed\");\n }\n return parsed;\n}\n\n// ---------- key + path resolution ----------\n\nfunction resolveDataDir(explicit?: string): string {\n if (explicit && explicit.length > 0) return path.resolve(explicit);\n const env = process.env.HYPERMAIL_MCP_DATA_DIR;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(homedir(), \".hypermail-mcp\");\n}\n\nfunction parseEnvKey(raw: string): Buffer | undefined {\n const s = raw.trim();\n // hex (64 chars)\n if (/^[0-9a-fA-F]{64}$/.test(s)) return Buffer.from(s, \"hex\");\n // base64 — accept any length, then check\n try {\n const buf = Buffer.from(s, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n } catch {\n /* ignore */\n }\n // last-resort: derive 32 bytes via SHA-256 over the raw string. This lets\n // users pass any passphrase; not ideal but predictable.\n return createHash(\"sha256\").update(s, \"utf8\").digest();\n}\n\nasync function resolveKey(dataDir: string): Promise<Buffer> {\n const env = process.env.HYPERMAIL_MCP_KEY;\n if (env && env.length > 0) {\n const k = parseEnvKey(env);\n if (k) return k;\n }\n\n // Try OS keychain via keytar (optional dep).\n const fromKeytar = await tryKeytarGet();\n if (fromKeytar) return fromKeytar;\n\n // Local-dev fallback: persist a generated key to a 0600 file next to the\n // accounts blob so subsequent runs can decrypt. Hosted deployments should\n // always set HYPERMAIL_MCP_KEY explicitly.\n const keyFile = path.join(dataDir, \"master.key\");\n try {\n const existing = await fs.readFile(keyFile);\n if (existing.length === KEY_LEN) return existing;\n } catch {\n /* fall through to generate */\n }\n const gen = randomBytes(KEY_LEN);\n await fs.writeFile(keyFile, gen, { mode: 0o600 });\n await tryKeytarSet(gen);\n return gen;\n}\n\nasync function tryKeytarGet(): Promise<Buffer | undefined> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n const val = await mod.getPassword(\"hypermail-mcp\", \"master\");\n if (val) {\n const buf = Buffer.from(val, \"base64\");\n if (buf.length === KEY_LEN) return buf;\n }\n } catch {\n /* keytar not installed or unsupported platform */\n }\n return undefined;\n}\n\nasync function tryKeytarSet(key: Buffer): Promise<void> {\n try {\n const mod = (await import(\"keytar\")) as typeof import(\"keytar\");\n await mod.setPassword(\"hypermail-mcp\", \"master\", key.toString(\"base64\"));\n } catch {\n /* ignore */\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\n\nimport { ResponseType, type Client } from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountRecord, AccountStore } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n EmailAddress,\n} from \"../types.js\";\nimport { OutlookClientFactory } from \"./client.js\";\nimport {\n awaitDeviceCodeReady,\n beginDeviceCode,\n type DeviceCodeBegin,\n type SerializedTokens,\n} from \"./auth.js\";\n\n// ---------- inline image conversion ----------\n\ninterface InlineAttachment {\n \"@odata.type\": string;\n name: string;\n contentType: string;\n contentId: string;\n contentBytes: string;\n isInline: boolean;\n}\n\n/**\n * Scans HTML for data:image/...;base64,... URIs, extracts the raw base64\n * data, assigns unique contentIds, and returns the transformed body\n * (with src=\"cid:...\" references) plus an array of inline fileAttachment\n * objects ready for the Graph API.\n *\n * Pass-through when there are no matches — returns the original body with\n * an empty attachments array.\n */\nexport function convertInlineImages(body: string): {\n body: string;\n attachments: InlineAttachment[];\n} {\n const attachments: InlineAttachment[] = [];\n // Match src=\"data:image/<subtype>;base64,<payload>\"\n // Supports png, jpg, jpeg, gif, svg+xml, webp, bmp, etc.\n const re = /src=\"data:image\\/([\\w+]+);base64,([^\"]+)\"/gi;\n\n const transformed = body.replace(re, (_fullMatch, mimeSubtype, b64) => {\n const contentId = `sig-img-${randomUUID()}`;\n const ext = mimeSubtype.toLowerCase().replace(/\\+/g, \"-\") === \"svg-xml\"\n ? \"svg\"\n : mimeSubtype.toLowerCase().replace(/\\+/g, \"-\");\n attachments.push({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name: `signature-image.${ext}`,\n contentType: `image/${mimeSubtype}`,\n contentId,\n contentBytes: b64,\n isInline: true,\n });\n return `src=\"cid:${contentId}\"`;\n });\n\n return { body: transformed, attachments };\n}\n\ninterface PendingFlow {\n begin: DeviceCodeBegin;\n emailHint?: string;\n startedAt: number;\n settled: \"pending\" | \"ready\" | \"error\" | \"expired\";\n account?: AccountRecord;\n error?: string;\n}\n\nexport interface OutlookProviderOptions {\n store: AccountStore;\n clientId?: string;\n tenantId?: string;\n}\n\nexport class OutlookProvider implements EmailProvider {\n readonly id = \"outlook\" as const;\n private readonly clients: OutlookClientFactory;\n private readonly pending = new Map<string, PendingFlow>();\n private readonly clientId?: string;\n private readonly tenantId?: string;\n\n constructor(private readonly opts: OutlookProviderOptions) {\n this.clientId = opts.clientId;\n this.tenantId = opts.tenantId;\n this.clients = new OutlookClientFactory(opts.store, opts.clientId, opts.tenantId);\n }\n\n // ---------- account lifecycle ----------\n\n async addAccount(input: AddAccountInput): Promise<AddAccountResult> {\n const begin = beginDeviceCode(undefined, this.clientId, this.tenantId);\n await awaitDeviceCodeReady(begin);\n\n const handle = randomUUID();\n const flow: PendingFlow = {\n begin,\n emailHint: input.email,\n startedAt: Date.now(),\n settled: \"pending\",\n };\n this.pending.set(handle, flow);\n\n // Fire-and-forget: when the user finishes, persist and update flow.\n begin.result\n .then(async ({ tokens, account }) => {\n const email = (account.username || input.email || \"\").toLowerCase();\n if (!email) {\n flow.settled = \"error\";\n flow.error = \"no email returned from Microsoft account\";\n return;\n }\n const rec: AccountRecord = {\n email,\n provider: \"outlook\",\n displayName: account.name ?? undefined,\n tokens: tokens as unknown as Record<string, unknown>,\n addedAt: new Date().toISOString(),\n };\n const saved = await this.opts.store.upsertAccount(rec);\n flow.account = saved;\n flow.settled = \"ready\";\n })\n .catch((err: unknown) => {\n flow.settled = \"error\";\n flow.error = err instanceof Error ? err.message : String(err);\n });\n\n return {\n status: \"pending\",\n handle,\n verification: {\n userCode: begin.userCode,\n verificationUri: begin.verificationUri,\n expiresAt: begin.expiresAt,\n message: begin.message,\n },\n };\n }\n\n async completeAddAccount(handle: string): Promise<CompleteAddAccountResult> {\n const flow = this.pending.get(handle);\n if (!flow) return { status: \"error\", error: \"unknown handle\" };\n // expire after 20 minutes regardless\n if (Date.now() - flow.startedAt > 20 * 60_000 && flow.settled === \"pending\") {\n flow.settled = \"expired\";\n flow.begin.cancel();\n }\n if (flow.settled === \"ready\" && flow.account) {\n this.pending.delete(handle);\n return { status: \"ready\", account: flow.account };\n }\n if (flow.settled === \"error\") {\n this.pending.delete(handle);\n return { status: \"error\", error: flow.error ?? \"unknown error\" };\n }\n if (flow.settled === \"expired\") {\n this.pending.delete(handle);\n return { status: \"expired\" };\n }\n return { status: \"pending\" };\n }\n\n // ---------- email ops ----------\n\n async listEmails(\n account: AccountRecord,\n opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n const folder = opts.folder ?? \"inbox\";\n const filterParts: string[] = [];\n if (opts.unreadOnly) filterParts.push(\"isRead eq false\");\n\n let req = client\n .api(`/me/mailFolders/${encodeURIComponent(folder)}/messages`)\n .top(limit)\n .skip(opts.skip ?? 0)\n .select([\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"))\n .orderby(\"receivedDateTime DESC\");\n\n if (filterParts.length > 0) req = req.filter(filterParts.join(\" and \"));\n\n const res = (await req.get()) as { value: GraphMessage[]; \"@odata.nextLink\"?: string };\n return {\n items: res.value.map((m) => mapSummary(m, folder)),\n hasMore: !!res[\"@odata.nextLink\"],\n };\n }\n\n async searchEmails(\n account: AccountRecord,\n query: string,\n opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n const client = this.clients.get(account);\n const limit = clampLimit(opts.limit, 25, 100);\n // $search requires the ConsistencyLevel: eventual header\n const res = (await client\n .api(\"/me/messages\")\n .header(\"ConsistencyLevel\", \"eventual\")\n .top(limit)\n .search(`\"${query.replace(/\"/g, '\\\\\"')}\"`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n ].join(\",\"),\n )\n .get()) as { value: GraphMessage[] };\n return res.value.map((m) => mapSummary(m));\n }\n\n async readEmail(account: AccountRecord, id: string): Promise<EmailFull> {\n const client = this.clients.get(account);\n const m = (await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .select(\n [\n \"id\",\n \"subject\",\n \"from\",\n \"toRecipients\",\n \"ccRecipients\",\n \"bccRecipients\",\n \"receivedDateTime\",\n \"bodyPreview\",\n \"isRead\",\n \"hasAttachments\",\n \"body\",\n ].join(\",\"),\n )\n .get()) as GraphMessage;\n\n let attachments: EmailFull[\"attachments\"] = undefined;\n if (m.hasAttachments) {\n try {\n const attRes = (await client\n .api(`/me/messages/${encodeURIComponent(id)}/attachments`)\n .select(\"id,name,contentType,size\")\n .get()) as { value: GraphAttachment[] };\n attachments = attRes.value.map((a) => ({\n id: a.id,\n name: a.name,\n contentType: a.contentType,\n size: a.size,\n }));\n } catch {\n /* ignore attachment listing failure */\n }\n }\n\n const summary = mapSummary(m);\n const body = m.body;\n return {\n ...summary,\n cc: (m.ccRecipients ?? []).map(mapRecipient),\n bcc: (m.bccRecipients ?? []).map(mapRecipient),\n bodyText: body?.contentType === \"text\" ? body.content : undefined,\n bodyHtml: body?.contentType === \"html\" ? body.content : undefined,\n attachments,\n };\n }\n\n async readAttachment(\n account: AccountRecord,\n messageId: string,\n attachmentId: string,\n ): Promise<AttachmentContent> {\n const client = this.clients.get(account);\n // First, get the attachment metadata to know the filename\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`)\n .select(\"name,contentType\")\n .get()) as { name: string; contentType?: string };\n\n // Download the raw content as ArrayBuffer\n const data = (await client\n .api(`/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}/$value`)\n .responseType(ResponseType.ARRAYBUFFER)\n .get()) as ArrayBuffer;\n\n // Write to temp file with original name\n const outPath = pathJoin(tmpdir(), att.name);\n writeFileSync(outPath, Buffer.from(data));\n\n return {\n name: att.name,\n contentType: att.contentType,\n path: outPath,\n };\n }\n\n // Shared helper — creates a draft from a reference message (forward or\n // reply), prepends our composed body before the existing content, and\n // attaches inline images. Returns the draft message ID.\n private async buildDraftFromReference(\n client: Client,\n createEndpoint: string,\n createPayload: Record<string, unknown>,\n converted: { body: string; attachments: InlineAttachment[] },\n ): Promise<string> {\n const draft: { id: string } = await client\n .api(createEndpoint)\n .post(createPayload);\n\n const draftMsg: { body?: { content?: string; contentType?: string } } =\n await client.api(`/me/messages/${draft.id}`).select(\"body\").get();\n\n const draftBody = draftMsg.body?.content ?? \"\";\n const draftContentType = draftMsg.body?.contentType ?? \"HTML\";\n const spacer = '<div style=\"line-height:12px\"><br></div>';\n const prepend = converted.body + spacer;\n const finalBody = draftBody.includes(\"<body\")\n ? draftBody.replace(/(<body[^>]*>)/i, `$1${prepend}`)\n : prepend + draftBody;\n\n await client.api(`/me/messages/${draft.id}`).patch({\n body: { contentType: draftContentType, content: finalBody },\n });\n\n for (const att of converted.attachments) {\n await client.api(`/me/messages/${draft.id}/attachments`).post(att);\n }\n\n return draft.id;\n }\n\n async sendEmail(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n\n if (msg.inReplyTo && msg.forwardMessageId) {\n throw new Error(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n\n // Convert data:image URIs to cid: references + inline attachments.\n const converted = convertInlineImages(msg.body);\n\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n {\n message: {\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n comment: \"\",\n },\n converted,\n );\n await client.api(`/me/messages/${draftId}/send`).post({});\n return { id: draftId };\n }\n\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client,\n createEndpoint,\n {},\n converted,\n );\n await client.api(`/me/messages/${draftId}/send`).post({});\n return { id: draftId };\n }\n\n // New email — use sendMail with inline attachments\n const payload: Record<string, unknown> = {\n message: {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n saveToSentItems: true,\n };\n if (converted.attachments.length > 0) {\n (payload.message as Record<string, unknown>).attachments =\n converted.attachments;\n }\n await client.api(\"/me/sendMail\").post(payload);\n // Graph's sendMail returns 202 with no body; we don't have an id back.\n return { id: \"\" };\n }\n\n async saveDraft(\n account: AccountRecord,\n msg: SendInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n\n if (msg.inReplyTo && msg.forwardMessageId) {\n throw new Error(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n\n const converted = convertInlineImages(msg.body);\n\n // Forward/reply drafts: same flow as sendEmail, but skip the final send.\n if (msg.forwardMessageId) {\n const draftId = await this.buildDraftFromReference(\n client,\n `/me/messages/${encodeURIComponent(msg.forwardMessageId)}/createForward`,\n {\n message: {\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n },\n comment: \"\",\n },\n converted,\n );\n return { id: draftId };\n }\n\n if (msg.inReplyTo) {\n const createEndpoint = msg.replyAll\n ? `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReplyAll`\n : `/me/messages/${encodeURIComponent(msg.inReplyTo)}/createReply`;\n const draftId = await this.buildDraftFromReference(\n client,\n createEndpoint,\n {},\n converted,\n );\n return { id: draftId };\n }\n\n // New email — create a draft message directly (POST /me/messages).\n // Graph creates drafts by default when posting to /me/messages.\n const draftPayload: Record<string, unknown> = {\n subject: msg.subject,\n body: {\n contentType: msg.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n },\n toRecipients: msg.to.map(toRecipient),\n ccRecipients: (msg.cc ?? []).map(toRecipient),\n bccRecipients: (msg.bcc ?? []).map(toRecipient),\n };\n if (converted.attachments.length > 0) {\n draftPayload.attachments = converted.attachments;\n }\n const draft: { id: string } = await client\n .api(\"/me/messages\")\n .post(draftPayload);\n return { id: draft.id };\n }\n\n async updateDraft(\n account: AccountRecord,\n id: string,\n update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n const payload: Record<string, unknown> = {};\n\n if (update.subject !== undefined) {\n payload.subject = update.subject;\n }\n if (update.to !== undefined) {\n payload.toRecipients = update.to.map(toRecipient);\n }\n if (update.cc !== undefined) {\n payload.ccRecipients = update.cc.map(toRecipient);\n }\n if (update.bcc !== undefined) {\n payload.bccRecipients = update.bcc.map(toRecipient);\n }\n if (update.body !== undefined) {\n const converted = convertInlineImages(update.body);\n payload.body = {\n contentType: update.isHtml ? \"HTML\" : \"Text\",\n content: converted.body,\n };\n if (converted.attachments.length > 0) {\n // Patch existing inline attachments: Graph will replace all\n // attachments on the message. We send only the new ones.\n payload.attachments = converted.attachments;\n }\n }\n\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch(payload);\n\n return { id };\n }\n\n async moveEmail(\n account: AccountRecord,\n id: string,\n destinationId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}/move`)\n .post({ destinationId });\n }\n\n async sendDraft(\n account: AccountRecord,\n id: string,\n ): Promise<{ id: string }> {\n const client = this.clients.get(account);\n await client.api(`/me/messages/${encodeURIComponent(id)}/send`).post({});\n return { id };\n }\n\n async addAttachmentToDraft(\n account: AccountRecord,\n draftId: string,\n name: string,\n contentBytes: string,\n contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n const client = this.clients.get(account);\n const att = (await client\n .api(`/me/messages/${encodeURIComponent(draftId)}/attachments`)\n .post({\n \"@odata.type\": \"#microsoft.graph.fileAttachment\",\n name,\n contentType: contentType ?? \"application/octet-stream\",\n contentBytes,\n })) as { id: string; name: string; contentType?: string };\n return {\n id: draftId,\n attachment: { id: att.id, name: att.name, contentType: att.contentType },\n };\n }\n\n async markRead(\n account: AccountRecord,\n id: string,\n isRead: boolean,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/messages/${encodeURIComponent(id)}`)\n .patch({ isRead });\n }\n\n async listFolders(\n account: AccountRecord,\n opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n const client = this.clients.get(account);\n const endpoint = opts.parentFolderId\n ? `/me/mailFolders/${encodeURIComponent(opts.parentFolderId)}/childFolders`\n : \"/me/mailFolders\";\n const res = (await client\n .api(endpoint)\n .select([\n \"id\",\n \"displayName\",\n \"parentFolderId\",\n \"childFolderCount\",\n \"totalItemCount\",\n \"unreadItemCount\",\n ].join(\",\"))\n .get()) as { value: GraphFolder[] };\n return (res.value ?? []).map(mapFolder);\n }\n\n async createFolder(\n account: AccountRecord,\n input: CreateFolderInput,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const parentId = input.parentFolderId ?? \"msgfolderroot\";\n const created = (await client\n .api(`/me/mailFolders/${encodeURIComponent(parentId)}/childFolders`)\n .post({ displayName: input.displayName })) as GraphFolder;\n return mapFolder(created);\n }\n\n async renameFolder(\n account: AccountRecord,\n folderId: string,\n newName: string,\n ): Promise<FolderInfo> {\n const client = this.clients.get(account);\n const updated = (await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .patch({ displayName: newName })) as GraphFolder;\n return mapFolder(updated);\n }\n\n async deleteFolder(\n account: AccountRecord,\n folderId: string,\n ): Promise<void> {\n const client = this.clients.get(account);\n await client\n .api(`/me/mailFolders/${encodeURIComponent(folderId)}`)\n .delete();\n }\n}\n\n// ---------- mapping helpers ----------\n\ninterface GraphRecipient {\n emailAddress?: { name?: string; address?: string };\n}\ninterface GraphMessage {\n id: string;\n subject?: string;\n from?: GraphRecipient;\n toRecipients?: GraphRecipient[];\n ccRecipients?: GraphRecipient[];\n bccRecipients?: GraphRecipient[];\n receivedDateTime?: string;\n bodyPreview?: string;\n isRead?: boolean;\n hasAttachments?: boolean;\n body?: { contentType?: \"text\" | \"html\"; content?: string };\n}\ninterface GraphAttachment {\n id: string;\n name: string;\n contentType?: string;\n size?: number;\n}\ninterface GraphFolder {\n id: string;\n displayName: string;\n parentFolderId?: string;\n childFolderCount: number;\n totalItemCount: number;\n unreadItemCount: number;\n}\n\nfunction mapFolder(f: GraphFolder): FolderInfo {\n return {\n id: f.id,\n displayName: f.displayName,\n parentFolderId: f.parentFolderId,\n childFolderCount: f.childFolderCount,\n totalItemCount: f.totalItemCount,\n unreadItemCount: f.unreadItemCount,\n };\n}\n\nfunction mapRecipient(r: GraphRecipient): EmailAddress {\n return {\n name: r.emailAddress?.name,\n address: r.emailAddress?.address ?? \"\",\n };\n}\n\nfunction mapSummary(m: GraphMessage, folder?: string): EmailSummary {\n return {\n id: m.id,\n subject: m.subject ?? \"\",\n from: m.from ? mapRecipient(m.from) : undefined,\n to: (m.toRecipients ?? []).map(mapRecipient),\n receivedAt: m.receivedDateTime,\n preview: m.bodyPreview,\n isRead: m.isRead,\n hasAttachments: m.hasAttachments,\n folder,\n };\n}\n\nfunction toRecipient(a: EmailAddress): GraphRecipient {\n return { emailAddress: { name: a.name, address: a.address } };\n}\n\nfunction clampLimit(v: number | undefined, dflt: number, max: number): number {\n if (!v || v <= 0) return dflt;\n return Math.min(v, max);\n}\n","import \"isomorphic-fetch\";\nimport {\n Client,\n type AuthenticationProvider,\n} from \"@microsoft/microsoft-graph-client\";\n\nimport type { AccountStore, AccountRecord } from \"../../store/account-store.js\";\nimport { acquireAccessToken, type SerializedTokens } from \"./auth.js\";\n\n/**\n * Builds a Graph `Client` bound to a stored account. The client uses an\n * `AuthenticationProvider` that calls msal silently on every request, and\n * writes the (possibly-refreshed) cache back into the AccountStore.\n *\n * Clients are cached per email since the underlying SDK reuses connections.\n */\nexport class OutlookClientFactory {\n private readonly cache = new Map<string, Client>();\n\n constructor(\n private readonly store: AccountStore,\n private readonly clientId?: string,\n private readonly tenantId?: string,\n ) {}\n\n get(account: AccountRecord): Client {\n const key = account.email.toLowerCase();\n const existing = this.cache.get(key);\n if (existing) return existing;\n\n const store = this.store;\n const provider: AuthenticationProvider = {\n getAccessToken: async () => {\n const fresh = store.getAccount(account.email) ?? account;\n const tokens = fresh.tokens as unknown as SerializedTokens;\n const { accessToken, tokens: nextTokens } = await acquireAccessToken(\n tokens,\n undefined,\n this.clientId,\n this.tenantId,\n );\n // Persist refreshed cache opportunistically; failures here shouldn't\n // break the in-flight Graph call.\n if (nextTokens.msalCache !== tokens.msalCache) {\n store\n .upsertAccount({\n ...fresh,\n tokens: nextTokens as unknown as Record<string, unknown>,\n })\n .catch(() => {\n /* swallow — next call will refresh again */\n });\n }\n return accessToken;\n },\n };\n\n const client = Client.initWithMiddleware({ authProvider: provider });\n this.cache.set(key, client);\n return client;\n }\n\n /** Drop a cached client (e.g. after removeAccount). */\n invalidate(email: string): void {\n this.cache.delete(email.toLowerCase());\n }\n}\n","import {\n PublicClientApplication,\n type Configuration,\n type AuthenticationResult,\n type AccountInfo,\n} from \"@azure/msal-node\";\n\n/**\n * Public client app id. Default is the well-known `ms-365` client id used by\n * the softeria/ms-365-mcp-server project — it's a public client registered\n * for personal MSA + multi-tenant work/school. Users can override via\n * MS_CLIENT_ID for their own Entra app registrations.\n */\nconst DEFAULT_CLIENT_ID = \"084a3e9f-a9f4-43f7-89f9-d229cf97853e\";\n// ^ Pre-registered public client app (same one used by softeria/ms-365-mcp-server).\n// Supports personal MSA + multi-tenant work/school via device-code flow.\n// Operators should set MS_CLIENT_ID to a client they control for production.\n\nconst DEFAULT_SCOPES = [\n \"offline_access\",\n \"User.Read\",\n \"Mail.ReadWrite\",\n \"Mail.Send\",\n];\n\nexport interface DeviceCodeBegin {\n userCode: string;\n verificationUri: string;\n message: string;\n expiresAt: string; // ISO\n /** Resolves with the auth result once the user completes the flow. */\n result: Promise<{ tokens: SerializedTokens; account: AccountInfo }>;\n /** Aborts the in-flight polling promise. */\n cancel(): void;\n}\n\nexport interface SerializedTokens {\n /** MSAL cache JSON, encrypted at rest by the account store. */\n msalCache: string;\n /** Home account id used to look up the account in the rehydrated cache. */\n homeAccountId: string;\n /** Tenant id captured at sign-in. */\n tenantId: string;\n /** Username captured at sign-in (typically the primary email). */\n username: string;\n scopes: string[];\n}\n\nfunction makeConfig(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): Configuration {\n const clientId = clientIdOverride || process.env.MS_CLIENT_ID || DEFAULT_CLIENT_ID;\n const tenant = tenantOverride || process.env.MS_TENANT_ID || \"common\";\n return {\n auth: {\n clientId,\n authority: `https://login.microsoftonline.com/${tenant}`,\n },\n cache: prevCacheJson\n ? {\n // msal-node supports an in-memory cache plugin; we hydrate manually\n // below via deserialize after construction.\n }\n : undefined,\n };\n}\n\nexport function buildPca(prevCacheJson?: string, clientIdOverride?: string, tenantOverride?: string): PublicClientApplication {\n const pca = new PublicClientApplication(makeConfig(prevCacheJson, clientIdOverride, tenantOverride));\n if (prevCacheJson) {\n pca.getTokenCache().deserialize(prevCacheJson);\n }\n return pca;\n}\n\n/**\n * Start a device-code flow. The returned `result` promise resolves once the\n * user has entered the code and consented; callers should poll it (or await it)\n * via `complete_add_account`.\n */\nexport function beginDeviceCode(\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): DeviceCodeBegin {\n const pca = buildPca(undefined, clientIdOverride, tenantOverride);\n let resolve!: (v: { tokens: SerializedTokens; account: AccountInfo }) => void;\n let reject!: (err: unknown) => void;\n const result = new Promise<{ tokens: SerializedTokens; account: AccountInfo }>(\n (res, rej) => {\n resolve = res;\n reject = rej;\n },\n );\n\n // We capture the deviceCodeCallback synchronously to surface the user-facing\n // info back out via this object before awaiting the long-running poll.\n let userCode = \"\";\n let verificationUri = \"\";\n let message = \"\";\n let expiresAt = new Date(Date.now() + 15 * 60_000).toISOString();\n let aborted = false;\n\n const ready = new Promise<void>((r) => {\n pca\n .acquireTokenByDeviceCode({\n scopes,\n deviceCodeCallback: (info) => {\n if (!info.userCode || !info.verificationUri) {\n // MSAL may fire the callback with an empty object if the\n // downstream HTTP request fails — reject so the caller\n // gets a clear error instead of silent empty strings.\n reject(\n new Error(\n \"Microsoft device-code endpoint returned no code. \" +\n \"Check MS_CLIENT_ID is a valid Azure Entra public-client application.\",\n ),\n );\n return;\n }\n userCode = info.userCode;\n verificationUri = info.verificationUri;\n message = info.message;\n if (info.expiresIn) {\n expiresAt = new Date(Date.now() + info.expiresIn * 1000).toISOString();\n }\n r();\n },\n })\n .then((authResult: AuthenticationResult | null) => {\n if (aborted) return;\n if (!authResult || !authResult.account) {\n reject(new Error(\"device-code flow returned no account\"));\n return;\n }\n const cache = pca.getTokenCache().serialize();\n const tokens: SerializedTokens = {\n msalCache: cache,\n homeAccountId: authResult.account.homeAccountId,\n tenantId: authResult.account.tenantId,\n username: authResult.account.username,\n scopes,\n };\n resolve({ tokens, account: authResult.account });\n })\n .catch((err) => {\n if (!aborted) reject(err);\n });\n });\n\n // Surface device-code info synchronously via a wrapper Promise:\n // we return the object but its strings are populated once `ready` settles.\n // To keep the API simple, we attach a getter that callers must `await` on.\n // Instead of getters, we wait for `ready` inside the begin helper:\n return {\n // these are placeholders until ready resolves\n get userCode() {\n return userCode;\n },\n get verificationUri() {\n return verificationUri;\n },\n get message() {\n return message;\n },\n get expiresAt() {\n return expiresAt;\n },\n result,\n cancel() {\n aborted = true;\n },\n // hidden helper for the caller to await initial code\n // (typed via a cast below where used)\n ...({ _ready: ready } as Record<string, unknown>),\n } as DeviceCodeBegin;\n}\n\n/** Await `_ready` so the user-code fields are populated. */\nexport async function awaitDeviceCodeReady(b: DeviceCodeBegin): Promise<void> {\n const r = (b as unknown as { _ready: Promise<void> })._ready;\n await r;\n}\n\n/**\n * Acquire a fresh access token for a stored account, refreshing silently from\n * the persisted MSAL cache. Returns the (possibly-updated) cache so the caller\n * can write it back to the store.\n */\nexport async function acquireAccessToken(\n tokens: SerializedTokens,\n scopes: string[] = DEFAULT_SCOPES,\n clientIdOverride?: string,\n tenantOverride?: string,\n): Promise<{ accessToken: string; tokens: SerializedTokens }> {\n const pca = buildPca(tokens.msalCache, clientIdOverride, tenantOverride);\n const cache = pca.getTokenCache();\n const account =\n (await cache.getAccountByHomeId(tokens.homeAccountId)) ??\n (await cache.getAllAccounts()).find((a) => a.username === tokens.username);\n if (!account) {\n throw new Error(\"no MSAL account in cache — re-run add_account\");\n }\n const res = await pca.acquireTokenSilent({ account, scopes });\n if (!res?.accessToken) {\n throw new Error(\"acquireTokenSilent returned no access token\");\n }\n const next: SerializedTokens = {\n ...tokens,\n msalCache: cache.serialize(),\n scopes,\n };\n return { accessToken: res.accessToken, tokens: next };\n}\n","import type { AccountRecord } from \"../../store/account-store.js\";\nimport type {\n AddAccountInput,\n AddAccountResult,\n AttachmentContent,\n CompleteAddAccountResult,\n CreateFolderInput,\n DraftUpdateInput,\n EmailFull,\n EmailProvider,\n EmailSummary,\n FolderInfo,\n ListEmailsOptions,\n ListEmailsResult,\n ListFoldersOptions,\n SearchEmailsOptions,\n SendInput,\n} from \"../types.js\";\n\nconst NOT_IMPLEMENTED =\n \"IMAP provider is not yet implemented in v1. Tracked at \" +\n \"src/providers/imap/index.ts — see src/providers/types.ts for the contract.\";\n\n/**\n * Placeholder IMAP provider — registered so the contract is locked in and\n * `add_account` returns a clear \"coming soon\" error instead of \"unknown provider\".\n *\n * v2 plan: use `imapflow` + `nodemailer` (for send). Tokens shape will be\n * `{ host, port, secure, user, password|appPassword }` encrypted at rest by\n * the AccountStore, identical to how Outlook's MSAL cache is stored.\n */\nexport class ImapProvider implements EmailProvider {\n readonly id = \"imap\" as const;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async addAccount(_input: AddAccountInput): Promise<AddAccountResult> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async completeAddAccount(_handle: string): Promise<CompleteAddAccountResult> {\n return { status: \"error\", error: NOT_IMPLEMENTED };\n }\n\n async listEmails(\n _account: AccountRecord,\n _opts: ListEmailsOptions,\n ): Promise<ListEmailsResult> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async searchEmails(\n _account: AccountRecord,\n _query: string,\n _opts: SearchEmailsOptions,\n ): Promise<EmailSummary[]> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async readEmail(_account: AccountRecord, _id: string): Promise<EmailFull> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async readAttachment(\n _account: AccountRecord,\n _messageId: string,\n _attachmentId: string,\n ): Promise<AttachmentContent> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async sendEmail(\n _account: AccountRecord,\n _msg: SendInput,\n ): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async saveDraft(\n _account: AccountRecord,\n _msg: SendInput,\n ): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async updateDraft(\n _account: AccountRecord,\n _id: string,\n _update: DraftUpdateInput,\n ): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async moveEmail(\n _account: AccountRecord,\n _id: string,\n _destinationId: string,\n ): Promise<void> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async sendDraft(_account: AccountRecord, _id: string): Promise<{ id: string }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async addAttachmentToDraft(\n _account: AccountRecord,\n _draftId: string,\n _name: string,\n _contentBytes: string,\n _contentType?: string,\n ): Promise<{ id: string; attachment: { id: string; name: string; contentType?: string } }> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async markRead(\n _account: AccountRecord,\n _id: string,\n _isRead: boolean,\n ): Promise<void> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async listFolders(\n _account: AccountRecord,\n _opts: ListFoldersOptions,\n ): Promise<FolderInfo[]> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async createFolder(\n _account: AccountRecord,\n _input: CreateFolderInput,\n ): Promise<FolderInfo> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async renameFolder(\n _account: AccountRecord,\n _folderId: string,\n _newName: string,\n ): Promise<FolderInfo> {\n throw new Error(NOT_IMPLEMENTED);\n }\n\n async deleteFolder(\n _account: AccountRecord,\n _folderId: string,\n ): Promise<void> {\n throw new Error(NOT_IMPLEMENTED);\n }\n}\n","import type { AccountStore, AccountRecord } from \"../store/account-store.js\";\nimport type { EmailProvider, ProviderId } from \"./types.js\";\nimport type { ProvidersConfig } from \"../config.js\";\nimport { OutlookProvider } from \"./outlook/index.js\";\nimport { ImapProvider } from \"./imap/index.js\";\n\nexport interface Registry {\n get(id: ProviderId): EmailProvider;\n resolveByEmail(email: string): { provider: EmailProvider; account: AccountRecord };\n list(): EmailProvider[];\n}\n\nexport interface BuildRegistryOptions {\n store: AccountStore;\n providers?: ProvidersConfig;\n}\n\nexport function buildRegistry(opts: BuildRegistryOptions): Registry {\n const outlookCfg = opts.providers?.outlook;\n const providers = new Map<ProviderId, EmailProvider>();\n providers.set(\"outlook\", new OutlookProvider({\n store: opts.store,\n clientId: outlookCfg?.clientId,\n tenantId: outlookCfg?.tenantId,\n }));\n providers.set(\"imap\", new ImapProvider());\n // gmail can be added later — registry will return a clear error if asked.\n\n function get(id: ProviderId): EmailProvider {\n const p = providers.get(id);\n if (!p) throw new Error(`unknown provider: ${id}`);\n return p;\n }\n\n function resolveByEmail(email: string): {\n provider: EmailProvider;\n account: AccountRecord;\n } {\n const account = opts.store.getAccount(email);\n if (!account) {\n throw new Error(\n `no account registered for \"${email}\". Call add_account first.`,\n );\n }\n return { provider: get(account.provider), account };\n }\n\n return {\n get,\n resolveByEmail,\n list: () => Array.from(providers.values()),\n };\n}\n","import { z } from \"zod\";\nimport type { ResolvedTools } from \"../config.js\";\n\n/** JSON-stringify a value into a single MCP text content block. */\nexport function ok(\n data: unknown,\n structuredContent?: Record<string, unknown>,\n) {\n const result: {\n content: Array<{ type: \"text\"; text: string }>;\n structuredContent?: Record<string, unknown>;\n } = {\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n };\n if (structuredContent !== undefined) {\n result.structuredContent = structuredContent;\n }\n return result;\n}\n\nexport function fail(message: string) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: message }],\n };\n}\n\nexport function errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n// ── shared schemas ──\n\nexport const emailAddrSchema = z.object({\n address: z.string().email(),\n name: z.string().optional(),\n});\n\nexport const emailAddrOutputSchema = z.object({\n name: z.string().optional(),\n address: z.string(),\n});\n\nexport const accountSummaryOutputSchema = z.object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n addedAt: z.string(),\n hasSignature: z.boolean(),\n hasStyle: z.boolean(),\n});\n\nexport const emailSummaryOutputSchema = z.object({\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n});\n\nexport const attachmentMetaOutputSchema = z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n});\n\nexport const styleOutputSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n});\n\nexport const folderInfoOutputSchema = z.object({\n id: z.string(),\n displayName: z.string(),\n parentFolderId: z.string().optional(),\n childFolderCount: z.number(),\n totalItemCount: z.number(),\n unreadItemCount: z.number(),\n});\n\n// ── body composition helpers ──\n\nexport interface ComposeBodyInput {\n body: string;\n isHtml?: boolean;\n signature?: string;\n style?: { fontFamily?: string; fontSize?: string; fontColor?: string };\n includeSignature: boolean;\n}\n\nexport function composeBody(\n input: ComposeBodyInput,\n): { body: string; isHtml: boolean } {\n const { body, isHtml = false, signature, style, includeSignature } = input;\n const hasSignature = includeSignature && !!signature;\n const hasStyle = !!(\n style &&\n (style.fontFamily || style.fontSize || style.fontColor)\n );\n\n if (!hasSignature && !hasStyle) {\n return { body, isHtml };\n }\n\n const styleAttr = hasStyle ? buildStyleAttr(style!) : \"\";\n\n if (isHtml) {\n let result = hasStyle\n ? `<div style=\"${styleAttr}\">${body}</div>`\n : body;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n }\n\n const escaped = escapeHtml(body);\n let result = `<div style=\"${styleAttr}\">${escaped}</div>`;\n if (hasSignature) result += `\\n<div class=\"signature\">${signature}</div>`;\n return { body: result, isHtml: true };\n}\n\nexport function buildStyleAttr(style: {\n fontFamily?: string;\n fontSize?: string;\n fontColor?: string;\n}): string {\n const parts: string[] = [];\n if (style.fontFamily) parts.push(`font-family: ${style.fontFamily}`);\n if (style.fontSize) parts.push(`font-size: ${style.fontSize}`);\n if (style.fontColor) parts.push(`color: ${style.fontColor}`);\n return parts.join(\"; \");\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/\\n/g, \"<br>\");\n}\n\n// ── tool filtering ──\n\n/** Returns true when `name` should be registered given the tool filtering config. */\nexport function shouldRegister(\n name: string,\n tools: ResolvedTools,\n): boolean {\n if (tools.enabledTools) {\n return tools.enabledTools.has(name);\n }\n if (tools.disabledTools) {\n return !tools.disabledTools.has(name);\n }\n return true;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ProviderId } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport {\n ok,\n fail,\n errMsg,\n accountSummaryOutputSchema,\n styleOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerAccountTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n },\n): void {\n const { store, registry, tools } = ctx;\n\n // ---------- list_accounts ----------\n\n const listAccountsOutputSchema = {\n accounts: z.array(accountSummaryOutputSchema),\n };\n\n if (shouldRegister(\"list_accounts\", tools)) {\n server.registerTool(\n \"list_accounts\",\n {\n description:\n \"List all email accounts known to this server (no secrets). \" +\n \"Use the returned `email` value as the `account` argument to other tools.\",\n inputSchema: {},\n outputSchema: listAccountsOutputSchema,\n },\n async () => {\n const rows = store.listAccounts().map((a) => ({\n email: a.email,\n provider: a.provider,\n displayName: a.displayName,\n addedAt: a.addedAt,\n hasSignature: !!a.signature,\n hasStyle: !!(\n a.style &&\n (a.style.fontFamily || a.style.fontSize || a.style.fontColor)\n ),\n }));\n const data = { accounts: rows };\n return ok(data, data);\n },\n );\n }\n\n // ---------- add_account ----------\n\n const addAccountOutputSchema = z.discriminatedUnion(\"status\", [\n z.object({\n status: z.literal(\"pending\"),\n handle: z.string(),\n verification: z.object({\n userCode: z.string(),\n verificationUri: z.string(),\n expiresAt: z.string(),\n message: z.string(),\n }),\n }),\n z.object({\n status: z.literal(\"ready\"),\n account: z.object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n tokens: z.record(z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n }),\n }),\n ]);\n\n if (shouldRegister(\"add_account\", tools)) {\n server.registerTool(\n \"add_account\",\n {\n description:\n \"Start adding an email account. For Outlook this returns a device code \" +\n \"the user must enter at the verification URL; then call `complete_add_account` \" +\n \"with the returned `handle` to finalize. Disabled in --read-only mode.\",\n inputSchema: {\n provider: z\n .enum([\"outlook\", \"imap\", \"gmail\"])\n .describe(\"Email backend. v1 only fully implements 'outlook'.\"),\n email: z\n .string()\n .email()\n .optional()\n .describe(\n \"Optional hint — the provider will verify it against the auth result.\",\n ),\n config: z\n .record(z.unknown())\n .optional()\n .describe(\n \"Provider-specific config (e.g. IMAP host/port). Unused for Outlook.\",\n ),\n },\n outputSchema: addAccountOutputSchema,\n },\n async (args) => {\n const provider = registry.get(args.provider as ProviderId);\n try {\n const res = await provider.addAccount({\n email: args.email,\n config: args.config,\n });\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- complete_add_account ----------\n\n const completeAddAccountOutputSchema = z.object({\n status: z.enum([\"pending\", \"ready\", \"expired\", \"error\"]),\n account: z\n .object({\n email: z.string(),\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n displayName: z.string().optional(),\n tokens: z.record(z.unknown()),\n addedAt: z.string(),\n signature: z.string().optional(),\n style: styleOutputSchema.optional(),\n })\n .optional(),\n error: z.string().optional(),\n });\n\n if (shouldRegister(\"complete_add_account\", tools)) {\n server.registerTool(\n \"complete_add_account\",\n {\n description:\n \"Poll/finalize a pending add_account flow. Returns `pending` until the user \" +\n \"completes the device-code step, then `ready` with the persisted account.\",\n inputSchema: {\n provider: z.enum([\"outlook\", \"imap\", \"gmail\"]),\n handle: z.string().min(1),\n },\n outputSchema: completeAddAccountOutputSchema,\n },\n async (args) => {\n const provider = registry.get(args.provider as ProviderId);\n if (!provider.completeAddAccount) {\n return fail(\n `provider ${args.provider} has no async add-account flow`,\n );\n }\n try {\n const res = await provider.completeAddAccount(args.handle);\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- account settings ----------\n\n const accountSettingsOutputSchema = {\n signature: z.string().nullable(),\n style: styleOutputSchema.nullable(),\n };\n\n if (shouldRegister(\"get_account_settings\", tools)) {\n server.registerTool(\n \"get_account_settings\",\n {\n description:\n \"Get signature (HTML) and style preferences for an account.\",\n inputSchema: { account: z.string().email() },\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n const data = {\n signature: acct.signature ?? null,\n style: acct.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"set_account_settings\", tools)) {\n server.registerTool(\n \"set_account_settings\",\n {\n description:\n \"Set signature (HTML snippet) and/or style preferences for an account. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n signature: z\n .string()\n .optional()\n .describe(\n \"HTML snippet — may contain formatting, images, links. Pass null to clear.\",\n ),\n style: z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.string().optional(),\n fontColor: z.string().optional(),\n })\n .optional()\n .describe(\n \"Font preferences applied to outgoing HTML emails. Pass null to clear.\",\n ),\n },\n outputSchema: accountSettingsOutputSchema,\n },\n async (args) => {\n try {\n const acct = store.getAccount(args.account);\n if (!acct)\n return fail(`no account registered for \"${args.account}\"`);\n const updated = await store.upsertAccount({\n ...acct,\n signature: args.signature ?? acct.signature,\n style: args.style ?? acct.style,\n });\n const data = {\n signature: updated.signature ?? null,\n style: updated.style ?? null,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- remove_account ----------\n\n const removeAccountOutputSchema = {\n removed: z.boolean(),\n email: z.string(),\n };\n\n if (shouldRegister(\"remove_account\", tools)) {\n server.registerTool(\n \"remove_account\",\n {\n description:\n \"Forget an account and delete its stored tokens. Disabled in --read-only mode.\",\n inputSchema: { email: z.string().email() },\n outputSchema: removeAccountOutputSchema,\n },\n async (args) => {\n const removed = await store.removeAccount(args.email);\n const data = { removed, email: args.email };\n return ok(data, data);\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport { selectBody } from \"../html-to-markdown.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrOutputSchema,\n emailSummaryOutputSchema,\n attachmentMetaOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerBrowseTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n },\n): void {\n const { registry, tools } = ctx;\n\n // ---------- email ops ----------\n\n const emailListOutputSchema = {\n account: z.string(),\n count: z.number(),\n items: z.array(emailSummaryOutputSchema),\n skip: z.number(),\n hasMore: z.boolean(),\n };\n\n if (shouldRegister(\"list_emails\", tools)) {\n server.registerTool(\n \"list_emails\",\n {\n description:\n \"List recent emails in a folder of the given account. Pass the user's email \" +\n \"address as `account`; the server routes to the correct backend automatically.\",\n inputSchema: {\n account: z.string().email(),\n folder: z.string().default(\"inbox\").optional(),\n limit: z.number().int().positive().max(100).optional(),\n unreadOnly: z.boolean().optional(),\n skip: z.number().int().min(0).optional(),\n },\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const { items, hasMore } = await provider.listEmails(account, {\n folder: args.folder,\n limit: args.limit,\n unreadOnly: args.unreadOnly,\n skip: args.skip,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n skip: args.skip ?? 0,\n hasMore,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"search_emails\", tools)) {\n server.registerTool(\n \"search_emails\",\n {\n description:\n \"Search emails by free-text query (KQL on Outlook). Returns lightweight summaries.\",\n inputSchema: {\n account: z.string().email(),\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n },\n outputSchema: emailListOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.searchEmails(account, args.query, {\n limit: args.limit,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readEmailOutputSchema = {\n id: z.string(),\n subject: z.string(),\n from: emailAddrOutputSchema.optional(),\n to: z.array(emailAddrOutputSchema).optional(),\n cc: z.array(emailAddrOutputSchema).optional(),\n bcc: z.array(emailAddrOutputSchema).optional(),\n receivedAt: z.string().optional(),\n preview: z.string().optional(),\n isRead: z.boolean().optional(),\n hasAttachments: z.boolean().optional(),\n folder: z.string().optional(),\n attachments: z.array(attachmentMetaOutputSchema).optional(),\n body: z.string(),\n bodyFormat: z.enum([\"markdown\", \"html\", \"text\"]),\n };\n\n if (shouldRegister(\"read_email\", tools)) {\n server.registerTool(\n \"read_email\",\n {\n description:\n \"Fetch a single email with full body and recipients by id. \" +\n \"Body is returned as `body` with `bodyFormat` indicating the format. \" +\n \"Default format is 'markdown' — HTML is automatically converted to save context tokens.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1),\n format: z\n .enum([\"markdown\", \"html\", \"text\"])\n .default(\"markdown\")\n .optional()\n .describe(\n \"Output body format. 'markdown' converts HTML to Markdown (default), \" +\n \"'html' returns the raw HTML, 'text' returns plain text.\",\n ),\n },\n outputSchema: readEmailOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const msg = await provider.readEmail(account, args.id);\n const format = args.format ?? \"markdown\";\n const body = selectBody(msg, format);\n const data = {\n id: msg.id,\n subject: msg.subject,\n from: msg.from,\n to: msg.to,\n cc: msg.cc,\n bcc: msg.bcc,\n receivedAt: msg.receivedAt,\n preview: msg.preview,\n isRead: msg.isRead,\n hasAttachments: msg.hasAttachments,\n folder: msg.folder,\n attachments: msg.attachments,\n body,\n bodyFormat: format,\n };\n return ok(data, data as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n const readAttachmentOutputSchema = {\n name: z.string(),\n contentType: z.string().optional(),\n path: z.string(),\n };\n\n if (shouldRegister(\"read_attachment\", tools)) {\n server.registerTool(\n \"read_attachment\",\n {\n description:\n \"Download an email attachment to a temporary file and return its path. \" +\n \"Use messageId and attachmentId from a prior read_email call.\",\n inputSchema: {\n account: z.string().email(),\n messageId: z.string().min(1),\n attachmentId: z.string().min(1),\n },\n outputSchema: readAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.readAttachment(\n account,\n args.messageId,\n args.attachmentId,\n );\n return ok(res, res as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import TurndownService from \"turndown\";\n\nconst turndown = new TurndownService();\n\n/** Light wrapper — callers just pass HTML, get markdown back. */\nexport function htmlToMarkdown(html: string): string {\n return turndown.turndown(html);\n}\n\n/** Pick the right body for the requested format. */\nexport function selectBody(\n msg: { bodyHtml?: string; bodyText?: string },\n format: \"markdown\" | \"html\" | \"text\",\n): string {\n switch (format) {\n case \"markdown\": {\n if (msg.bodyHtml) return htmlToMarkdown(msg.bodyHtml);\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"html\": {\n if (msg.bodyHtml) return msg.bodyHtml;\n if (msg.bodyText) return msg.bodyText;\n return \"\";\n }\n case \"text\": {\n if (msg.bodyText) return msg.bodyText;\n if (msg.bodyHtml) return msg.bodyHtml.replace(/<[^>]*>/g, \"\");\n return \"\";\n }\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport {\n ok,\n fail,\n errMsg,\n folderInfoOutputSchema,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerFolderTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n },\n): void {\n const { registry, tools } = ctx;\n\n // ---------- list_folders ----------\n\n const listFoldersOutputSchema = {\n account: z.string(),\n count: z.number(),\n items: z.array(folderInfoOutputSchema),\n };\n\n if (shouldRegister(\"list_folders\", tools)) {\n server.registerTool(\n \"list_folders\",\n {\n description:\n \"List available mail folders. Returns top-level folders by default, \" +\n \"or child folders of the given parent when `parentFolderId` is provided.\",\n inputSchema: {\n account: z.string().email(),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, lists child folders of this folder. \" +\n \"When omitted, lists top-level folders (children of the root).\",\n ),\n },\n outputSchema: listFoldersOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const items = await provider.listFolders(account, {\n parentFolderId: args.parentFolderId,\n });\n const data = {\n account: account.email,\n count: items.length,\n items,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- create_folder ----------\n\n const createFolderOutputSchema = {\n created: z.literal(true),\n folder: folderInfoOutputSchema,\n };\n\n if (shouldRegister(\"create_folder\", tools)) {\n server.registerTool(\n \"create_folder\",\n {\n description:\n \"Create a new mail folder. Creates under the root folder by default, \" +\n \"or under the specified parent when `parentFolderId` is provided. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n displayName: z\n .string()\n .min(1)\n .describe(\"Name of the new folder\"),\n parentFolderId: z\n .string()\n .optional()\n .describe(\n \"When provided, creates the folder as a child of this folder. \" +\n \"When omitted, creates under the root folder.\",\n ),\n },\n outputSchema: createFolderOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.createFolder(account, {\n displayName: args.displayName,\n parentFolderId: args.parentFolderId,\n });\n const data = { created: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- delete_folder ----------\n\n const deleteFolderOutputSchema = {\n deleted: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"delete_folder\", tools)) {\n server.registerTool(\n \"delete_folder\",\n {\n description:\n \"Delete a mail folder by ID. Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to delete\"),\n },\n outputSchema: deleteFolderOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.deleteFolder(account, args.folderId);\n const data = { deleted: true as const, id: args.folderId };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- rename_folder ----------\n\n const renameFolderOutputSchema = {\n renamed: z.literal(true),\n folder: folderInfoOutputSchema,\n };\n\n if (shouldRegister(\"rename_folder\", tools)) {\n server.registerTool(\n \"rename_folder\",\n {\n description:\n \"Rename an existing mail folder. Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n folderId: z\n .string()\n .min(1)\n .describe(\"ID of the folder to rename\"),\n newName: z\n .string()\n .min(1)\n .describe(\"New display name for the folder\"),\n },\n outputSchema: renameFolderOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const folder = await provider.renameFolder(\n account,\n args.folderId,\n args.newName,\n );\n const data = { renamed: true as const, folder };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport { ok, fail, errMsg, shouldRegister } from \"./shared.js\";\n\nexport function registerOrganizeTools(\n server: McpServer,\n ctx: {\n registry: Registry;\n tools: ResolvedTools;\n },\n): void {\n const { registry, tools } = ctx;\n\n // ---------- archive ----------\n\n const archiveMoveSchema = {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n };\n\n const archiveOutputSchema = {\n archived: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"archive_email\", tools)) {\n server.registerTool(\n \"archive_email\",\n {\n description:\n \"Move a message to the Archive folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: archiveOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, \"archive\");\n const data = { archived: true as const, id: args.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- trash ----------\n\n const trashOutputSchema = {\n trashed: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"trash_email\", tools)) {\n server.registerTool(\n \"trash_email\",\n {\n description:\n \"Move a message to the Deleted Items (trash) folder. Disabled in --read-only mode.\",\n inputSchema: archiveMoveSchema,\n outputSchema: trashOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, \"deleteditems\");\n const data = { trashed: true as const, id: args.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- move ----------\n\n const moveEmailOutputSchema = {\n moved: z.literal(true),\n id: z.string(),\n destination: z.string(),\n };\n\n if (shouldRegister(\"move_email\", tools)) {\n server.registerTool(\n \"move_email\",\n {\n description:\n \"Move a message to any folder by well-known name (e.g. 'inbox', 'drafts', \" +\n \"'junkemail', 'sentitems', 'outbox') or custom folder ID. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to move\"),\n destination: z\n .string()\n .min(1)\n .describe(\n \"Destination folder — a well-known folder name \" +\n \"('archive', 'deleteditems', 'inbox', 'drafts', 'junkemail', \" +\n \"'sentitems', 'outbox') or a raw folder ID.\",\n ),\n },\n outputSchema: moveEmailOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.moveEmail(account, args.id, args.destination);\n const data = {\n moved: true as const,\n id: args.id,\n destination: args.destination,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- mark_read / mark_unread ----------\n\n const markReadInputSchema = {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Message ID to mark as read\"),\n };\n\n const markReadOutputSchema = {\n marked: z.literal(true),\n id: z.string(),\n isRead: z.boolean(),\n };\n\n if (shouldRegister(\"mark_read\", tools)) {\n server.registerTool(\n \"mark_read\",\n {\n description:\n \"Mark a message as read. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.markRead(account, args.id, true);\n const data = {\n marked: true as const,\n id: args.id,\n isRead: true,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n if (shouldRegister(\"mark_unread\", tools)) {\n server.registerTool(\n \"mark_unread\",\n {\n description:\n \"Mark a message as unread. Disabled in --read-only mode.\",\n inputSchema: markReadInputSchema,\n outputSchema: markReadOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n await provider.markRead(account, args.id, false);\n const data = {\n marked: true as const,\n id: args.id,\n isRead: false,\n };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport type { AccountRecord, AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { EmailProvider, SendInput } from \"../providers/types.js\";\nimport type { ResolvedTools } from \"../config.js\";\nimport {\n ok,\n fail,\n errMsg,\n emailAddrSchema,\n composeBody,\n shouldRegister,\n} from \"./shared.js\";\n\nexport function registerComposeTools(\n server: McpServer,\n ctx: {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n },\n): void {\n const { store, registry, tools } = ctx;\n\n const sendEmailSchema = z.object({\n account: z.string().email(),\n to: z.array(emailAddrSchema).min(1),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string(),\n body: z.string(),\n isHtml: z.boolean().optional(),\n include_signature: z\n .boolean()\n .describe(\n \"Whether to append the account's saved HTML signature to the email. \" +\n \"If true, don't include a signature in the body param to avoid double signature. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n inReplyTo: z\n .string()\n .optional()\n .describe(\n \"Message ID to reply to. When set, sends as a threaded reply \" +\n \"which includes the quoted thread history automatically.\",\n ),\n replyAll: z\n .boolean()\n .default(false)\n .optional()\n .describe(\n \"When true and `inReplyTo` is set, reply to all recipients \" +\n \"instead of just the sender.\",\n ),\n forwardMessageId: z\n .string()\n .optional()\n .describe(\n \"Message ID to forward. When set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"Mutually exclusive with `inReplyTo`.\",\n ),\n });\n\n type SendEmailArgs = z.infer<typeof sendEmailSchema>;\n\n async function handleSendOrDraft(\n args: SendEmailArgs,\n action: (\n provider: EmailProvider,\n account: AccountRecord,\n msg: SendInput,\n ) => Promise<{ id: string }>,\n resultKey: string,\n toolName: string,\n ) {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n if (args.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n const composed = composeBody({\n body: args.body,\n isHtml: args.isHtml,\n signature: account.signature,\n style: account.style,\n includeSignature: args.include_signature,\n });\n if (args.inReplyTo && args.forwardMessageId) {\n return fail(\n \"inReplyTo and forwardMessageId are mutually exclusive — use one or the other\",\n );\n }\n const res = await action(provider, account, {\n to: args.to,\n cc: args.cc,\n bcc: args.bcc,\n subject: args.subject,\n body: composed.body,\n isHtml: composed.isHtml,\n inReplyTo: args.inReplyTo,\n replyAll: args.replyAll,\n forwardMessageId: args.forwardMessageId,\n });\n const result: Record<string, unknown> = { [resultKey]: true, ...res };\n if (toolName === \"draft_email\" && res.id) {\n const draft = await provider.readEmail(account, res.id);\n result.draftHtml = draft.bodyHtml;\n }\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n }\n\n // ---------- send_email ----------\n\n const sendEmailOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_email\", tools)) {\n server.registerTool(\n \"send_email\",\n {\n description:\n \"Send an email from the given account. Appends the \" +\n \"account's signature (HTML) and applies style preferences when \" +\n \"`include_signature` is true. Returns an error if \" +\n \"`include_signature` is true but no signature is configured. \" +\n \"When `inReplyTo` is set, sends as a reply (or reply-all) which \" +\n \"preserves thread history and conversation threading. \" +\n \"When `forwardMessageId` is set, sends as a forward of the \" +\n \"specified message, preserving the original content. \" +\n \"`inReplyTo` and `forwardMessageId` are mutually exclusive. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: sendEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.sendEmail(a, m),\n \"sent\",\n \"send_email\",\n ),\n );\n }\n\n // ---------- draft_email ----------\n\n const draftEmailOutputSchema = {\n draft: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"draft_email\", tools)) {\n server.registerTool(\n \"draft_email\",\n {\n description:\n \"Create a draft email from the given account without sending it. \" +\n \"Works identically to send_email — appends signature when \" +\n \"`include_signature` is true, applies style, and supports replies \" +\n \"and forwards — but saves the message to the Drafts folder \" +\n \"instead of sending. Returns the draft message ID and the draft's \" +\n \"HTML body content (`draftHtml`). Before sending the draft, \" +\n \"inspect `draftHtml` to verify the draft looks correct: no \" +\n \"duplicate signature blocks, no broken or missing inline images, \" +\n \"no malformed HTML, and no other formatting issues. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: sendEmailSchema,\n outputSchema: draftEmailOutputSchema,\n },\n async (args) =>\n handleSendOrDraft(\n args as SendEmailArgs,\n (p, a, m) => p.saveDraft(a, m),\n \"draft\",\n \"draft_email\",\n ),\n );\n }\n\n // ---------- edit_draft ----------\n\n const editDraftSchema = z.object({\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to edit\"),\n to: z.array(emailAddrSchema).optional(),\n cc: z.array(emailAddrSchema).optional(),\n bcc: z.array(emailAddrSchema).optional(),\n subject: z.string().optional(),\n body: z.string().optional(),\n isHtml: z.boolean().optional(),\n include_signature: z\n .boolean()\n .optional()\n .describe(\n \"Whether to re-apply the account's saved HTML signature to the body. \" +\n \"If true, don't include a signature in the body param. \" +\n \"Only meaningful when `body` is also provided. \" +\n \"Returns an error if true but no signature is configured for this account.\",\n ),\n });\n\n type EditDraftArgs = z.infer<typeof editDraftSchema>;\n\n const editDraftOutputSchema = {\n edited: z.literal(true),\n id: z.string(),\n draftHtml: z.string().optional(),\n };\n\n if (shouldRegister(\"edit_draft\", tools)) {\n server.registerTool(\n \"edit_draft\",\n {\n description:\n \"Edit an existing draft email by ID. Only the fields you provide \" +\n \"are updated — unmentioned fields stay unchanged. When `body` is \" +\n \"provided and `include_signature` is true, the account's signature \" +\n \"is re-applied. Returns the draft ID and the draft's updated HTML \" +\n \"body content (`draftHtml`). Before sending, inspect `draftHtml` \" +\n \"to verify the draft looks correct. \" +\n \"Does not support changing `inReplyTo` or `forwardMessageId` — \" +\n \"those are set at creation time via `draft_email`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: editDraftSchema,\n outputSchema: editDraftOutputSchema,\n },\n async (args) => {\n const a = args as EditDraftArgs;\n try {\n const { provider, account } = registry.resolveByEmail(a.account);\n if (a.include_signature && !account.signature) {\n return fail(\n \"include_signature is true but no signature is configured for this account. \" +\n \"Set up a signature first with set_account_settings.\",\n );\n }\n let bodyPayload: string | undefined;\n let isHtmlPayload: boolean | undefined;\n if (a.body !== undefined) {\n const composed = composeBody({\n body: a.body,\n isHtml: a.isHtml,\n signature: account.signature,\n style: account.style,\n includeSignature: !!a.include_signature,\n });\n bodyPayload = composed.body;\n isHtmlPayload = composed.isHtml;\n }\n const res = await provider.updateDraft(account, a.id, {\n to: a.to,\n cc: a.cc,\n bcc: a.bcc,\n subject: a.subject,\n body: bodyPayload,\n isHtml: isHtmlPayload,\n });\n const draft = await provider.readEmail(account, res.id);\n const result: Record<string, unknown> = {\n edited: true as const,\n id: res.id,\n draftHtml: draft.bodyHtml,\n };\n return ok(result, result);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- send_draft ----------\n\n const sendDraftOutputSchema = {\n sent: z.literal(true),\n id: z.string(),\n };\n\n if (shouldRegister(\"send_draft\", tools)) {\n server.registerTool(\n \"send_draft\",\n {\n description:\n \"Send an existing draft email by ID. \" +\n \"Use this with draft IDs returned by `draft_email` or `edit_draft`. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID to send\"),\n },\n outputSchema: sendDraftOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.sendDraft(account, args.id);\n const data = { sent: true as const, id: res.id };\n return ok(data, data);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n\n // ---------- add_attachment_to_draft ----------\n\n const addAttachmentOutputSchema = {\n attached: z.literal(true),\n id: z.string(),\n attachment: z.object({\n id: z.string(),\n name: z.string(),\n contentType: z.string().optional(),\n }),\n };\n\n if (shouldRegister(\"add_attachment_to_draft\", tools)) {\n server.registerTool(\n \"add_attachment_to_draft\",\n {\n description:\n \"Add a file attachment to an existing draft email by ID. \" +\n \"`contentBytes` must be base64-encoded file content. \" +\n \"`contentType` is the MIME type (e.g. 'application/pdf'); \" +\n \"defaults to 'application/octet-stream' if omitted. \" +\n \"Disabled in --read-only mode.\",\n inputSchema: {\n account: z.string().email(),\n id: z.string().min(1).describe(\"Draft message ID\"),\n name: z\n .string()\n .min(1)\n .describe(\"Attachment filename (e.g. 'report.pdf')\"),\n contentBytes: z\n .string()\n .min(1)\n .describe(\"Base64-encoded file content\"),\n contentType: z\n .string()\n .optional()\n .describe(\"MIME type (e.g. 'application/pdf')\"),\n },\n outputSchema: addAttachmentOutputSchema,\n },\n async (args) => {\n try {\n const { provider, account } = registry.resolveByEmail(args.account);\n const res = await provider.addAttachmentToDraft(\n account,\n args.id,\n args.name,\n args.contentBytes,\n args.contentType,\n );\n const data = {\n attached: true as const,\n id: res.id,\n attachment: res.attachment,\n };\n return ok(data, data as unknown as Record<string, unknown>);\n } catch (err) {\n return fail(errMsg(err));\n }\n },\n );\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport type { AccountStore } from \"../store/account-store.js\";\nimport type { Registry } from \"../providers/registry.js\";\nimport type { ResolvedTools } from \"../config.js\";\n\n// Re-export compose helpers for tests\nexport { composeBody, escapeHtml, buildStyleAttr } from \"./shared.js\";\n\n// Submodule registration functions\nimport { registerAccountTools } from \"./accounts.js\";\nimport { registerBrowseTools } from \"./browse.js\";\nimport { registerFolderTools } from \"./folders.js\";\nimport { registerOrganizeTools } from \"./organize.js\";\nimport { registerComposeTools } from \"./compose.js\";\n\nexport interface RegisterToolsOptions {\n store: AccountStore;\n registry: Registry;\n tools: ResolvedTools;\n}\n\nexport function registerTools(\n server: McpServer,\n opts: RegisterToolsOptions,\n): void {\n const { store, registry, tools } = opts;\n\n registerAccountTools(server, { store, registry, tools });\n registerBrowseTools(server, { store: store, registry, tools });\n registerFolderTools(server, { registry, tools });\n registerOrganizeTools(server, { registry, tools });\n registerComposeTools(server, { store, registry, tools });\n}\n","export const VERSION = \"0.3.0\";\n","import { readFileSync } from \"node:fs\";\nimport { z } from \"zod\";\n\n// ── Schema ──\n\nconst httpConfigSchema = z.object({\n enabled: z.boolean().default(false),\n port: z.number().int().min(1).max(65535).default(3000),\n host: z.string().default(\"127.0.0.1\"),\n});\n\nconst toolsConfigSchema = z.object({\n disabled: z.array(z.string()).optional(),\n enabled: z.array(z.string()).optional(),\n});\n\nconst outlookProviderSchema = z.object({\n clientId: z.string().optional(),\n tenantId: z.string().optional(),\n});\n\nconst providersConfigSchema = z.object({\n outlook: outlookProviderSchema.optional(),\n});\n\nconst rawConfigSchema = z.object({\n dataDir: z.string().optional(),\n http: httpConfigSchema.optional(),\n tools: toolsConfigSchema.optional(),\n providers: providersConfigSchema.optional(),\n});\n\n// ── Types ──\n\nexport interface HttpConfig {\n enabled: boolean;\n port: number;\n host: string;\n}\n\nexport interface ToolsConfig {\n disabled?: string[];\n enabled?: string[];\n}\n\nexport interface OutlookProviderConfig {\n clientId?: string;\n tenantId?: string;\n}\n\nexport interface ProvidersConfig {\n outlook?: OutlookProviderConfig;\n}\n\n/** Fully resolved application configuration (after ${VAR} expansion and CLI merge). */\nexport interface AppConfig {\n dataDir?: string;\n http: HttpConfig;\n tools?: ToolsConfig;\n providers?: ProvidersConfig;\n}\n\n/** CLI flags that can override config file values. */\nexport interface CliOverrides {\n http?: boolean;\n port?: number;\n host?: string;\n dataDir?: string;\n}\n\n// ── Known tool names ──\n\n/**\n * Every tool that {@link registerTools} may register.\n * Used for validation — typos in tools.disabled / tools.enabled are caught at startup.\n */\nexport const KNOWN_TOOLS = [\n \"list_accounts\",\n \"add_account\",\n \"complete_add_account\",\n \"get_account_settings\",\n \"set_account_settings\",\n \"remove_account\",\n \"list_emails\",\n \"search_emails\",\n \"read_email\",\n \"read_attachment\",\n \"archive_email\",\n \"trash_email\",\n \"move_email\",\n \"mark_read\",\n \"mark_unread\",\n \"list_folders\",\n \"create_folder\",\n \"delete_folder\",\n \"rename_folder\",\n \"send_email\",\n \"draft_email\",\n \"edit_draft\",\n \"send_draft\",\n \"add_attachment_to_draft\",\n] as const;\n\n// ── ${VAR} resolution ──\n\nconst ENV_VAR_RE = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\n\nfunction resolveEnvVars(value: string): string {\n return value.replace(ENV_VAR_RE, (_match, name: string) => {\n return process.env[name] ?? \"\";\n });\n}\n\n/** Recursively resolve `${VAR}` placeholders in all string values. */\nfunction deepResolve(obj: unknown): unknown {\n if (typeof obj === \"string\") return resolveEnvVars(obj);\n if (Array.isArray(obj)) return obj.map(deepResolve);\n if (obj && typeof obj === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as Record<string, unknown>)) {\n out[key] = deepResolve(val);\n }\n return out;\n }\n return obj;\n}\n\n// ── Validation ──\n\nfunction validateToolNames(\n toolNames: string[] | undefined,\n listName: string,\n): void {\n if (!toolNames || toolNames.length === 0) return;\n const known = new Set<string>(KNOWN_TOOLS as readonly string[]);\n for (const name of toolNames) {\n if (!known.has(name)) {\n throw new Error(\n `Unknown tool \"${name}\" in ${listName}. Known tools: ${KNOWN_TOOLS.join(\", \")}`,\n );\n }\n }\n}\n\n// ── Loading ──\n\n/**\n * Load and validate `hypermail-config.json`.\n *\n * @param configPath File path, or `undefined` to use defaults.\n * @param cliOverrides CLI flags that take precedence over config file values.\n * @returns A fully resolved {@link AppConfig}.\n */\nexport function loadConfig(\n configPath: string | undefined,\n cliOverrides: CliOverrides = {},\n): AppConfig {\n let raw: Record<string, unknown> = {};\n\n if (configPath) {\n try {\n raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch (err) {\n const detail =\n err instanceof SyntaxError\n ? \"Invalid JSON\"\n : err instanceof Error\n ? err.message\n : String(err);\n throw new Error(`Failed to read config file \"${configPath}\": ${detail}`);\n }\n }\n\n // Resolve ${VAR} before zod validation so env-var references become real values.\n raw = deepResolve(raw) as Record<string, unknown>;\n\n // Validate structure\n const parsed = rawConfigSchema.parse(raw);\n\n // Manual validations that go beyond zod's capabilities\n if (parsed.tools) {\n if (parsed.tools.disabled && parsed.tools.enabled) {\n throw new Error(\n \"tools.disabled and tools.enabled are mutually exclusive — use one or the other\",\n );\n }\n if (parsed.tools.enabled !== undefined && parsed.tools.enabled.length === 0) {\n throw new Error(\n \"tools.enabled is empty — at least one tool must be listed. \" +\n \"To enable all tools, omit the tools section entirely.\",\n );\n }\n validateToolNames(parsed.tools.disabled, \"tools.disabled\");\n validateToolNames(parsed.tools.enabled, \"tools.enabled\");\n }\n\n // Merge CLI overrides on top of config file values\n const http: HttpConfig = {\n enabled: cliOverrides.http ?? parsed.http?.enabled ?? false,\n port: cliOverrides.port ?? parsed.http?.port ?? 3000,\n host: cliOverrides.host ?? parsed.http?.host ?? \"127.0.0.1\",\n };\n\n return {\n dataDir:\n cliOverrides.dataDir ??\n parsed.dataDir ??\n process.env.HYPERMAIL_MCP_DATA_DIR,\n http,\n tools: parsed.tools\n ? { disabled: parsed.tools.disabled, enabled: parsed.tools.enabled }\n : undefined,\n providers: parsed.providers as ProvidersConfig | undefined,\n };\n}\n\n// ── Helpers ──\n\n/** Extracted tool filtering state for {@link registerTools}. */\nexport interface ResolvedTools {\n /** If set, only these tools are registered (allowlist mode). */\n enabledTools: Set<string> | null;\n /** If set, these tools are NOT registered (blocklist mode). */\n disabledTools: Set<string> | null;\n}\n\n/** Convert {@link AppConfig.tools} into the sets that {@link registerTools} consumes. */\nexport function resolveTools(config: AppConfig): ResolvedTools {\n if (!config.tools) {\n return { enabledTools: null, disabledTools: null };\n }\n return {\n enabledTools: config.tools.enabled\n ? new Set(config.tools.enabled)\n : null,\n disabledTools: config.tools.disabled\n ? new Set(config.tools.disabled)\n : null,\n };\n}\n","import { startServer } from \"./server.js\";\nimport { loadConfig } from \"./config.js\";\n\ntype ParsedArgs = {\n http: boolean;\n port: number;\n host: string;\n dataDir?: string;\n config?: string;\n help: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {\n http: false,\n port: 3000,\n host: \"127.0.0.1\",\n help: false,\n };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n switch (a) {\n case \"--http\":\n out.http = true;\n break;\n case \"--port\":\n out.port = Number(argv[++i] ?? \"3000\");\n break;\n case \"--host\":\n out.host = String(argv[++i] ?? \"127.0.0.1\");\n break;\n case \"--data-dir\":\n out.dataDir = String(argv[++i] ?? \"\");\n break;\n case \"--config\":\n out.config = String(argv[++i] ?? \"\");\n break;\n case \"-h\":\n case \"--help\":\n out.help = true;\n break;\n default:\n if (a && a.startsWith(\"--\")) {\n // ignore unknown flags rather than crashing — keeps the CLI forgiving\n // when embedded in MCP host configs.\n }\n }\n }\n return out;\n}\n\nfunction printHelp(): void {\n const msg = `hypermail-mcp — unified email MCP server\n\nUsage:\n hypermail-mcp [options]\n\nOptions:\n --http Run as Streamable HTTP server (default: stdio)\n --port <n> HTTP port (default: 3000)\n --host <addr> HTTP bind address (default: 127.0.0.1)\n --data-dir <path> Where to store the encrypted accounts file\n (default: $HYPERMAIL_MCP_DATA_DIR or ~/.hypermail-mcp)\n --config <path> Path to hypermail-config.json\n -h, --help Show this help\n\nConfiguration:\n All server settings (data dir, HTTP, tool filtering, provider credentials)\n live in hypermail-config.json. Pass it via --config.\n\nExample hypermail-config.json:\n {\n \"dataDir\": \"/path/to/data\",\n \"http\": { \"enabled\": false },\n \"tools\": { \"disabled\": [\"send_email\"] },\n \"providers\": {\n \"outlook\": { \"clientId\": \"\\${MS_CLIENT_ID}\", \"tenantId\": \"\\${MS_TENANT_ID}\" }\n }\n }\n`;\n process.stdout.write(msg);\n}\n\nasync function main(): Promise<void> {\n const opts = parseArgs(process.argv.slice(2));\n if (opts.help) {\n printHelp();\n return;\n }\n\n const config = loadConfig(opts.config, {\n http: opts.http,\n port: opts.port,\n host: opts.host,\n dataDir: opts.dataDir,\n });\n\n await startServer({ config });\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[hypermail-mcp] fatal:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":["randomUUID","result","z","z","z","z","z","z","z","z","z","z","z","randomUUID"]}