mailcue-mcp 0.1.0 → 0.1.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/index.js CHANGED
@@ -35,7 +35,12 @@ function isLocked(config) {
35
35
 
36
36
  // src/server.ts
37
37
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
38
- import { Mailcue, MailcueError } from "mailcue";
38
+ import {
39
+ AuthenticationError,
40
+ AuthorizationError,
41
+ Mailcue,
42
+ MailcueError
43
+ } from "mailcue";
39
44
  import { z } from "zod";
40
45
 
41
46
  // src/format.ts
@@ -187,8 +192,22 @@ function text(value) {
187
192
  function toolError(message) {
188
193
  return { content: [{ type: "text", text: message }], isError: true };
189
194
  }
195
+ var MISSING_SCOPE_RE = /required '([^']+)' permission/;
190
196
  function describeError(err) {
191
197
  if (err instanceof ToolError) return err.message;
198
+ if (err instanceof AuthorizationError) {
199
+ const scope = err.scope ?? MISSING_SCOPE_RE.exec(err.message)?.[1];
200
+ if (scope) {
201
+ return `Permission denied: this MailCue API key does not have the "${scope}" permission required for this action. Use a key that includes it, or ask the key owner to grant it. This will not succeed on retry.`;
202
+ }
203
+ if (/mailbox/i.test(err.message)) {
204
+ return "Permission denied: this MailCue API key is restricted to specific mailboxes and is not allowed to access this one. Use an allowed mailbox, or ask the key owner to widen the key. This will not succeed on retry.";
205
+ }
206
+ return `Permission denied: ${err.message}. This will not succeed on retry.`;
207
+ }
208
+ if (err instanceof AuthenticationError) {
209
+ return "Authentication failed: the MailCue API key or bearer token is missing or invalid. Check the MAILCUE_API_KEY / MAILCUE_BEARER_TOKEN configuration.";
210
+ }
192
211
  if (err instanceof MailcueError) {
193
212
  const status = err.status ? ` (HTTP ${err.status})` : "";
194
213
  return `MailCue request failed${status}: ${err.message}`;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/server.ts","../src/format.ts","../src/instructions.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nimport { ConfigError, isLocked, loadConfig } from './config.js';\nimport { buildServer } from './server.js';\n\nfunction logStderr(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\nasync function main(): Promise<void> {\n let config;\n try {\n config = loadConfig();\n } catch (err) {\n if (err instanceof ConfigError) {\n logStderr(`mailcue-mcp: ${err.message}`);\n process.exit(1);\n }\n throw err;\n }\n\n const server = buildServer(config);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const scope = isLocked(config) ? `locked to ${config.mailbox}` : 'multi-mailbox';\n logStderr(`mailcue-mcp ready on stdio — ${config.baseUrl} (${scope})`);\n}\n\nmain().catch((err) => {\n logStderr(`mailcue-mcp: fatal: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n","/**\n * Configuration is read entirely from the environment so the server can be\n * dropped into any MCP client config block without code changes.\n *\n * MAILCUE_BASE_URL MailCue server URL (default http://localhost:8088)\n * MAILCUE_API_KEY X-API-Key credential (mc_...)\n * MAILCUE_BEARER_TOKEN JWT alternative to MAILCUE_API_KEY\n * MAILCUE_MAILBOX optional. When set, the agent is locked to this one\n * mailbox: every tool operates on it, the `mailbox`\n * argument disappears, and cross-mailbox tools are not\n * registered at all.\n */\n\nconst DEFAULT_BASE_URL = 'http://localhost:8088';\n\nexport interface McpConfig {\n baseUrl: string;\n apiKey?: string;\n bearerToken?: string;\n /** When set, the server runs in single-mailbox (locked) mode. */\n mailbox?: string;\n}\n\nexport class ConfigError extends Error {}\n\nfunction clean(value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n return trimmed === '' ? undefined : trimmed;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): McpConfig {\n const apiKey = clean(env['MAILCUE_API_KEY']);\n const bearerToken = clean(env['MAILCUE_BEARER_TOKEN']);\n\n if (!apiKey && !bearerToken) {\n throw new ConfigError(\n 'Missing credentials: set MAILCUE_API_KEY (preferred) or MAILCUE_BEARER_TOKEN.',\n );\n }\n\n const config: McpConfig = {\n baseUrl: clean(env['MAILCUE_BASE_URL']) ?? DEFAULT_BASE_URL,\n };\n if (apiKey) config.apiKey = apiKey;\n if (bearerToken) config.bearerToken = bearerToken;\n\n const mailbox = clean(env['MAILCUE_MAILBOX']);\n if (mailbox) config.mailbox = mailbox;\n\n return config;\n}\n\nexport function isLocked(config: McpConfig): config is McpConfig & { mailbox: string } {\n return typeof config.mailbox === 'string';\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { Mailcue, MailcueError, type SendEmailParams } from 'mailcue';\nimport { z, type ZodRawShape } from 'zod';\n\nimport { isLocked, type McpConfig } from './config.js';\nimport {\n formatEmail,\n formatList,\n formatMailboxes,\n formatStats,\n} from './format.js';\nimport { buildInstructions } from './instructions.js';\n\nexport const SERVER_VERSION = '0.1.0';\n\ntype ToolResult = {\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n};\n\n/** A failure we deliberately surface to the model as tool output, not a crash. */\nclass ToolError extends Error {}\n\nfunction text(value: string): ToolResult {\n return { content: [{ type: 'text', text: value }] };\n}\n\nfunction toolError(message: string): ToolResult {\n return { content: [{ type: 'text', text: message }], isError: true };\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof ToolError) return err.message;\n if (err instanceof MailcueError) {\n const status = err.status ? ` (HTTP ${err.status})` : '';\n return `MailCue request failed${status}: ${err.message}`;\n }\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst FOLDER = z\n .string()\n .optional()\n .describe('IMAP folder to act in. Defaults to INBOX.');\n\nexport function buildServer(config: McpConfig): McpServer {\n const locked = isLocked(config);\n\n const client = new Mailcue({\n baseUrl: config.baseUrl,\n ...(config.apiKey ? { apiKey: config.apiKey } : {}),\n ...(config.bearerToken ? { bearerToken: config.bearerToken } : {}),\n });\n\n const server = new McpServer(\n { name: 'mailcue', version: SERVER_VERSION },\n { instructions: buildInstructions(config) },\n );\n\n // In locked mode the mailbox is fixed and never exposed as an argument; in\n // multi-mailbox mode every tool requires it.\n const mailboxArg: ZodRawShape = locked\n ? {}\n : {\n mailbox: z\n .string()\n .describe('Mailbox address to act on, e.g. user@example.com.'),\n };\n\n const resolveMailbox = (provided?: string): string => {\n if (config.mailbox) return config.mailbox;\n const value = provided?.trim();\n if (!value) {\n throw new ToolError(\n 'A \"mailbox\" argument is required. Call list_mailboxes to see available addresses.',\n );\n }\n return value;\n };\n\n const run = (handler: (args: Record<string, unknown>) => Promise<ToolResult>) => {\n return async (args: Record<string, unknown>): Promise<ToolResult> => {\n try {\n return await handler(args);\n } catch (err) {\n return toolError(describeError(err));\n }\n };\n };\n\n server.registerTool(\n 'list_emails',\n {\n title: 'List emails',\n description:\n 'List emails in a mailbox folder, newest first. Returns summaries, each with a uid you can pass to get_email, reply_email, or delete_email.',\n inputSchema: {\n ...mailboxArg,\n folder: FOLDER,\n page: z.number().int().min(1).optional().describe('1-based page number. Default 1.'),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Results per page. Default 50.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; folder?: string; page?: number; pageSize?: number };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const res = await client.emails.list({\n mailbox,\n folder,\n ...(a.page !== undefined ? { page: a.page } : {}),\n ...(a.pageSize !== undefined ? { pageSize: a.pageSize } : {}),\n });\n return text(formatList(res, folder));\n }),\n );\n\n server.registerTool(\n 'search_emails',\n {\n title: 'Search emails',\n description:\n 'Full-text search a mailbox folder by sender, subject, or body content. Returns matching summaries with uids.',\n inputSchema: {\n ...mailboxArg,\n query: z.string().min(1).describe('Text to search for.'),\n folder: FOLDER,\n page: z.number().int().min(1).optional().describe('1-based page number. Default 1.'),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Results per page. Default 50.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n mailbox?: string;\n query: string;\n folder?: string;\n page?: number;\n pageSize?: number;\n };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const res = await client.emails.list({\n mailbox,\n folder,\n search: a.query,\n ...(a.page !== undefined ? { page: a.page } : {}),\n ...(a.pageSize !== undefined ? { pageSize: a.pageSize } : {}),\n });\n return text(formatList(res, folder));\n }),\n );\n\n server.registerTool(\n 'get_email',\n {\n title: 'Get email',\n description:\n 'Fetch one full email by uid: full body, headers, and attachment metadata. Read this before replying to or deleting a message.',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('The email uid, as returned by list_emails or search_emails.'),\n folder: FOLDER,\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; uid: string; folder?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const email = await client.emails.get(a.uid, { mailbox, folder });\n return text(formatEmail(email));\n }),\n );\n\n server.registerTool(\n 'send_email',\n {\n title: 'Send email',\n description: locked\n ? `Send a new email from ${config.mailbox}. Provide \"text\" for plain or \"html\" for rich (at least one).`\n : 'Send a new email. Provide \"text\" for plain or \"html\" for rich (at least one).',\n inputSchema: {\n ...(locked\n ? {}\n : {\n from: z\n .string()\n .describe('Sender mailbox address. You must own this mailbox.'),\n }),\n to: z.array(z.string()).min(1).describe('One or more recipient addresses.'),\n cc: z.array(z.string()).optional().describe('Optional CC recipients.'),\n subject: z.string().describe('Email subject line.'),\n text: z.string().optional().describe('Plain-text body.'),\n html: z.string().optional().describe('HTML body.'),\n replyTo: z.string().optional().describe('Optional Reply-To address.'),\n },\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n from?: string;\n to: string[];\n cc?: string[];\n subject: string;\n text?: string;\n html?: string;\n replyTo?: string;\n };\n if (a.text === undefined && a.html === undefined) {\n throw new ToolError('Provide at least one of \"text\" or \"html\".');\n }\n const from = config.mailbox ?? resolveMailbox(a.from);\n const params: SendEmailParams = { from, to: a.to, subject: a.subject };\n if (a.cc !== undefined) params.cc = a.cc;\n if (a.text !== undefined) params.text = a.text;\n if (a.html !== undefined) params.html = a.html;\n if (a.replyTo !== undefined) params.replyTo = a.replyTo;\n const res = await client.emails.send(params);\n return text(\n JSON.stringify({ status: 'sent', messageId: res.messageId, message: res.message }, null, 2),\n );\n }),\n );\n\n server.registerTool(\n 'reply_email',\n {\n title: 'Reply to email',\n description:\n 'Reply to an email by uid. The recipient, the \"Re:\" subject, and threading headers (In-Reply-To, References) are set for you. Provide \"text\" or \"html\".',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('uid of the message to reply to.'),\n folder: FOLDER,\n text: z.string().optional().describe('Plain-text reply body.'),\n html: z.string().optional().describe('HTML reply body.'),\n },\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n mailbox?: string;\n uid: string;\n folder?: string;\n text?: string;\n html?: string;\n };\n if (a.text === undefined && a.html === undefined) {\n throw new ToolError('Provide at least one of \"text\" or \"html\".');\n }\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const original = await client.emails.get(a.uid, { mailbox, folder });\n\n const subject = /^re:/i.test(original.subject)\n ? original.subject\n : `Re: ${original.subject}`;\n const params: SendEmailParams = {\n from: mailbox,\n to: [original.fromAddress],\n subject,\n };\n if (original.messageId) {\n params.inReplyTo = original.messageId;\n params.references = [original.messageId];\n }\n if (a.text !== undefined) params.text = a.text;\n if (a.html !== undefined) params.html = a.html;\n\n const res = await client.emails.send(params);\n return text(\n JSON.stringify(\n { status: 'sent', to: original.fromAddress, subject, messageId: res.messageId },\n null,\n 2,\n ),\n );\n }),\n );\n\n server.registerTool(\n 'delete_email',\n {\n title: 'Delete email',\n description:\n 'Permanently delete an email by uid. This cannot be undone. Only delete when explicitly asked or clearly required.',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('uid of the message to delete.'),\n folder: FOLDER,\n },\n annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; uid: string; folder?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n await client.emails.delete(a.uid, { mailbox, folder });\n return text(JSON.stringify({ status: 'deleted', uid: a.uid, mailbox, folder }, null, 2));\n }),\n );\n\n server.registerTool(\n 'mailbox_stats',\n {\n title: 'Mailbox stats',\n description: 'Per-folder message counts (total and unread) for a mailbox.',\n inputSchema: { ...mailboxArg },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const stats = await client.mailboxes.stats(mailbox);\n return text(formatStats(stats));\n }),\n );\n\n // Discovery only makes sense — and is only safe — when not locked to one box.\n if (!locked) {\n server.registerTool(\n 'list_mailboxes',\n {\n title: 'List mailboxes',\n description:\n 'List the mailboxes available on this server, with their addresses and unread counts. Use this to choose a \"mailbox\" argument for the other tools.',\n inputSchema: {},\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async () => {\n const res = await client.mailboxes.list();\n return text(formatMailboxes(res));\n }),\n );\n }\n\n return server;\n}\n","/**\n * Shape MailCue SDK responses into compact, token-efficient text for the model.\n * Tools return readable JSON rather than dumping raw HTML bodies.\n */\n\nimport type {\n EmailDetail,\n EmailListResponse,\n EmailSummary,\n MailboxListResponse,\n MailboxStats,\n} from 'mailcue';\n\nconst MAX_BODY_CHARS = 8000;\n\n/** Best-effort HTML -> text so the model reads prose, not markup. */\nexport function htmlToText(html: string): string {\n return html\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<\\/(p|div|tr|li|h[1-6])>/gi, '\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<[^>]+>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_BODY_CHARS) return text;\n return `${text.slice(0, MAX_BODY_CHARS)}\\n\\n[...truncated ${text.length - MAX_BODY_CHARS} chars. Use get_email with the uid for the full message.]`;\n}\n\nfunction summaryView(e: EmailSummary): Record<string, unknown> {\n return {\n uid: e.uid,\n from: e.fromAddress,\n to: e.toAddresses,\n subject: e.subject,\n date: e.date,\n unread: !e.isRead,\n hasAttachments: e.hasAttachments,\n preview: e.preview,\n };\n}\n\nexport function formatList(res: EmailListResponse, folder: string): string {\n const view = {\n folder,\n total: res.total,\n page: res.page,\n pageSize: res.pageSize,\n hasMore: res.hasMore,\n returned: res.emails.length,\n emails: res.emails.map(summaryView),\n };\n return JSON.stringify(view, null, 2);\n}\n\nexport function formatEmail(e: EmailDetail): string {\n const bestBody = e.textBody ?? (e.htmlBody ? htmlToText(e.htmlBody) : '');\n const view = {\n uid: e.uid,\n mailbox: e.mailbox,\n messageId: e.messageId,\n from: e.fromAddress,\n to: e.toAddresses,\n cc: e.ccAddresses,\n subject: e.subject,\n date: e.date,\n unread: !e.isRead,\n isSigned: e.isSigned,\n isEncrypted: e.isEncrypted,\n attachments: e.attachments.map((a) => ({\n partId: a.partId,\n filename: a.filename,\n contentType: a.contentType,\n size: a.size,\n })),\n body: truncate(bestBody),\n };\n return JSON.stringify(view, null, 2);\n}\n\nexport function formatStats(s: MailboxStats): string {\n return JSON.stringify(\n {\n address: s.address,\n totalEmails: s.totalEmails,\n unreadEmails: s.unreadEmails,\n totalSizeBytes: s.totalSizeBytes,\n folders: s.folders.map((f) => ({\n name: f.name,\n messages: f.messageCount,\n unseen: f.unseenCount,\n })),\n },\n null,\n 2,\n );\n}\n\nexport function formatMailboxes(res: MailboxListResponse): string {\n return JSON.stringify(\n {\n total: res.total,\n mailboxes: res.mailboxes.map((m) => ({\n address: m.address,\n displayName: m.displayName,\n emailCount: m.emailCount,\n unreadCount: m.unreadCount,\n })),\n },\n null,\n 2,\n );\n}\n","/**\n * Server-level MCP `instructions`. The MCP client surfaces this to the model\n * during initialization, so it is the place to teach an agent how to run its\n * own mailbox well. The text adapts to whether a single mailbox is locked.\n */\n\nimport { isLocked, type McpConfig } from './config.js';\n\nexport function buildInstructions(config: McpConfig): string {\n const locked = isLocked(config);\n\n const scope = locked\n ? `You are operating a single mailbox: ${config.mailbox}. This is YOUR inbox.\nYou cannot see or touch any other mailbox. Tools do not take a \"mailbox\"\nargument — every action runs against ${config.mailbox} automatically, and\nmail you send goes out from ${config.mailbox}.`\n : `This server is in multi-mailbox mode. Every tool takes a required\n\"mailbox\" argument naming the address to act on. Call list_mailboxes first to\ndiscover which addresses exist before reading or sending.`;\n\n return `MailCue MCP — an email mailbox you operate directly.\n\nMailCue is a full email server (Postfix + Dovecot + IMAP/SMTP behind a REST\nAPI). Through this server you can read, search, triage, send, reply to, and\ndelete real email, the same way a person uses an inbox client.\n\n# Scope\n${scope}\n\n# Tools\n- list_emails Browse a folder (default INBOX), newest first. Returns\n summaries with a \"uid\" for each message.\n- get_email Fetch one full message by uid: bodies, headers, attachment\n list. Read this before replying or acting on a message.\n- search_emails Full-text search across a folder (sender, subject, body).\n- send_email Send a new message. Provide \"text\" for plain or \"html\" for\n rich; you may pass both.\n- reply_email Reply to a message by uid. Threading headers (In-Reply-To,\n References), the \"Re:\" subject, and the recipient are filled\n in for you. Just pass the uid and your reply body.\n- delete_email Permanently delete a message by uid. There is no undo.${\n locked ? '' : '\\n- list_mailboxes Discover the mailboxes you can act on.'\n }\n- mailbox_stats Per-folder counts (total / unread) for a mailbox.\n\n# How to work\n1. To answer \"what's in my inbox\" or \"any new mail\", call list_emails (or\n mailbox_stats for just counts). uids come from these listings.\n2. uids are scoped to a (mailbox, folder) pair. Use the same folder you listed\n from when calling get_email / reply_email / delete_email.\n3. Always get_email before you reply or delete, so you act on the real content\n rather than the short preview.\n4. Prefer reply_email over send_email when responding to an existing thread —\n it preserves threading so the conversation stays intact.\n5. delete_email is irreversible. Only delete when explicitly asked, or when the\n task clearly calls for it.\n6. Bodies may be truncated in tool output; re-fetch with get_email for the full\n text when you need it.`;\n}\n"],"mappings":";;;AAAA,SAAS,4BAA4B;;;ACarC,IAAM,mBAAmB;AAUlB,IAAM,cAAN,cAA0B,MAAM;AAAC;AAExC,SAAS,MAAM,OAA+C;AAC5D,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,YAAY,KAAK,SAAY;AACtC;AAEO,SAAS,WAAW,MAAyB,QAAQ,KAAgB;AAC1E,QAAM,SAAS,MAAM,IAAI,iBAAiB,CAAC;AAC3C,QAAM,cAAc,MAAM,IAAI,sBAAsB,CAAC;AAErD,MAAI,CAAC,UAAU,CAAC,aAAa;AAC3B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAoB;AAAA,IACxB,SAAS,MAAM,IAAI,kBAAkB,CAAC,KAAK;AAAA,EAC7C;AACA,MAAI,OAAQ,QAAO,SAAS;AAC5B,MAAI,YAAa,QAAO,cAAc;AAEtC,QAAM,UAAU,MAAM,IAAI,iBAAiB,CAAC;AAC5C,MAAI,QAAS,QAAO,UAAU;AAE9B,SAAO;AACT;AAEO,SAAS,SAAS,QAA8D;AACrF,SAAO,OAAO,OAAO,YAAY;AACnC;;;ACvDA,SAAS,iBAAiB;AAC1B,SAAS,SAAS,oBAA0C;AAC5D,SAAS,SAA2B;;;ACWpC,IAAM,iBAAiB;AAGhB,SAAS,WAAW,MAAsB;AAC/C,SAAO,KACJ,QAAQ,6BAA6B,EAAE,EACvC,QAAQ,+BAA+B,EAAE,EACzC,QAAQ,8BAA8B,IAAI,EAC1C,QAAQ,gBAAgB,IAAI,EAC5B,QAAQ,YAAY,EAAE,EACtB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,aAAa,IAAI,EACzB,QAAQ,WAAW,MAAM,EACzB,KAAK;AACV;AAEA,SAAS,SAASA,OAAsB;AACtC,MAAIA,MAAK,UAAU,eAAgB,QAAOA;AAC1C,SAAO,GAAGA,MAAK,MAAM,GAAG,cAAc,CAAC;AAAA;AAAA,gBAAqBA,MAAK,SAAS,cAAc;AAC1F;AAEA,SAAS,YAAY,GAA0C;AAC7D,SAAO;AAAA,IACL,KAAK,EAAE;AAAA,IACP,MAAM,EAAE;AAAA,IACR,IAAI,EAAE;AAAA,IACN,SAAS,EAAE;AAAA,IACX,MAAM,EAAE;AAAA,IACR,QAAQ,CAAC,EAAE;AAAA,IACX,gBAAgB,EAAE;AAAA,IAClB,SAAS,EAAE;AAAA,EACb;AACF;AAEO,SAAS,WAAW,KAAwB,QAAwB;AACzE,QAAM,OAAO;AAAA,IACX;AAAA,IACA,OAAO,IAAI;AAAA,IACX,MAAM,IAAI;AAAA,IACV,UAAU,IAAI;AAAA,IACd,SAAS,IAAI;AAAA,IACb,UAAU,IAAI,OAAO;AAAA,IACrB,QAAQ,IAAI,OAAO,IAAI,WAAW;AAAA,EACpC;AACA,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACrC;AAEO,SAAS,YAAY,GAAwB;AAClD,QAAM,WAAW,EAAE,aAAa,EAAE,WAAW,WAAW,EAAE,QAAQ,IAAI;AACtE,QAAM,OAAO;AAAA,IACX,KAAK,EAAE;AAAA,IACP,SAAS,EAAE;AAAA,IACX,WAAW,EAAE;AAAA,IACb,MAAM,EAAE;AAAA,IACR,IAAI,EAAE;AAAA,IACN,IAAI,EAAE;AAAA,IACN,SAAS,EAAE;AAAA,IACX,MAAM,EAAE;AAAA,IACR,QAAQ,CAAC,EAAE;AAAA,IACX,UAAU,EAAE;AAAA,IACZ,aAAa,EAAE;AAAA,IACf,aAAa,EAAE,YAAY,IAAI,CAAC,OAAO;AAAA,MACrC,QAAQ,EAAE;AAAA,MACV,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,MACf,MAAM,EAAE;AAAA,IACV,EAAE;AAAA,IACF,MAAM,SAAS,QAAQ;AAAA,EACzB;AACA,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACrC;AAEO,SAAS,YAAY,GAAyB;AACnD,SAAO,KAAK;AAAA,IACV;AAAA,MACE,SAAS,EAAE;AAAA,MACX,aAAa,EAAE;AAAA,MACf,cAAc,EAAE;AAAA,MAChB,gBAAgB,EAAE;AAAA,MAClB,SAAS,EAAE,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC7B,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACZ,EAAE;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,gBAAgB,KAAkC;AAChE,SAAO,KAAK;AAAA,IACV;AAAA,MACE,OAAO,IAAI;AAAA,MACX,WAAW,IAAI,UAAU,IAAI,CAAC,OAAO;AAAA,QACnC,SAAS,EAAE;AAAA,QACX,aAAa,EAAE;AAAA,QACf,YAAY,EAAE;AAAA,QACd,aAAa,EAAE;AAAA,MACjB,EAAE;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AClHO,SAAS,kBAAkB,QAA2B;AAC3D,QAAM,SAAS,SAAS,MAAM;AAE9B,QAAM,QAAQ,SACV,uCAAuC,OAAO,OAAO;AAAA;AAAA,4CAEpB,OAAO,OAAO;AAAA,8BACvB,OAAO,OAAO,MACtC;AAAA;AAAA;AAIJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOP,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yEAcH,SAAS,KAAK,2DAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBF;;;AF7CO,IAAM,iBAAiB;AAQ9B,IAAM,YAAN,cAAwB,MAAM;AAAC;AAE/B,SAAS,KAAK,OAA2B;AACvC,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,CAAC,EAAE;AACpD;AAEA,SAAS,UAAU,SAA6B;AAC9C,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG,SAAS,KAAK;AACrE;AAEA,SAAS,cAAc,KAAsB;AAC3C,MAAI,eAAe,UAAW,QAAO,IAAI;AACzC,MAAI,eAAe,cAAc;AAC/B,UAAM,SAAS,IAAI,SAAS,UAAU,IAAI,MAAM,MAAM;AACtD,WAAO,yBAAyB,MAAM,KAAK,IAAI,OAAO;AAAA,EACxD;AACA,MAAI,eAAe,MAAO,QAAO,IAAI;AACrC,SAAO,OAAO,GAAG;AACnB;AAEA,IAAM,SAAS,EACZ,OAAO,EACP,SAAS,EACT,SAAS,2CAA2C;AAEhD,SAAS,YAAY,QAA8B;AACxD,QAAM,SAAS,SAAS,MAAM;AAE9B,QAAM,SAAS,IAAI,QAAQ;AAAA,IACzB,SAAS,OAAO;AAAA,IAChB,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,IACjD,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,EAClE,CAAC;AAED,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,WAAW,SAAS,eAAe;AAAA,IAC3C,EAAE,cAAc,kBAAkB,MAAM,EAAE;AAAA,EAC5C;AAIA,QAAM,aAA0B,SAC5B,CAAC,IACD;AAAA,IACE,SAAS,EACN,OAAO,EACP,SAAS,mDAAmD;AAAA,EACjE;AAEJ,QAAM,iBAAiB,CAAC,aAA8B;AACpD,QAAI,OAAO,QAAS,QAAO,OAAO;AAClC,UAAM,QAAQ,UAAU,KAAK;AAC7B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,CAAC,YAAoE;AAC/E,WAAO,OAAO,SAAuD;AACnE,UAAI;AACF,eAAO,MAAM,QAAQ,IAAI;AAAA,MAC3B,SAAS,KAAK;AACZ,eAAO,UAAU,cAAc,GAAG,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,QACX,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iCAAiC;AAAA,QACnF,UAAU,EACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,+BAA+B;AAAA,MAC7C;AAAA,MACA,aAAa,EAAE,cAAc,MAAM,eAAe,KAAK;AAAA,IACzD;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AACV,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,MAAM,MAAM,OAAO,OAAO,KAAK;AAAA,QACnC;AAAA,QACA;AAAA,QACA,GAAI,EAAE,SAAS,SAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,QAC/C,GAAI,EAAE,aAAa,SAAY,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7D,CAAC;AACD,aAAO,KAAK,WAAW,KAAK,MAAM,CAAC;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,QACX,GAAG;AAAA,QACH,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAqB;AAAA,QACvD,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iCAAiC;AAAA,QACnF,UAAU,EACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,+BAA+B;AAAA,MAC7C;AAAA,MACA,aAAa,EAAE,cAAc,MAAM,eAAe,KAAK;AAAA,IACzD;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AAOV,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,MAAM,MAAM,OAAO,OAAO,KAAK;AAAA,QACnC;AAAA,QACA;AAAA,QACA,QAAQ,EAAE;AAAA,QACV,GAAI,EAAE,SAAS,SAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,QAC/C,GAAI,EAAE,aAAa,SAAY,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7D,CAAC;AACD,aAAO,KAAK,WAAW,KAAK,MAAM,CAAC;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,QACX,GAAG;AAAA,QACH,KAAK,EAAE,OAAO,EAAE,SAAS,6DAA6D;AAAA,QACtF,QAAQ;AAAA,MACV;AAAA,MACA,aAAa,EAAE,cAAc,MAAM,eAAe,KAAK;AAAA,IACzD;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AACV,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,QAAQ,MAAM,OAAO,OAAO,IAAI,EAAE,KAAK,EAAE,SAAS,OAAO,CAAC;AAChE,aAAO,KAAK,YAAY,KAAK,CAAC;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa,SACT,yBAAyB,OAAO,OAAO,kEACvC;AAAA,MACJ,aAAa;AAAA,QACX,GAAI,SACA,CAAC,IACD;AAAA,UACE,MAAM,EACH,OAAO,EACP,SAAS,oDAAoD;AAAA,QAClE;AAAA,QACJ,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,kCAAkC;AAAA,QAC1E,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,QACrE,SAAS,EAAE,OAAO,EAAE,SAAS,qBAAqB;AAAA,QAClD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kBAAkB;AAAA,QACvD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YAAY;AAAA,QACjD,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4BAA4B;AAAA,MACtE;AAAA,MACA,aAAa,EAAE,cAAc,OAAO,eAAe,KAAK;AAAA,IAC1D;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AASV,UAAI,EAAE,SAAS,UAAa,EAAE,SAAS,QAAW;AAChD,cAAM,IAAI,UAAU,2CAA2C;AAAA,MACjE;AACA,YAAM,OAAO,OAAO,WAAW,eAAe,EAAE,IAAI;AACpD,YAAM,SAA0B,EAAE,MAAM,IAAI,EAAE,IAAI,SAAS,EAAE,QAAQ;AACrE,UAAI,EAAE,OAAO,OAAW,QAAO,KAAK,EAAE;AACtC,UAAI,EAAE,SAAS,OAAW,QAAO,OAAO,EAAE;AAC1C,UAAI,EAAE,SAAS,OAAW,QAAO,OAAO,EAAE;AAC1C,UAAI,EAAE,YAAY,OAAW,QAAO,UAAU,EAAE;AAChD,YAAM,MAAM,MAAM,OAAO,OAAO,KAAK,MAAM;AAC3C,aAAO;AAAA,QACL,KAAK,UAAU,EAAE,QAAQ,QAAQ,WAAW,IAAI,WAAW,SAAS,IAAI,QAAQ,GAAG,MAAM,CAAC;AAAA,MAC5F;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,QACX,GAAG;AAAA,QACH,KAAK,EAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,QAC1D,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,QAC7D,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kBAAkB;AAAA,MACzD;AAAA,MACA,aAAa,EAAE,cAAc,OAAO,eAAe,KAAK;AAAA,IAC1D;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AAOV,UAAI,EAAE,SAAS,UAAa,EAAE,SAAS,QAAW;AAChD,cAAM,IAAI,UAAU,2CAA2C;AAAA,MACjE;AACA,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,WAAW,MAAM,OAAO,OAAO,IAAI,EAAE,KAAK,EAAE,SAAS,OAAO,CAAC;AAEnE,YAAM,UAAU,QAAQ,KAAK,SAAS,OAAO,IACzC,SAAS,UACT,OAAO,SAAS,OAAO;AAC3B,YAAM,SAA0B;AAAA,QAC9B,MAAM;AAAA,QACN,IAAI,CAAC,SAAS,WAAW;AAAA,QACzB;AAAA,MACF;AACA,UAAI,SAAS,WAAW;AACtB,eAAO,YAAY,SAAS;AAC5B,eAAO,aAAa,CAAC,SAAS,SAAS;AAAA,MACzC;AACA,UAAI,EAAE,SAAS,OAAW,QAAO,OAAO,EAAE;AAC1C,UAAI,EAAE,SAAS,OAAW,QAAO,OAAO,EAAE;AAE1C,YAAM,MAAM,MAAM,OAAO,OAAO,KAAK,MAAM;AAC3C,aAAO;AAAA,QACL,KAAK;AAAA,UACH,EAAE,QAAQ,QAAQ,IAAI,SAAS,aAAa,SAAS,WAAW,IAAI,UAAU;AAAA,UAC9E;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,QACX,GAAG;AAAA,QACH,KAAK,EAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,QACxD,QAAQ;AAAA,MACV;AAAA,MACA,aAAa,EAAE,cAAc,OAAO,iBAAiB,MAAM,eAAe,KAAK;AAAA,IACjF;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AACV,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,OAAO,OAAO,OAAO,EAAE,KAAK,EAAE,SAAS,OAAO,CAAC;AACrD,aAAO,KAAK,KAAK,UAAU,EAAE,QAAQ,WAAW,KAAK,EAAE,KAAK,SAAS,OAAO,GAAG,MAAM,CAAC,CAAC;AAAA,IACzF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,EAAE,GAAG,WAAW;AAAA,MAC7B,aAAa,EAAE,cAAc,MAAM,eAAe,KAAK;AAAA,IACzD;AAAA,IACA,IAAI,OAAO,SAAS;AAClB,YAAM,IAAI;AACV,YAAM,UAAU,eAAe,EAAE,OAAO;AACxC,YAAM,QAAQ,MAAM,OAAO,UAAU,MAAM,OAAO;AAClD,aAAO,KAAK,YAAY,KAAK,CAAC;AAAA,IAChC,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,aACE;AAAA,QACF,aAAa,CAAC;AAAA,QACd,aAAa,EAAE,cAAc,MAAM,eAAe,KAAK;AAAA,MACzD;AAAA,MACA,IAAI,YAAY;AACd,cAAM,MAAM,MAAM,OAAO,UAAU,KAAK;AACxC,eAAO,KAAK,gBAAgB,GAAG,CAAC;AAAA,MAClC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;AF3VA,SAAS,UAAU,SAAuB;AACxC,UAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AACrC;AAEA,eAAe,OAAsB;AACnC,MAAI;AACJ,MAAI;AACF,aAAS,WAAW;AAAA,EACtB,SAAS,KAAK;AACZ,QAAI,eAAe,aAAa;AAC9B,gBAAU,gBAAgB,IAAI,OAAO,EAAE;AACvC,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AAEA,QAAM,SAAS,YAAY,MAAM;AACjC,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAE9B,QAAM,QAAQ,SAAS,MAAM,IAAI,aAAa,OAAO,OAAO,KAAK;AACjE,YAAU,qCAAgC,OAAO,OAAO,KAAK,KAAK,GAAG;AACvE;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,YAAU,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACnF,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["text"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/server.ts","../src/format.ts","../src/instructions.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nimport { ConfigError, isLocked, loadConfig } from './config.js';\nimport { buildServer } from './server.js';\n\nfunction logStderr(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\nasync function main(): Promise<void> {\n let config;\n try {\n config = loadConfig();\n } catch (err) {\n if (err instanceof ConfigError) {\n logStderr(`mailcue-mcp: ${err.message}`);\n process.exit(1);\n }\n throw err;\n }\n\n const server = buildServer(config);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const scope = isLocked(config) ? `locked to ${config.mailbox}` : 'multi-mailbox';\n logStderr(`mailcue-mcp ready on stdio — ${config.baseUrl} (${scope})`);\n}\n\nmain().catch((err) => {\n logStderr(`mailcue-mcp: fatal: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n","/**\n * Configuration is read entirely from the environment so the server can be\n * dropped into any MCP client config block without code changes.\n *\n * MAILCUE_BASE_URL MailCue server URL (default http://localhost:8088)\n * MAILCUE_API_KEY X-API-Key credential (mc_...)\n * MAILCUE_BEARER_TOKEN JWT alternative to MAILCUE_API_KEY\n * MAILCUE_MAILBOX optional. When set, the agent is locked to this one\n * mailbox: every tool operates on it, the `mailbox`\n * argument disappears, and cross-mailbox tools are not\n * registered at all.\n */\n\nconst DEFAULT_BASE_URL = 'http://localhost:8088';\n\nexport interface McpConfig {\n baseUrl: string;\n apiKey?: string;\n bearerToken?: string;\n /** When set, the server runs in single-mailbox (locked) mode. */\n mailbox?: string;\n}\n\nexport class ConfigError extends Error {}\n\nfunction clean(value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n return trimmed === '' ? undefined : trimmed;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): McpConfig {\n const apiKey = clean(env['MAILCUE_API_KEY']);\n const bearerToken = clean(env['MAILCUE_BEARER_TOKEN']);\n\n if (!apiKey && !bearerToken) {\n throw new ConfigError(\n 'Missing credentials: set MAILCUE_API_KEY (preferred) or MAILCUE_BEARER_TOKEN.',\n );\n }\n\n const config: McpConfig = {\n baseUrl: clean(env['MAILCUE_BASE_URL']) ?? DEFAULT_BASE_URL,\n };\n if (apiKey) config.apiKey = apiKey;\n if (bearerToken) config.bearerToken = bearerToken;\n\n const mailbox = clean(env['MAILCUE_MAILBOX']);\n if (mailbox) config.mailbox = mailbox;\n\n return config;\n}\n\nexport function isLocked(config: McpConfig): config is McpConfig & { mailbox: string } {\n return typeof config.mailbox === 'string';\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n AuthenticationError,\n AuthorizationError,\n Mailcue,\n MailcueError,\n type SendEmailParams,\n} from 'mailcue';\nimport { z, type ZodRawShape } from 'zod';\n\nimport { isLocked, type McpConfig } from './config.js';\nimport {\n formatEmail,\n formatList,\n formatMailboxes,\n formatStats,\n} from './format.js';\nimport { buildInstructions } from './instructions.js';\n\nexport const SERVER_VERSION = '0.1.0';\n\ntype ToolResult = {\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n};\n\n/** A failure we deliberately surface to the model as tool output, not a crash. */\nclass ToolError extends Error {}\n\nfunction text(value: string): ToolResult {\n return { content: [{ type: 'text', text: value }] };\n}\n\nfunction toolError(message: string): ToolResult {\n return { content: [{ type: 'text', text: message }], isError: true };\n}\n\n// Matches the backend's \"... missing the required 'email:send' permission\".\nconst MISSING_SCOPE_RE = /required '([^']+)' permission/;\n\nfunction describeError(err: unknown): string {\n if (err instanceof ToolError) return err.message;\n // Permission failures (403): the key is authenticated but not allowed to do\n // this. Tell the model exactly what is missing so it stops retrying.\n // AuthorizationError is the SDK's 403 type (the newer PermissionError\n // subclasses it, so this also covers SDKs that expose a parsed scope).\n if (err instanceof AuthorizationError) {\n const scope =\n (err as { scope?: string }).scope ?? MISSING_SCOPE_RE.exec(err.message)?.[1];\n if (scope) {\n return (\n `Permission denied: this MailCue API key does not have the \"${scope}\" ` +\n `permission required for this action. Use a key that includes it, or ask ` +\n `the key owner to grant it. This will not succeed on retry.`\n );\n }\n if (/mailbox/i.test(err.message)) {\n return (\n 'Permission denied: this MailCue API key is restricted to specific ' +\n 'mailboxes and is not allowed to access this one. Use an allowed mailbox, ' +\n 'or ask the key owner to widen the key. This will not succeed on retry.'\n );\n }\n return `Permission denied: ${err.message}. This will not succeed on retry.`;\n }\n // Auth failures (401): missing/invalid credentials. AuthorizationError is\n // checked first above since it also extends AuthenticationError.\n if (err instanceof AuthenticationError) {\n return (\n 'Authentication failed: the MailCue API key or bearer token is missing or ' +\n 'invalid. Check the MAILCUE_API_KEY / MAILCUE_BEARER_TOKEN configuration.'\n );\n }\n if (err instanceof MailcueError) {\n const status = err.status ? ` (HTTP ${err.status})` : '';\n return `MailCue request failed${status}: ${err.message}`;\n }\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst FOLDER = z\n .string()\n .optional()\n .describe('IMAP folder to act in. Defaults to INBOX.');\n\nexport function buildServer(config: McpConfig): McpServer {\n const locked = isLocked(config);\n\n const client = new Mailcue({\n baseUrl: config.baseUrl,\n ...(config.apiKey ? { apiKey: config.apiKey } : {}),\n ...(config.bearerToken ? { bearerToken: config.bearerToken } : {}),\n });\n\n const server = new McpServer(\n { name: 'mailcue', version: SERVER_VERSION },\n { instructions: buildInstructions(config) },\n );\n\n // In locked mode the mailbox is fixed and never exposed as an argument; in\n // multi-mailbox mode every tool requires it.\n const mailboxArg: ZodRawShape = locked\n ? {}\n : {\n mailbox: z\n .string()\n .describe('Mailbox address to act on, e.g. user@example.com.'),\n };\n\n const resolveMailbox = (provided?: string): string => {\n if (config.mailbox) return config.mailbox;\n const value = provided?.trim();\n if (!value) {\n throw new ToolError(\n 'A \"mailbox\" argument is required. Call list_mailboxes to see available addresses.',\n );\n }\n return value;\n };\n\n const run = (handler: (args: Record<string, unknown>) => Promise<ToolResult>) => {\n return async (args: Record<string, unknown>): Promise<ToolResult> => {\n try {\n return await handler(args);\n } catch (err) {\n return toolError(describeError(err));\n }\n };\n };\n\n server.registerTool(\n 'list_emails',\n {\n title: 'List emails',\n description:\n 'List emails in a mailbox folder, newest first. Returns summaries, each with a uid you can pass to get_email, reply_email, or delete_email.',\n inputSchema: {\n ...mailboxArg,\n folder: FOLDER,\n page: z.number().int().min(1).optional().describe('1-based page number. Default 1.'),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Results per page. Default 50.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; folder?: string; page?: number; pageSize?: number };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const res = await client.emails.list({\n mailbox,\n folder,\n ...(a.page !== undefined ? { page: a.page } : {}),\n ...(a.pageSize !== undefined ? { pageSize: a.pageSize } : {}),\n });\n return text(formatList(res, folder));\n }),\n );\n\n server.registerTool(\n 'search_emails',\n {\n title: 'Search emails',\n description:\n 'Full-text search a mailbox folder by sender, subject, or body content. Returns matching summaries with uids.',\n inputSchema: {\n ...mailboxArg,\n query: z.string().min(1).describe('Text to search for.'),\n folder: FOLDER,\n page: z.number().int().min(1).optional().describe('1-based page number. Default 1.'),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Results per page. Default 50.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n mailbox?: string;\n query: string;\n folder?: string;\n page?: number;\n pageSize?: number;\n };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const res = await client.emails.list({\n mailbox,\n folder,\n search: a.query,\n ...(a.page !== undefined ? { page: a.page } : {}),\n ...(a.pageSize !== undefined ? { pageSize: a.pageSize } : {}),\n });\n return text(formatList(res, folder));\n }),\n );\n\n server.registerTool(\n 'get_email',\n {\n title: 'Get email',\n description:\n 'Fetch one full email by uid: full body, headers, and attachment metadata. Read this before replying to or deleting a message.',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('The email uid, as returned by list_emails or search_emails.'),\n folder: FOLDER,\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; uid: string; folder?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const email = await client.emails.get(a.uid, { mailbox, folder });\n return text(formatEmail(email));\n }),\n );\n\n server.registerTool(\n 'send_email',\n {\n title: 'Send email',\n description: locked\n ? `Send a new email from ${config.mailbox}. Provide \"text\" for plain or \"html\" for rich (at least one).`\n : 'Send a new email. Provide \"text\" for plain or \"html\" for rich (at least one).',\n inputSchema: {\n ...(locked\n ? {}\n : {\n from: z\n .string()\n .describe('Sender mailbox address. You must own this mailbox.'),\n }),\n to: z.array(z.string()).min(1).describe('One or more recipient addresses.'),\n cc: z.array(z.string()).optional().describe('Optional CC recipients.'),\n subject: z.string().describe('Email subject line.'),\n text: z.string().optional().describe('Plain-text body.'),\n html: z.string().optional().describe('HTML body.'),\n replyTo: z.string().optional().describe('Optional Reply-To address.'),\n },\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n from?: string;\n to: string[];\n cc?: string[];\n subject: string;\n text?: string;\n html?: string;\n replyTo?: string;\n };\n if (a.text === undefined && a.html === undefined) {\n throw new ToolError('Provide at least one of \"text\" or \"html\".');\n }\n const from = config.mailbox ?? resolveMailbox(a.from);\n const params: SendEmailParams = { from, to: a.to, subject: a.subject };\n if (a.cc !== undefined) params.cc = a.cc;\n if (a.text !== undefined) params.text = a.text;\n if (a.html !== undefined) params.html = a.html;\n if (a.replyTo !== undefined) params.replyTo = a.replyTo;\n const res = await client.emails.send(params);\n return text(\n JSON.stringify({ status: 'sent', messageId: res.messageId, message: res.message }, null, 2),\n );\n }),\n );\n\n server.registerTool(\n 'reply_email',\n {\n title: 'Reply to email',\n description:\n 'Reply to an email by uid. The recipient, the \"Re:\" subject, and threading headers (In-Reply-To, References) are set for you. Provide \"text\" or \"html\".',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('uid of the message to reply to.'),\n folder: FOLDER,\n text: z.string().optional().describe('Plain-text reply body.'),\n html: z.string().optional().describe('HTML reply body.'),\n },\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as {\n mailbox?: string;\n uid: string;\n folder?: string;\n text?: string;\n html?: string;\n };\n if (a.text === undefined && a.html === undefined) {\n throw new ToolError('Provide at least one of \"text\" or \"html\".');\n }\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n const original = await client.emails.get(a.uid, { mailbox, folder });\n\n const subject = /^re:/i.test(original.subject)\n ? original.subject\n : `Re: ${original.subject}`;\n const params: SendEmailParams = {\n from: mailbox,\n to: [original.fromAddress],\n subject,\n };\n if (original.messageId) {\n params.inReplyTo = original.messageId;\n params.references = [original.messageId];\n }\n if (a.text !== undefined) params.text = a.text;\n if (a.html !== undefined) params.html = a.html;\n\n const res = await client.emails.send(params);\n return text(\n JSON.stringify(\n { status: 'sent', to: original.fromAddress, subject, messageId: res.messageId },\n null,\n 2,\n ),\n );\n }),\n );\n\n server.registerTool(\n 'delete_email',\n {\n title: 'Delete email',\n description:\n 'Permanently delete an email by uid. This cannot be undone. Only delete when explicitly asked or clearly required.',\n inputSchema: {\n ...mailboxArg,\n uid: z.string().describe('uid of the message to delete.'),\n folder: FOLDER,\n },\n annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string; uid: string; folder?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const folder = a.folder ?? 'INBOX';\n await client.emails.delete(a.uid, { mailbox, folder });\n return text(JSON.stringify({ status: 'deleted', uid: a.uid, mailbox, folder }, null, 2));\n }),\n );\n\n server.registerTool(\n 'mailbox_stats',\n {\n title: 'Mailbox stats',\n description: 'Per-folder message counts (total and unread) for a mailbox.',\n inputSchema: { ...mailboxArg },\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async (args) => {\n const a = args as { mailbox?: string };\n const mailbox = resolveMailbox(a.mailbox);\n const stats = await client.mailboxes.stats(mailbox);\n return text(formatStats(stats));\n }),\n );\n\n // Discovery only makes sense — and is only safe — when not locked to one box.\n if (!locked) {\n server.registerTool(\n 'list_mailboxes',\n {\n title: 'List mailboxes',\n description:\n 'List the mailboxes available on this server, with their addresses and unread counts. Use this to choose a \"mailbox\" argument for the other tools.',\n inputSchema: {},\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n run(async () => {\n const res = await client.mailboxes.list();\n return text(formatMailboxes(res));\n }),\n );\n }\n\n return server;\n}\n","/**\n * Shape MailCue SDK responses into compact, token-efficient text for the model.\n * Tools return readable JSON rather than dumping raw HTML bodies.\n */\n\nimport type {\n EmailDetail,\n EmailListResponse,\n EmailSummary,\n MailboxListResponse,\n MailboxStats,\n} from 'mailcue';\n\nconst MAX_BODY_CHARS = 8000;\n\n/** Best-effort HTML -> text so the model reads prose, not markup. */\nexport function htmlToText(html: string): string {\n return html\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<\\/(p|div|tr|li|h[1-6])>/gi, '\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<[^>]+>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_BODY_CHARS) return text;\n return `${text.slice(0, MAX_BODY_CHARS)}\\n\\n[...truncated ${text.length - MAX_BODY_CHARS} chars. Use get_email with the uid for the full message.]`;\n}\n\nfunction summaryView(e: EmailSummary): Record<string, unknown> {\n return {\n uid: e.uid,\n from: e.fromAddress,\n to: e.toAddresses,\n subject: e.subject,\n date: e.date,\n unread: !e.isRead,\n hasAttachments: e.hasAttachments,\n preview: e.preview,\n };\n}\n\nexport function formatList(res: EmailListResponse, folder: string): string {\n const view = {\n folder,\n total: res.total,\n page: res.page,\n pageSize: res.pageSize,\n hasMore: res.hasMore,\n returned: res.emails.length,\n emails: res.emails.map(summaryView),\n };\n return JSON.stringify(view, null, 2);\n}\n\nexport function formatEmail(e: EmailDetail): string {\n const bestBody = e.textBody ?? (e.htmlBody ? htmlToText(e.htmlBody) : '');\n const view = {\n uid: e.uid,\n mailbox: e.mailbox,\n messageId: e.messageId,\n from: e.fromAddress,\n to: e.toAddresses,\n cc: e.ccAddresses,\n subject: e.subject,\n date: e.date,\n unread: !e.isRead,\n isSigned: e.isSigned,\n isEncrypted: e.isEncrypted,\n attachments: e.attachments.map((a) => ({\n partId: a.partId,\n filename: a.filename,\n contentType: a.contentType,\n size: a.size,\n })),\n body: truncate(bestBody),\n };\n return JSON.stringify(view, null, 2);\n}\n\nexport function formatStats(s: MailboxStats): string {\n return JSON.stringify(\n {\n address: s.address,\n totalEmails: s.totalEmails,\n unreadEmails: s.unreadEmails,\n totalSizeBytes: s.totalSizeBytes,\n folders: s.folders.map((f) => ({\n name: f.name,\n messages: f.messageCount,\n unseen: f.unseenCount,\n })),\n },\n null,\n 2,\n );\n}\n\nexport function formatMailboxes(res: MailboxListResponse): string {\n return JSON.stringify(\n {\n total: res.total,\n mailboxes: res.mailboxes.map((m) => ({\n address: m.address,\n displayName: m.displayName,\n emailCount: m.emailCount,\n unreadCount: m.unreadCount,\n })),\n },\n null,\n 2,\n );\n}\n","/**\n * Server-level MCP `instructions`. The MCP client surfaces this to the model\n * during initialization, so it is the place to teach an agent how to run its\n * own mailbox well. The text adapts to whether a single mailbox is locked.\n */\n\nimport { isLocked, type McpConfig } from './config.js';\n\nexport function buildInstructions(config: McpConfig): string {\n const locked = isLocked(config);\n\n const scope = locked\n ? `You are operating a single mailbox: ${config.mailbox}. This is YOUR inbox.\nYou cannot see or touch any other mailbox. Tools do not take a \"mailbox\"\nargument — every action runs against ${config.mailbox} automatically, and\nmail you send goes out from ${config.mailbox}.`\n : `This server is in multi-mailbox mode. Every tool takes a required\n\"mailbox\" argument naming the address to act on. Call list_mailboxes first to\ndiscover which addresses exist before reading or sending.`;\n\n return `MailCue MCP — an email mailbox you operate directly.\n\nMailCue is a full email server (Postfix + Dovecot + IMAP/SMTP behind a REST\nAPI). Through this server you can read, search, triage, send, reply to, and\ndelete real email, the same way a person uses an inbox client.\n\n# Scope\n${scope}\n\n# Tools\n- list_emails Browse a folder (default INBOX), newest first. Returns\n summaries with a \"uid\" for each message.\n- get_email Fetch one full message by uid: bodies, headers, attachment\n list. Read this before replying or acting on a message.\n- search_emails Full-text search across a folder (sender, subject, body).\n- send_email Send a new message. Provide \"text\" for plain or \"html\" for\n rich; you may pass both.\n- reply_email Reply to a message by uid. Threading headers (In-Reply-To,\n References), the \"Re:\" subject, and the recipient are filled\n in for you. Just pass the uid and your reply body.\n- delete_email Permanently delete a message by uid. There is no undo.${\n locked ? '' : '\\n- list_mailboxes Discover the mailboxes you can act on.'\n }\n- mailbox_stats Per-folder counts (total / unread) for a mailbox.\n\n# How to work\n1. To answer \"what's in my inbox\" or \"any new mail\", call list_emails (or\n mailbox_stats for just counts). uids come from these listings.\n2. uids are scoped to a (mailbox, folder) pair. Use the same folder you listed\n from when calling get_email / reply_email / delete_email.\n3. Always get_email before you reply or delete, so you act on the real content\n rather than the short preview.\n4. Prefer reply_email over send_email when responding to an existing thread —\n it preserves threading so the conversation stays intact.\n5. delete_email is irreversible. Only delete when explicitly asked, or when the\n task clearly calls for it.\n6. Bodies may be truncated in tool output; re-fetch with get_email for the full\n text when you need it.`;\n}\n"],"mappings":"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","names":["text"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailcue-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Model Context Protocol server for MailCue — gives an AI agent its own mailbox",
5
5
  "author": "Olib AI <hello@olib.ai>",
6
6
  "license": "MIT",