Skip to main content
Glama
hgn

Notmuch

by hgn

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
mail_search

Search notmuch and return a paged summary, at thread or message granularity.

Use granularity="threads" for "what conversations are there about Y": each row is one thread, dated by its newest (or oldest) matched message, with an authors column that can mix matched and unmatched participants (see the legend in the output). Use granularity="messages" for "the last mail from X" or "how many mails did X write": each row is one matching message with its own date, from and subject.

Do not use this to fetch full bodies (use mail_read_message / mail_read_thread) or to turn a person's name into addresses first (use mail_list_addresses; from: also matches notification mail that merely mentions the name).

Args: query: A notmuch query, e.g. 'from:alice subject:invoice'. See notmuch-search-terms(7) for the full syntax, including 'date:this_year..', 'date:last_month..', 'date:1Y..' and 'date:2026-01-01..2026-06-30' for date ranges. scope: Name of a configured scope to AND with query (see mail_list_scopes). Defaults to the configured default scope. limit: Maximum number of rows to return. Defaults to and is capped by the server's configured limits. offset: Number of matching rows to skip, for paging through results already seen. response_format: 'concise' (one line per row) or 'detailed' (adds message counts/tags for threads, or the message_id for messages). granularity: 'threads' (one row per conversation) or 'messages' (one row per matching message). sort: 'newest-first' or 'oldest-first'.

mail_read_thread

Return every message in a thread, oldest first, with '--- [N/M] ---' separators.

Use this once mail_search has identified a thread_id and you need the conversation in order. For a single message, use mail_read_message instead. For a long thread, consider calling mail_thread_overview first: it shows one line per message (date, size, from, subject changes) so you can pick the one or two messages worth reading in full here, instead of pulling the whole thread.

Args: thread_id: A thread identifier as returned by mail_search (with or without the 'thread:' prefix). response_format: 'concise' (From/Date/Subject, short body) or 'detailed' (full headers, full body up to the configured limit).

mail_thread_overviewA

One line per message: index, date, size, from, and a marker when the subject changes from the thread's root subject.

Use this before mail_read_thread on any thread you have not looked at yet, especially a long one: it costs a fraction of the tokens and lets you decide which one or two messages to actually read in full, instead of pulling all eighty. Do not use it in place of mail_read_thread when you already know you need the full content.

Args: thread_id: A thread identifier as returned by mail_search (with or without the 'thread:' prefix). layout: 'tree' (the actual reply nesting, from notmuch's own thread structure; for a patch series with parallel discussion strands this is materially different from linear order) or 'flat' (linear oldest-first order, matching mail_read_thread's [N/M] numbering).

mail_related_threadsA

Find other threads that might be the same topic coming up again.

This is a heuristic, not semantic search: it combines normalized- subject overlap (after stripping Re:/Fwd:/[PATCH ...]/list-tag noise) with participant overlap, over the configured default scope. It can miss related threads that used different wording, and can surface unrelated ones that merely share a generic subject term or a common participant. Treat the result as a lead to check with mail_read_thread, not as a definitive answer.

Args: thread_id: A thread identifier as returned by mail_search (with or without the 'thread:' prefix). limit: Maximum number of related threads to return.

mail_pendingA

Threads that need attention: mail owed by you, or mail you are waiting on.

direction='owed': threads matching scope that no message has ever been tagged 'replied' on, i.e. mail you have not answered. Use this for "what do I still need to reply to".

direction='waiting': threads where your own address sent the most recent message and nobody has responded since. Use this for "who owes ME a reply". Needs at least one address configured under [identity] addresses in the config (normally defaulted automatically from notmuch's own user.primary_email/user.other_email); without that, this direction raises an actionable error rather than guessing.

Both directions sort oldest (most overdue) first, since age is the point. This is not a substitute for mail_search when you want to see the messages themselves, only for triaging what is outstanding.

Args: direction: 'owed' (you have not replied) or 'waiting' (you are waiting on a reply). older_than: Only include threads whose relevant date is at least this old, e.g. '14d', '2w', '3m', '1y'. Omit for no age floor. scope: Name of a configured scope to restrict the search (see mail_list_scopes). Defaults to the configured default scope. limit: Maximum number of threads to return.

mail_read_message

Return a single message's headers and body.

Use this for one specific message. For an entire conversation in order, use mail_read_thread instead.

Args: message_id: A Message-ID as seen in mail_search/mail_read_thread output, with or without angle brackets or the 'id:' prefix. response_format: 'concise' (From/Date/Subject, short body) or 'detailed' (full headers, full body up to the configured limit).

mail_countA

Count messages or threads matching a query, without fetching any of them.

Cheap way to check whether a correspondent, subject or thread exists at all before running a full mail_search, e.g. "how many mails did I get from X" (count="messages", the right default) versus "how many separate conversations" (count="threads"). Not a substitute for mail_search when you need to see the matches themselves.

Args: query: A notmuch query, e.g. 'from:alice'. See notmuch-search-terms(7) for the full syntax, including relative date ranges such as 'date:this_year..', 'date:last_month..', 'date:1Y..' and 'date:2026-01-01..2026-06-30'. scope: Name of a configured scope to AND with query (see mail_list_scopes). Defaults to the configured default scope. count: 'messages' or 'threads'.

mail_list_addressesA

Resolve a name or query into the concrete email addresses behind it.

Searching from: directly is unreliable: it also matches mail that merely mentions the name in a display name (e.g. a share notification like "Kathrin Pietsch (via Google Keep) <keep-shares@ google.com>"), and a name can belong to more than one real address or person. Call this tool first whenever you only have a name, then search or count using the address(es) it returns.

Args: query: A notmuch query, typically a name fragment, e.g. 'kathrin'. scope: Name of a configured scope to AND with query (see mail_list_scopes). Defaults to the configured default scope. output: 'sender' (addresses this query's messages were From), 'recipients' (addresses in To/Cc/Bcc), or 'count' (sender addresses ranked by occurrence count, the way to find someone's most-used address among several). limit: Maximum number of addresses to return.

mail_list_attachmentsA

List a message's attachments (part index, filename, content type, size).

Call this before mail_read_attachment to learn valid part_index values; it does not return attachment content itself.

Args: message_id: A Message-ID as seen in mail_search/mail_read_thread output.

mail_read_attachmentA

Read one attachment: text, PDF, image, office document or calendar invite.

Dispatches by content type: text/* and PDF (via pdftotext) come back as text; image/* comes back as an actual image the model can look at (downscaled if oversized and Pillow is installed, otherwise refused with its size); office documents (doc/docx/odt/rtf) are converted to text via pandoc or libreoffice; calendar invitations (text/calendar, .ics) are rendered as a readable summary (method, time, location, organizer, attendees with their response status). Call mail_list_attachments first to get a valid part_index. Archives and other binary formats are not supported and raise an explanatory error.

Args: message_id: A Message-ID as seen in mail_search/mail_read_thread output. part_index: The 1-based part index from mail_list_attachments.

mail_find_attachmentsA

Find attachments across a whole search, not just within one message.

Use this for questions like "all invoices from 2025" or "which PDFs did I get from the accountant", where the attachment itself, not the message, is what you are looking for. For a single message's attachments, use mail_list_attachments instead. Note that notmuch's own query syntax already supports 'attachment:*.pdf' and 'tag:attachment' inside query if you want to filter at the notmuch level too.

Args: query: A notmuch query selecting the messages to scan for attachments. scope: Name of a configured scope to AND with query (see mail_list_scopes). Defaults to the configured default scope. type: Filter by 'pdf', 'image', 'doc' (office documents), or a raw filename extension such as 'png' or 'xlsx'. Omit for no filter. limit: Maximum number of attachment rows to return.

mail_list_scopesA

List the configured scopes with their notmuch query and description.

Call this to discover valid scope values for mail_search/mail_count/ mail_tag instead of guessing scope names.

mail_prepare_replyA

Derive reply/forward headers and the quoted or forwarded body.

This is read-only: it computes what a reply or forward should look like but writes nothing. Pass the result's To/Cc/Subject/In-Reply-To to mail_create_draft (draft tier) if you want it actually saved as a draft.

Args: message_id: A Message-ID as seen in mail_search/mail_read_thread output. quote: Whether to include the original body (quoted with '> ' for reply/reply-all, or as a labelled forwarded block for forward). mode: 'reply' (sender only, honouring Reply-To), 'reply-all' (all original recipients minus your own configured addresses, honouring Mail-Followup-To, which is what mailing lists set and what makes the difference between a correct reply and an embarrassing one), or 'forward' (no In-Reply-To/References, subject gets exactly one 'Fwd:' prefix, body is a labelled forwarded block with the original headers, not an interleaved quote).

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hgn/mcp-server-notmuch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server