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.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
skills listSkill Instructions
name: agent-mail description: "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."
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/**vsbackend/**
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_NAMEenvironment 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
highimportance 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
More by Dicklesworthstone
View allMCP Agent Mail - Mail-like coordination layer for multi-agent workflows. Identities, inbox/outbox, file reservations, contact policies, threaded messaging, pre-commit guard, Human Overseer, static exports, disaster recovery. Git+SQLite backed. Python/FastMCP.
Beads Viewer - Graph-aware triage engine for Beads projects. Computes PageRank, betweenness, critical path, and cycles. Use --robot-* flags for AI agents.
Lesson 11: Local Skill Management with ms: skills:
Coding Agent Session Search - unified CLI/TUI to index and search local coding agent history from Claude Code, Codex, Gemini, Cursor, Aider, ChatGPT, Pi-Agent, Factory, and more. Purpose-built for AI agent consumption with robot mode.