mcpField
G
GhostPaw Email

GhostPaw Email

Local
email.ghostpaw.devCommunication1Updated 1d ago

About GhostPaw Email

GhostPaw Email is a Node.js email engine for developers and AI agents, combining IMAP/SMTP operations with a SQLite cache and structured tools for reading, searching, sending, and organizing mail.

Key features

  1. 01IMAP sync and SMTP sending
  2. 02SQLite cache and full-text search
  3. 03Threaded messages and on-demand bodies
  4. 04Tools for reading, composing, and organizing
  5. 05CLI, library, and agent skills

Use cases

  1. 01Search cached mail or IMAP messages
  2. 02Read threads, bodies, and attachments
  3. 03Compose, reply to, or forward email
  4. 04Sync and organize mailbox folders

MCP support

The MCP server exposes email tools to MCP clients over stdio, including reading, searching, composing, organizing, and syncing mail. Cached reads and discovery do not require account credentials.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"ghostpawjs-email": {
"command": "npx",
"args": [
"-y",
"@ghostpaw/email"
],
"env": {
"GHOSTPAW_EMAIL_DB": "<GHOSTPAW_EMAIL_DB>"
}
}
}
}
Run commandnpx -y @ghostpaw/email
Environment variables to set
GHOSTPAW_EMAIL_DBSQLite database path (default: ~/.ghostpaw/email.db)

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npm@ghostpaw/email0.5.10

Tools

5

Saved tool list · updated today

ParameterTypeRequiredDescription
uidintegerNoMessage UID (required for message/attachment/eml).
viewenumYesWhat to read.folders | queue | thread | message | attachment | eml
limitintegerNoMaximum messages to return (queue view).
folderstringNoFolder path (required for queue/message/attachment/eml).
refreshbooleanNoFetch live folder list from server before returning (folders/queue view).
partPathstringNoPart path for a specific attachment (optional for attachment view).
threadIdstringNoThread ID (required for thread view).
unreadOnlybooleanNoFilter to unread messages only (queue view).

Details

From the project README

GhostPaw email: Your agent can read the inbox. Sending is a separate tool.

@ghostpaw/email

npm CI site runtime deps MCP Registry node license

Agent email: IMAP and SMTP in-process, cached in SQLite, with reading and sending as separate tools.

npm install @ghostpaw/email

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.

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: '[email protected]', 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: '[email protected]' }],
  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:

ConceptPurpose
AccountOne email identity with IMAP/SMTP connection config
FolderOne IMAP mailbox path with sync metadata and role detection
MessageA locally cached email header record with flags, labels, and envelope
BodyThe decoded text/html content and raw RFC 2822 bytes of one message
AttachmentA decoded MIME part with on-demand binary fetch
SyncLogA record of one completed sync pass per folder
ThreadA 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 likeWhat it actually is
An email inboxA Folder with role: 'inbox' and synced messages
A conversationA Thread computed from References and In-Reply-To chains
An unread emailA Message without \Seen in its flags array
A starred emailA Message with \Flagged in its flags
A PDF attached to a messageAn 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 [email protected] --pass secret

# Then use it
email sync                              # pull latest from server
email read                             # check inbox
email search "invoice"                 # FTS5 search
email compose send --to [email protected] --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 [email protected] --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:

ToolWhat it does
mail_readRead folder lists, message queues, threads, bodies, attachments, or raw EML
mail_searchFTS5 local search or IMAP SEARCH on the server
mail_composeSend, reply, forward, save/update/send drafts
mail_organizeFlags, labels, copy, move, archive, trash, junk, folder management
mail_syncConnect, 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

DocumentAudience
SKILL.mdAgent operators and Claude Code users running email as a bash tool
HUMAN.mdHuman developers using the Mailbox API with read / write / network
LLM.mdAgent builders wiring soul, tools, and skills into LLM systems
docs/README.mdArchitecture 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

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.