inbox-relay
Provides tools for searching and reading Gmail mail, listing threads and labels, applying labels and archiving high-confidence threads, and creating draft replies without sending mail.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@inbox-relaySearch my inbox for new recruiter emails from this week"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
inbox-relay
An MCP server that triages a recruiter inbox: read, label, draft. It never sends mail — by permission, not by promise.
What it does
Searches and reads recruiter mail over Gmail
Labels threads into eight categories:
interview,offer-process,recruiter/new,recruiter/replied,rejects,application,read-later,promosArchives labeled mail out of the inbox (reversible — everything stays findable under its label)
Drafts replies for you to send manually
Related MCP server: lilith-gmail
What it never does
Send mail. The only Gmail scope requested is
gmail.modify(read, label, archive, create drafts). Thegmail.sendscope is never requested, so sending is impossible even if the code tried.Auto-archive unsure mail. Low-confidence classifications stay in the inbox for human review.
Quickstart
npm install
npm run buildSet up a Google Cloud OAuth client (Desktop app), enable the Gmail API, and
put the credentials in your environment (see .env.example). Run the OAuth
consent flow once to mint a token at GMAIL_TOKEN_PATH — that file is
gitignored and never committed. Then:
npm start
# or inspect the tools live:
npm run inspectTools (v1)
Tool | What it does |
| Gmail search over the inbox |
| Fetch one message in full |
| Thread-level inbox view |
| All Gmail labels + ids |
| Label + archive (high-confidence only) |
| Draft only — you send it |
classify_message (category + priority + confidence + reason) lands in
Week 2 with the rubric-driven LLM classifier and the rules baseline.
Labels
See docs/annotation-guide.md for definitions,
signals, precedence rules, and the thread-history rule (cold-outreach vs
recruiter/new is decided by thread history, not memory).
Evals
The golden dataset is the contract: see evals/README.md.
Real mail stays local and gitignored; the public repo carries no real emails,
only the annotation guide and the eval methodology.
Project status
Week 1 scaffold: server skeleton, Gmail wiring for search/get/labels/drafts, taxonomy, annotation guide. Week 2: classifier + rules baseline scored. Week 3: draft tool polish, LLM classifier scored vs baseline, eval write-up.
License
MIT.
Available Tools
6 toolsapply_labelA
Label a message AND archive it out of the inbox (reversible). Only call this for high-confidence classifications; unsure messages stay in the inbox.
| Name | Required | Description | Default |
|---|---|---|---|
| label_id | Yes | ||
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations, the description carries the burden and does disclose the key hidden trait: this mutates inbox state by archiving, and the change is reversible. It omits residual behavior an agent might want (whether label_id must pre-exist from list_labels, what happens on unknown ids, and the response shape), which keeps it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the compound action and its reversibility first, then the usage gate. Nothing is redundant or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation tool with no annotations and no output schema, the description covers the side effect and the when-to-use rule but leaves parameters and return behavior entirely undocumented. It is adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both required parameters, so nothing in the structured data explains them. The description adds no meaning at all about message_id or label_id — notably it never says label_id must come from list_labels, which is the main failure mode.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (label) plus a non-obvious second effect (archive out of the inbox), which distinguishes it from the name alone. It is clearly separable from read-oriented siblings like get_message and search_messages, though it does not explicitly reference them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit gating condition: call only for high-confidence classifications, and leave unsure messages in the inbox. It does not name an alternative action for the low-confidence case (e.g., label without archiving, or just read with get_message).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_draftA
Create a Gmail DRAFT only. The user sends it manually. This never sends.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | Yes | ||
| subject | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses the most important trait, that this never sends and the user sends manually, but omits authentication needs, rate limits, return values, and other side-effect details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and immediately followed by the key safety constraint. Every sentence adds useful information with no waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-parameter creation tool with no output schema, the description covers the core purpose and non-sending behavior. However, it leaves parameter semantics and post-creation return behavior unaddressed, which is a meaningful gap for a mutation tool without annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All three parameters have zero schema description coverage, so the description should compensate but says nothing about them. The names to, subject, and body are largely self-explanatory, which prevents a score of 1, but no formats, constraints, or multi-recipient semantics are provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: create a Gmail DRAFT. It clearly distinguishes the action from sending, but does not differentiate from sibling tools because none of the listed siblings create drafts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly establishes the use case: compose a draft for manual sending by the user, never automatic sending. It does not name explicit alternatives or when-not conditions, but the context is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageB
Fetch one message in full: headers, body, and labels.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the full burden. 'Fetch' implies a read-only, non-destructive operation and the field list tells the agent what comes back, but nothing is said about missing/invalid ids, permissions, or whether the full body is always present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and immediately followed by the return payload. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-parameter read tool this covers the core contract, and the return fields are enumerated despite no output schema. The main gap is id provenance and error behavior when the message is not found.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single parameter is a bare string named 'id'. The description does not clarify whether this is a message id, a thread id, or a label-qualified reference, nor where to obtain it, so it adds nothing beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch one message') plus the scope of what is returned ('headers, body, and labels'), which clearly separates it from the plural search_messages. It stops short of naming the sibling explicitly, but the singular/full-record framing is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: 'one message' combined with a required id signals retrieval-by-identifier rather than searching. There is no explicit statement that search_messages should be used first to obtain the id, and no exclusion of list_threads.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_labelsA
List all Gmail labels with their ids (needed before apply_label).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'List' implies a read-only operation, and the description indicates all labels and their ids are returned, but it does not explicitly state lack of side effects, authentication requirements, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no wasted words. It conveys purpose, output detail, and workflow context efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter listing tool with no output schema, the description is nearly complete: it says what is listed, what identifying field is included, and when it is needed. Minor gaps remain around explicit read-only safety and output formatting.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so parameter semantics baseline is 4. The description does not need to explain input parameters, and it correctly focuses on output content instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('List all Gmail labels') and clarifies the returned data ('with their ids'). It also distinguishes the tool from siblings by naming its prerequisite relationship to 'apply_label'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase '(needed before apply_label)' gives clear workflow context for when to use this tool. It does not explicitly state when not to use it or name alternatives, but the intended usage is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_threadsB
List inbox threads, optionally filtered by a Gmail search query.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it discloses almost nothing: no ordering, result limits, pagination behavior, auth requirements, or whether threads are returned as summaries or full messages. For a list tool that may return unbounded data, the absence of any pagination or limit statement is a real gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the primary action and resource, with the optional qualifier trailing. Nothing wasted and nothing buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter read tool this is close to minimum viable, but with no annotations and no output schema the description leaves return shape, volume, and pagination unaddressed. The agent can call it, but cannot predict what comes back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 it does add meaningful semantics by identifying the single parameter as a Gmail search query. It stops short of explaining the query syntax, whether the filter applies to inbox-only results, or how an empty query behaves.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List inbox threads") plus the optional Gmail query filter, so the agent knows exactly what the tool returns conceptually. It does not, however, distinguish itself from the sibling search_messages, which looks like it does something very similar.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Inbox threads" and "optionally filtered by a Gmail search query" imply a default-browse and an optional-search mode, so usage is inferable. But there is no explicit when-to-use guidance and no mention of the obvious alternative, search_messages, which is the main selection question an agent faces here.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messagesB
Search the inbox (Gmail search syntax). Returns matching message ids.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| max_results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose two useful behaviors: the search scope is the inbox and the response contains ids only, not message bodies. It says nothing about pagination, how max_results caps the search, rate limits, or truncation of large result sets.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with purpose then return shape. No filler, nothing an agent must scan past.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A simple two-parameter read tool with no output schema, so it does not need extensive prose, but the undocumented max_results and absent pagination behavior leave a real gap for an agent planning result retrieval.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It does clarify that query uses Gmail search syntax, which is genuinely valuable, but max_results is left entirely unexplained (defaults, maximum, relationship to pagination).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Search the inbox") plus the return shape ("matching message ids"). This differentiates it reasonably from get_message and list_threads, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the mention of Gmail search syntax and the fact that only ids come back hints that get_message should follow for content. There is no explicit statement of when to use this versus list_threads or get_message, and no exclusions or prerequisites.
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.
6 tool updates
v0.1.0- First observed
apply_label - First observed
create_draft - First observed
get_message - First observed
list_labels - First observed
list_threads - First observed
search_messages
TDQS
Scored across 6 tools
Most tools target distinct resource+action pairs (search messages, fetch message, list labels, label+archive, draft). The only real overlap is search_messages vs list_threads, since both accept Gmail search queries, but the message-vs-thread distinction and the return shapes are stated clearly enough to pick correctly.
Every tool follows a clean verb_noun snake_case pattern: search_messages, get_message, list_threads, list_labels, apply_label, create_draft. No style mixing or vague verbs.
Six tools is tightly scoped for a triage/relay workflow: search, read, enumerate threads/labels, label-and-archive, and draft. Each tool earns its place with no filler.
Covers the core triage loop (find, read, classify, draft) well. Minor gaps: there is no tool to fetch a full thread (only list_threads) and no way to undo the archive/label despite apply_label being described as reversible, which leaves a potential dead end.
Maintenance
Related MCP Connectors
Search and triage all your mailboxes; draft replies and campaigns; send only as you allow.
Manage Gmail end-to-end: search, read, send, draft, label, and organize threads. Automate workflow…
Read and search FranklyMail email and prepare drafts, replies, and forwards for human approval.
Search Gmail and Outlook, save drafts, manage email rules, and view email stats.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to read unread Gmail messages and create threaded draft replies, without ever sending email automatically.MIT
- FlicenseNot gradedqualityDmaintenanceEnables semantic search, retrieval, and summarization of Gmail emails with privacy-aware classification and PII sanitization.1-
- FlicenseNot gradedqualityCmaintenanceEnables intelligent Gmail management, including email triage, newsletter classification, promotional email cleanup, summarization, filter suggestions, draft replies, and audit logging.-
- AlicenseNot gradedqualityAmaintenanceEnables safe, multi-account Gmail and Microsoft 365 operations with explicit aliases, including searching, reading, drafting, archiving, labels/categories, and human-reviewed sending via a localhost approval window.MIT