# Output Shapes — binding tool output structures ← Back to Index · ← Previous: Tools **Purpose:** While `README.md` and `docs/llms.txt` define the **inputs** for each tool, this file defines their **outputs**. It is part of the contract. Implementations must match exactly; deviations are bugs. **Conventions:** - All outputs are JSON-serializable. - Timestamps: ISO 8601 with offset (e.g. `2026-05-21T14:30:00+02:00`). - Addresses: always `{ name?: string, address: string }`. - UIDs: `number` (IMAP UIDs are 32-bit unsigned). - Flags: array of strings, IMAP notation (`\Seen`, `\Flagged`, custom keywords without backslash). - Errors are **not** modeled here — they arrive as structured errors (`{ code, message, details? }`, see `AGENTS.md`). - Optional fields are marked with `?`. When absent, the field is omitted (not `null`), unless explicitly noted otherwise. - Binary data (attachments) is never inlined as base64 in large lists — only on explicit request via `imap_download_attachment`. --- ## Common Sub-Types ```ts type Address = { name?: string; address: string }; type MessageEnvelope = { uid: number; seq?: number; // Sequence number, if available subject: string; from: Address[]; to: Address[]; cc?: Address[]; bcc?: Address[]; replyTo?: Address[]; date: string; // ISO 8601 messageId?: string; inReplyTo?: string; references?: string[]; flags: string[]; size: number; // Bytes hasAttachments: boolean; }; type AttachmentMeta = { partId: string; // IMAP body part (z. B. "2", "2.1") filename?: string; // RFC-2231-dekodiert contentType: string; // z. B. "application/pdf" size: number; // Bytes contentId?: string; // for inline / cid references disposition?: "inline" | "attachment"; }; type MailboxInfo = { path: string; // server-nativer Name, z. B. "INBOX", "[Gmail]/Sent Mail" delimiter: string; // Hierarchy separator, e.g. "/" or "." flags: string[]; // Mailbox-Flags specialUse?: string; // \\Inbox \\Sent \\Drafts \\Trash \\Junk \\Archive \\All \\Flagged subscribed: boolean; }; ``` --- ## IMAP — Lesen ### `imap_list_mailboxes` ```ts { mailboxes: MailboxInfo[] } ``` ### `imap_status_mailbox` ```ts { path: string; messages: number; // total unseen: number; recent: number; uidNext?: number; uidValidity?: number; } ``` ### `imap_list_messages` ```ts { mailbox: string; page: number; pageSize: number; total: number; // Gesamtanzahl im Folder messages: MessageEnvelope[]; } ``` ### `imap_get_message` ```ts { envelope: MessageEnvelope; text?: string; // text/plain Body, dekodiert html?: string; // text/html Body, dekodiert attachments: AttachmentMeta[]; // Metadata, NO binary data } ``` ### `imap_get_message_headers` ```ts { uid: number; headers: Record; // All headers, raw-decoded } ``` ### `imap_get_message_raw` ```ts { uid: number; rfc822: string; // Complete RFC-822 source } ``` ### `imap_get_messages_bulk` ```ts { mailbox: string; messages: Array<{ envelope: MessageEnvelope; text?: string; html?: string; attachments: AttachmentMeta[]; }>; notFound: number[]; // Requested UIDs that did not exist } ``` ### `imap_search` ```ts { mailbox: string; uids: number[]; // Treffer, aufsteigend sortiert count: number; } ``` ### `imap_download_attachment` ```ts { partId: string; filename?: string; contentType: string; size: number; // Exactly one of: savedPath?: string; // wenn save_path angegeben war base64?: string; // wenn kein save_path — Inhalt inline } ``` ### `imap_get_thread` ```ts { rootUid: number; mailbox: string; messages: MessageEnvelope[]; // chronologisch sortiert, inkl. des angefragten // Order follows the References / In-Reply-To chain, as far as resolvable } ``` ### `imap_get_quota` ```ts { root: string; usage: number; // KB belegt limit: number; // KB Limit, -1 = unlimitiert // weitere QUOTA-Resources, falls Server mehrere meldet: resources?: Array<{ name: string; usage: number; limit: number }>; } ``` ### `imap_check_capabilities` ```ts { capabilities: string[] } // z. B. ["IMAP4rev1", "IDLE", "MOVE", "CONDSTORE", ...] ``` --- ## IMAP — Schreiben All write tools return a uniform mutation report: ### `imap_mark_message` ```ts { uid: number; flags: string[] } // resultierende Flags nach STORE ``` ### `imap_bulk_mark` ```ts { modified: number; // Number of actually modified messages uids: number[]; // betroffene UIDs notFound: number[]; } ``` ### `imap_move_message` ```ts { fromMailbox: string; toMailbox: string; sourceUid: number; targetUid?: number; // neue UID im Ziel, falls vom Server gemeldet (UIDPLUS) } ``` ### `imap_copy_message` ```ts { fromMailbox: string; toMailbox: string; sourceUid: number; targetUid?: number; } ``` ### `imap_bulk_move` ```ts { fromMailbox: string; toMailbox: string; moved: number; uids: number[]; notFound: number[]; } ``` ### `imap_append_message` ```ts { mailbox: string; uid?: number; // UID of the created message (UIDPLUS), if available } ``` ### `imap_expunge` ```ts { mailbox: string; expunged: number } // Anzahl entfernter Messages ``` ### `imap_delete_message` ```ts { uid: number; mailbox: string; expunged: boolean; // true wenn auch EXPUNGE lief, false wenn nur \\Deleted gesetzt } ``` --- ## IMAP — Folder-CRUD Einheitlich: ### `imap_create_mailbox` ```ts { path: string; created: true } ``` ### `imap_delete_mailbox` ```ts { path: string; deleted: true } ``` ### `imap_rename_mailbox` ```ts { from: string; to: string; renamed: true } ``` ### `imap_subscribe_mailbox` ```ts { path: string; subscribed: true } ``` ### `imap_unsubscribe_mailbox` ```ts { path: string; subscribed: false } ``` --- ## SMTP Gemeinsame Sent-Ablage-Felder (bei `smtp_send`, `smtp_reply`, `smtp_forward`, `smtp_send_raw`): - `savedToSent: boolean` — Was a copy saved to the Sent folder? - `sentMailbox?: string` — in welchen Folder (falls abgelegt) - `sentSaveError?: string` — Send succeeded, but save to Sent failed (email was still delivered) ### `smtp_send` ```ts { messageId: string; // Message-ID der gesendeten Mail accepted: string[]; // Accepted recipient addresses rejected: string[]; // abgelehnte response: string; // SMTP-Server-Antwort (letzte Zeile) savedToSent: boolean; sentMailbox?: string; sentSaveError?: string; } ``` ### `smtp_reply` ```ts { messageId: string; inReplyTo: string; // Message-ID des Originals accepted: string[]; rejected: string[]; response: string; savedToSent: boolean; sentMailbox?: string; sentSaveError?: string; } ``` ### `smtp_forward` ```ts { messageId: string; accepted: string[]; rejected: string[]; response: string; savedToSent: boolean; sentMailbox?: string; sentSaveError?: string; } ``` ### `smtp_verify_connection` ```ts { ok: boolean; host: string; port: number; tls: "implicit" | "starttls" | "none"; latencyMs: number; } ``` ### `smtp_send_raw` ```ts { messageId?: string; // falls in der raw-Message gesetzt accepted: string[]; rejected: string[]; response: string; savedToSent: boolean; sentMailbox?: string; sentSaveError?: string; } ``` --- --- ## Meta — Server-Introspektion ### `meta_health` ```ts { account: string; imap: { ok: boolean; latencyMs?: number; capabilities?: string[]; error?: string }; smtp: { ok: boolean; latencyMs?: number; error?: string }; } ``` ### `meta_server_info` ```ts { name: "classic-imap-smtp-mcp"; version: string; // SemVer activeTools: string[]; // Namen der registrierten Tools flags: { safe: boolean; readonly: boolean; noImap: boolean; noSmtp: boolean; allowTools?: string[]; denyTools?: string[]; }; } ``` --- ## Note on MCP Serialization The MCP protocol delivers tool results as `content` blocks. These shapes are the **logical** output model. The server wraps them as JSON text content blocks (or structured content once the SDK supports it stably). Implementers: check what the current SDK version prefers as return path, and map the logical model accordingly — the field names and types above remain binding in any case. --- Next: Client Setup →