Skip to main content
Glama
slosar

mu-mcp

by slosar

mu-mcp

A small, read-only Model Context Protocol server that lets agents search and read a local Maildir indexed by mu. It exposes two tools:

  • search_mail: search with mu's query language, returning bounded message metadata.

  • read_mail: read one matching message as plain text, with a configurable output cap.

This connector does not send, delete, move, flag, or otherwise modify mail.

Requirements

  • Python 3.10 or later

  • mu installed and initialized/indexed for the account you want to use

  • An MCP client that supports local stdio servers

Related MCP server: mu-mcp

Install

From a checkout:

python -m pip install .

Or run directly from the repository with python -m mu_mcp.server after installing the package. For development, install python -m pip install -e '.[dev]'.

Configure an MCP client

The server communicates over stdio. Example configuration for clients that use the common mcpServers format:

{
  "mcpServers": {
    "mu-mail": {
      "command": "mu-mcp",
      "env": {
        "MUHOME": "/home/you/.mu",
        "MU_BIN": "/usr/bin/mu"
      }
    }
  }
}

MUHOME and MU_BIN are optional. MUHOME is passed to mu as --muhome; otherwise mu's normal configuration and MUHOME environment behavior apply. MU_MCP_TIMEOUT sets the per-command timeout in seconds (default 30). Keep stdout reserved for MCP: diagnostics are returned as tool errors.

Tools

search_mail(query, limit=20, sort="date", descending=true)

Accepts native mu query syntax. Examples:

from:alice@example.com subject:invoice
after:2025-01-01 before:2025-02-01
flag:unread
"project aurora" AND to:team@example.com

At most 100 results are allowed. Sorting is restricted to date, from, subject, or size. Results include common headers, flags, and message IDs; local filesystem paths are intentionally omitted.

read_mail(query, max_chars=12000)

Finds one matching result and asks mu view for its headers and plain-text content. Use a discriminating query, such as message-id:<id>, sender plus subject, and/or a date range. max_chars must be between 500 and 40,000. The result includes a truncated flag. Attachments are not extracted.

Privacy and safety

Email content is sensitive. This server runs locally and returns message data only to the connected MCP client, but that client or its model provider may process tool results under its own policies. Connect only clients you trust. Queries are passed as argument values directly to mu without a shell, and the server has no mail mutation tools. Message paths come from mu search results and are not accepted as user-provided filesystem paths.

Development

python -m pip install -e '.[dev]'
pytest

Tests mock the mu process and do not read your mailbox. See mu's query syntax for the full search language.

License

MIT. See LICENSE.

Available Tools

2 tools
read_mailA

Read the first message matching a mu query; message output is truncated.

Use a specific query such as "message-id:abc@example.com" or combine sender, subject, and date terms to identify the intended email. Returns headers and plain-text content. This tool does not modify the mailbox.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
max_charsNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose key traits: output is truncated, it returns headers and plain-text content, and it explicitly states it does not modify the mailbox. It omits auth requirements and behavior when no message matches, but the core behavioral profile is present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core behavior and read-only guarantee are front-loaded, and the query guidance is compact and free of filler. Slightly more length could have been traded for documenting max_chars, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read tool with no annotations and no output schema, the description covers the essentials: matched-scope, truncation, returned content type, and non-mutation. The remaining gaps (max_chars semantics, empty-result behavior) are minor but real.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It partially does for 'query' by explaining message-id syntax and combinable terms, but 'max_chars' is never mentioned, and the truncation note only indirectly implies its purpose. One of two parameters remains effectively undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read the first message matching a mu query') and clarifies the scope with 'first message' vs. a broader list. It does not explicitly contrast itself with the sibling search_mail, so sibling differentiation is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It advises using a specific query and gives effective query strategies ('message-id:abc@example.com' or combining sender, subject, date terms), which is useful invocation guidance. However, it never says when to choose read_mail over search_mail, so the tool-selection guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_mailA

Search the local mu-indexed mailbox using mu query syntax.

Examples: "from:alice@example.com subject:invoice", "after:2025-01-01 before:2025-02-01", or "flag:unread". Returns at most 100 metadata records; local filesystem paths are excluded.

ParametersJSON Schema
NameRequiredDescriptionDefault
sortNodate
limitNo
queryYes
descendingNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations present, the description carries the full burden and does disclose non-obvious behavior: a hard cap of 100 metadata records and the deliberate exclusion of local filesystem paths. It stops short of stating read-only semantics, pagination/offset behavior, or what happens when results exceed the cap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with purpose, then syntax examples, then return behavior. The examples earn their space because the schema gives no query documentation, though the return sentence partly duplicates what the output schema already conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is optional, yet the description usefully adds the 100-record cap and path exclusion. The remaining gap is the 0%-covered sort/limit/descending parameters, which an agent must infer or default blindly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and largely does not. It illustrates the 'query' parameter with mu syntax examples and hints at a result cap, but says nothing about sort, limit (default 20 vs the stated 100 ceiling), or descending, leaving three of four parameters semantically undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource: 'Search the local mu-indexed mailbox', including the query dialect used. It implicitly contrasts with read_mail by being a search rather than a fetch, but never names the sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied via three concrete example queries, which shows the agent how to form a query. However, there is no statement of when to choose search_mail versus read_mail, nor any prerequisite (e.g. that a mu index must already exist) or exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedread_mail
    • First observedsearch_mail

TDQS

A3.7/5.0

Scored across 2 tools

Disambiguation4/5

search_mail returns metadata records while read_mail returns message content, so their core actions are distinct. However, both accept mu queries and an agent might initially attempt to use search_mail for reading, though descriptions clarify the limitations.

Naming Consistency5/5

Both tool names follow the same snake_case verb_noun pattern: search_mail and read_mail. The convention is clear and consistently applied.

Tool Count3/5

Two tools is quite thin for a mailbox server; while the read-only scope justifies minimalism, common operations like listing folders or fetching full messages are absent. The count feels borderline rather than well-scoped.

Completeness3/5

The surface covers basic search and read, but read_mail truncates output and there is no way to retrieve full messages or attachments. These are notable gaps for a mail retrieval tool, though read-only limits some expected operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLMs to search and read email from a notmuch archive, providing tools for searching threads, retrieving messages, and listing tags through an MCP endpoint.
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables local LLMs to search email via mu, keeping all data on-device for privacy.
    5
    -
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server that exposes a local notmuch email database to an LLM client such as Claude. It is read-first: searching, reading, and understanding mail is always available; writing anything (drafts, tags, exported files) requires an explicit opt-in flag and is confined to clearly bounded locations.
    13
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Reads and searches local email archives (.mbox or .eml) with full MIME parsing, enabling queries about senders, subjects, dates, and bodies while keeping all data on your machine.
    3
    127 npm
    MIT