# csitte/mailwarden [Health: Active]

**Category:** 💬 Communication  
**Repository:** https://github.com/csitte/mailwarden  
**GitHub Stars:** 0  
**npm Downloads (last month):** 3322  
**Views:** 3  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/csitte-mailwarden

## Description
Native Gmail MCP server with full mailbox control — search, read, label, archive, trash, download attachments, and the feature no other Gmail server ships: snooze threads until a date. Every call hits the live Gmail API (no synced index that silently misses mail). Install with npx -y mailwarden.

## Tools
Capabilities this server exposes over MCP:

- **search** — Search Gmail with native query syntax (e.g. 'in:inbox from:foo@bar.com newer_than:7d'). Returns thread summaries; read-state/category predicates are re-verified against each hit's live labels. Paginated: when more results exist, the response carries a nextPageToken — pass it back via pageToken to fetch the next page. USE WHEN: locating threads by sender, subject, date, label, or read state. DO NOT USE: to fetch a thread you already have the ID of (use get_thread). SIDE EFFECTS: none.
- **get_thread** — Fetch a full thread by ID: headers, plaintext + HTML bodies, and attachment metadata. USE WHEN: reading a thread's content after finding it via search. DO NOT USE: with a message ID — this takes thread IDs. SIDE EFFECTS: none (does not mark as read).
- **list_labels** — List all Gmail labels (system + user). USE WHEN: inspecting the mailbox structure, or to get exact label names/ids — though modify_labels/bulk_modify/create_label all accept a plain label name directly, so a lookup is rarely required. SIDE EFFECTS: none.
- **list_snoozed** — List all snoozed threads with their due dates. SIDE EFFECTS: none.
- **get_profile** — Return the authorized account: email address plus total message/thread counts. USE WHEN: confirming WHICH mailbox is connected before a bulk or filter action, or as a cheap liveness check. DO NOT USE: to enumerate messages — this returns only counts, not a listing (use search). SIDE EFFECTS: none.
- **triage_digest** — Structured overview of a mailbox slice for triage DECISIONS — sender / label / age buckets plus unread and attachment counts, instead of a raw thread list. USE WHEN: deciding what to bulk-archive/snooze/label, or summarizing inbox state ('what's in my inbox?'). DO NOT USE: to read a specific thread (use search/get_thread). Samples up to `max` most-recent matches; hasMore flags that more matched than were sampled. byAge buckets by each thread's FIRST message date (thread age, not last activity). SIDE EFFECTS: none.
- **create_label** — Create a user label and return its id. Idempotent: if the name already exists (case-insensitive), its existing id is returned and nothing is created. Nested labels: separate levels with '/' (e.g. 'Clients/Acme') — each missing parent level is created too. USE WHEN: you want a label's id up front, or to pre-create a label without applying it to anything. DO NOT USE: just to file mail under a new label — modify_labels/bulk_modify already auto-create an unknown name passed in `add`. SIDE EFFECTS: creates the label if missing; no mail is changed.
- **modify_labels** — Add/remove labels on a thread. Archive = remove 'INBOX'; mark read = remove 'UNREAD'. Labels may be given by name or by id: an unknown name in `add` is created automatically (use '/' for nested labels), an unknown name in `remove` is ignored. USE WHEN: applying custom labels or label combinations in one call. DO NOT USE: for plain archive/read/unread — the dedicated tools are clearer. SIDE EFFECTS: changes the thread's labels (and may create a label named in `add`); reversible by the inverse call.
- **bulk_modify** — Bulk-apply label changes to every message matching a Gmail query, batched at 1000 messages per API request. Labels may be given by name or by id: an unknown name in `add` is created automatically (use '/' for nested labels), an unknown name in `remove` is ignored. Returns matched/modified counts, affected thread IDs (capped at 500 — modifiedThreadCount has the true total), and per-chunk failures (partial success is reported, not hidden). If more messages match than maxMessages, only the first maxMessages are processed and 'capped' is true — raise maxMessages or re-run to finish the rest. Note: the query hits Gmail's search index as-is, WITHOUT the live re-verification search performs — for read-state-precise bulk ops, verify with search first. USE WHEN: mass operations — 'archive all newsletters older than 30 days' (query + remove INBOX), bulk labeling, bulk mark-read. DO NOT USE: for a single thread (use modify_labels or the dedicated tools), or with neither add nor remove. SIDE EFFECTS: modifies up to maxMessages messages in one call; label changes are reversible by the inverse call.
- **archive** — Archive a thread (remove it from the inbox). USE WHEN: inbox triage — the thread is handled and should leave the inbox. DO NOT USE: to delete (use trash) or to defer to a date (use snooze). SIDE EFFECTS: thread leaves the inbox; reversible via modify_labels add INBOX.
- **mark_read** — Mark a thread as read. SIDE EFFECTS: removes UNREAD; reversible via mark_unread.
- **mark_unread** — Mark a thread as unread. SIDE EFFECTS: adds UNREAD; reversible via mark_read.
- **trash** — Move a thread to Trash. USE WHEN: the thread should be discarded. DO NOT USE: for inbox cleanup of mail worth keeping (use archive). SIDE EFFECTS: thread moves to Trash; recoverable via untrash for ~30 days, then Gmail deletes it permanently.
- **untrash** — Restore a thread from Trash. SIDE EFFECTS: removes the TRASH label; user labels are preserved, but INBOX is NOT re-added — use modify_labels (add INBOX) to return it to the inbox.
- **download_attachment** — Download an attachment to a local file path. If MAILWARDEN_DOWNLOAD_DIR is set, destPath is resolved inside (and restricted to) that directory. USE WHEN: the user wants an attachment saved to disk (IDs come from get_thread's attachment metadata). SIDE EFFECTS: writes a local file; never overwrites — an existing file gets a numeric suffix (file-1.pdf). The response's 'saved' field is the path actually used. Mailbox unchanged.
- **snooze** — Snooze a thread until a date or time: archives it now, resurfaces when it comes due and sweep_snoozed runs. `until` accepts an explicit date (YYYY-MM-DD), a date+time (YYYY-MM-DD HH:MM or e.g. '2026-06-20 9am'), OR a preset resolved server-side: today, tomorrow, weekend (next Saturday), next week (next Monday), a weekday name (monday–sunday, next occurrence), 'in N days', or 'in N hours'. A preset may carry a trailing time ('tomorrow 9am', 'monday 8:30'). A timed snooze wakes at the next sweep on/after that minute. USE WHEN: deferring a thread to a later date/time instead of leaving it in the inbox. DO NOT USE: for permanent removal (use archive or trash). SIDE EFFECTS: removes INBOX, adds a dated MCP/Snoozed label; reversible via unsnooze.
- **unsnooze** — Cancel a snooze: return the thread to the inbox now. SIDE EFFECTS: removes the snooze label, restores INBOX.
- **sweep_snoozed** — Resurface all snoozed threads whose date is due (<= today), batched at 1000 messages per API request. USE WHEN: the user asks to process due snoozes, or as a scheduled maintenance call. SIDE EFFECTS: due threads return to the inbox marked unread; safe to run repeatedly. failedCount/errors report messages a batch could not wake (their label is kept for the next sweep).
- **list_filters** — List all Gmail filters — the server-side rules that auto-apply label actions to incoming mail. Shows each filter's criteria and label actions, and (for auditing) any `forward` address an existing filter carries. USE WHEN: reviewing existing automation, or to get a filter's id before delete_filter. SIDE EFFECTS: none. Requires the gmail.settings.basic scope — re-run `mailwarden --auth` if you authorized an earlier version.
- **create_filter** — Create a Gmail filter: matching incoming mail automatically gets the given label actions. Give at least one criterion and at least one action. Actions are label add/remove only (labels by name or id; an unknown name in addLabels is auto-created). Common recipes: skip the inbox → removeLabels ['INBOX']; auto-mark-read → removeLabels ['UNREAD']; auto-trash → addLabels ['TRASH']; star → addLabels ['STARRED']; file under a label → addLabels ['Receipts']. A filter only affects mail arriving AFTER it's created; set applyToExisting:true to ALSO apply the same actions once to mail already in the mailbox (builds a Gmail search from the criteria and runs a bulk modify — same loose-index caveat as bulk_modify; up to maxMessages, default 1000). USE WHEN: setting up a persistent auto-triage rule (e.g. 'always archive + label newsletters from x'), optionally cleaning up the existing backlog too. NOTE: forwarding filters are intentionally not supported — mailwarden creates no send/exfiltration path. SIDE EFFECTS: adds a server-side rule affecting future mail (reversible via delete_filter); with applyToExisting also modifies existing messages. Requires gmail.settings.basic.
- **delete_filter** — Delete a Gmail filter by id (get ids from list_filters). USE WHEN: removing an auto-triage rule. SIDE EFFECTS: removes the server-side rule; future mail is no longer auto-processed by it. Requires gmail.settings.basic.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "mailwarden": {
    "command": "npx",
    "args": ["-y","mailwarden"]
  }
}
```

## Documentation

## What the csitte/mailwarden MCP server does

The csitte/mailwarden MCP server exposes Gmail mailbox operations through the Model Context Protocol. It can find threads with Gmail query syntax, retrieve complete thread content, inspect labels and account details, and produce a structured triage digest with sender, label, age, unread, and attachment information.

Mailbox changes include archiving, marking threads read or unread, moving them to or restoring them from Trash, adding or removing labels, and applying label changes in bulk. Attachments can be written to a local path. The server also manages Gmail filters for automatic label actions on incoming mail, including optional application of those actions to existing messages.

Its distinctive workflow is mailbox-side snoozing. A snoozed thread leaves the inbox and receives a dated label; a later sweep returns due threads to the inbox as unread. This state is visible in Gmail and survives server restarts.

## How it works

The csitte/mailwarden MCP server sends requests to Gmail rather than maintaining a synchronized mailbox copy. Search accepts Gmail's native query syntax and returns paginated thread summaries. For predicates such as unread, read, starred, inbox, and category, returned threads are checked against live labels to reduce false positives from stale thread-level search state.

Use `search` to locate a thread, then pass its thread ID to `get_thread` for headers, plaintext and HTML bodies, and attachment metadata. `bulk_modify` operates on messages matching a Gmail query in batches of up to 1,000 API requests and reports partial failures. Its query uses Gmail's search index without the live re-verification performed by `search`, so precise read-state bulk actions should be verified first.

Tool responses declare output schemas and include structured content. Failures expose a code and retryable indicator. The server does not provide send tools, drafts, forwarding, or permanent deletion paths. Message headers can include the receiving server's recorded SPF, DKIM, and DMARC results, with unchecked results reported as such.

## Setup and configuration

Install the csitte/mailwarden MCP server with `npx -y mailwarden` and configure it as a local stdio MCP process in the client. Gmail authorization is required, and the connected account can be confirmed with `get_profile`, which returns the account email and mailbox counts.

The optional `MAILWARDEN_DOWNLOAD_DIR` variable confines downloaded attachments to a directory. If configured, destination paths are resolved within that directory and existing files are not overwritten. Token encryption at rest is also optional through `MAILWARDEN_TOKEN_PASSPHRASE`; the supplied material does not describe it as required for normal operation.

Filter management requires the `gmail.settings.basic` scope. If that scope was not included in an earlier authorization, re-run the server's authorization flow. Filter forwarding is not supported; filter actions are limited to Gmail label additions and removals.

## Tools and capabilities

- Search and paginate Gmail threads with native query syntax.
- Read thread bodies, headers, and attachment metadata without marking messages read.
- Inspect, create, add, remove, and bulk-apply Gmail labels.
- Archive, trash, restore, mark read, and mark unread threads.
- Snooze, list, unsnooze, and sweep due threads.
- Create, inspect, and delete server-side Gmail filters.
- Download attachments with collision-safe local filenames.
- Generate mailbox triage digests and verify the authorized account.

## Limitations and notes

Snoozed messages resurface when `sweep_snoozed` runs; a timed snooze wakes on the next sweep at or after its target time. Bulk operations can be capped by `maxMessages`, and affected thread IDs are limited in the response even when the modified count is higher.

`untrash` removes the Trash label but does not restore the Inbox label. Gmail filters affect new mail unless `applyToExisting` is requested. The server operates against Gmail and writes attachments locally, but it does not provide a general mailbox export or message-sending workflow.

_Full upstream README: https://allmcps.com/mcp/csitte-mailwarden/readme_

