MCP Agent Mail
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| HOST | No | Server bind host | 127.0.0.1 |
| PORT | No | Server bind port | 8765 |
| LOG_LEVEL | No | Future: server log level | info |
| MCP_MAIL_STORE | No | Root for per-project archives and SQLite | ~/.mcp-agent-mail |
| ATTACHMENT_POLICY | No | Future: auto, file, or inline default for image conversion | auto |
| IMAGE_INLINE_MAX_BYTES | No | Threshold for inlining WebP images during send_message (if enabled) | 65536 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| health_checkC | Return basic readiness information for the Agent Mail server. |
| ensure_projectA | Idempotently create or ensure a project exists for the given human key. When to use
How it works
CRITICAL: Project Identity Rules
Parametershuman_key : str An absolute path-like project key (e.g., "/data/projects/backend"), typically the agent's working directory. This MUST be an absolute path, not a relative path or arbitrary slug, but it does NOT need to exist on the local filesystem - it is an opaque project KEY (collaborating agents may not share a filesystem). This is the canonical identifier for the project - all agents using the same key share the same project identity. identity_mode : str, optional Per-call override of the server's PROJECT_IDENTITY_MODE setting; one of "dir", "git-remote", "git-common-dir", "git-toplevel". Only takes effect when worktree-friendly identity is enabled (WORKTREES_ENABLED=1). Returnsdict Minimal project descriptor: { id, slug, human_key, created_at }. ExamplesJSON-RPC: Common mistakes
Idempotency
|
| register_agentA | Create or update an agent identity within a project and persist its profile to Git. When to use
Semantics
Agent IdentityTwo naming modes are supported:
Invalid examples: "BackendHarmonizer", "DatabaseMigrator" (descriptive role names are rejected in strict mode). Parametersproject_key : str
The same human key you passed to Returnsdict { id, name, program, model, task_description, inception_ts, last_active_ts, project_id } ExamplesRegister with auto-generated name (RECOMMENDED): Register with explicit valid name: Pitfalls
|
| deregister_agentB | Remove an agent from a project. Marks the agent as inactive and removes it from the active roster. Messages from/to the agent are preserved for audit but the agent can no longer send or receive new messages. |
| retire_agentA | Soft-delete an agent: mark it as retired so it stops accepting new messages while preserving message history. Retired agents are hidden from active agent lists but visible in 'all agents' views. |
| sweep_stale_agentsB | Retire abandoned agents in the caller's project using the server's conservative inactivity heuristic. The caller is never retired, the threshold has a 60-second floor, and active file reservations block retirement by default. |
| unretire_agentB | Restore a retired agent back to active status. The agent will resume accepting new messages. |
| archive_projectA | Soft-delete a project: mark it as archived so it is hidden from active project lists. All messages are preserved and the project can be restored with unarchive_project. |
| unarchive_projectC | Restore an archived project back to active status. |
| hard_delete_agentA | IRREVERSIBLY delete an agent and ALL associated data: messages sent by the agent, message recipient records, file reservations, agent links, window identities, and on-disk archive files (inbox, outbox, attachments). This is NOT soft-delete — data is permanently destroyed and cannot be recovered. Requires the confirmation parameter to be exactly 'I UNDERSTAND'. |
| hard_delete_projectA | IRREVERSIBLY delete a project and ALL associated data: every agent, message, message recipient, file reservation, agent link, window identity, message summary, sibling suggestion, product link, and the entire on-disk project archive directory. This is NOT soft-delete — data is permanently destroyed and cannot be recovered. Requires the confirmation parameter to be exactly 'I UNDERSTAND'. |
| whoisA | Return enriched profile details for an agent, optionally including recent archive commits. DiscoveryTo discover available agent names, use: resource://agents/{project_key} Agent names are NOT the same as program names or user names. Parametersproject_key : str Project slug or human key. agent_name : str Agent name to look up (use resource://agents/{project_key} to discover names). include_recent_commits : bool If true, include latest commits touching the project archive authored by the configured git author. commit_limit : int Maximum number of recent commits to include. Returnsdict Agent profile augmented with { recent_commits: [{hexsha, summary, authored_ts}] } when requested. |
| create_agent_identityA | Create a new, unique agent identity and persist its profile to Git. How this differs from |
| list_window_identitiesC | List active window identities for a project. Returns all non-expired window identities with their display names, last activity timestamps, and age. Parametersproject_key : str Project identifier. Returnsdict { identities: [{ id, window_uuid, display_name, created_ts, last_active_ts, expires_ts }] } |
| rename_windowB | Update the display name of a window identity. Parametersproject_key : str Project identifier. window_uuid : str The UUID of the window identity to rename. new_display_name : str New display name (must be a valid adjective+noun agent name). Returnsdict Updated window identity record. |
| expire_windowC | Mark a window identity as expired. Parametersproject_key : str Project identifier. window_uuid : str The UUID of the window identity to expire. Returnsdict { window_uuid, expired: bool, expired_at } |
| send_messageA | Send a Markdown message to one or more recipients and persist canonical and mailbox copies to Git. DiscoveryTo discover available agent names for recipients, use: resource://agents/{project_key} Agent names are NOT the same as program names or user names. What this does
Parametersproject_key : str
Project identifier (same used with Returnsdict { "deliveries": [ { "project": str, "payload": { ... message payload ... } } ], "count": int } Edge cases
Do / Don'tDo:
Don't:
Examples
|
| purge_old_messagesC | Delete messages older than the configured retention period. Defaults to retention_max_age_days from config (180 days). Returns count of messages purged. |
| reply_messageA | Reply to an existing message, preserving or establishing a thread. Behavior
Parametersproject_key : str
Project identifier.
message_id : int
The id of the message you are replying to.
sender_name : str
Your agent name (must be registered in the project).
body_md : str
Reply body in Markdown.
to, cc, bcc : Optional[list[str]]
Recipients by agent name. If omitted, Do / Don'tDo:
Don't:
Returnsdict
Message payload including ExamplesMinimal reply to original sender:
If the caller has not already authenticated as Reply with explicit recipients and CC: |
| request_contactA | Request contact approval to message another agent. Creates (or refreshes) a pending AgentLink and sends a small ack_required intro message. DiscoveryTo discover available agent names, use: resource://agents/{project_key} Agent names are NOT the same as program names or user names. Parametersproject_key : str Project slug or human key. from_agent : str Your agent name (must be registered in the project). to_agent : str Target agent name (use resource://agents/{project_key} to discover names). to_project : Optional[str] Target project if different from your project (cross-project coordination). reason : str Optional explanation for the contact request. ttl_seconds : int Time to live for the contact approval request (default: 7 days). |
| respond_contactC | Approve or deny a contact request. |
| list_contactsC | List contact links for an agent in a project. |
| set_contact_policyC | Set contact policy for an agent: open | auto | contacts_only | block_all. |
| fetch_inboxA | Retrieve recent messages for an agent without mutating read/ack state. Filters
Usage patterns
Returnslist[dict]
Each message includes: { id, subject, from, created_ts, importance, ack_required, kind, read_at, [body_md] }
Example |
| fetch_topicA | Fetch all messages in a project with a given topic tag, regardless of recipient. Parametersproject_key : str
Project identifier.
topic_name : str
The topic tag to filter by (case-insensitive).
limit : int
Max number of messages to return (default 50).
include_bodies : bool
Include full Markdown bodies in the payloads (default true).
since_ts : Optional[str]
ISO-8601 timestamp; only messages newer than this are returned.
unread_only : bool
When True, restrict to messages where the viewer has a recipient
row that has not been explicitly marked read. This narrows beyond
the default sender-or-recipient visibility — messages the viewer
sent (but is not a recipient of) and broadcast/thread-visible
messages where the viewer has no MessageRecipient row are
excluded under this flag, because "unread" is only well-defined
for a recipient row. A bare Returnslist[dict] Each message includes: { id, subject, from, created_ts, importance, topic, [body_md] } |
| mark_message_readA | Mark a specific message as read for the given agent. Notes
Idempotency
Returnsdict { message_id, read: bool, read_at: iso8601 | null } Example |
| acknowledge_messageA | Acknowledge a message addressed to an agent (and mark as read). Behavior
Idempotency
When to use
Returnsdict { message_id, acknowledged: bool, acknowledged_at: iso8601 | null, read_at: iso8601 | null } Example |
| macro_start_sessionB | Macro helper that boots a project session: ensure project, register agent, optionally file_reservation paths, and fetch the latest inbox snapshot. |
| macro_prepare_threadC | Macro helper that aligns an agent with an existing thread by ensuring registration, summarising the thread, and fetching recent inbox context. |
| macro_file_reservation_cycleC | Reserve a set of file paths and optionally release them at the end of the workflow. |
| macro_contact_handshakeC | Request contact permissions and optionally auto-approve plus send a welcome message. |
| search_messagesA | Full-text search over subject and body for a project. Tips
Query examples
Parametersproject_key : str Project identifier. query : str FTS5 query string. limit : int Max results to return. Returnslist[dict] Each entry: { id, subject, importance, ack_required, created_ts, thread_id, from } Example |
| summarize_threadA | Extract participants, key points, and action items for one or more threads. Single-thread mode (thread_id is a single ID):
Multi-thread mode (thread_id is comma-separated IDs like "TKT-1,TKT-2,TKT-3"):
Parametersproject_key : str Project identifier. thread_id : str Single thread ID for detailed summary, OR comma-separated IDs for aggregate digest. include_examples : bool If true (single-thread mode only), include up to 3 sample messages. llm_mode : bool If true and LLM is enabled, refine the summary with AI. llm_model : Optional[str] Override model name for the LLM call. per_thread_limit : int Max messages to consider per thread (multi-thread mode). ExamplesSingle thread: Multiple threads: |
| summarize_recentA | Summarize all recent project messages within a time window. Fetches messages from the last Idempotent: if a summary already exists for the same time window (within 5-minute tolerance) it is returned from cache. Parametersproject_key : str Project identifier (slug or human key). since_hours : float How far back to look (default 1 hour). llm_mode : bool Use LLM to refine the summary (default True). llm_model : str, optional Override LLM model name. max_messages : int Maximum messages to include (default 500, capped at 500). format : str, optional Output format (json or toon). |
| fetch_summaryA | Retrieve stored project-wide summaries. Parametersproject_key : str Project identifier. since_hours : float Return summaries whose end_ts is within this window (default 24h). limit : int Maximum summaries to return (default 5). format : str, optional Output format. |
| install_precommit_guardA | Install the Agent Mail pre-commit guard into a git repository. The guard blocks a commit that stages files another agent holds an
exclusive file reservation on (set Parametersproject_key : str Project whose file reservations the guard enforces. code_repo_path : str Path to the git repository to install the hook into. format : str, optional Output format. Returnsdict
|
| uninstall_precommit_guardA | Remove the Agent Mail commit guards from a git repository. Removes Agent Mail's own pre-commit and pre-push guard plugins (and a legacy single-file Agent Mail hook); other hooks in the repository are left in place. Parameterscode_repo_path : str Path to the git repository to remove the guard from. format : str, optional Output format. Returnsdict
|
| file_reservation_pathsA | Request advisory file reservations (leases) on project-relative paths/globs. Semantics
Do / Don'tDo:
Don't:
Parametersproject_key : str agent_name : str paths : list[str] File paths or glob patterns relative to the project workspace (e.g., "app/api/*.py"). ttl_seconds : int Time to live for the file_reservation; expired file_reservations are auto-released. exclusive : bool If true, exclusive intent; otherwise shared/observe-only. reason : str Optional explanation (helps humans reviewing Git artifacts). Returnsdict { granted: [{id, path_pattern, exclusive, reason, expires_ts}], conflicts: [{path, holders: [...]}] } Example |
| release_file_reservationsA | Release active file reservations held by an agent. Behavior
Returnsdict { released: int, released_at: iso8601 } Idempotency
ExamplesRelease all active reservations for agent: Release by ids: |
| force_release_file_reservationB | Force-release a stale file reservation held by another agent after inactivity heuristics. The tool validates that the reservation appears abandoned (agent inactive beyond threshold and no recent mail/filesystem/git activity). When released, an optional notification is sent to the previous holder summarizing the heuristics. |
| renew_file_reservationsB | Extend expiry for active file reservations held by an agent without reissuing them. Parametersproject_key : str Project slug or human key. agent_name : str Agent identity who owns the reservations. extend_seconds : int Seconds to extend from the later of now or current expiry (min 60s). paths : Optional[list[str]] Restrict renewals to matching path patterns. file_reservation_ids : Optional[list[int]] Restrict renewals to matching reservation ids. Returnsdict { renewed: int, file_reservations: [{id, path_pattern, old_expires_ts, new_expires_ts}] } |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| environment_resource_exact | |
| tooling_directory_resource_exact | |
| tooling_schemas_resource_exact | |
| tooling_metrics_resource_exact | |
| tooling_locks_resource_exact | |
| projects_resource_exact |
TDQS
Scored across 41 tools
Most tools target distinct resources and actions, but several clusters overlap: agent lifecycle (register/create/deregister/retire/unretire), message state (mark read vs acknowledge), summary views (fetch/summarize thread/recent), and macro helpers duplicate lower-level operations. Detailed descriptions disambiguate some overlaps, but the set still requires careful selection.
Nearly all names use snake_case and follow verb_noun or resource_action patterns, such as ensure_project, send_message, and release_file_reservations. Minor deviations like whois and a few long macro_* names slightly reduce predictability, but overall the naming is consistent.
41 tools is far above a well-scoped set for one MCP server; it mixes core messaging, admin, contact, reservation, summary, guard, and macro operations. Although each tool may earn its place, the volume increases selection burden and feels heavy for the domain.
The surface covers project and agent lifecycle, messaging, contacts, file reservations, summaries, and pre-commit guards comprehensively. Minor gaps include no direct list_projects/list_agents tool and no edit/delete individual message, but resource-based discovery and purge/archive paths mitigate these.