Skip to main content
Glama
GhostPawJS

GhostPaw Email

@ghostpaw/email

npm node license dependencies TypeScript MCP Registry

A standalone email engine for Node.js, built on SQLite.

Email treats IMAP sync, SMTP send, local caching, threading, search, and transport errors as one coherent model instead of a grab bag of protocol adapters. It ships as a single prebundled blob with zero runtime dependencies, designed for three audiences at once: human developers working directly in code, LLM agents operating through a structured soul / tools / skills runtime, and agent operators who want a ready-to-use email CLI binary without writing any wiring code.

MCP server

Every client below starts the same stdio server: npx -y @ghostpaw/email mcp. Cached messages live in ~/.ghostpaw/email.db unless the GHOSTPAW_EMAIL_DB environment variable (absolute path) or --db <path> says otherwise.

Claude Code

claude mcp add ghostpaw-email -- npx -y @ghostpaw/email mcp

or as a plugin, which also installs the skill:

/plugin marketplace add GhostPawJS/email
/plugin install ghostpaw-email@ghostpaw-email

Email CLI (~/.email/config.toml)

[mcp_servers.ghostpaw-email]
command = "npx"
args = ["-y", "@ghostpaw/email", "mcp"]

Cursor (.cursor/mcp.json), Claude Desktop (claude_desktop_config.json) or a project .mcp.json:

{
  "mcpServers": {
    "ghostpaw-email": {
      "command": "npx",
      "args": ["-y", "@ghostpaw/email", "mcp"]
    }
  }
}

Claude Desktop users can also install server.mcpb from the latest GitHub release. A Dockerfile is included for container hosts: docker build -t ghostpaw-email . && docker run -i --rm -v email:/data ghostpaw-email.

The server speaks MCP 2026-07-28 (stateless, server/discover) and the initialize-based revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05.

Network operations use the existing CLI account configuration (email account add) or EMAIL_IMAP_HOST, EMAIL_SMTP_HOST, EMAIL_USER and EMAIL_PASS (or EMAIL_ACCESS_TOKEN). Discovery and cached reads need no account or credentials. The surface database defaults to ~/.ghostpaw/email.db; point --db at an existing account cache to read it. Each network call opens and closes its IMAP session. Connection commands do not retain a session between calls.

Related MCP server: MailOKF MCP

Tool CLI

npx -y @ghostpaw/email tools
npx -y @ghostpaw/email call mail_read '{"view":"folders"}' --db :memory:
npx -y @ghostpaw/email call mail_search '{"query":"invoice"}'

Both email and ghostpaw-email run the same CLI. Existing account, read, search, compose, organize and sync commands remain available. The full guide is preserved in skills/email/references/cli.md.

Agent Skill: SKILL.md and skills/email/ ship in the package; print the skill with npx -y @ghostpaw/email skill.

Install

npm install @ghostpaw/email        # as a library
npm install -g @ghostpaw/email     # as a global CLI
npx @ghostpaw/email --help         # one-off, no install needed

Requires Node.js 24+ (uses the built-in node:sqlite module).

Quick Start

import { Mailbox } from '@ghostpaw/email';

const mailbox = new Mailbox({
  imap: { host: 'imap.example.com', port: 993, tls: true },
  smtp: { host: 'smtp.example.com', port: 465, tls: true },
  auth: { user: 'user@example.com', pass: 'secret' },
  storage: 'mail.db',
});

await mailbox.connect();

const folders = mailbox.read.folders();
await mailbox.network.sync();
const messages = mailbox.read.messages('INBOX', { limit: 20 });

await mailbox.write.send({
  to: [{ address: 'bob@example.com' }],
  subject: 'Hello',
  text: 'Sent from @ghostpaw/email.',
});

await mailbox.disconnect();

connect() opens the SQLite database, initialises the schema, upserts the account, and authenticates the IMAP session — one call does everything.

The Model

Seven stored concepts and three derived ones:

Concept

Purpose

Account

One email identity with IMAP/SMTP connection config

Folder

One IMAP mailbox path with sync metadata and role detection

Message

A locally cached email header record with flags, labels, and envelope

Body

The decoded text/html content and raw RFC 2822 bytes of one message

Attachment

A decoded MIME part with on-demand binary fetch

SyncLog

A record of one completed sync pass per folder

Thread

A JWZ conversation tree derived from References/In-Reply-To headers

The model means each kind of mail state has its own home:

What it looks like

What it actually is

An email inbox

A Folder with role: 'inbox' and synced messages

A conversation

A Thread computed from References and In-Reply-To chains

An unread email

A Message without \Seen in its flags array

A starred email

A Message with \Flagged in its flags

A PDF attached to a message

An Attachment with metadata from BODYSTRUCTURE and data fetched on demand

"Sync found 12 new messages"

A SyncLog row recording strategy, counts, and duration

State is derived, not toggled. Thread IDs are computed from header chains at sync time, folder roles are detected from IMAP special-use attributes, and attachment metadata is extracted from BODYSTRUCTURE — all materialised during sync, never stored as manual status fields.

Two Audiences

Human developers

Use the Mailbox class with typed read, write, and network surfaces for direct-code access to every mail operation:

import { Mailbox } from '@ghostpaw/email';

const mailbox = new Mailbox(config);
await mailbox.connect();

const threads = mailbox.read.threads('INBOX', { limit: 20 });
const detail = await mailbox.read.getMessage('INBOX', uid);
await mailbox.write.reply('INBOX', uid, { text: 'Acknowledged.' });
await mailbox.write.archive('INBOX', [uid]);

See HUMAN.md for the full human-facing guide with worked examples.

LLM agents

Use the tools, skills, and soul namespaces for a structured runtime surface designed to minimise LLM cognitive load:

import { skills, soul, tools } from '@ghostpaw/email';

// 5 intent-shaped tools covering the full mailbox lifecycle
const allTools = tools.aligned.emailTools;
const readTool = tools.aligned.getEmailToolByName('mail_read');

// 8 reusable workflow skills for multi-step scenarios
const triageSkill = skills.getEmailSkillByName('triage-inbox');

// Thinking foundation for system prompts
const systemPrompt = soul.renderEmailSoulPromptFoundation();

The shared facade exposes name, description, whenToUse, whenNotToUse, inputSchema, readOnly, and sideEffects. Handlers take a context containing read, write, and network surfaces and the existing tool input. They return { ok, outcome, summary, next, data }; data.entities contains the message or mailbox references, and next contains follow-up hints. Errors map to ok: false. Read operations may refresh the local cache, so metadata conservatively marks all tools as writing state.

const definitions = tools.aligned.listEmailToolDefinitions();
const tool = tools.aligned.getEmailToolByName('mail_read');
if (!tool) throw new Error('mail_read is unavailable');
const result = await tool.handler(
  { read: mailbox.read, write: mailbox.write, network: mailbox.network },
  { view: 'folders' },
);
console.log(result.ok, result.summary);

The deprecated tools.emailTools and tools.getEmailToolByName() remain available with the original { outcome, summary, entities, nextSteps } result and unchanged inputs. Migrate to tools.aligned to use the shared shape.

See LLM.md for the full AI-facing guide covering soul, tools, and skills.

CLI (bash)

The package ships as a standalone email binary. Accounts are stored in ~/.config/email/accounts.json and every command accepts --json for machine-readable output.

# Add an account once
email account add --name work \
  --imap-host imap.example.com --smtp-host smtp.example.com \
  --user you@example.com --pass secret

# Then use it
email sync                              # pull latest from server
email read                             # check inbox
email search "invoice"                 # FTS5 search
email compose send --to bob@example.com --subject "Hi" --body "Hello"

# Machine-readable output for agents and scripts
email read queue --json | jq '.entities[].title'
echo "body text" | email compose send --to bob@example.com --subject "Hi"

All commands return the same { outcome, summary, entities, nextSteps } shape as the tool layer, with consistent exit codes (0 success, 1 user error, 2 config, 3 auth, 4 network, 5 tool error).

See SKILL.md for the complete CLI reference for agent operators and Claude Code / OpenClaw users.

Tools

Five tools shaped around operator intent, not raw protocol operations:

Tool

What it does

mail_read

Read folder lists, message queues, threads, bodies, attachments, or raw EML

mail_search

FTS5 local search or IMAP SEARCH on the server

mail_compose

Send, reply, forward, save/update/send drafts

mail_organize

Flags, labels, copy, move, archive, trash, junk, folder management

mail_sync

Connect, disconnect, reconnect, sync, refresh folders, watch

Key Properties

  • Zero runtime dependencies. Only node:sqlite, node:tls, node:net, node:zlib, node:crypto (built into Node 24+).

  • Single prebundled blob. One ESM + one CJS entry in dist/. No subpath exports, no code splitting.

  • Pure SQLite storage. FTS5 full-text search, six tables, and deterministic derived reads. Mailbox creates and manages its own DatabaseSync instance.

  • Full IMAP engine. Streaming tokenizer, response parser, COMPRESS=DEFLATE, IDLE (RFC 2177), CONDSTORE/QRESYNC (RFC 7162), XOAUTH2/OAUTHBEARER.

  • Full SMTP client. TLS/STARTTLS/plaintext, PLAIN/LOGIN/XOAUTH2, dot stuffing, APPEND to Sent after send.

  • Fetch-on-demand bodies. Initial sync pulls headers and BODYSTRUCTURE only. Message bodies and attachment bytes are fetched when actually read.

  • JWZ threading. Conversation trees computed from References/In-Reply-To headers, with depth-ordered rendering and cross-folder support.

  • Intention-shaped writes. send, reply, forward, archive, trash, saveDraft, sendDraft — operations that say what happened, not generic CRUD.

  • Additive AI runtime. soul for posture, tools for actions, skills for workflow guidance — all optional, all structured.

  • Colocated tests. Every non-type module has a colocated .test.ts file. The documented behaviour is backed by executable coverage.

Package Surface

import {
  Mailbox,      // porcelain class — the primary entry point
  initSchema,   // schema setup (called automatically by Mailbox.connect())
  read,         // read surface factory
  write,        // write surface factory
  network,      // network surface factory
  tools,        // LLM tool definitions + registry
  skills,       // LLM workflow skills + registry
  soul,         // thinking foundation for system prompts
} from '@ghostpaw/email';

All domain and runtime types are also available at the root for TypeScript consumers:

import type {
  EmailConfig,
  AuthConfig,
  EmailReadSurface,
  EmailWriteSurface,
  EmailNetworkSurface,
  EmailToolDefinition,
  EmailToolResult,
  EmailSkill,
  EmailSoul,
  ComposeInput,
  ReplyInput,
  ForwardInput,
  Message,
  MessageDetail,
  Thread,
  Folder,
  Attachment,
  AttachmentMeta,
  SyncResult,
  WatchEvent,
} from '@ghostpaw/email';

Documentation

Document

Audience

SKILL.md

Agent operators and Claude Code users running email as a bash tool

HUMAN.md

Human developers using the Mailbox API with read / write / network

LLM.md

Agent builders wiring soul, tools, and skills into LLM systems

docs/README.md

Architecture overview: model, invariants, protocol boundaries, source layout

docs/entities/

Per-entity manuals with schema, operations, and invariants

Development

npm install
npm test            # node:test runner
npm run typecheck   # tsc --noEmit
npm run lint        # biome check
npm run build       # ESM + CJS + declarations via tsup

The repo is pinned to Node 24.14.0 via .nvmrc / .node-version / .tool-versions / mise.toml / Volta. Use whichever version manager you prefer.

Support

If this package helps your project, consider sponsoring its maintenance:

GitHub Sponsors


Anonyfox • MIT License

Related MCP Connectors

  • Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.

    https://www.primitive.dev/mcp
  • Email inboxes for AI agents: send, receive, reply, search, and manage threaded email over MCP.

    https://mcp.agentmail.to/mcp
  • Your IMAP mailbox as an MCP server: read, search and (if you allow it) organize mail. Open source.

    https://mcp4mail.online/mcp
  • Your agent needs a mailbox of its own — to receive, thread, draft and send, with attachments, without borrowing your personal inbox or your company's SMTP. **What you can ask for** • "Create an inbox for this agent and tell me its address." • "Read the new messages in this thread and draft a reply." • "Send this message with the attachment and wait for the response." • "Search this inbox for everything from that domain." • "Show delivery metrics and the events on this inbox." **How to use it** Point any MCP client at https://mcp.aisa.one/mail/mcp and sign in with OAuth — there is no key to create or paste. 49 tools: create and delete inboxes, list and read messages, raw message bodies, attachments, threads, drafts and draft attachments, send and reply, message search, inbox events, metrics, and list entries — reads and writes. **Why this rather than the source** A real inbox an agent owns, rather than an SMTP credential it borrows from a human. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Find the contact elsewhere in the catalogue, then write to them from here — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/sales/mcp finds the person to write to.

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A local MCP server that provides LLM clients with read/write access to email and calendar data from Gmail, iCloud, and generic IMAP providers. It runs entirely on your machine, keeping data private while enabling email management, calendar operations, and task handling through natural language.
    39
    MIT
  • A
    license
    C
    quality
    B
    maintenance
    A local-first Python MCP server that turns Gmail, Outlook/Microsoft 365, iCloud Mail, and generic IMAP/SMTP mailboxes into a synchronized, searchable OKF knowledge layer, exposing 38 tools and four resources for mailbox actions, synchronization, retrieval, attachments, and optional semantic search while keeping the provider mailbox authoritative.
    38
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A self-hosted, multi-mailbox MCP server that exposes IMAP/SMTP operations as tools for AI agents, enabling email management like listing folders, reading, searching, sending, and moving messages via natural language.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Local IMAP control plane for AI agents, providing an HTTP API and MCP tools to read, search, move, flag, and optionally send emails, with support for iCloud and generic IMAP accounts.
    MIT