personal-mail-mcp

personal-mail-mcp

A local MCP server that connects Codex to Microsoft Graph and Gmail for reading and managing personal mail and calendar accounts.

Category
访问服务器

README

personal-mail-mcp

Local MCP server for Codex access to personal mail and calendar accounts.

It connects Codex to Microsoft Graph and Gmail so a local assistant can review inbox mail, scan for appointment confirmations, create or update calendar entries, find unread mail that may have been missed outside the Inbox, and build safe archive plans for low-value messages. The project also includes Codex skills for recurring workflows such as appointment harvesting, inbox triage, missed-mail review, and full mail review.

This project is provided as-is. It works for my own setup, but it has not been tested broadly across other accounts, tenants, mail providers, or Outlook/Gmail configurations.

Current target:

  • GoDaddy-hosted Exchange mailboxes and calendar through Microsoft Graph.
  • Gmail through Google APIs.
  • Read-only audit/plan tools plus explicit archive and calendar-write tools.

No OAuth secrets or token caches should be committed. Copy config/accounts.example.toml to config/accounts.toml for local settings. Copy config/auth.example.toml to config/auth.toml for OAuth app settings. Keep local config files private to your user account.

Recommended permissions for local-only files:

chmod 700 .private .tokens
chmod 600 config/accounts.toml config/auth.toml config/mail_rules.local.toml

Local project setup

Create and install the local environment:

cd <repo-path>
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[providers]'

Codex config

Add the MCP server to ~/.codex/config.toml:

[mcp_servers.personal_mail]
type = "stdio"
command = "<repo-path>/.venv/bin/python"
args = ["-m", "personal_mail_mcp.server"]
startup_timeout_sec = 30

Restart Codex after changing the config so the MCP server appears in the active tool list.

Account config

Create config/accounts.toml:

[[accounts]]
id = "exchange_primary"
provider = "microsoft"
email = "primary@example.com"
calendar = true

[[accounts]]
id = "exchange_secondary"
provider = "microsoft"
email = "secondary@example.com"
calendar = false

[[accounts]]
id = "google_primary"
provider = "google"
email = "public-example@gmail.com"
calendar = false

This file is ignored by git.

Microsoft app registration

The GoDaddy accounts are Exchange Online accounts reachable through Microsoft Graph. No GoDaddy-specific API is needed.

  1. Open the Microsoft Entra admin center:

    https://entra.microsoft.com/
    
  2. Go to:

    Entra ID > App registrations > New registration
    

    If the left navigation is different, search for App registrations in the portal search box.

  3. Register the app:

    Name: personal-mail-mcp
    Supported account types: Single tenant only - your Microsoft 365 tenant
    
  4. On the app registration Overview page, copy:

    Application (client) ID
    Directory (tenant) ID
    
  5. Under Authentication, add a redirect URL for a native/local app:

    http://localhost
    

    This appears under Mobile and desktop applications / Redirect URLs in the current portal UI.

  6. Under Authentication settings, enable public/native client flows. The portal wording may be one of:

    Allow public client flows
    Enable the following mobile and desktop flows
    Treat application as a public client
    

    Set it to Yes and save.

  7. Under API permissions, add Microsoft Graph delegated permissions:

    Mail.Read
    Mail.ReadWrite
    Calendars.ReadWrite
    offline_access
    

Create config/auth.toml with the copied IDs:

[microsoft]
client_id = "APPLICATION_CLIENT_ID_FROM_ENTRA"
tenant = "DIRECTORY_TENANT_ID_FROM_ENTRA"

[google]
client_secrets_file = ".private/google-oauth-client.json"

Do not put OpenAI, ChatGPT, Codex, or GitHub tokens in this file. This file is ignored by git.

Connect Exchange Online accounts

cd <repo-path>
.venv/bin/python -m personal_mail_mcp.cli status
PYTHONUNBUFFERED=1 .venv/bin/python -m personal_mail_mcp.cli connect exchange_primary
PYTHONUNBUFFERED=1 .venv/bin/python -m personal_mail_mcp.cli connect exchange_secondary

Each connect command prints a Microsoft device-code URL and code. Open the URL, enter the code, and sign in with the matching account:

exchange_primary   -> primary Exchange Online mailbox
exchange_secondary -> secondary Exchange Online mailbox

Successful connections write local token cache files under .tokens/, which is ignored by git.

Verify:

.venv/bin/python -m personal_mail_mcp.cli status

The Microsoft accounts should show:

token_cached: true

Read-only verification

Fetch the latest five message subjects from the main Exchange mailbox:

.venv/bin/python -m personal_mail_mcp.cli recent-messages exchange_primary --limit 5

The equivalent MCP tool exposed to Codex is:

microsoft_recent_messages(account_id, limit=5)

Gmail setup

Use a Google Cloud project for the Gmail API and OAuth desktop credentials.

  1. Open Google Cloud Console:

    https://console.cloud.google.com/
    
  2. Create or select a project, then enable:

    Gmail API
    
  3. Configure OAuth consent under:

    Google Auth Platform > Branding
    

    Use a simple app name such as personal-mail-mcp. For personal Gmail accounts, use External audience and add your Gmail address as a test user under:

    Google Auth Platform > Audience > Test users
    
  4. Create a desktop OAuth client under:

    Google Auth Platform > Clients > Create client
    

    Use:

    Application type: Desktop app
    Name: personal-mail-mcp
    
  5. Download the OAuth client JSON and store it locally:

    <repo-path>/.private/google-oauth-client.json
    

    Tighten permissions:

    chmod 600 .private/google-oauth-client.json
    
  6. Ensure config/auth.toml points to the file:

    [google]
    client_secrets_file = ".private/google-oauth-client.json"
    
  7. Connect the Gmail account:

    cd <repo-path>
    PYTHONUNBUFFERED=1 .venv/bin/python -m personal_mail_mcp.cli connect google_primary
    

    Open the printed Google URL, sign in with the configured test user, and approve the Gmail read/modify scopes.

  8. Verify:

    .venv/bin/python -m personal_mail_mcp.cli status
    

    The Gmail account should show:

    token_cached: true
    

Fetch the latest three Gmail inbox subjects:

.venv/bin/python -m personal_mail_mcp.cli recent-gmail google_primary --limit 3

The equivalent MCP tool exposed to Codex is:

gmail_recent_messages(account_id, limit=5)

Mail triage

The MCP server includes reusable inbox audit and archive helpers so repeated triage does not require ad hoc scripts.

Run a read-only audit across accounts:

cd <repo-path>
.venv/bin/python -m personal_mail_mcp.cli audit-mail exchange_primary exchange_secondary google_primary --limit-per-account 250

Create a dry-run archive plan. This returns only archive candidates grouped across all requested accounts by archive reason, sender, and normalized subject. Each message includes its account id, message id, subject, sender, and received date:

.venv/bin/python -m personal_mail_mcp.cli archive-plan exchange_primary exchange_secondary google_primary --limit-per-account 250

List a single inbox with pagination:

.venv/bin/python -m personal_mail_mcp.cli inbox exchange_primary --limit 100

Scan for unread mail outside the Inbox, such as archived or rule-moved messages. The command classifies those messages and returns attention candidates separately from obvious archive/noise:

.venv/bin/python -m personal_mail_mcp.cli missed-mail exchange_primary exchange_secondary google_primary --limit-per-account 100

Archive selected messages by id:

.venv/bin/python -m personal_mail_mcp.cli archive-mail exchange_primary <message-id> [<message-id> ...]

The equivalent MCP tools exposed to Codex are:

mail_inbox(account_id, limit=100)
mail_audit(account_ids, limit_per_account=250)
mail_archive_plan(account_ids, limit_per_account=250)
missed_mail(account_ids, limit_per_account=100)
archive_messages(account_id, message_ids)

The audit classifier is intentionally deterministic. It groups mail into keep, flag, archive, and review. Use mail_archive_plan as the normal review step before moving messages; it is read-only and contains the exact ids needed for archive_messages. When the same archive pattern appears more than once or across multiple accounts, the plan also returns filter recommendations that can be used to create mailbox/provider rules for future messages.

Remote filter/rule creation is possible but requires additional OAuth scopes: Microsoft Graph message rules require MailboxSettings.ReadWrite; Gmail filter creation requires gmail.settings.basic. Until those are added and approved, the server should only recommend filters rather than creating them.

Reusable defaults live in config/mail_rules.default.toml. User-specific senders, retention counts, and archive patterns belong in config/mail_rules.local.toml, which is ignored by git. Use config/mail_rules.example.toml as a template for local overrides.

Optional Codex skill

This project includes a shareable Codex skill:

skills/email-appointment-harvest
skills/inbox-triage
skills/missed-mail-review
skills/review-all-mail

The skill documents the repeatable workflow for scanning recent email, proposing appointment/calendar candidates, waiting for approval, and then creating or updating only approved calendar entries.

Install it into a Codex environment:

mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills"
cp -R skills/email-appointment-harvest "${CODEX_HOME:-$HOME/.codex}/skills/"
cp -R skills/inbox-triage "${CODEX_HOME:-$HOME/.codex}/skills/"
cp -R skills/missed-mail-review "${CODEX_HOME:-$HOME/.codex}/skills/"
cp -R skills/review-all-mail "${CODEX_HOME:-$HOME/.codex}/skills/"

Restart Codex after installing. Example request:

Use email appointment harvest to scan the last 7 days of email for appointments,
propose calendar entries, and add only the entries I approve.

The installed skill assumes this MCP server is configured in Codex and that the mail/calendar OAuth tokens have already been connected.

Security notes

  • config/auth.toml, config/accounts.toml, and .tokens/ are local-only.
  • The Microsoft app is a public/native client; do not create or store a client secret for this CLI flow.
  • Gmail client credentials under .private/ and token caches under .tokens/ should be mode 600 for files and 700 for directories.
  • Microsoft Mail.ReadWrite, Google gmail.modify, and Microsoft Calendars.ReadWrite are required for the current archive/calendar tools. Keep the app registration scoped to only the delegated permissions you use.
  • Treat archive_messages and calendar mutation tools as write actions. Prefer mail_archive_plan and calendar reads before applying changes.
  • Rotate any personal access tokens that were ever stored in plaintext config.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选