MCP Agent Mail
A mail-like coordination layer for coding agents, exposed as an HTTP-only FastMCP server. 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).
Why Agent Mail Exists
Modern projects often run multiple coding agents at once. Without coordination, agents:
- Overwrite each other's edits or panic on unexpected diffs
- Miss critical context from parallel workstreams
- Require humans to "liaison" messages across tools
Agent Mail provides:
- Identities: Memorable adjective+noun names (e.g., "GreenCastle", "BlueLake")
- Messaging: GitHub-Flavored Markdown with threading, importance levels, and acknowledgments
- File Reservations: Advisory leases on files/globs to signal editing intent
- Search: FTS5 full-text search across message history
- Audit Trail: Every message and reservation is committed to Git
Starting the Server
# Quick start (alias added during installation)
am
# Or manually
cd ~/projects/mcp_agent_mail && ./scripts/run_server_with_token.sh
# Check server health
curl http://127.0.0.1:8765/health/liveness
Default: http://127.0.0.1:8765. Change port with uv run python -m mcp_agent_mail.cli config set-port 9000.
Critical Concept: project_key
The project_key is the absolute path to your working directory. This is the canonical identifier for a project.
# Two agents in the SAME directory = SAME project
Agent A in /data/projects/backend → project_key="/data/projects/backend"
Agent B in /data/projects/backend → project_key="/data/projects/backend"
# They share the same mailbox, file reservations, and coordination
# Two agents in DIFFERENT directories = DIFFERENT projects
Agent A in /data/projects/backend → project_key="/data/projects/backend"
Agent B in /data/projects/frontend → project_key="/data/projects/frontend"
# They need explicit contact requests to message each other
Macros vs Granular Tools
Prefer macros when you want speed or are on a smaller model:
| Macro |
What It Does |
macro_start_session |
Ensures project → registers agent → optional file reservations → fetches inbox |
macro_prepare_thread |
Registers agent → summarizes thread → fetches inbox context |
macro_file_reservation_cycle |
Reserves paths → optional auto-release after work |
macro_contact_handshake |
Requests contact → auto-accepts → sends welcome message |
Use granular tools when you need explicit control over each step.
MCP Tools Reference
Health & Discovery
| Tool |
Signature |
Returns |
health_check |
() |
{status, environment, http_host, http_port, database_url} |
Project & Agent Management
| Tool |
Signature |
Returns |
ensure_project |
(human_key: str) |
{id, slug, human_key, created_at} |
register_agent |
(project_key, program, model, name?, task_description?, attachments_policy?) |
Agent profile |
create_agent_identity |
(project_key, program, model, name_hint?, task_description?, attachments_policy?) |
Agent profile (always creates new) |
whois |
(project_key, agent_name, include_recent_commits?, commit_limit?) |
Enriched agent profile |
Agent naming: Names must be adjective+noun (e.g., "GreenCastle", "BlueLake"). If invalid, the server auto-generates one (mode: coerce).
Messaging
| Tool |
Signature |
Returns |
send_message |
(project_key, sender_name, to[], subject, body_md, cc?, bcc?, attachment_paths?, convert_images?, importance?, ack_required?, thread_id?, auto_contact_if_blocked?) |
{deliveries, count, attachments?} |
reply_message |
(project_key, message_id, sender_name, body_md, to?, cc?, bcc?, subject_prefix?) |
{thread_id, reply_to, deliveries, count} |
fetch_inbox |
(project_key, agent_name, limit?, urgent_only?, include_bodies?, since_ts?) |
list[message] |
mark_message_read |
(project_key, agent_name, message_id) |
{message_id, read, read_at} |
acknowledge_message |
(project_key, agent_name, message_id) |
{message_id, acknowledged, acknowledged_at, read_at} |
search_messages |
(project_key, query, limit?) |
list[message] |
summarize_thread |
(project_key, thread_id, include_examples?, llm_mode?, llm_model?, per_thread_limit?) |
{thread_id, summary, examples} |
Importance levels: low, normal, high, urgent
Contact Policies
| Tool |
Signature |
Returns |
request_contact |
(project_key, from_agent, to_agent, to_project?, reason?, ttl_seconds?) |
Contact link |
respond_contact |
(project_key, to_agent, from_agent, accept, from_project?, ttl_seconds?) |
Contact link |
list_contacts |
(project_key, agent_name) |
list[contact] |
set_contact_policy |
(project_key, agent_name, policy) |
Agent profile |
Policies: open, auto (default), contacts_only, block_all
File Reservations
| Tool |
Signature |
Returns |
file_reservation_paths |
(project_key, agent_name, paths[], ttl_seconds?, exclusive?, reason?) |
{granted[], conflicts[]} |
release_file_reservations |
(project_key, agent_name, paths?, file_reservation_ids?) |
{released, released_at} |
renew_file_reservations |
(project_key, agent_name, extend_seconds?, paths?, file_reservation_ids?) |
{renewed, file_reservations[]} |
force_release_file_reservation |
(project_key, agent_name, file_reservation_id, notify_previous?, note?) |
{released, released_at, reservation} |
File reservations are advisory but auditable. The optional pre-commit guard blocks commits that conflict with others' active exclusive reservations.
Pre-Commit Guard
| Tool |
Signature |
Returns |
install_precommit_guard |
(project_key, code_repo_path) |
{hook} |
uninstall_precommit_guard |
(code_repo_path) |
{removed} |
Session Macros
| Tool |
Signature |
Returns |
macro_start_session |
(human_key, program, model, task_description?, agent_name?, file_reservation_paths?, file_reservation_reason?, file_reservation_ttl_seconds?, inbox_limit?) |
{project, agent, file_reservations, inbox} |
macro_prepare_thread |
(project_key, thread_id, program, model, agent_name?, task_description?, register_if_missing?, include_examples?, inbox_limit?, include_inbox_bodies?, llm_mode?, llm_model?) |
{project, agent, thread, inbox} |
macro_file_reservation_cycle |
(project_key, agent_name, paths[], ttl_seconds?, exclusive?, reason?, auto_release?) |
{file_reservations, released} |
macro_contact_handshake |
(project_key, requester, target, to_project?, reason?, ttl_seconds?, auto_accept?, welcome_subject?, welcome_body?) |
{request, response, welcome_message} |
MCP Resources Reference
| URI |
Params |
Returns |
resource://config/environment |
— |
Server configuration |
resource://tooling/directory |
— |
Tool clusters + workflow playbooks |
resource://tooling/schemas |
— |
Argument hints for all tools |
resource://tooling/metrics |
— |
Call/error counts per tool |
resource://projects |
— |
All projects |
resource://project/{slug} |
slug |
Project + agents |
resource://inbox/{agent} |
?project=<abs-path>&limit=20&since_ts=...&urgent_only=...&include_bodies=... |
Inbox listing |
resource://outbox/{agent} |
?project=<abs-path>&limit=20 |
Sent messages |
resource://thread/{thread_id} |
?project=<abs-path>&include_bodies=true |
Thread listing |
resource://message/{id} |
?project=<abs-path> |
Single message |
resource://file_reservations/{slug} |
?active_only=true |
File reservations + staleness metadata |
resource://views/urgent-unread/{agent} |
?project=<abs-path> |
High/urgent unread messages |
resource://views/ack-required/{agent} |
?project=<abs-path> |
Pending acknowledgements |
resource://views/ack-overdue/{agent} |
?project=<abs-path>&ttl_minutes=30 |
Overdue acknowledgements |
Example Agent Workflow
# 1. Start session (one call does everything)
result = macro_start_session(
human_key="/data/projects/backend",
program="claude-code",
model="opus-4.5",
task_description="Implementing auth module"
)
agent_name = result["agent"]["name"] # e.g., "GreenCastle"
project_key = result["project"]["human_key"]
# 2. Check inbox for context
for msg in result["inbox"]:
if msg["importance"] in ["high", "urgent"]:
acknowledge_message(project_key, agent_name, msg["id"])
# 3. Reserve files before editing
file_reservation_paths(
project_key, agent_name,
paths=["src/auth/**/*.ts"],
ttl_seconds=3600,
exclusive=True,
reason="bd-123" # Link to Beads task
)
# 4. Do work, send progress updates
send_message(
project_key, agent_name,
to=["BlueLake"],
subject="[bd-123] Auth module progress",
body_md="Completed login flow. Starting session management.",
thread_id="bd-123"
)
# 5. Release reservations when done
release_file_reservations(project_key, agent_name)
Cross-Project Coordination
When repos are separate (e.g., frontend and backend):
Option A: Single project bus
- Register both agents under the same
project_key
- Keep reservation patterns specific:
frontend/** vs backend/**
Option B: Separate projects with contact links
# Backend agent requests contact
request_contact(
project_key="/data/projects/backend",
from_agent="GreenCastle",
to_agent="BlueLake",
to_project="/data/projects/frontend",
reason="API contract coordination"
)
# Frontend agent accepts
respond_contact(
project_key="/data/projects/frontend",
to_agent="BlueLake",
from_agent="GreenCastle",
from_project="/data/projects/backend",
accept=True
)
# Now they can message each other
Pre-Commit Guard
The optional pre-commit guard blocks commits that touch files reserved by other agents:
# Install guard into your code repo
mcp-agent-mail guard install /data/projects/backend /data/projects/backend
# Check guard status
mcp-agent-mail guard status /data/projects/backend
# Uninstall
mcp-agent-mail guard uninstall /data/projects/backend
Requirements:
- Set
AGENT_NAME environment variable so the guard knows who you are
- File reservations must be active (not expired)
Bypass (use sparingly):
AGENT_MAIL_BYPASS=1 git commit -m "..."
# Or: AGENT_MAIL_GUARD_MODE=warn (advisory mode, doesn't block)
Build Slots (Long-Running Tasks)
For dev servers, watchers, or builds that hold resources:
# Acquire a slot
acquire_build_slot(project_key, agent_name, "frontend-build", ttl_seconds=3600, exclusive=True)
# Renew during long runs
renew_build_slot(project_key, agent_name, "frontend-build", extend_seconds=1800)
# Release when done
release_build_slot(project_key, agent_name, "frontend-build")
CLI helper:
mcp-agent-mail am-run frontend-build -- npm run dev
Product Bus (Multi-Repo Coordination)
Group multiple repos under a single "product" for cross-project search and inbox:
# Create a product
mcp-agent-mail products ensure MyProduct --name "My Product"
# Link repos
mcp-agent-mail products link MyProduct /data/projects/backend
mcp-agent-mail products link MyProduct /data/projects/frontend
# Product-wide search
mcp-agent-mail products search MyProduct "urgent AND deploy" --limit 50
# Product-wide inbox
mcp-agent-mail products inbox MyProduct BlueLake --urgent-only
# Product-wide thread summary
mcp-agent-mail products summarize-thread MyProduct "bd-123"
Web UI (Human-Facing)
Browse projects, agents, inboxes, and messages at http://127.0.0.1:8765/mail:
- Unified Inbox: Recent messages across all projects
- Project Overview: Search, agents, file reservations
- Agent Inbox: Messages for a specific agent
- Message Detail: Full body, attachments, thread context
- Human Overseer: Send high-priority messages to agents from the web
Human Overseer
Click "Send Message" in any project view to send messages as HumanOverseer:
- Messages include a preamble instructing agents to pause and prioritize
- Bypasses contact policies
- Marked as
high importance automatically
Static Mailbox Export
Export mailboxes as portable, read-only HTML bundles:
# Interactive wizard (easiest)
uv run python -m mcp_agent_mail.cli share wizard
# Manual export
uv run python -m mcp_agent_mail.cli share export --output ./bundle
# Preview locally
uv run python -m mcp_agent_mail.cli share preview ./bundle --port 9000
# Verify integrity
uv run python -m mcp_agent_mail.cli share verify ./bundle
Features:
- Self-contained HTML viewer with FTS5 search
- Ed25519 signing for tamper-evident distribution
- Optional age encryption for confidential archives
- Deploy to GitHub Pages or Cloudflare Pages
Integration with Beads
Beads (bd) owns task status/priority; Agent Mail owns conversations and audit trails.
Conventions:
- Use Beads issue ID as Mail
thread_id: send_message(..., thread_id="bd-123")
- Prefix subjects:
[bd-123] Starting auth refactor
- Include issue ID in file reservation
reason: file_reservation_paths(..., reason="bd-123")
Typical flow:
# 1. Pick ready work
bd ready --json
# 2. Reserve files
file_reservation_paths(project_key, agent_name, ["src/**"], reason="bd-123")
# 3. Announce start
send_message(..., thread_id="bd-123", subject="[bd-123] Starting work")
# 4. Complete
bd close bd-123 --reason "Completed"
release_file_reservations(project_key, agent_name)
Search Syntax (FTS5)
"exact phrase" # Phrase search
prefix* # Prefix match
term1 AND term2 # Boolean AND
term1 OR term2 # Boolean OR
term1 NOT term2 # Exclusion
subject:login # Field-specific
body:"build plan" # Field-specific phrase
CLI Commands
cd ~/projects/mcp_agent_mail
# Server
uv run python -m mcp_agent_mail.cli serve-http
uv run python -m mcp_agent_mail.cli migrate
# Configuration
uv run python -m mcp_agent_mail.cli config set-port 9000
uv run python -m mcp_agent_mail.cli config show-port
# Projects
uv run python -m mcp_agent_mail.cli list-projects --include-agents
# File Reservations
uv run python -m mcp_agent_mail.cli file_reservations list <project> --active-only
uv run python -m mcp_agent_mail.cli file_reservations soon <project> --minutes 10
# Acknowledgements
uv run python -m mcp_agent_mail.cli acks pending <project> <agent>
uv run python -m mcp_agent_mail.cli acks overdue <project> <agent> --ttl-minutes 30
# Guard
uv run python -m mcp_agent_mail.cli guard install <project_key> <code_repo_path>
uv run python -m mcp_agent_mail.cli guard uninstall <code_repo_path>
uv run python -m mcp_agent_mail.cli guard status <code_repo_path>
# Export
uv run python -m mcp_agent_mail.cli share wizard
uv run python -m mcp_agent_mail.cli share export --output ./bundle
uv run python -m mcp_agent_mail.cli share preview ./bundle
# Archive/Restore
uv run python -m mcp_agent_mail.cli archive save --label nightly
uv run python -m mcp_agent_mail.cli archive list --json
uv run python -m mcp_agent_mail.cli archive restore <file>.zip --force
# DANGER: Full reset
uv run python -m mcp_agent_mail.cli clear-and-reset-everything --force
Configuration Variables
| Variable |
Default |
Description |
STORAGE_ROOT |
~/.mcp_agent_mail_git_mailbox_repo |
Root for project repos and SQLite |
HTTP_HOST |
127.0.0.1 |
Bind host |
HTTP_PORT |
8765 |
Bind port |
HTTP_BEARER_TOKEN |
— |
Static bearer token for auth |
HTTP_ALLOW_LOCALHOST_UNAUTHENTICATED |
true |
Allow localhost without auth |
LLM_ENABLED |
true |
Enable LLM for summaries |
LLM_DEFAULT_MODEL |
gpt-5-mini |
Default model for summaries |
CONTACT_ENFORCEMENT_ENABLED |
true |
Enforce contact policies |
FILE_RESERVATIONS_ENFORCEMENT_ENABLED |
true |
Block messages on conflicts |
AGENT_NAME_ENFORCEMENT_MODE |
coerce |
strict, coerce, always_auto |
Troubleshooting
| Issue |
Solution |
| "sender_name not registered" |
Call register_agent or macro_start_session first |
| "from_agent not registered" |
Check project_key matches the agent's project |
| "FILE_RESERVATION_CONFLICT" |
Adjust patterns, wait for expiry, or use non-exclusive |
| Pre-commit blocks commits |
Set AGENT_NAME, or use AGENT_MAIL_BYPASS=1 |
| Inbox empty but messages exist |
Check since_ts, limit; verify recipient names match exactly |
Ready-to-Paste AGENTS.md Blurb
## MCP Agent Mail — coordination for multi-agent workflows
**What it is:** A mail-like layer for coding agents with identities, inbox/outbox,
searchable threads, and advisory file reservations. Human-auditable artifacts in Git.
**How to use:**
1. Register identity: `ensure_project` + `register_agent` (or `macro_start_session`)
2. Reserve files: `file_reservation_paths(project_key, agent_name, ["src/**"], exclusive=true)`
3. Communicate: `send_message(..., thread_id="bd-123")`, `fetch_inbox`, `acknowledge_message`
4. Fast reads: `resource://inbox/{agent}?project=<abs-path>&limit=20`
**Macros vs granular:**
- Prefer macros for speed: `macro_start_session`, `macro_prepare_thread`
- Use granular for control: `register_agent`, `file_reservation_paths`, `send_message`
**Common pitfalls:**
- "from_agent not registered" → call `register_agent` first
- "FILE_RESERVATION_CONFLICT" → adjust patterns or wait for expiry
Installation
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/mcp_agent_mail/main/scripts/install.sh?$(date +%s)" | bash -s -- --yes
1---2name: agent-mail3description: MCP Agent Mail - mail-like coordination layer for coding agents with memorable identities, inbox/outbox, searchable threads, advisory file reservations, pre-commit guards, and human-auditable Git artifacts. The backbone of multi-agent workflows.4---56# MCP Agent Mail78A mail-like coordination layer for coding agents, exposed as an HTTP-only FastMCP server. Gives agents memorable identities, an inbox/outbox, searchable message history, and voluntary file reservation "leases" to avoid stepping on each other.910Think 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).1112## Why Agent Mail Exists1314Modern projects often run multiple coding agents at once. Without coordination, agents:15- Overwrite each other's edits or panic on unexpected diffs16- Miss critical context from parallel workstreams17- Require humans to "liaison" messages across tools1819Agent Mail provides:20- **Identities**: Memorable adjective+noun names (e.g., "GreenCastle", "BlueLake")21- **Messaging**: GitHub-Flavored Markdown with threading, importance levels, and acknowledgments22- **File Reservations**: Advisory leases on files/globs to signal editing intent23- **Search**: FTS5 full-text search across message history24- **Audit Trail**: Every message and reservation is committed to Git2526---2728## Starting the Server2930```bash31# Quick start (alias added during installation)32am3334# Or manually35cd ~/projects/mcp_agent_mail && ./scripts/run_server_with_token.sh3637# Check server health38curl http://127.0.0.1:8765/health/liveness39```4041Default: `http://127.0.0.1:8765`. Change port with `uv run python -m mcp_agent_mail.cli config set-port 9000`.4243---4445## Critical Concept: project_key4647**The `project_key` is the absolute path to your working directory.** This is the canonical identifier for a project.4849```bash50# Two agents in the SAME directory = SAME project51Agent A in /data/projects/backend → project_key="/data/projects/backend"52Agent B in /data/projects/backend → project_key="/data/projects/backend"53# They share the same mailbox, file reservations, and coordination5455# Two agents in DIFFERENT directories = DIFFERENT projects56Agent A in /data/projects/backend → project_key="/data/projects/backend"57Agent B in /data/projects/frontend → project_key="/data/projects/frontend"58# They need explicit contact requests to message each other59```6061---6263## Macros vs Granular Tools6465**Prefer macros** when you want speed or are on a smaller model:6667| Macro | What It Does |68|-------|--------------|69| `macro_start_session` | Ensures project → registers agent → optional file reservations → fetches inbox |70| `macro_prepare_thread` | Registers agent → summarizes thread → fetches inbox context |71| `macro_file_reservation_cycle` | Reserves paths → optional auto-release after work |72| `macro_contact_handshake` | Requests contact → auto-accepts → sends welcome message |7374**Use granular tools** when you need explicit control over each step.7576---7778## MCP Tools Reference7980### Health & Discovery8182| Tool | Signature | Returns |83|------|-----------|---------|84| `health_check` | `()` | `{status, environment, http_host, http_port, database_url}` |8586### Project & Agent Management8788| Tool | Signature | Returns |89|------|-----------|---------|90| `ensure_project` | `(human_key: str)` | `{id, slug, human_key, created_at}` |91| `register_agent` | `(project_key, program, model, name?, task_description?, attachments_policy?)` | Agent profile |92| `create_agent_identity` | `(project_key, program, model, name_hint?, task_description?, attachments_policy?)` | Agent profile (always creates new) |93| `whois` | `(project_key, agent_name, include_recent_commits?, commit_limit?)` | Enriched agent profile |9495**Agent naming**: Names must be adjective+noun (e.g., "GreenCastle", "BlueLake"). If invalid, the server auto-generates one (mode: `coerce`).9697### Messaging9899| Tool | Signature | Returns |100|------|-----------|---------|101| `send_message` | `(project_key, sender_name, to[], subject, body_md, cc?, bcc?, attachment_paths?, convert_images?, importance?, ack_required?, thread_id?, auto_contact_if_blocked?)` | `{deliveries, count, attachments?}` |102| `reply_message` | `(project_key, message_id, sender_name, body_md, to?, cc?, bcc?, subject_prefix?)` | `{thread_id, reply_to, deliveries, count}` |103| `fetch_inbox` | `(project_key, agent_name, limit?, urgent_only?, include_bodies?, since_ts?)` | `list[message]` |104| `mark_message_read` | `(project_key, agent_name, message_id)` | `{message_id, read, read_at}` |105| `acknowledge_message` | `(project_key, agent_name, message_id)` | `{message_id, acknowledged, acknowledged_at, read_at}` |106| `search_messages` | `(project_key, query, limit?)` | `list[message]` |107| `summarize_thread` | `(project_key, thread_id, include_examples?, llm_mode?, llm_model?, per_thread_limit?)` | `{thread_id, summary, examples}` |108109**Importance levels**: `low`, `normal`, `high`, `urgent`110111### Contact Policies112113| Tool | Signature | Returns |114|------|-----------|---------|115| `request_contact` | `(project_key, from_agent, to_agent, to_project?, reason?, ttl_seconds?)` | Contact link |116| `respond_contact` | `(project_key, to_agent, from_agent, accept, from_project?, ttl_seconds?)` | Contact link |117| `list_contacts` | `(project_key, agent_name)` | `list[contact]` |118| `set_contact_policy` | `(project_key, agent_name, policy)` | Agent profile |119120**Policies**: `open`, `auto` (default), `contacts_only`, `block_all`121122### File Reservations123124| Tool | Signature | Returns |125|------|-----------|---------|126| `file_reservation_paths` | `(project_key, agent_name, paths[], ttl_seconds?, exclusive?, reason?)` | `{granted[], conflicts[]}` |127| `release_file_reservations` | `(project_key, agent_name, paths?, file_reservation_ids?)` | `{released, released_at}` |128| `renew_file_reservations` | `(project_key, agent_name, extend_seconds?, paths?, file_reservation_ids?)` | `{renewed, file_reservations[]}` |129| `force_release_file_reservation` | `(project_key, agent_name, file_reservation_id, notify_previous?, note?)` | `{released, released_at, reservation}` |130131**File reservations are advisory** but auditable. The optional pre-commit guard blocks commits that conflict with others' active exclusive reservations.132133### Pre-Commit Guard134135| Tool | Signature | Returns |136|------|-----------|---------|137| `install_precommit_guard` | `(project_key, code_repo_path)` | `{hook}` |138| `uninstall_precommit_guard` | `(code_repo_path)` | `{removed}` |139140### Session Macros141142| Tool | Signature | Returns |143|------|-----------|---------|144| `macro_start_session` | `(human_key, program, model, task_description?, agent_name?, file_reservation_paths?, file_reservation_reason?, file_reservation_ttl_seconds?, inbox_limit?)` | `{project, agent, file_reservations, inbox}` |145| `macro_prepare_thread` | `(project_key, thread_id, program, model, agent_name?, task_description?, register_if_missing?, include_examples?, inbox_limit?, include_inbox_bodies?, llm_mode?, llm_model?)` | `{project, agent, thread, inbox}` |146| `macro_file_reservation_cycle` | `(project_key, agent_name, paths[], ttl_seconds?, exclusive?, reason?, auto_release?)` | `{file_reservations, released}` |147| `macro_contact_handshake` | `(project_key, requester, target, to_project?, reason?, ttl_seconds?, auto_accept?, welcome_subject?, welcome_body?)` | `{request, response, welcome_message}` |148149---150151## MCP Resources Reference152153| URI | Params | Returns |154|-----|--------|---------|155| `resource://config/environment` | — | Server configuration |156| `resource://tooling/directory` | — | Tool clusters + workflow playbooks |157| `resource://tooling/schemas` | — | Argument hints for all tools |158| `resource://tooling/metrics` | — | Call/error counts per tool |159| `resource://projects` | — | All projects |160| `resource://project/{slug}` | slug | Project + agents |161| `resource://inbox/{agent}` | `?project=<abs-path>&limit=20&since_ts=...&urgent_only=...&include_bodies=...` | Inbox listing |162| `resource://outbox/{agent}` | `?project=<abs-path>&limit=20` | Sent messages |163| `resource://thread/{thread_id}` | `?project=<abs-path>&include_bodies=true` | Thread listing |164| `resource://message/{id}` | `?project=<abs-path>` | Single message |165| `resource://file_reservations/{slug}` | `?active_only=true` | File reservations + staleness metadata |166| `resource://views/urgent-unread/{agent}` | `?project=<abs-path>` | High/urgent unread messages |167| `resource://views/ack-required/{agent}` | `?project=<abs-path>` | Pending acknowledgements |168| `resource://views/ack-overdue/{agent}` | `?project=<abs-path>&ttl_minutes=30` | Overdue acknowledgements |169170---171172## Example Agent Workflow173174```python175# 1. Start session (one call does everything)176result = macro_start_session(177 human_key="/data/projects/backend",178 program="claude-code",179 model="opus-4.5",180 task_description="Implementing auth module"181)182agent_name = result["agent"]["name"] # e.g., "GreenCastle"183project_key = result["project"]["human_key"]184185# 2. Check inbox for context186for msg in result["inbox"]:187 if msg["importance"] in ["high", "urgent"]:188 acknowledge_message(project_key, agent_name, msg["id"])189190# 3. Reserve files before editing191file_reservation_paths(192 project_key, agent_name,193 paths=["src/auth/**/*.ts"],194 ttl_seconds=3600,195 exclusive=True,196 reason="bd-123" # Link to Beads task197)198199# 4. Do work, send progress updates200send_message(201 project_key, agent_name,202 to=["BlueLake"],203 subject="[bd-123] Auth module progress",204 body_md="Completed login flow. Starting session management.",205 thread_id="bd-123"206)207208# 5. Release reservations when done209release_file_reservations(project_key, agent_name)210```211212---213214## Cross-Project Coordination215216When repos are separate (e.g., frontend and backend):217218**Option A: Single project bus**219- Register both agents under the same `project_key`220- Keep reservation patterns specific: `frontend/**` vs `backend/**`221222**Option B: Separate projects with contact links**223```python224# Backend agent requests contact225request_contact(226 project_key="/data/projects/backend",227 from_agent="GreenCastle",228 to_agent="BlueLake",229 to_project="/data/projects/frontend",230 reason="API contract coordination"231)232233# Frontend agent accepts234respond_contact(235 project_key="/data/projects/frontend",236 to_agent="BlueLake",237 from_agent="GreenCastle",238 from_project="/data/projects/backend",239 accept=True240)241242# Now they can message each other243```244245---246247## Pre-Commit Guard248249The optional pre-commit guard blocks commits that touch files reserved by other agents:250251```bash252# Install guard into your code repo253mcp-agent-mail guard install /data/projects/backend /data/projects/backend254255# Check guard status256mcp-agent-mail guard status /data/projects/backend257258# Uninstall259mcp-agent-mail guard uninstall /data/projects/backend260```261262**Requirements:**263- Set `AGENT_NAME` environment variable so the guard knows who you are264- File reservations must be active (not expired)265266**Bypass (use sparingly):**267```bash268AGENT_MAIL_BYPASS=1 git commit -m "..."269# Or: AGENT_MAIL_GUARD_MODE=warn (advisory mode, doesn't block)270```271272---273274## Build Slots (Long-Running Tasks)275276For dev servers, watchers, or builds that hold resources:277278```python279# Acquire a slot280acquire_build_slot(project_key, agent_name, "frontend-build", ttl_seconds=3600, exclusive=True)281282# Renew during long runs283renew_build_slot(project_key, agent_name, "frontend-build", extend_seconds=1800)284285# Release when done286release_build_slot(project_key, agent_name, "frontend-build")287```288289CLI helper:290```bash291mcp-agent-mail am-run frontend-build -- npm run dev292```293294---295296## Product Bus (Multi-Repo Coordination)297298Group multiple repos under a single "product" for cross-project search and inbox:299300```bash301# Create a product302mcp-agent-mail products ensure MyProduct --name "My Product"303304# Link repos305mcp-agent-mail products link MyProduct /data/projects/backend306mcp-agent-mail products link MyProduct /data/projects/frontend307308# Product-wide search309mcp-agent-mail products search MyProduct "urgent AND deploy" --limit 50310311# Product-wide inbox312mcp-agent-mail products inbox MyProduct BlueLake --urgent-only313314# Product-wide thread summary315mcp-agent-mail products summarize-thread MyProduct "bd-123"316```317318---319320## Web UI (Human-Facing)321322Browse projects, agents, inboxes, and messages at `http://127.0.0.1:8765/mail`:323324- **Unified Inbox**: Recent messages across all projects325- **Project Overview**: Search, agents, file reservations326- **Agent Inbox**: Messages for a specific agent327- **Message Detail**: Full body, attachments, thread context328- **Human Overseer**: Send high-priority messages to agents from the web329330### Human Overseer331332Click "Send Message" in any project view to send messages as `HumanOverseer`:333- Messages include a preamble instructing agents to pause and prioritize334- Bypasses contact policies335- Marked as `high` importance automatically336337---338339## Static Mailbox Export340341Export mailboxes as portable, read-only HTML bundles:342343```bash344# Interactive wizard (easiest)345uv run python -m mcp_agent_mail.cli share wizard346347# Manual export348uv run python -m mcp_agent_mail.cli share export --output ./bundle349350# Preview locally351uv run python -m mcp_agent_mail.cli share preview ./bundle --port 9000352353# Verify integrity354uv run python -m mcp_agent_mail.cli share verify ./bundle355```356357**Features:**358- Self-contained HTML viewer with FTS5 search359- Ed25519 signing for tamper-evident distribution360- Optional age encryption for confidential archives361- Deploy to GitHub Pages or Cloudflare Pages362363---364365## Integration with Beads366367Beads (`bd`) owns task status/priority; Agent Mail owns conversations and audit trails.368369**Conventions:**370- Use Beads issue ID as Mail `thread_id`: `send_message(..., thread_id="bd-123")`371- Prefix subjects: `[bd-123] Starting auth refactor`372- Include issue ID in file reservation `reason`: `file_reservation_paths(..., reason="bd-123")`373374**Typical flow:**375```bash376# 1. Pick ready work377bd ready --json378379# 2. Reserve files380file_reservation_paths(project_key, agent_name, ["src/**"], reason="bd-123")381382# 3. Announce start383send_message(..., thread_id="bd-123", subject="[bd-123] Starting work")384385# 4. Complete386bd close bd-123 --reason "Completed"387release_file_reservations(project_key, agent_name)388```389390---391392## Search Syntax (FTS5)393394```395"exact phrase" # Phrase search396prefix* # Prefix match397term1 AND term2 # Boolean AND398term1 OR term2 # Boolean OR399term1 NOT term2 # Exclusion400subject:login # Field-specific401body:"build plan" # Field-specific phrase402```403404---405406## CLI Commands407408```bash409cd ~/projects/mcp_agent_mail410411# Server412uv run python -m mcp_agent_mail.cli serve-http413uv run python -m mcp_agent_mail.cli migrate414415# Configuration416uv run python -m mcp_agent_mail.cli config set-port 9000417uv run python -m mcp_agent_mail.cli config show-port418419# Projects420uv run python -m mcp_agent_mail.cli list-projects --include-agents421422# File Reservations423uv run python -m mcp_agent_mail.cli file_reservations list <project> --active-only424uv run python -m mcp_agent_mail.cli file_reservations soon <project> --minutes 10425426# Acknowledgements427uv run python -m mcp_agent_mail.cli acks pending <project> <agent>428uv run python -m mcp_agent_mail.cli acks overdue <project> <agent> --ttl-minutes 30429430# Guard431uv run python -m mcp_agent_mail.cli guard install <project_key> <code_repo_path>432uv run python -m mcp_agent_mail.cli guard uninstall <code_repo_path>433uv run python -m mcp_agent_mail.cli guard status <code_repo_path>434435# Export436uv run python -m mcp_agent_mail.cli share wizard437uv run python -m mcp_agent_mail.cli share export --output ./bundle438uv run python -m mcp_agent_mail.cli share preview ./bundle439440# Archive/Restore441uv run python -m mcp_agent_mail.cli archive save --label nightly442uv run python -m mcp_agent_mail.cli archive list --json443uv run python -m mcp_agent_mail.cli archive restore <file>.zip --force444445# DANGER: Full reset446uv run python -m mcp_agent_mail.cli clear-and-reset-everything --force447```448449---450451## Configuration Variables452453| Variable | Default | Description |454|----------|---------|-------------|455| `STORAGE_ROOT` | `~/.mcp_agent_mail_git_mailbox_repo` | Root for project repos and SQLite |456| `HTTP_HOST` | `127.0.0.1` | Bind host |457| `HTTP_PORT` | `8765` | Bind port |458| `HTTP_BEARER_TOKEN` | — | Static bearer token for auth |459| `HTTP_ALLOW_LOCALHOST_UNAUTHENTICATED` | `true` | Allow localhost without auth |460| `LLM_ENABLED` | `true` | Enable LLM for summaries |461| `LLM_DEFAULT_MODEL` | `gpt-5-mini` | Default model for summaries |462| `CONTACT_ENFORCEMENT_ENABLED` | `true` | Enforce contact policies |463| `FILE_RESERVATIONS_ENFORCEMENT_ENABLED` | `true` | Block messages on conflicts |464| `AGENT_NAME_ENFORCEMENT_MODE` | `coerce` | `strict`, `coerce`, `always_auto` |465466---467468## Troubleshooting469470| Issue | Solution |471|-------|----------|472| "sender_name not registered" | Call `register_agent` or `macro_start_session` first |473| "from_agent not registered" | Check `project_key` matches the agent's project |474| "FILE_RESERVATION_CONFLICT" | Adjust patterns, wait for expiry, or use non-exclusive |475| Pre-commit blocks commits | Set `AGENT_NAME`, or use `AGENT_MAIL_BYPASS=1` |476| Inbox empty but messages exist | Check `since_ts`, `limit`; verify recipient names match exactly |477478---479480## Ready-to-Paste AGENTS.md Blurb481482```483## MCP Agent Mail — coordination for multi-agent workflows484485**What it is:** A mail-like layer for coding agents with identities, inbox/outbox,486searchable threads, and advisory file reservations. Human-auditable artifacts in Git.487488**How to use:**4891. Register identity: `ensure_project` + `register_agent` (or `macro_start_session`)4902. Reserve files: `file_reservation_paths(project_key, agent_name, ["src/**"], exclusive=true)`4913. Communicate: `send_message(..., thread_id="bd-123")`, `fetch_inbox`, `acknowledge_message`4924. Fast reads: `resource://inbox/{agent}?project=<abs-path>&limit=20`493494**Macros vs granular:**495- Prefer macros for speed: `macro_start_session`, `macro_prepare_thread`496- Use granular for control: `register_agent`, `file_reservation_paths`, `send_message`497498**Common pitfalls:**499- "from_agent not registered" → call `register_agent` first500- "FILE_RESERVATION_CONFLICT" → adjust patterns or wait for expiry501```502503---504505## Installation506507```bash508curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/mcp_agent_mail/main/scripts/install.sh?$(date +%s)" | bash -s -- --yes509```