mcp-agent-mail 0.1.0
Coordinated multi-agent messaging and coordination MCP server.
License: MIT
Requires Python: >=3.11

# MCP Agent Mail

![Agent Mail Showcase](screenshots/output/agent_mail_showcase.gif)

> "It's like gmail for your coding agents!"

## Fork Improvements

This fork extends the [original MCP Agent Mail](https://github.com/Dicklesworthstone/mcp_agent_mail) with several production-ready enhancements:

- **🚀 Lazy Loading System (Phase 2)** - Reduces token usage by ~65% with core mode (10 essential tools vs. 27), plus meta-tools (`list_extended_tools`, `call_extended_tool`) for dynamic tool discovery and invocation
- **🎯 Globally Unique Agent Names** - Prevents agent name confusion across projects with database-enforced uniqueness, flexible coerce/strict enforcement modes, and automatic migration for existing deployments
- **⚡ Simplified Registration** - `register_agent` now auto-creates projects, eliminating the need for separate `ensure_project` calls in most workflows
- **🔧 Flexible Project Keys** - Supports any string identifier (repo names, custom IDs) as project keys, not just absolute paths
- **💬 Contact-Free Messaging** - Direct agent-to-agent messaging without contact request approval, streamlining multi-agent coordination

These improvements make the system more efficient, flexible, and easier to use in production multi-agent workflows.

---

A mail-like coordination layer for coding agents, exposed as an HTTP-only FastMCP server. It gives agents memorable identities, an inbox/outbox, searchable message history, and voluntary file reservation "leases" to avoid stepping on each other.

Think of it as asynchronous email + directory + change-intent signaling for your agents, backed by Git (for human-auditable artifacts) and SQLite (for indexing and queries).

Status: Under active development. The design is captured in detail in `project_idea_and_guide.md` (start with the original prompt at the top of that file).

## Why this exists

Modern projects often run multiple coding agents at once (backend, frontend, scripts, infra). Without a shared coordination fabric, agents:

- Overwrite each other's edits or panic on unexpected diffs
- Miss critical context from parallel workstreams
- Require humans to "liaison" messages across tools and teams

This project provides a lightweight, interoperable layer so agents can:

- Register a temporary-but-persistent identity (e.g., GreenCastle)
- Send/receive GitHub-Flavored Markdown messages with images
- Search, summarize, and thread conversations
- Declare advisory file reservations (leases) on files/globs to signal intent
- Inspect a directory of active agents, programs/models, and activity

It's designed for: FastMCP clients and CLI tools (Claude Code, Codex, Gemini CLI, etc.) coordinating across one or more codebases.

## TLDR Quickstart

### One-line installer

```bash
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/mcp_agent_mail/main/scripts/install.sh | bash -s -- --yes
```

What this does:

- Installs uv if missing and updates your PATH for this session
- Creates a Python 3.14 virtual environment and installs dependencies with uv
- Runs the auto-detect integration to wire up supported agent tools
- Starts the MCP HTTP server on port 8765 and prints a masked bearer token
- Creates helper scripts under `scripts/` (including `run_server_with_token.sh`)

Prefer a specific location or options? Add flags like `--dir <path>`, `--project-dir <path>`, `--no-start`, `--start-only`, `--port <number>`, or `--token <hex>`.

**Port conflicts?** Use `--port` to specify a different port (default: 8765):

```bash
# Install with custom port
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/mcp_agent_mail/main/scripts/install.sh | bash -s -- --port 9000 --yes

# Or use the CLI command after installation
uv run python -m mcp_agent_mail.cli config set-port 9000
```

### If you want to do it yourself

Clone the repo, set up and install with uv in a python 3.14 venv (install uv if you don't have it already), and then run `scripts/automatically_detect_all_installed_coding_agents_and_install_mcp_agent_mail_in_all.sh`. This will automatically set things up for your various installed coding agent tools and start the MCP server on port 8765. If you want to run the MCP server again in the future, simply run `scripts/run_server_with_token.sh`:

```bash
# Install uv (if you don't have it already)
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"

# Clone the repo
git clone https://github.com/Dicklesworthstone/mcp_agent_mail
cd mcp_agent_mail

# Create a Python 3.14 virtual environment and install dependencies
uv python install 3.14
uv venv -p 3.14
source .venv/bin/activate
uv sync

# Detect installed coding agents, integrate, and start the MCP server on port 8765
scripts/automatically_detect_all_installed_coding_agents_and_install_mcp_agent_mail_in_all.sh

# Later, to run the MCP server again with the same token
scripts/run_server_with_token.sh

# Now, simply launch Codex-CLI or Claude Code or other agent tools in other consoles; they should have the mail tool available. See below for a ready-made chunk of text you can add to the end of your existing AGENTS.md or CLAUDE.md files to help your agents better utilize the new tools.

# Change port after installation
uv run python -m mcp_agent_mail.cli config set-port 9000
```

## Ready-Made Blurb to Add to Your AGENTS.md or CLAUDE.md Files:
```
## MCP Agent Mail: coordination for multi-agent workflows

What it is
- A mail-like layer that lets coding agents coordinate asynchronously via MCP tools and resources.
- Provides identities, inbox/outbox, searchable threads, and advisory file reservations, with human-auditable artifacts in Git.

Why it's useful
- Prevents agents from stepping on each other with explicit file reservations (leases) for files/globs.
- Keeps communication out of your token budget by storing messages in a per-project archive.
- Offers quick reads (`resource://inbox/...`, `resource://thread/...`) and macros that bundle common flows.

How to use effectively
1) Same repository
   - Register an identity: call `ensure_project`, then `register_agent` using this repo's absolute path as `project_key`.
   - Reserve files before you edit: `file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true)` to signal intent and avoid conflict.
   - Communicate with threads: use `send_message(..., thread_id="FEAT-123")`; check inbox with `fetch_inbox` and acknowledge with `acknowledge_message`.
   - Read fast: `resource://inbox/{Agent}?project=<abs-path>&limit=20` or `resource://thread/{id}?project=<abs-path>&include_bodies=true`.
   - Tip: set `AGENT_NAME` in your environment so the pre-commit guard can block commits that conflict with others' active exclusive file reservations.

2) Across different repos in one project (e.g., Next.js frontend + FastAPI backend)
   - Option A (single project bus): register both sides under the same `project_key` (shared key/path). Keep reservation patterns specific (e.g., `frontend/**` vs `backend/**`).
   - Option B (separate projects): each repo has its own `project_key`; agents can message each other directly using `send_message` with cross-project addressing. Keep a shared `thread_id` (e.g., ticket key) across repos for clean summaries/audits.

Macros vs granular tools
- Prefer macros when you want speed or are on a smaller model: `macro_start_session`, `macro_prepare_thread`, `macro_file_reservation_cycle`, `macro_contact_handshake`.
- Use granular tools when you need control: `register_agent`, `file_reservation_paths`, `send_message`, `fetch_inbox`, `acknowledge_message`.

Common pitfalls
- "from_agent not registered": always `register_agent` in the correct `project_key` first.
- "FILE_RESERVATION_CONFLICT": adjust patterns, wait for expiry, or use a non-exclusive reservation when appropriate.
- Auth errors: if JWT+JWKS is enabled, include a bearer token with a `kid` that matches server JWKS; static bearer is used only when JWT is disabled.
```

## Integrating with Beads (dependency-aware task planning)

Beads is a lightweight task planner (`bd` CLI) that complements Agent Mail by keeping status and dependencies in one place while Mail handles messaging, file reservations, and audit trails. Project: [steveyegge/beads](https://github.com/steveyegge/beads)

Highlights:
- Beads owns task prioritization; Agent Mail carries the conversations and artifacts.
- Shared identifiers (e.g., `bd-123`) keep Beads issues, Mail threads, and commits aligned.
- Install the `bd` CLI via prebuilt release or Go build; see the repository for platform specifics.

Copy/paste blurb for agent-facing docs (leave as-is for reuse):

```

## Integrating with Beads (dependency-aware task planning)

Beads provides a lightweight, dependency-aware issue database and a CLI (`bd`) for selecting "ready work," setting priorities, and tracking status. It complements MCP Agent Mail's messaging, audit trail, and file-reservation signals. Project: [steveyegge/beads](https://github.com/steveyegge/beads)

Recommended conventions
- **Single source of truth**: Use **Beads** for task status/priority/dependencies; use **Agent Mail** for conversation, decisions, and attachments (audit).
- **Shared identifiers**: Use the Beads issue id (e.g., `bd-123`) as the Mail `thread_id` and prefix message subjects with `[bd-123]`.
- **Reservations**: When starting a `bd-###` task, call `file_reservation_paths(...)` for the affected paths; include the issue id in the `reason` and release on completion.

Typical flow (agents)
1) **Pick ready work** (Beads)
   - `bd ready --json` → choose one item (highest priority, no blockers)
2) **Reserve edit surface** (Mail)
   - `file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true, reason="bd-123")`
3) **Announce start** (Mail)
   - `send_message(..., thread_id="bd-123", subject="[bd-123] Start: <short title>", ack_required=true)`
4) **Work and update**
   - Reply in-thread with progress and attach artifacts/images; keep the discussion in one thread per issue id
5) **Complete and release**
   - `bd close bd-123 --reason "Completed"` (Beads is status authority)
   - `release_file_reservations(project_key, agent_name, paths=["src/**"])`
   - Final Mail reply: `[bd-123] Completed` with summary and links

Mapping cheat-sheet
- **Mail `thread_id`** ↔ `bd-###`
- **Mail subject**: `[bd-###] …`
- **File reservation `reason`**: `bd-###`
- **Commit messages (optional)**: include `bd-###` for traceability

Event mirroring (optional automation)
- On `bd update --status blocked`, send a high-importance Mail message in thread `bd-###` describing the blocker.
- On Mail "ACK overdue" for a critical decision, add a Beads label (e.g., `needs-ack`) or bump priority to surface it in `bd ready`.

Pitfalls to avoid
- Don't create or manage tasks in Mail; treat Beads as the single task queue.
- Always include `bd-###` in message `thread_id` to avoid ID drift across tools.

```

## Core ideas (at a glance)

- HTTP-only FastMCP server (Streamable HTTP). No SSE, no STDIO.
- Dual persistence model:
  - Human-readable markdown in a per-project Git repo for every canonical message and per-recipient inbox/outbox copy
  - SQLite with FTS5 for fast search, directory queries, and file reservations/leases
- "Directory/LDAP" style queries for agents; auto-generated adjective+noun codenames keep things memorable (custom alphanumeric names are also allowed)
- Advisory file reservations for editing surfaces; optional pre-commit guard
- Resource layer for convenient reads (e.g., `resource://inbox/{agent}`)

## Typical use cases

- Multiple agents splitting a large refactor across services while staying in sync
- Frontend and backend teams of agents coordinating thread-by-thread
- Protecting critical migrations with exclusive file reservations and a pre-commit guard
- Searching and summarizing long technical discussions as threads evolve
- Discovering and linking related projects (e.g., frontend/backend) through AI-powered suggestions

## Architecture

```mermaid
graph LR
  A[Agents]
  S[Server]
  G[Git repo]
  Q[SQLite FTS5]

  A -->|HTTP tools/resources| S
  S -->|writes/reads| G
  S -->|indexes/queries| Q

  subgraph GitTree["Git tree"]
    GI1[agents/profile.json]
    GI2[agents/mailboxes/...]
    GI3[messages/YYYY/\nMM/\nid.md]
    GI4[file_reservations/\nsha1.json]
    GA[attachments/xx/\nsha1.webp]
  end

  G --- GI1
  G --- GI2
  G --- GI3
  G --- GI4
  G --- GA
```

## Web UI (human-facing mail viewer)

The server ships a lightweight, server-rendered Web UI for humans. It lets you browse projects, agents, inboxes, single messages, attachments, file reservations, and perform full-text search with FTS5 when available (with an automatic LIKE fallback).

- Where it lives: built into the HTTP server in `mcp_agent_mail.http` under the `/mail` path.
- Who it's for: humans reviewing activity; agents should continue to use the MCP tools/resources API.

### Launching the Web UI

Recommended (simple):

```bash
scripts/run_server_with_token.sh
# then open http://127.0.0.1:8765/mail
```

Advanced (manual commands):

```bash
uv run python -m mcp_agent_mail.http --host 127.0.0.1 --port 8765
# or:
uv run uvicorn mcp_agent_mail.http:build_http_app --factory --host 127.0.0.1 --port 8765
```

Auth notes:
- GET pages in the UI are not gated by the RBAC middleware (it classifies POSTed MCP calls only), but if you set a bearer token the separate BearerAuth middleware protects all routes by default.
- For local dev, set `HTTP_ALLOW_LOCALHOST_UNAUTHENTICATED=true` (and optionally `HTTP_BEARER_TOKEN`), so localhost can load the UI without headers.
- Health endpoints are always open at `/health/*`.

### Routes and what you can do

- `/mail` (Unified inbox + Projects + Related Projects Discovery)
  - Shows a unified, reverse-chronological inbox of recent messages across all projects with excerpts, relative timestamps, sender/recipients, and project badges.
  - Below the inbox, lists all projects (slug, human name, created time) with sibling suggestions.
  - Suggests **likely sibling projects** when two slugs appear to be parts of the same product (e.g., backend vs. frontend). Suggestions are ranked with heuristics and, when `LLM_ENABLED=true`, an LLM pass across key docs (`README.md`, `AGENTS.md`, etc.).
  - Humans can **Confirm Link** or **Dismiss** suggestions from the dashboard. Confirmed siblings become highlighted badges for organizational clarity. Agents can message across projects directly without requiring contact approval.

- `/mail/projects` (Projects index)
  - Dedicated projects list view; click a project to drill in.

- `/mail/{project}` (Project overview + search + agents)
  - Rich search form with filters:
    - Scope: subject/body/both, Order: relevance or time, optional "boost subject".
    - Query tokens: supports `subject:foo`, `body:"multi word"`, quoted phrases, and bare terms.
    - Uses FTS5 bm25 scoring when available; otherwise falls back to SQL LIKE on subject/body with your chosen scope.
  - Results show subject, sender, created time, thread id, and a highlighted snippet when using FTS.
  - Agents panel shows registered agents for the project with a link to each inbox.
  - Quick links to File Reservations and Attachments for the project header.

- `/mail/{project}/inbox/{agent}` (Inbox for one agent)
  - Reverse-chronological list with subject, sender, created time, importance badge, thread id.
  - Pagination (`?page=N&limit=M`).

- `/mail/{project}/message/{id}` (Message detail)
  - Shows subject, sender, created time, importance, recipients (To/Cc/Bcc), thread messages.
  - Body rendering:
    - If the server pre-converted markdown to HTML, it's sanitized with Bleach (limited tags/attributes, safe CSS via CSSSanitizer) and then displayed.
    - Otherwise markdown is rendered client-side with Marked + Prism for code highlighting.
  - Attachments are referenced from the message frontmatter (WebP files or inline data URIs).

- `/mail/{project}/search?q=...` (Dedicated search page)
  - Same query syntax as the project overview search, with a token "pill" UI for assembling/removing filters.

- `/mail/{project}/file_reservations` (File Reservations list)
  - Displays active and historical file reservations (exclusive/shared, path pattern, timestamps, released/expired state).

- `/mail/{project}/attachments` (Messages with attachments)
  - Lists messages that contain any attachments, with subject and created time.
  
- `/mail/unified-inbox` (Cross-project activity)
  - Shows recent messages across all projects with thread counts and sender/recipients.

### Human Overseer: Sending Messages to Agents

Sometimes a human operator needs to guide or redirect agents directly, whether to handle an urgent issue, provide clarification, or adjust priorities. The **Human Overseer** feature provides a web-based message composer that lets humans send high-priority messages to any combination of agents in a project.

**Access:** Click the prominent **"Send Message"** button (with the Overseer badge) in the header of any project view (`/mail/{project}`), or navigate directly to `/mail/{project}/overseer/compose`.

#### What Makes Overseer Messages Special

1. **Automatic Preamble**: Every message includes a formatted preamble that clearly identifies it as coming from a human operator and instructs agents to:
   - **Pause current work** temporarily
   - **Prioritize the human's request** over existing tasks
   - **Resume original plans** afterward (unless modified by the instructions)

2. **High Priority**: All overseer messages are automatically marked as **high importance**, ensuring they stand out in agent inboxes.

3. **Policy Bypass**: Overseer messages bypass normal contact policies, so humans can always reach any agent regardless of their contact settings.

4. **Special Sender Identity**: Messages come from a special agent named **"HumanOverseer"** (automatically created per project) with:
   - Program: `WebUI`
   - Model: `Human`
   - Contact Policy: `open`

#### The Message Preamble

Every overseer message begins with this preamble (automatically prepended):

```
---

🚨 MESSAGE FROM HUMAN OVERSEER 🚨

This message is from a human operator overseeing this project. Please prioritize
the instructions below over your current tasks.

You should:
1. Temporarily pause your current work
2. Complete the request described below
3. Resume your original plans afterward (unless modified by these instructions)

The human's guidance supersedes all other priorities.

---

[Your message body follows here]
```

#### Using the Composer

The composer interface provides:

- **Recipient Selection**: Checkbox grid of all registered agents (with "Select All" / "Clear" shortcuts)
- **Subject Line**: Required, shown in agent inboxes
- **Message Body**: GitHub-flavored Markdown editor with preview
- **Thread ID** (optional): Continue an existing conversation or start a new one
- **Preamble Preview**: See exactly how your message will appear to agents

#### Example Use Cases

**Urgent Issue:**
```
Subject: Urgent: Stop migration and revert changes

The database migration in PR #453 is causing data corruption in staging.

Please:
1. Immediately stop any migration-related work
2. Revert commits from the last 2 hours
3. Wait for my review before resuming

I'm investigating the root cause now.
```

**Priority Adjustment:**
```
Subject: New Priority: Security Vulnerability

A critical security vulnerability was just disclosed in our auth library.

Drop your current tasks and:
1. Update `auth-lib` to version 2.4.1 immediately
2. Review all usages in src/auth/
3. Run the full security test suite
4. Report status in thread #892

This takes precedence over the refactoring work.
```

**Clarification:**
```
Subject: Clarification on API design approach

I see you're debating REST vs. GraphQL in thread #234.

Go with REST for now because:
- Our frontend team has more REST experience
- GraphQL adds complexity we don't need yet
- We can always add GraphQL later if needed

Resume the API implementation with REST.
```

#### How Agents See Overseer Messages

When agents check their inbox (via `fetch_inbox` or `resource://inbox/{name}`), overseer messages appear like any other message but with:

- **Sender**: `HumanOverseer`
- **Importance**: `high` (displayed prominently)
- **Body**: Starts with the overseer preamble, followed by the human's message
- **Visual cues**: In the Web UI, these messages may have special highlighting (future enhancement)

Agents can reply to overseer messages just like any other message, continuing the conversation thread.

#### Technical Details

- **Storage**: Overseer messages are stored identically to agent-to-agent messages (Git + SQLite)
- **Git History**: Fully auditable; message appears in `messages/YYYY/MM/{id}.md` with commit history
- **Thread Continuity**: Can be part of existing threads or start new ones
- **No Authentication Bypass**: The overseer compose form still requires proper HTTP server authentication (if enabled)

#### Design Philosophy

The Human Overseer feature is designed to be:

- **Explicit**: Agents clearly know when guidance comes from a human vs. another agent
- **Respectful**: Instructions acknowledge agents have existing work and shouldn't just "drop everything" permanently
- **Temporary**: Agents are told to resume original plans once the human's request is complete
- **Flexible**: Humans can override this guidance directly in their message body

This creates a clear hierarchy (human → agents) while maintaining the collaborative, respectful tone of the agent communication system.

### Related Projects Discovery

The Projects index (`/mail`) features an **AI-powered discovery system** that intelligently suggests which projects should be linked together, such as frontend + backend or related microservices.

#### How Discovery Works

**1. Smart Analysis**
The system uses multiple signals to identify relationships:
- **Pattern matching**: Compares project names and paths (e.g., "my-app-frontend" ↔ "my-app-backend")
- **AI understanding** (when `LLM_ENABLED=true`): Reads `README.md`, `AGENTS.md`, and other docs to understand each project's purpose and detect natural relationships
- **Confidence scoring**: Ranks suggestions from 0-100% with clear rationales

**2. Beautiful Suggestions**
Related projects appear as polished cards on your dashboard with:
- 🎯 Visual confidence indicators showing match strength
- 💬 AI-generated rationales explaining the relationship
- ✅ **Confirm Link** - accept the suggestion
- ✖️ **Dismiss** - hide irrelevant matches

**3. Quick Navigation**
Once confirmed, both projects display interactive badges for instant navigation between related codebases.

#### Why Suggestions, Not Auto-Linking?

> **TL;DR**: We keep you in control. Discovery helps you find relationships; explicit approvals control who can actually communicate.

**Agent Mail uses agent-centric messaging**: every message follows explicit permission chains:

```
Send Message → Find Recipient → Check AgentLink Approval → Deliver
```

This design ensures:
- **Security**: No accidental cross-project message delivery
- **Transparency**: You always know who can talk to whom
- **Audit trails**: All communication paths are explicitly approved

**Why not auto-link with AI?**
If we let an LLM automatically authorize messaging between projects, we'd be:
- ❌ Bypassing contact policies without human oversight
- ❌ Risking message misdelivery to unintended recipients
- ❌ Creating invisible routing paths that are hard to audit
- ❌ Potentially linking ambiguously-named projects incorrectly

Instead, we give you **discovery + control**:
- ✅ AI suggests likely relationships (safe, read-only analysis)
- ✅ You confirm what makes sense (one click)
- ✅ Confirmed links update UI badges for better organization
- ✅ Agents can message across projects directly without additional approval

#### The Workflow

```text
1. System suggests: "These projects look related" (AI analysis)
           ↓
2. You confirm: "Yes, link them" (updates UI badges for clarity)
           ↓
3. Agents communicate: send_message with cross-project addressing
```

**NOTE:** Contact approval is no longer required. Agents can send messages across projects directly.

### Search syntax (UI)

The UI shares the same parsing as the API's `_parse_fts_query`:
- Field filters: `subject:login`, `body:"api key"`
- Phrase search: `"build plan"`
- Combine terms: `login AND security` (FTS)
- Fallback LIKE: scope determines whether subject, body, or both are searched

### Prerequisites to see data

The UI reads from the same SQLite + Git artifacts as the MCP tools. To populate content:
1) Ensure a project exists (via tool call or CLI):
   - Ensure/create project: `ensure_project(human_key)`
2) Register one or more agents: `register_agent(project_key, program, model, name?)`
3) Send messages: `send_message(...)` (attachments and inline images are supported; images may be converted to WebP).

Once messages exist, visit `/mail`, click your project, then open an agent inbox or search.

### Implementation and dependencies

- Templates live in `src/mcp_agent_mail/templates/` and are rendered by Jinja2.
- Markdown is converted with `markdown2` on the server where possible; HTML is sanitized with Bleach (with CSS sanitizer when available).
- Tailwind CSS, Lucide icons, Alpine.js, Marked, and Prism are loaded via CDN in `base.html` for a modern look without a frontend build step.
- All rendering is server-side; there's no SPA router. Pages degrade cleanly without JavaScript.

### Security considerations

- HTML sanitization: Only a conservative set of tags/attributes are allowed; CSS is filtered. Links are limited to http/https/mailto/data.
- Auth: Use bearer token or JWT when exposing beyond localhost. For local dev, enable localhost bypass as noted above.
- Rate limiting (optional): Token-bucket limiter can be enabled; UI GET requests are light and unaffected by POST limits.

### Troubleshooting the UI

- Blank page or 401 on localhost: Either unset `HTTP_BEARER_TOKEN` or set `HTTP_ALLOW_LOCALHOST_UNAUTHENTICATED=true`.
- No projects listed: Create one with `ensure_project`.
- Empty inbox: Verify recipient names match exactly and messages were sent to that agent.
- Search returns nothing: Try simpler terms or the LIKE fallback (toggle scope/body).

## Static Mailbox Export (Share & Distribute Archives)

The `share` command group provides a complete pipeline for exporting mailbox archives into self-contained static HTML bundles. These bundles can be distributed to stakeholders, auditors, or team members who need read-only access to message history without running the full MCP Agent Mail server.

### Why export to static bundles?

**Compliance and audit trails**: Deliver immutable snapshots of project communication to auditors or compliance officers. The static bundle includes cryptographic signatures for tamper-evident distribution.

**Stakeholder review**: Share conversation history with product managers, executives, or external consultants who don't need write access. They can browse messages, search threads, and view attachments in their browser without authentication.

**Offline access**: Create portable archives for air-gapped environments, disaster recovery backups, or situations where internet connectivity is unreliable.

**Long-term archival**: Preserve project communication in a format that will remain readable decades from now. Static HTML requires no database server, no runtime dependencies, and survives software obsolescence better than proprietary formats.

**Secure distribution**: Encrypt bundles with age for confidential projects. Only recipients with the private key can decrypt and view the contents.

### What's included in an export

Each bundle contains:

- **Static HTML viewer**: A single-page application with three-pane interface (projects, threads, messages) that runs entirely in the browser. No server required after the initial file serving.
- **SQLite database snapshot**: A read-only copy of the messages, agents, and metadata, loaded via SQL.js (WebAssembly).
- **Full-text search**: FTS5 search index embedded in the database allows fast subject/body searches entirely client-side.
- **Attachments**: Images and files, either bundled directly (for small files) or marked as external references (for large files).
- **Integrity metadata**: SHA-256 hashes for all assets (vendor libraries, database, attachments) stored in `manifest.json` for verification.
- **Optional signature**: Ed25519 cryptographic signature over the manifest to prove authenticity and detect tampering.
- **Security hardening**: Content Security Policy headers, DOMPurify sanitization, and Trusted Types enforcement protect against XSS attacks in message bodies.

### Quick Start: Interactive Deployment Wizard

The easiest way to export and deploy is the interactive wizard, which supports both GitHub Pages and Cloudflare Pages:

```bash
# Via CLI (recommended)
uv run python -m mcp_agent_mail.cli share wizard

# Or run the script directly
./scripts/share_to_github_pages.py
```

#### What the wizard does

The wizard provides a fully automated end-to-end deployment experience:

1. **Configuration management**: Remembers your last settings and offers to reuse them, saving time on repeated exports
2. **Deployment target selection**: Choose between GitHub Pages, Cloudflare Pages, or local export
3. **Automatic CLI installation**: Detects and installs missing tools (`gh` for GitHub, `wrangler` for Cloudflare)
4. **Guided authentication**: Step-by-step browser login flows for GitHub and Cloudflare
5. **Smart project selection**:
   - Shows all available projects in a formatted table
   - Supports multiple selection modes: `all`, single number (`1`), lists (`1,3,5`), or ranges (`1-3`, `2-5,8`)
   - Remembers your previous selection for quick re-export
6. **Redaction configuration**: Choose between `standard` (scrub secrets like API keys/tokens, keep agent names) or `strict` (redact all message bodies)
7. **Cryptographic signing**: Optional Ed25519 signing with automatic key generation or use your existing key
8. **Pre-flight validation**: Checks that GitHub repo names are available before starting the export
9. **Deployment summary**: Shows what will be deployed (project count, bundle size, target, signing status) and asks for confirmation
10. **Export and preview**: Exports the bundle and launches a local preview server with automatic port detection (tries 9000-9100)
11. **Real-time deployment**: Streams git and deployment output in real-time so you can follow the progress
12. **Automatic deployment**: Creates repos, enables Pages, pushes code, and gives you the live URL

#### Configuration persistence

The wizard saves your configuration to `~/.mcp-agent-mail/wizard-config.json` after each successful deployment. On subsequent runs, it will show:

```
Previous Configuration Found
  Projects: 3 selected
  Redaction: standard
  Target: github-new

Use these settings again? (Y/n):
```

This allows rapid re-deployment with the same settings. The saved configuration includes:
- Selected project indices (validates against current project list)
- Redaction preset
- Deployment target and parameters (repo name, privacy, project name)
- Signing preferences (whether to sign, whether to generate new key)

Configuration is project-agnostic: if you add or remove projects, the wizard validates saved indices and prompts for re-selection if needed.

#### Multi-project selection

The project selector supports flexible selection syntax:

```
Available Projects:
#  Slug                Path
1  backend-abc123      /abs/path/backend
2  frontend-xyz789     /abs/path/frontend
3  infra-def456        /abs/path/infra
4  scripts-ghi789      /abs/path/scripts

Select projects to export (e.g., 'all', '1,3,5', or '1-3'):
```

**Selection modes:**
- `all`: Export all projects (default)
- `1`: Export project #1 only
- `1,3,5`: Export projects #1, #3, and #5
- `1-3`: Export projects #1, #2, and #3 (inclusive range)
- `2-4,7`: Export projects #2, #3, #4, and #7 (combined range and list)

Invalid selections (out of range, malformed) are rejected with helpful error messages and the wizard prompts again.

#### Dynamic port allocation

The preview server automatically detects an available port in the range 9000-9100 instead of failing if port 9000 is in use. The actual port is displayed:

```
Launching preview server...
Using port 9001 (Ctrl+C to stop server)
Waiting for server to start...
✓ Server ready, opening browser at http://127.0.0.1:9001
```

This prevents port conflicts when multiple previews are running or when port 9000 is used by other services.

#### Deployment summary panel

Before starting the export, the wizard shows a comprehensive summary:

```
═══ Deployment Summary ═══

Projects: 3 selected
Bundle size: ~32 MB
Redaction: standard
Target: GitHub Pages
  Repository: mailbox-viewer-2024
  Visibility: Private
Signing: Enabled (Ed25519)

Proceed with export and deployment? (Y/n):
```

This gives you a final chance to review all settings and cancel if needed. The bundle size is estimated based on ~10 MB per project plus ~2 MB for static assets.

#### Real-time deployment streaming

Git operations and Cloudflare deployments stream output in real-time so you can see exactly what's happening:

```
Initializing git repository and pushing...
Initializing repository...
  Initialized empty Git repository in /tmp/mailbox-preview-abc123/.git/
✓ Initializing repository complete
Adding files...
✓ Adding files complete
Creating commit...
  [main (root-commit) 1a2b3c4] Initial mailbox export
   425 files changed, 123456 insertions(+)
✓ Creating commit complete
Pushing to GitHub...
  Enumerating objects: 430, done.
  Counting objects: 100% (430/430), done.
  Delta compression using up to 8 threads
  Compressing objects: 100% (425/425), done.
  Writing objects: 100% (430/430), 12.34 MiB | 5.67 MiB/s, done.
✓ Pushing to GitHub complete

✓ Successfully pushed to owner/mailbox-viewer-2024
```

This provides transparency and helps diagnose issues if deployment fails.

#### Platform-specific details

**For GitHub Pages:**
- Wizard detects your package manager (brew/apt/dnf) and offers automated installation of `gh` CLI
- For apt/dnf, shows complete manual installation instructions (including repo setup) since automation requires sudo
- Runs `gh auth login` interactively to authenticate via browser
- Creates new repository with your specified name and visibility (public/private)
- Initializes git, commits, and pushes with streaming output
- Enables GitHub Pages automatically via the GitHub API
- Provides the GitHub Pages URL (may take 1-2 minutes to become live)

**For Cloudflare Pages:**
- Detects npm and offers automated installation of `wrangler` CLI
- Runs `wrangler login` interactively to authenticate via browser
- Deploys directly to Cloudflare's global CDN (no git repository needed)
- Streams wrangler output in real-time
- Provides the `.pages.dev` URL immediately (site is live instantly)
- Benefits: instant deployment, 275+ global locations, automatic HTTPS, unlimited requests on free tier

**For local export:**
- Saves bundle to specified directory
- No CLI installation or authentication required
- Suitable for manual deployment to custom hosting or inspection

#### Error handling and recovery

The wizard includes comprehensive error handling:

- **Pre-flight validation**: Checks GitHub repo availability before starting export to avoid conflicts
- **Port conflict resolution**: Automatically finds an available port for preview server
- **Invalid selection handling**: Validates project selections and prompts for correction
- **CLI installation failures**: Shows manual installation instructions if automatic installation fails
- **Git operation failures**: Each git step is validated; stops on first failure with clear error message
- **Deployment failures**: Distinguishes between repo creation, push, and Pages enablement failures

If deployment fails after export, the bundle remains in the temp directory and can be deployed manually using the git commands shown in the manual deployment section below.

The wizard handles all operations automatically. For manual control or advanced options, see the detailed workflows below.

### Basic export workflow (manual)

**1. Export a bundle**

```bash
# Export all projects to a directory
uv run python -m mcp_agent_mail.cli share export --output ./my-bundle

# Export specific projects only
uv run python -m mcp_agent_mail.cli share export \
  --output ./my-bundle \
  --project backend-abc123 \
  --project frontend-xyz789

# Export with Ed25519 signing for tamper-evident distribution
uv run python -m mcp_agent_mail.cli share export \
  --output ./my-bundle \
  --signing-key ./keys/signing.key \
  --signing-public-out ./keys/signing.pub

# Export and encrypt with age for secure distribution
uv run python -m mcp_agent_mail.cli share export \
  --output ./my-bundle \
  --age-recipient age1abc...xyz \
  --age-recipient age1def...uvw
```

The export process:

1. Creates a snapshot of the SQLite database (read-only, no WAL/SHM files)
2. Copies message bodies, attachments, and metadata into the bundle structure
3. Applies redaction rules based on the scrub preset (default: `standard`)
4. Generates `manifest.json` with SHA-256 hashes for all assets
5. Optionally signs the manifest with Ed25519 (produces `manifest.sig.json`)
6. Packages everything into a ZIP archive (optional, enabled by default)
7. Optionally encrypts the ZIP with age (produces `bundle.zip.age`)

**2. Preview locally**

```bash
# Serve the bundle on localhost:9000
uv run python -m mcp_agent_mail.cli share preview ./my-bundle

# Custom port and auto-open browser
uv run python -m mcp_agent_mail.cli share preview ./my-bundle \
  --port 8080 \
  --open-browser
```

This launches a lightweight HTTP server that serves the static files. Open `http://127.0.0.1:9000/` in your browser to explore the archive.

**3. Verify integrity**

```bash
# Verify SRI hashes and signature
uv run python -m mcp_agent_mail.cli share verify ./my-bundle

# Verify with explicit public key (overrides manifest.sig.json)
uv run python -m mcp_agent_mail.cli share verify ./my-bundle \
  --public-key AAAA...base64...
```

Verification checks:

- SHA-256 hashes for all vendor libraries (Marked.js, DOMPurify, SQL.js)
- SHA-256 hashes for the SQLite database and attachments
- Ed25519 signature over the canonical manifest (if present)

**4. Decrypt (if encrypted)**

```bash
# Decrypt with age identity file (private key)
uv run python -m mcp_agent_mail.cli share decrypt bundle.zip.age \
  --identity ~/.age/key.txt

# Decrypt with passphrase (interactive prompt)
uv run python -m mcp_agent_mail.cli share decrypt bundle.zip.age \
  --passphrase

# Specify custom output path
uv run python -m mcp_agent_mail.cli share decrypt bundle.zip.age \
  --output ./decrypted-bundle.zip \
  --identity ~/.age/key.txt
```

After decryption, unzip the archive and use `share preview` to view it.

### Export options reference

| Option | Type | Default | Description |
| :-- | :-- | :-- | :-- |
| `--output`, `-o` | Path | (required) | Directory where the static bundle will be written |
| `--project`, `-p` | List | All projects | Limit export to specific project slugs or human keys (repeatable) |
| `--inline-threshold` | Bytes | 65536 (64KB) | Inline attachments smaller than this as base64 data URIs |
| `--detach-threshold` | Bytes | 26214400 (25MB) | Mark attachments larger than this as external (not bundled) |
| `--scrub-preset` | String | `standard` | Redaction preset: `standard` or `strict` (see Redaction presets section) |
| `--chunk-threshold` | Bytes | 20971520 (20MB) | Spli