mcpField
O
Outlook MCP

Outlook MCP

本地服务
github.com通信协作40今天更新

关于 Outlook MCP

Outlook MCP 是面向个人 Microsoft Outlook 账户的 MCP 服务,为需要结构化访问邮件和效率数据的 Agent 构建者提供接口。工具覆盖邮件、日历、联系人、任务、草稿和附件,并提供只读模式与操作系统密钥环令牌存储等控制。

主要功能

  1. 01读取、搜索和整理邮件
  2. 02发送邮件并管理草稿
  3. 03管理日历事件及文件
  4. 04管理联系人和 To Do 任务
  5. 05批量操作与邮件会话管理
  6. 06只读模式和密钥环令牌存储

适用场景

  1. 01汇总并整理收到的邮件
  2. 02安排日程并回复邀请
  3. 03根据旅行或邮件计划创建任务
  4. 04起草回复并整理文件夹

MCP 相关

将 Outlook 操作作为类型化 MCP 工具提供,并附带常见流程的工作流提示词。支持 stdio 和可选的 Streamable HTTP 传输。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"mpalermiti-outlook": {
"command": "uvx",
"args": [
"outlook-graph-mcp"
]
}
}
}
启动命令uvx outlook-graph-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypioutlook-graph-mcp1.29.0

工具

68

收录的工具列表 · 更新于 今天

此工具无需参数。

详细介绍

outlook-mcp

通过 Microsoft Graph API 为 Microsoft Outlook 个人账户提供的 MCP 服务。

PyPI Python License: MIT MCP Registry

仅限 Microsoft 个人账户 — @outlook.com、@hotmail.com、@live.com。不支持工作/学校账户(Entra ID):此服务基于个人账户构建并经过测试。欢迎提交修复,让工具能在工作账户上正常运行,同时不改变个人账户用户看到的内容。

**免责声明:**这是一个独立的开源项目,与 Microsoft Corporation 无关联,未获其认可或支持。“Outlook”和“Microsoft Graph”是 Microsoft 的商标。


适用对象

如果你符合以下情况,这个项目可能适合你:

  • 你是Agent 构建者,想把 Outlook 接入自己的基础设施(OpenClaw、Claude Code、Cursor、自定义 MCP 主机),并希望获得类型化的工具接口,而不是需要自行解析的标准输出
  • 你使用Microsoft 个人账户(Outlook.com / Hotmail / Live),希望拥有完全控制权:自带 Azure 应用,无需企业授权流程,也没有共享客户端 ID
  • 你需要全面的功能覆盖——邮件、日历、联系人、待办事项、草稿、文件夹、批量操作、会话线程——而不是仅支持邮件或日历的封装工具
  • 你重视安全:令牌存储在操作系统密钥环中(macOS 上使用 Keychain,Linux 上使用 libsecret——除非选择启用,否则绝不以明文存储),支持细粒度的 allow_categories、可选的 read_only 模式,且零遥测

如果你需要工作/学校 M365 账户(请使用 Microsoft 官方工具——Entra ID 身份验证和管理员授权流程不在本项目范围内),或者只需基本的邮件客户端(本项目提供 72 个工具,远超“读取收件箱”所需),那么本项目不适合你。

与其他 Outlook 工具的区别

在面向个人 Outlook 的工具中,这是唯一一个一流的 MCP 服务——大多数替代方案都是 bash 脚本,或形似技能的命令行封装,需要 Agent 通过 shell 调用。这个区别很重要:Agent 获取的是具有结构化参数和返回值的类型化工具模式,而不是需要解析的标准输出。其他工具不具备的功能还包括:针对分诊优化的 /$batch(批量操作速度提升 10-20×)、支持名称解析的递归文件夹操作、细粒度的分类权限、多个邮箱(通过 OUTLOOK_MCP_CONFIG_DIR 为每个账户运行一个服务),以及完整的附件写入功能,包括为草稿和日历事件提供的大于 3 MB 的上传会话。


这能实现什么

让你的 AI Agent 完全访问 Outlook。以下示例提示词可直接使用:

  • “总结我过去 24 小时内未读的邮件,并标记需要及时处理的内容。”
  • “我现在的重点收件箱里有什么?其他收件箱里有没有看起来应该放到重点收件箱的内容?”
  • “收件箱里有没有物流更新?跟踪我正在等待的物品以及预计送达时间。”
  • “扫描我的邮件,查找即将续订的订阅——未来两周内有哪些即将自动扣费?”
  • “我下周要去西雅图——查看日历中的行程,并创建一项包含打包清单的待办任务。”
  • “替我草拟一封回复,回复我姐姐的上一条消息,告诉她我这个周末会给她打电话。”
  • “把本周所有新闻邮件和促销邮件移到‘稍后阅读’文件夹——每批处理 20 封。”

该服务提供 72 个独立工具(默认加载 71 个;文档阅读器需主动启用),让 Agent 能自行组合工作流——读取、分诊、撰写、安排日程、跟踪任务——无需硬编码宏。

兼容平台

已列入官方 MCP Registry,名称为 io.github.mpalermiti/outlook-mcp。


功能

涵盖 13 个类别的 72 个工具。默认加载 71 个;outlook_read_attachment 属于可选加入的 documents 组(见工具集选择)。

  • 身份验证(1) —— 检查身份验证状态(通过 CLI 登录)
  • 邮件读取(7) —— 列出收件箱(支持“重点收件箱”和未分类筛选条件)、读取邮件、通过 $batch 按 ID 批量读取、搜索(KQL)、列出文件夹、增量同步收件箱变更,以及汇总邮件/事件/联系人的“自上次调用以来”信息
  • 邮件写入(3) —— 发送、回复/回复全部、转发
  • 邮件分类处理(9) —— 移动、删除(默认软删除)、标记、分类、标记为已读/未读、重新分类(重点收件箱)、列出/设置/删除按发件人划分的重点收件箱覆盖规则
  • 日历读取(4) —— 列出事件(展开重复事件)、获取事件详情、按关键字查找事件、增量同步事件变更
  • 日历写入(6) —— 创建、更新、删除、回复(接受/拒绝/暂定)、附加和移除事件文件
  • 联系人(7) —— 列出、搜索、获取、创建、更新、删除、增量同步变更
  • 待办事项(14) —— 任务列表、任务(列出/获取/创建/更新/完成/删除)、清单项目(添加/更新/删除)、任务附件(列出/下载/上传/删除)
  • 草稿(5) —— 列出、创建(新邮件,或在邮件会话中回复、回复全部或转发)、更新、发送、删除
  • 附件(6) —— 列出、下载、读取文档文本(可选加入)、发送带附件的邮件、向草稿添加附件、移除草稿附件
  • 文件夹管理(3) —— 创建、重命名、删除邮件文件夹
  • 会话和批处理(3) —— 列出会话、复制邮件、批量分类处理
  • 用户和管理(4) —— whoami、列出日历、列出类别、邮件提示

设计原则:

  • BYOID —— 自带 ID。注册自己的 Azure AD 应用,不使用共享客户端 ID。
  • 零遥测 —— 不进行分析、不在本地缓存、不调用第三方。
  • 令牌存储 —— 通过 azure-identity 使用操作系统密钥环(macOS Keychain、Windows Credential Store、Linux Secret Service)。
  • 输入验证 —— 在进行任何 API 调用之前,验证所有输入(电子邮件、Graph ID、OData、KQL、日期时间)。
  • 只读模式 —— 在配置中设置 read_only: true,即可阻止所有写入操作。请注意,这限制的是工具,而非令牌——参见read_only 的作用与不作用范围。
  • 软删除 —— 默认将已删除邮件移至“已删除邮件”。硬删除需要显式设置 permanent: true。
  • 时区感知 —— 日历操作遵循你配置的 IANA 时区。
  • 相对日期 —— 每个日期时间参数都接受 ISO 8601 格式或偏移量:7d 表示 7 天前,+7d 表示 7 天后,now 表示此刻。单位:m、h、d、w。
  • 附件访问受限 —— 附件的读取和写入仅限于 attachments_dir,因此,即使邮件要求 Agent 发送磁盘其他位置的文件,也无法照做。
  • 增量游标受限 —— delta_token 是由调用方持有的状态,因此属于不可信输入。所有可能携带 Graph Bearer 令牌的 URL 都会经过解析,并要求其使用 https 且位于 graph.microsoft.com,从而防止恶意游标将邮箱令牌重定向给其他人。其路径还必须是对应工具的增量端点,因此游标无法将增量工具指向邮箱的其他位置。
  • 工作流提示词 —— morning_brief、triage_folder 和 catch_up 以 MCP 提示词的形式提供,无需逐次调用来重建常见操作序列。
便于 Agent 使用的形态(1.8.0)

两项纯代码升级,让 AI Agent 使用工具时开销更低,也更容易恢复:

  • 简洁模式 — 对六个高频读取工具(outlook_list_inbox、outlook_read_message、outlook_read_messages、outlook_search_mail、outlook_list_events、outlook_list_thread)传入 concise=True,即可省去冗余字段:完整邮件正文、会话中引用的先前邮件文本、正文预览和收件箱列表中的类别 — 典型情况下可将负载减少约 10 倍。对于 outlook_list_events,取舍有所不同,减少的字段也更少:会移除 organizer、response_status、type、show_as 和 key,新增 is_organizer 和 attendees_count,并将 is_online 改为 is_online_meeting,因此简洁扫描无法判断某个实例是周期性事件还是一次性事件。默认值 concise=False 会保留现有的响应结构 — 严格向后兼容。

  • 结构化 Graph 错误 — 每个工具都会将 msgraph SDK 异常转换为工具错误,其文本包含 Graph 的消息和恢复提示:401 时重新认证;403/ErrorAccessDenied 时提供指向仓库 ROADMAP 中无法解决的问题列表 的链接;404/ErrorItemNotFound 时重新列出;429 时退避;503 时重试 — 但可向他人发送邮件的工具(邮件、邀请、事件更新、RSVP)除外:遇到 5xx 时,提示写入可能已经成功,并说明在哪里检查,因为这些写入失败一次后绝不会重新发送。OutlookMCPError 子类和验证错误会原样传递。


Azure AD 应用注册

你需要注册一个免费的 Azure AD 应用,以获取客户端 ID。

前提条件(个人 Microsoft 帐户)

Microsoft 已弃用未加入 Azure AD 租户的个人帐户的应用注册功能。你需要先创建一个免费的 Azure 帐户:

  1. 前往 azure.microsoft.com/free,使用个人 @outlook.com 帐户注册。身份验证需要提供信用卡,但不会向你收费。这会创建一个正式的 Azure AD 租户。
注册应用
  1. 前往 应用注册,并使用你的 @outlook.com 帐户登录。

  2. 点击 “+ 新注册” 并填写:

    • 名称: 任意名称,但不能包含 Microsoft 品牌相关字词(例如 mp-outlook-mcp — “Outlook MCP”这类名称会被拒绝)
    • 支持的帐户类型: 选择 “仅个人 Microsoft 帐户”
    • 重定向 URI: 留空
  3. 点击 注册。从概述页面复制 应用程序(客户端)ID。

  4. 前往 身份验证(预览) → 设置选项卡 → 将 “允许公共客户端流” 切换为 是 → 保存。

  5. 前往 API 权限 → 添加权限 → Microsoft Graph → 委托的权限 → 添加:

    • Mail.ReadWrite、Mail.Send
    • Calendars.ReadWrite
    • Contacts.ReadWrite、Tasks.ReadWrite
    • MailboxSettings.Read
    • User.Read、offline_access

无需客户端密钥。设备代码流使用公共客户端身份验证。


快速开始

安装

选项 A — 从 PyPI 安装(推荐):

uv tool install outlook-graph-mcp
# or: pipx install outlook-graph-mcp
# or: pip install outlook-graph-mcp

若要以文本形式读取 PDF 和 XLSX 附件,请改为安装可选的 documents 扩展 (uv tool install 'outlook-graph-mcp[documents]'),并启用选择加入的 documents 组; 请参阅附件。

选项 B — 从源码安装:

git clone https://github.com/mpalermiti/outlook-mcp.git
cd outlook-mcp
uv sync
配置

创建 ~/.outlook-mcp/config.json:

{
  "client_id": "YOUR_APPLICATION_CLIENT_ID",
  "tenant_id": "consumers",
  "timezone": "America/Los_Angeles",
  "read_only": true,
  "attachments_dir": "~/.outlook-mcp/attachments"
}

唯一必填字段是 client_id。其他字段均有合理的默认值。请先设置 read_only: true — 熟悉后再将其改为 false。

注册到 MCP 客户端

如果从 PyPI 安装:

{
  "mcpServers": {
    "outlook": {
      "command": "outlook-mcp"
    }
  }
}

如果从源代码安装:

{
  "mcpServers": {
    "outlook": {
      "command": "uv",
      "args": ["--directory", "/path/to/outlook-mcp", "run", "outlook-mcp"]
    }
  }
}

对于 OpenClaw,使用 openclaw mcp CLI——它会为你写入 ~/.openclaw/openclaw.json 中的 mcp.servers:

# If installed from PyPI:
openclaw mcp set outlook '{"command":"outlook-mcp"}'

# If installed from source:
openclaw mcp set outlook '{"command":"uv","args":["--directory","/path/to/outlook-mcp","run","outlook-mcp"]}'

# Verify:
openclaw mcp list
openclaw mcp show outlook --json

注册后重启 OpenClaw 网关。有关 SSE/HTTP 传输方式,请参阅 OpenClaw MCP 文档。

身份验证

在 MCP 服务运行所在的机器上执行一次:

outlook-mcp auth          # installed from PyPI
uv run outlook-mcp auth   # from a source checkout

你会获得一个 URL 和一个代码。在任意浏览器中打开该 URL,输入代码,然后使用 Microsoft 账户登录。令牌会缓存在操作系统密钥环中,MCP 服务会自动获取这些令牌。

即使配置以 read_only: true 开始,同意屏幕也会列出完整的读写权限集合(Mail.ReadWrite、Mail.Send、Calendars.ReadWrite、Contacts.ReadWrite、Tasks.ReadWrite、MailboxSettings.Read、User.Read),因为 read_only 控制的是工具,而不是令牌(请参阅“read_only”的作用与不作用);此外,首次同意时未包含的权限,之后若不重新登录便无法授予。(唯一例外是 read_only_consent: true,它只请求读取权限;该选项适用于另一个只读应用,详见同一标题下的说明。)此后每个请求——静默刷新和每次 Graph 调用——都会使用 .default 权限范围;对于已完成同意的账户,这恰好代表“你已授予的权限集合”。这样的顺序是有意为之:在个人账户上,首次同意若只请求 .default,可能会建立一个没有委派权限的会话,之后便无法兑换(AADSTS70000),除非重新登录(#82)。

其他 CLI 命令(从源代码检出目录运行时,前缀为 uv run):

outlook-mcp status   # Check auth status
outlook-mcp logout   # Remove this instance's auth record (the OS token cache is left to age out)
outlook-mcp serve    # Start MCP server (default; stdio, or HTTP with OUTLOOK_MCP_TRANSPORT)

故障排除

每次调用都出现 me-token-to-replace is invalid

你安装的是 2026-09-18 之后发布的 1.22.0。全新安装该版本时会解析到 1.13 或更高版本的 microsoft-kiota-*,而 msgraph-core 1.5.1 无法处理这些版本,因此每个 /me 请求到达 Graph 时都会变成 /users/me-token-to-replace。此问题已在 1.22.1 中修复,该版本将 kiota 限制在 1.13 以下(#80)。在 1.26.0 中,这一限制改为要求 msgraph-core>=1.5.2,该版本包含修复,并且兼容 kiota 1.13 及更高版本:

uv tool upgrade outlook-graph-mcp
# or: pipx upgrade outlook-graph-mcp
# or: pip install --upgrade outlook-graph-mcp

你的配置和登录状态不受影响;无需重新进行身份验证。

Linux 上出现 SSL: CERTIFICATE_VERIFY_FAILED

如果身份验证失败并显示 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate,说明 Python 环境无法找到系统 CA 证书包。这在精简版/容器化 Linux 镜像以及 uv tool install 创建的隔离 venv 中很常见。

将 Python 指向系统 CA 证书包。设置这两个变量——身份验证(通过 azure-identity → requests)会读取 REQUESTS_CA_BUNDLE,而 delta/$batch 路径(通过 httpx)会读取 SSL_CERT_FILE:

export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt      # httpx + Python ssl
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt  # azure-identity auth

路径因发行版而异:Debian/Ubuntu 使用 /etc/ssl/certs/ca-certificates.crt;RHEL/Fedora 使用 /etc/pki/tls/certs/ca-bundle.crt。如果该文件不存在,请安装相应发行版的 CA 软件包(ca-certificates)。请在 MCP 客户端启动服务所用的同一环境中设置这些变量,使其在运行时生效,而不只是对一次性的 auth 命令生效。

令牌缓存未加密存储(Linux)

在没有加密存储的 Linux 上(libsecret/PyGObject 无法导入,或 Secret Service 未运行),outlook-mcp auth 和服务会拒绝以明文写入令牌缓存,并会说明每次工具调用失败的原因。请安装加密存储所需的系统软件包——参阅隐私与安全——或者设置 allow_unencrypted_token_cache: true 以接受明文缓存文件;之后,服务会在启动时记录一次性警告。


工具参考

日期。 每个日期时间参数(after、before、start、end、due、 deferred_send_datetime)都接受 ISO 8601 格式——2026-10-22 或 2026-10-22T14:30:00Z——或 相对偏移量:7d 表示七天前,+7d 表示七天后,now 表示此刻。单位为 m、h、d、w。不带符号表示过去,符合常见的 CLI 约定,因此未来的截止日期需要加上 +。不带时区的输入会按你配置的 timezone 解释;响应始终为 UTC。

文件夹。 每个 folder 参数、outlook_create_folder 的 parent_folder 参数,以及 outlook_batch_triage 的移动目标,都可使用常用名称(inbox、junkemail)、显示名称(Junk Email)、Graph ID 或路径:Inbox/Travel/Flights 表示 Inbox 下的 Travel 下的 Flights。文件夹名称本身含有 / 时,写作 //(Inbox/Q1//Q2)。显示名称会优先查找同名的顶层文件夹;如果多个嵌套文件夹同名,则会拒绝操作,并在错误信息中列出它们的路径。outlook_rename_folder 和 outlook_delete_folder 使用 ID。

身份验证
工具描述
outlook_auth_status检查是否已通过身份验证,以及是否启用了只读模式。

注意: 身份验证通过 CLI(outlook-mcp auth)处理,而非通过 MCP 工具。请参阅上文的身份验证。

邮件读取
工具描述
outlook_list_inbox列出文件夹中的邮件。folder 接受显示名称、常用名称、路径(Inbox/Travel/Flights)或 Graph ID。可按已读状态、发件人、日期范围、Focused Inbox 分类或无类别(uncategorized_only)筛选。通过 cursor(或 skip)分页。
outlook_read_message按 ID 或 Message-ID 标头值(<[email protected]>,精确匹配;响应中的 id 是其他工具所需的 Graph ID)获取完整邮件。格式:text、html 或 full(两者都有)。传入 include_deferred_send=True,也会显示草稿的计划发送时间。传入 include_sender_auth=True,会添加 sender_authentication,即 Microsoft 对 From 域名的判定:authenticated、from_domain、dkim、dmarc 和 compauth 结果,以及简短的 reason。仅采用 Microsoft 自身最靠前的 Authentication-Results 标头;只有通过验证且与 From 域名对齐时,authenticated 才为 true。它仅证明 from_domain,绝不证明显示名称;false 表示未经验证,而非伪造。
outlook_read_messages通过 Graph $batch 在一次往返中按 ID 批量读取最多 20 封邮件。对于相同的 (format, concise, include_deferred_send, include_sender_auth),每封邮件的结构与 outlook_read_message 逐字节一致。可容忍部分失败:部分 ID 返回的 404 会显示在 failures[] 中,不会导致整个调用失败。使用此工具,而不要调用 N 次 outlook_read_message。
outlook_search_mail使用 KQL 查询搜索邮件。可选按文件夹名称、路径或 ID 限定范围。cursor 会在开始搜索的文件夹中继续搜索。已发现 Graph 有时会在结果略超 250 条时结束搜索,却不作提示(Exchange Online 为 255–275 条;Outlook.com 也观察到 275 条),因此超过 250 条的最后一页会带有 incomplete,提示较早的匹配项可能缺失,并说明如何获取这些结果。
outlook_list_folders列出邮件文件夹及其计数、parent_id 和 child_count。传入 recursive=true 可遍历完整文件夹树(包括子文件夹);此时每个文件夹都会带有 path,该值可用于所有 folder 参数。
outlook_list_inbox_delta仅列出自上次调用以来收件箱的变化。folder(默认为 inbox)接受名称、路径或 ID。首次调用返回完整快照和 delta_token;后续调用(传回该令牌)仅返回新增、更新或删除的项目。删除项的返回形式为 {id, is_deleted: True}。游标无状态,Agent 会持久化并重放。
outlook_changes_since汇总邮件、事件和联系人的增量,生成一份结构化的“自上次调用以来”的摘要。返回计数、urgent_flagged 邮件、按发件人排列的前 5 项(by_sender)以及新增/取消的事件。每种资源都有独立的 delta_token;令牌过期时(HTTP 410)会自动重新同步相应资源,并显示 _meta.resync。首次调用涵盖最近 fallback_window_hours 小时(默认为 24 小时):邮件请求 Graph 按接收时间筛选,并在 Graph 忽略筛选时由客户端强制执行(_meta.mail_window_fallback);联系人按最后修改时间保留,事件则按日历视图保留(该时间窗口加上未来 7 天)。如果 Graph 遵循邮件筛选条件,后续调用会继续使用该条件:对于在窗口开始时间之前收到的邮件,只报告删除、移出收件箱以及已读/未读状态变化,不报告新增标记或类别。has_more 会列出因单次调用上限而未完成同步的资源;请将存储的 delta_tokens 字典替换为返回的字典并传回,不要合并这些字典。如果邮件引导同步尚未完成,它会保留 mail_bootstrap_from,因此后续调用会继续使用原始起始边界,并在 window.from 中报告该边界。若回复中没有新游标,则会返回传入的令牌。专为循环运行的 Agent 设计。
邮件撰写
工具描述
outlook_send_message发送电子邮件。支持 TO/CC/BCC、HTML 或 Markdown 正文、重要性级别、reply_to 和已读回执(request_read_receipt)。
outlook_reply回复或回复全部收件人,正文位于引用原文上方。纯文本会保留段落、换行和 - 列表;纯文本会话会收到纯文本回复。
outlook_forward将邮件转发给一位或多位收件人,并可添加备注;备注会像回复正文一样保留换行。

除非设置 is_html=True(HTML 按原样发送)或 is_markdown=True,否则正文均为纯文本。Markdown 会转换为 HTML,并仅支持以下安全子集:段落、换行、-/*/+ 和编号列表、**粗体**、*斜体*、`代码`,以及仅指向 https: 和 mailto: 地址的 [链接文本](url) 链接。图片 ![alt](url) 会转换为指向图片的链接,不会嵌入图片。其他所有内容(包括原始 HTML)均按原样显示。outlook_send_message、outlook_reply、outlook_forward(其 comment)、outlook_create_draft 和 outlook_update_draft 均支持此功能;在纯文本会话中,Markdown 回复会作为纯文本按原样发送。

邮件整理
工具描述
outlook_move_message按名称、路径或 ID 将邮件移至文件夹。
outlook_delete_message删除邮件。默认软删除(移至“已删除邮件”)。设置 permanent: true 可永久删除。
outlook_flag_message设置后续跟进标记:flagged、complete 或 notFlagged。
outlook_categorize_message为邮件设置类别。
outlook_mark_read将邮件标记为已读或未读。
outlook_reclassify_message在“重点收件箱”和“其他”之间移动邮件(focused / other)。
outlook_list_inbox_overrides列出“重点收件箱”的发件人覆盖规则。
outlook_set_inbox_override创建或更新发件人的“重点收件箱”覆盖规则(focused / other)。发件人匹配不区分大小写;若规则已存在则使用 PATCH,否则使用 POST。
outlook_delete_inbox_override按 ID 删除“重点收件箱”覆盖规则。
日历读取
工具描述
outlook_list_events列出指定日期范围内的事件。会展开重复事件。每个事件都包含 type:系列中的实例为 occurrence 或 exception,一次性事件为 singleInstance——因此无需再次调用,就能从列表中区分重复工作。这里不会出现 seriesMaster:calendarView 会返回展开后的实例,因此要查看主事件,请使用 outlook_get_event。每个事件还包含 show_as,即 Outlook 标记的忙闲状态“Show as”。可通过 days、after、before 配置。calendar 用于选择要读取的日历:省略(或设为 "primary")时使用默认日历;否则可填写显示名称(不区分大小写;未找到或存在歧义时,错误信息会列出可用选项)或 outlook_list_calendars 返回的 ID。cursor 会继续读取其来源列表,因此后续页面无需传入 calendar,也无需再次查询。具有 key 的事件(参见 outlook_create_event)会带上该字段;没有 key 的事件则不包含此字段。concise=True 时会省略 type、show_as 和 key。
outlook_get_event获取完整事件详情:与会者、正文、在线会议 URL、重复规则、type(singleInstance / seriesMaster / occurrence / exception)、show_as、key(事件没有该字段时为 null),以及 attachments——每个文件的 id、name、size、content_type 和 is_inline,不会返回文件字节(没有附件时为 [];仅当 Graph 报告该事件有附件时,才需通过第二次请求读取)。传入 event_id 或邀请的 message_id,即可在你的日历中解析出确切事件(绝不会按主题解析)。返回当前详情和邀请是否过时的信息,以及可空的 is_organizer、allow_new_time_proposals、is_cancelled 和包含时区的与会者 proposed_new_time 时间段。缺失的元数据保持为 null;组织者状态相对于日历所有者而言。
outlook_find_event_by_key查找 key 与给定值匹配的事件——这是调用方通过 outlook_create_event 或 outlook_update_event 设置的自有引用。没有日期范围限制:几个月后的预订和明天的预订一样都能找到。搜索默认日历,或搜索通过 calendar 指定的日历(解析方式同 outlook_list_events)。返回默认列表格式的事件,并包含 key:包括单个事件和系列主事件,但不包括实例,因此找到的 ID 就是要更新的 ID。没有匹配项时返回空列表;若有超过 25 个事件共用该 key,则 has_more 为 true。
outlook_list_events_delta仅列出自上次调用以来指定时间范围内发生变化的事件。首次调用时必须提供 start 和 end(ISO 8601)(Graph 的限制——无法同步整个日历)。每个有变化的事件都包含默认 outlook_list_events 列表返回的所有字段,但 key 除外;同时包含 type 和 show_as,以及 is_deleted(concise=True 有其自身更精简的格式,delta 工具不会采用该格式)。与列表接口不同,此端点会返回 seriesMaster 项,因此,如果调用方以 outlook_list_events 的结果作为初始数据,应预期此处出现初始数据中没有的 ID。删除的事件以 {id, is_deleted: True} 返回,不包含其他内容。游标无状态。
日历写入
工具描述
outlook_create_event创建包含地点和参会者的事件。(is_online 对个人账户没有影响——Graph 会忽略消费者邮箱的 isOnlineMeeting。)传入 recurrence 可创建系列:使用简写(daily、weekdays、weekly、monthly、yearly,以 start 为基准),或在其他情况下使用完整的 Graph recurrence object。range.startDate 默认为事件的开始日期。timezone(IANA 名称,例如 America/Los_Angeles,不能使用缩写)是事件所锚定的时区,也是系列展开所用的时区;省略时使用配置中的 timezone。show_as 设置 Outlook 标注的忙闲状态“显示为”——free、tentative、busy、oof(不在办公室)、workingElsewhere 或 unknown;省略时,Graph 会应用自己的默认值 busy。calendar 可在其他日历中创建事件,解析方式与 outlook_list_events 相同:省略(或使用 "primary")表示默认日历,否则可传入显示名称或 outlook_list_calendars 返回的 ID。Graph 列为只读(canEdit: false)的日历会在发送任何内容前被拒绝。需要事件 ID 的工具不需要 calendar:ID 可以指向你任意一个自有日历中的事件。key 会将你自己的事件引用(例如预订编号:1–128 个字母、数字及 . _ : @ -)存储在隐藏扩展属性中,以便在同一预订发生变更时,outlook_find_event_by_key 能再次找到该事件。两个事件可以使用相同的键;创建前请先查找。
outlook_update_event更新事件字段(主题、时间、地点、正文、参会者、全天状态、show_as)。只更新发生变化的字段。传入 recurrence 可将单个事件转换为系列,传入 remove_recurrence=True 可将系列恢复为单个事件。attendees 会替换整个来宾列表,并发送邀请或取消通知;is_all_day 需要在同一次调用中提供 start 和 end,而 show_as 可单独更新。更新时段会保留事件所锚定的时区;同时提供 start、end 和 timezone 可将事件重新锚定到其他时区,这也是修复在时区功能出现之前创建的系列的方法。如果系列中有已编辑或已删除的实例,则拒绝对其执行 start、end 或 recurrence 更新,并列出这些实例——否则 Graph 会静默丢弃所有这些实例。key 可设置或替换事件的键,也可单独更新;无法清除键。
outlook_delete_event删除日历事件。
outlook_rsvp回复事件邀请:accept、decline 或 tentative。可选地附上消息。
outlook_attach_to_event为事件添加文件附件,例如航班电子机票。attachment_paths 会在 attachments_dir 中解析,与 outlook_attach_to_draft 的方式相同;如果文件不存在,或路径位于该目录之外,则不会添加任何附件。超过 3 MB 的文件会使用上传会话;如果 Graph 拒绝某个分块,或上传未报告完成,调用会报错并停止,而不会报告文件已附加。返回新附件的 ID(使用上传会话的文件暂时不会返回 ID)。添加附件时不会将文件发送给参会者;他们会在事件下一次更新时收到文件,因此对于有参会者的事件,需要在受限的 allow_categories 下使用 mail_send。
outlook_remove_event_attachment根据 outlook_attach_to_event 返回或 outlook_get_event 列出的 ID,从事件中移除一个附件。
联系人
工具描述
outlook_list_contacts使用游标分页列出联系人。摘要包含 categories;outlook_search_contacts 会省略该键,因为 Graph 的 $search 不会返回它。
outlook_search_contacts按姓名或电子邮件搜索联系人。使用 phone 而不是 query 可查找号码,无论其书写方式如何:无论是否带国家/地区代码、前导 00 或国内长途前缀 0、空格或连字符,只要至少提供末尾 7 位数字即可。Graph 的联系人 $search 只能按号码的存储形式查找,而且无法筛选电话号码字段,因此电话搜索会读取联系人列表(每页 1,000 个,最多读取 10,000 个联系人)并比较数字。当匹配结果多于 count,或第 10,000 个之后仍有联系人时,has_more 为 true。
outlook_get_contact按 ID 获取完整联系人详情,包括 middle_name、job_title、birthday、家庭/工作/其他地址、类别和个人备注。
outlook_create_contact创建新联系人。title 是姓名前缀(如 “Dr.”、“Ms.”),Outlook 会在显示名称中显示该前缀;职位应填写在 job_title 中。phone_type(mobile 为默认值,也可以是 business 或 home)表示 phone 属于哪种号码。birthday 是日期(YYYY-MM-DD),会存储为 UTC 时间 11:59,以确保 UTC−11 至 UTC+12 的所有时区显示同一天;outlook_get_contact 会返回该时间戳。middle_name、personal_notes 和 categories 会按给定值设置。
outlook_update_contact更新联系人字段,包括 middle_name、company、title、job_title 和 personal_notes。categories 会替换联系人的整个类别列表,就像 outlook_categorize_message 会替换邮件的类别一样,因此 [] 会移除所有类别;要添加类别,请先读取联系人。phone_type 的作用与创建时相同;business 或 home 号码会用给定的号码替换该类型下的整个号码列表。clear_phones 会清空其中指定的类型,因此 phone_type="business", clear_phones=["mobile"] 可在一次更新中将保存为手机号码的号码移至工作号码。home_address、business_address 和 other_address 采用 outlook_get_contact 返回的格式——可包含 street、city、state、postal_code、country_or_region 中的任意子集——并会替换整个地址,因此请传回所有要保留的部分。省略某项即可保持其不变。birthday 会像创建时一样设置或替换日期。email 会用给定地址替换所有地址;add_emails 和 remove_emails 只会更改其中指定的地址,并保留其余地址(一个联系人最多可保存 3 个地址)。这些操作会与联系人当前保存的地址合并,并通过 If-Match 固定在读取时的版本上,因此如果期间有人进行编辑,更新会以 412 拒绝,而不会覆盖更改。移除联系人并不拥有的地址会被拒绝。
outlook_delete_contact删除联系人。
outlook_list_contacts_delta仅列出自上次调用以来的联系人变更。删除项会以 {id, is_deleted: True} 的形式返回。游标是无状态的。
待办事项
工具描述
outlook_list_task_lists列出待办事项列表。
outlook_list_tasks按状态筛选并分页列出任务。
outlook_get_task获取任务的完整详情:备注(body)、清单项(未勾选项排在前面)、截止日期和重复标记。
outlook_create_task创建任务,并设置截止日期、重要性和重复规则。
outlook_update_task更新任务字段。
outlook_complete_task将任务标记为已完成。
outlook_delete_task删除任务。
outlook_add_checklist_item向任务添加清单项(子步骤)。
outlook_update_checklist_item更新清单项——标记为已完成(is_checked)或重命名(部分更新)。
outlook_delete_checklist_item从任务中删除清单项。
outlook_list_task_attachments分页列出待办任务的附件(id、名称、大小、content_type)。
outlook_download_task_attachment将任务附件的内容下载到本地文件(限制在 attachments_dir 内),或通过 as_content=True 返回内容。
outlook_upload_task_attachment通过内联 base64 POST 将本地文件(来自 attachments_dir)附加到任务(1 字节至 20 MiB)。
outlook_delete_task_attachment从待办任务中移除附件。
草稿
工具描述
outlook_list_drafts分页列出草稿邮件。
outlook_create_draft创建草稿;可按需使用 HTML(is_html=True)或 Markdown(is_markdown=True)正文。使用 reply_to_message_id(回复所有人时设置 reply_all=True)或 forward_message_id 时,草稿会在该邮件的对话线程中创建,并在下方引用原邮件;不会发送任何内容。Graph 会自动填入回复邮件的收件人和主题;转发邮件则需要提供 to。支持通过 deferred_send_datetime 安排发送时间(服务器端,与 Outlook 桌面版的“延迟发送”兼容)。
outlook_update_draft更新草稿字段。HTML 正文可使用 is_html=True,Markdown 正文可使用 is_markdown=True;也可通过 deferred_send_datetime 设置或清除计划发送时间。
outlook_send_draft发送现有草稿。
outlook_delete_draft删除草稿。
附件

自 1.20.0 起,这些工具只能访问 attachments_dir(默认值为 ~/.outlook-mcp/attachments)。 仅提供文件名时,文件会在该目录中解析;目录之外的路径会被拒绝,包括通过符号链接访问的路径。 若要通过邮件发送文件,请先将其移到该目录中,或者扩大 attachments_dir 的范围,但请注意,其中可访问的任何内容都可能被发送。1.20.0 之前,这些工具可以读取服务器进程能够读取的任何文件,因此,当 Agent 收到要求附加某个文件的邮件时,可能会照做。

同样的限制也适用于 To Do 附件工具(outlook_upload_task_attachment、 outlook_download_task_attachment):上传时从 attachments_dir 读取,下载时写入该目录,因此两者都无法从磁盘任意读取文件。(下载不受 todo_write 限制——它们是读取操作,与 outlook_download_attachment 一样;限制它们的是路径围栏,而非类别。)

无法访问服务器磁盘的客户端,例如远程客户端或沙盒客户端,可以在调用时直接传递字节,这样就不会从磁盘读取或写入任何内容。 对任一下载工具设置 as_content=True,即可在结果中返回附件,大小上限为 10 MB: PNG、JPEG、GIF 和 WebP 图像上限为 5 MB;文本上限为 100,000 个字符,并以文本形式返回;其他内容(包括 PDF)则作为嵌入式资源返回,其中包含 base64 字节及其类型。未完整的图像(例如缺少结束块的 PNG)也会作为该资源返回。 包含控制字符的文本,或其字符集解码后包含孤立代理项的文本,也会作为该资源返回,从而保持原样。 outlook_send_with_attachments 和 outlook_attach_to_draft 中的 attachments 参数可接收内联文件,格式为 [{name, content_base64, content_type?}],每个文件上限为 3 MB(Graph 的简单附件大小限制)。路径参数仍受路径围栏限制。内联文件是 Agent 已持有的字节,也可以直接放入消息正文,因此不会扩大访问范围。 outlook_attach_to_event 和 outlook_upload_task_attachment 只接受路径。

工具描述
outlook_list_attachments列出邮件中的附件。
outlook_download_attachment下载附件并将解码后的字节保存到 attachments_dir,或通过 as_content=True 返回附件内容。
outlook_read_attachment选择启用(属于 documents 组,默认不加载;见下文)。读取 PDF 页面、XLSX 单元格/公式/已保存结果,或按其声明的字符集读取文本(默认为 UTF-8);可通过 offset/max_chars 分页读取文本,不保存文件。
outlook_send_with_attachments发送带附件的邮件,附件可从 attachments_dir 读取(大于 3MB 时自动使用上传会话),也可通过 attachments 内联传入。如果大文件上传失败,则不会发送邮件;错误信息会指出留在 Drafts 中的草稿,以便删除,或改用 outlook_attach_to_draft 完成操作,避免重复发送。
outlook_attach_to_draft将 attachments_dir 中的附件(大于 3MB 时自动使用上传会话)或 attachments 中的内联附件添加到现有草稿。大文件上传失败时会返回错误,不会报告文件已附加。返回新附件 ID(上传会话文件暂时不会返回 ID)。
outlook_remove_draft_attachment从草稿中移除单个附件。

如需读取文档的可读内容,而非原始字节,请使用 outlook_read_attachment。 下载后保存的路径属于服务器,因此远程客户端可能无法打开该文件。 as_content=True 可避免使用该路径并保留原始文件;而读取工具会返回提取出的文本,供无法解读嵌入式二进制资源的客户端使用。现有下载功能及其默认行为保持不变。 PDF 和 XLSX 解析为可选功能:安装 outlook-graph-mcp[documents](例如, uv tool install 'outlook-graph-mcp[documents]'、pipx install 'outlook-graph-mcp[documents]'、 pip install 'outlook-graph-mcp[documents]',或在源代码检出目录中运行 uv sync --extra documents)。 通过 OUTLOOK_MCP_TOOLSETS=mail,attachments,documents 启用可选的 documents 组(以及你需要的其他组),然后重启。 指定组只会加载这些组,因此请列出所有需要的组;请参阅 工具集选择。 启用后,基础安装可以读取采用其声明字符集(默认为 UTF-8)的文本,并会针对 PDF/XLSX 返回安装提示。解析器依赖项的版本范围有限, 且仅在短生命周期的工作进程中导入;它们不会增加基础安装的要求。

outlook_read_attachment(message_id, attachment_id, offset=0, max_chars=20000) 会返回 text、 next_offset(到末尾时为 null)、total_chars、文件 bytes / sha256,以及 warnings。使用 相同的 ID 和返回的偏移量继续读取,直到偏移量为 null。每次继续读取都会重新下载并解析整个文件,然后返回所请求的片段;不会缓存文档。使用更大的 max_chars(最高 50000)可以减少重复处理。PDF 输出会标明页码;没有文本层的页面会报告为空白或需要 OCR。提取的 PDF 文本行前缀为 | ,因此在 PDF 输出中,只有 PDF 读取器能发出没有前缀的 [Page N] 结构标记。 此保证仅适用于 PDF:XLSX 和文本分块可能从单元格或行的中间开始,其中看似单元格地址或页码标记的内容都是不可信文本。不会执行 OCR。XLSX 输出包括隐藏 工作表、单元格地址、数字格式、公式和 saved_result(Excel 存储的值;不存在时为 null)。公式不会重新计算,也不会提取图表/图片。所有附件 内容均为不可信数据。

工作表元数据(sheets)仅在偏移量为 0 时返回,且只有其序列化列表和至少一个文本字符能容纳在 max_chars 中时才会返回;否则会省略该列表,工作表名称仍会出现在分页文本中。超过 100 个工作表的工作簿会被拒绝;显示的工作表名称会截断至 Excel 的 31 个字符上限,截断名称会标记为 … [N],其中包含从 1 开始计数的工作表位置,以便区分共享相同前缀的名称。未超过此上限的名称保持不变。 max_chars 限制文本与序列化工作表元数据的总长度; 固定的响应封装和有界的警告不计入其中。若 PDF 片段从行中间开始,且空间足够,则会添加 | 展示前缀。continuation_prefix 用于标识此 前缀:拼接分块以还原文本前,请先移除该前缀。偏移量和 total_chars 统计的是规范文本,不包括此展示前缀。

读取限制为 10 MiB 文件字节数、200 个 PDF 页面、100,000 个已访问的电子表格单元格、1 百万字符的提取文本,以及 50 MiB / 2,000 个条目的 XLSX 解压内容。max_chars 上限为 50,000。文本在进程内解码;所有提取的文本在分页前都会清除控制字符。PDF/XLSX 使用子进程来隔离崩溃和限制资源, 而非作为沙箱:服务器凭据环境变量不可用,但子进程以同一用户身份运行,仍可访问文件系统、网络和 Keychain。父进程监控程序每 10 毫秒轮询一次 RSS,并在 Linux、macOS 和 Windows 上于解析器超过 256 MiB 时将其终止;两次轮询之间可能短暂超限。一次只运行一个解析器,墙钟超时为 30 秒。 在支持的系统上,操作系统资源限制会作为补充措施。 达到限制时会明确报错,绝不会静默返回不完整的文档。

文件夹管理
工具描述
outlook_create_folder创建邮件文件夹(顶层文件夹,或嵌套在 parent_folder 下;parent_folder 可以是名称、路径或 ID)。
outlook_rename_folder按 ID 重命名邮件文件夹。
outlook_delete_folder按 ID 删除邮件文件夹(拒绝删除已知文件夹)。
线程和批处理
工具描述
outlook_list_thread获取对话线程中的所有邮件。
outlook_copy_message将邮件复制到其他文件夹(名称、路径或 ID)。
outlook_batch_triage批量移动、标记、分类或标记为已读(每次最多 20 封)。只需一次 Graph /$batch 往返调用——对于大量邮件的分拣,速度比逐封调用快 10–20 倍;如果 Graph 对某封邮件进行限流,会在其 Retry-After 时间后重新发送,而不是将其报告为失败。mark_read 接受 true/false(或 read/unread)。
用户和管理员
工具描述
outlook_whoami获取当前用户资料。
outlook_list_calendars列出可用日历,包括 owner(name、address)和 can_view_private_items。缺少所有者或私人项目权限元数据时,值为 null;false 表示你无法查看该日历中的私人项目。若日历名称重复,请使用日历 ID。
outlook_list_categories列出带颜色的类别定义。
outlook_get_mail_tips发送前检查(外出通知、投递限制)。

提示词

MCP 提示词内置了三个工作流,因此无需逐次调用来重建常见操作序列。任何支持提示词的 MCP 客户端都会列出这些提示词;在大多数客户端中,它们会以斜杠命令或提示词选择器的形式显示。

提示词参数功能
morning_brieffolder(默认值为 inbox)按成本最低的顺序查看今天的活动、未读邮件和到期任务——每项只扫描一次,使用 concise=True 和批量读取。
triage_folderfolder(默认值为 inbox)、count(默认值为 50)低成本扫描文件夹一次,将邮件分类为需回复、归档或垃圾邮件,并通过一次 outlook_batch_triage 调用完成处理,而非逐封调用。
catch_upsince(默认值为 24h)通过增量路径查看邮件、日历和联系人的变化——成本约为按计划重新扫描的十分之一。

只有调用时才会产生开销:prompts/list 仅包含名称和各一行简介,正文会在使用时获取。


配置

配置文件位于 ~/.outlook-mcp/config.json(在 macOS 和 Linux 上以 0600 权限创建;Windows 请参阅下文的 配置权限)。所有平台均以 UTF-8 格式读取,并接受字节顺序标记。设置 OUTLOOK_MCP_CONFIG_DIR 环境变量可更改此设置目录的位置(config.json、身份验证记录和附件默认目录也会随之移动)——请参阅下文的两个账户,两个实例。

字段类型默认值描述
client_idstringnullAzure AD 应用程序(客户端)ID。身份验证必填。
tenant_idstring"consumers"Azure AD 租户。个人 Microsoft 账户请使用 "consumers"。
expected_usernamestringnull自 1.29 起:此实例的可选登录用户名。刷新已保存的其他用户名登录信息前会拒绝该操作;保存新登录记录或使用其凭据前会先检查新登录信息。不区分大小写;会直接比较 Microsoft 登录用户名,不会解析别名。不设置则保持现有行为。较旧版本会忽略此键并发出警告,且不会执行此限制。
timezonestring"UTC"IANA 时区(例如 "America/New_York")。用于解析未指定时区的日期,并作为你创建的每个事件的时区基准——周期性事件会在此时区中展开,因此在默认的 "UTC" 时区下,每周 09:00 的会议会在时钟切换时前后移动一小时。请设置为你所在的时区。
read_onlyboolfalse为 true 时,所有写入工具(发送、回复、移动、删除、创建、更新、RSVP)都会返回错误。此设置限制的是工具,而非 Microsoft 令牌——请参阅下文。
read_only_consentboolfalse为 true 时,outlook-mcp auth 仅向 Microsoft 请求读取权限,而非读写权限集。适用于第二个只读应用注册——请参阅 read_only 的作用与不作用。必须同时设置 read_only: true;否则配置会被拒绝。
attachments_dirstring"~/.outlook-mcp/attachments"附件工具唯一可读取或写入的目录。Agent 提供的每个路径都会经过解析,且必须位于此目录内——指向目录外的符号链接或 .. 都会被拒绝。只有在了解该目录中任何可访问的内容都可能被通过电子邮件发送后,才扩大其范围。
allow_categorieslist[string][]可选。将写入工具限制为特定类别(见下文)。空列表 = read_only: false 时允许所有写入操作。
allow_unencrypted_token_cacheboolfalse当平台没有加密存储(未安装 libsecret 的 Linux)时,允许以明文写入 OAuth 令牌缓存。默认关闭:身份验证会停止并说明原因,而不会悄悄以明文持久保存可重复使用的 Graph 令牌。macOS 和 Windows 始终使用加密,不受影响。
环境配置(可选)

auth、serve 和 status 共用同一个加载器。它会先加载并验证 config.json (如果文件不存在,则使用现有默认值),然后读取以下可选变量。配置文件损坏、 无法读取或为符号链接时,启动仍会被拒绝;环境变量无法绕过此限制。 覆盖值不会自动写回文件。

变量输入与文件/默认值的关系
OUTLOOK_MCP_CLIENT_ID非空字符串仅当文件中没有 client_id 时才提供该值;如果对应的是不同的应用注册,则会被拒绝
OUTLOOK_MCP_TENANT_ID非空字符串覆盖 tenant_id
OUTLOOK_MCP_TIMEZONEIANA 时区覆盖 timezone
OUTLOOK_MCP_READ_ONLYtrue 或 false可以启用限制,但不能禁用限制
OUTLOOK_MCP_READ_ONLY_CONSENTtrue 或 false可以启用只读同意;要求最终生效的 read_only: true
OUTLOOK_MCP_ALLOW_CATEGORIES类别名称的 JSON 数组可以缩小允许的类别范围,但不能扩大范围
OUTLOOK_MCP_ATTACHMENTS_DIR目录路径必须解析为已配置目录或其子目录
OUTLOOK_MCP_ALLOW_UNENCRYPTED_TOKEN_CACHEtrue 或 false可以禁止明文存储;除非文件中已允许,否则不能启用明文存储

未设置的变量不起作用。将受支持的变量设为空值会导致启动被拒绝, 包括空的 Compose ${VAR} 透传值。布尔值仅接受 true/false (不区分大小写,允许首尾有空格);列表输入必须为 JSON,例如 ["mail_drafts","contacts_write"]。 空类别列表表示所有类别,因此不能用它替代受限的文件列表。 每项安全设置都会单独检查:启用只读模式并不能成为放宽其他设置的理由。 需要在文件中明确同意的安全权限,仍然必须在文件中明确同意。

附件根目录会展开并解析,但不会创建目录。覆盖值会保留为经过检查的绝对路径; ..、同级目录前缀和符号链接都无法越出已配置的根目录。 每次检查附件路径时都会重新检查该根目录,包括启动后目录变为符号链接的情况。 在 Windows 上,解析操作可能访问不同驱动器/共享位置或未经批准的 UNC/设备位置之前, 系统就会拒绝此类位置。 无效输入、拼错的安全变量,以及试图放宽策略的操作都会阻止启动,并指出需要在启动环境中 修正的变量。现有的 OUTLOOK_MCP_CONFIG_DIR、工具集和传输变量含义不变。不设置任何 新增变量时,文件加载行为保持不变。 这些检查保护的是受支持的设置变量,而不是整个启动环境: 任何能够控制该环境的人,也可以通过 OUTLOOK_MCP_CONFIG_DIR 或 HOME 更改设置文件的目标。

工具集选择(可选)——OUTLOOK_MCP_TOOLSETS

每轮都会将 71 个默认工具架构加载到客户端的上下文中(test_tool_surface_budget.py 使用 chars/4 这一代理指标进行测量;这与 ROADMAP 中针对 62 个工具表面的约 8.6k o200k 估算采用的衡量标准不同)。只需要部分工具表面的客户端可以将 OUTLOOK_MCP_TOOLSETS 环境变量设置为以逗号分隔的工具组列表,只加载这些组。account 组(身份验证 / 身份信息)始终可用。

# e.g. a recurring mail + calendar agent: 31 tools instead of 71 (about half the tool tokens per turn)
OUTLOOK_MCP_TOOLSETS="mail,calendar,digest,delta"

工具组:mail、drafts、attachments、calendar、contacts、todo、folders、digest、delta、admin、documents。未设置时会加载 71 个默认架构;除非明确指定,否则不会启用 documents。完整声明的工具表面包含 72 个工具。这只会影响所公布的工具;已启用的工具行为保持不变。

指定任意工具组后,只会加载指定的组以及 account;不属于任何工具组的名称不会匹配任何内容。因此,要在默认集合中添加 documents,需指定全部 11 个组:OUTLOOK_MCP_TOOLSETS=mail,drafts,attachments,calendar,contacts,todo,folders,digest,delta,admin,documents。

这些工具组与工具参考中的标题并不对应。mail 包含邮件读取、撰写和分类工具、outlook_list_thread、outlook_copy_message 以及 outlook_batch_triage,但 outlook_list_folders 属于 folders;Focused Inbox 工具(outlook_reclassify_message 和三个 override 工具)与分类和邮件提示一起属于 admin;三个 *_delta 工具属于 delta,而 outlook_changes_since 属于 digest;outlook_list_calendars 属于 calendar;两个草稿附件工具属于 drafts,而 outlook_read_attachment 属于 documents;account 则包含 outlook_auth_status 和 outlook_whoami。

双账号、双实例(可选)——OUTLOOK_MCP_CONFIG_DIR

一个服务进程服务于一个邮箱。要使用两个账号,请注册两个客户端条目,并为每个条目指定各自的设置目录,使用 OUTLOOK_MCP_CONFIG_DIR——同时搭配 OUTLOOK_MCP_TOOLSETS,让每个实例也只加载所需的工具组:

{
  "mcpServers": {
    "outlook-net": {
      "command": "outlook-mcp",
      "env": {
        "OUTLOOK_MCP_TOOLSETS": "mail,calendar,contacts",
        "OUTLOOK_MCP_CONFIG_DIR": "~/.outlook-mcp-net"
      }
    },
    "outlook-neko": {
      "command": "outlook-mcp",
      "env": {
        "OUTLOOK_MCP_TOOLSETS": "todo",
        "OUTLOOK_MCP_CONFIG_DIR": "~/.outlook-mcp-neko"
      }
    }
  }
}

然后为每个实例分别运行一次 outlook-mcp auth,并设置相同的环境变量,以便在各自的目录中写入认证记录。每个实例都会从自己的目录读取自己的 config.json(包括自己的 client_id、timezone 和权限)。

只移动配置目录——绝不要移动 HOME。 令牌缓存不在该目录中:它保留在操作系统钥匙串中。在 macOS 上,主机上的每个 azure-identity 缓存都共用同一个 Keychain 条目,并通过一个信号文件协调——在此服务器上,该文件是 ~/.IdentityService/outlook-mcp.nocae(azure-identity 会为每个非 CAE 缓存名称追加 .nocae;CAE 缓存会是同一条目对应的另一个文件)。两个进程都必须继续查看同一个信号文件,以便缓存写入能够锁定并合并到同一个共享条目中——这正是移动配置目录可以保留的行为,而重定向 HOME(或缓存位置)会破坏它:两个信号文件都会认为自己拥有该 Keychain 条目,并相互覆盖对方的令牌。OUTLOOK_MCP_CONFIG_DIR 有意只更改 config.json、认证记录和附件的存放位置;未设置或为空时,仍使用默认值 ~/.outlook-mcp。

从 1.29 版本起,要为某个实例指定必须使用的登录账号,请在该实例的 config.json 中添加 "expected_username": "[email protected]"。较旧版本会发出警告并忽略此键,不会执行限制。此可选限制会对比 Microsoft 保存的登录用户名,且不区分大小写;它不会解析电子邮件别名。若缓存的用户名不匹配,系统会在构建或刷新凭据前拒绝使用,并且 outlook-mcp status 会显示拒绝原因和解决办法,但不会显示任一用户名:使用预期账号登录,或在 expected_username 有误时将其更正。新的登录会在 Microsoft 交互式登录完成后、记录保存或凭据使用前进行检查。登录被拒绝时,先前的认证记录保持不变,但 azure-identity 可能已经将该账号的刷新令牌添加到本地共享操作系统令牌缓存中。在 macOS 上,这仍是同一个 Keychain 条目,先前账号的令牌也仍保留在其中。outlook-mcp 中的任何功能(包括 logout)都不会移除这些缓存令牌。

未设置或设为 null 时,会保留当前行为。值为空或拼写错误(例如 expected_usename)时,启动会停止,而不是静默禁用此限制。

远程 / HTTP 传输(可选)——OUTLOOK_MCP_TRANSPORT

默认使用 stdio,上述每个客户端条目也都使用它。对于运行在其他机器或容器中的服务,或者无法启动本地进程的客户端,可设置 OUTLOOK_MCP_TRANSPORT=streamable-http,改为在 /mcp 提供 MCP 的可流式 HTTP 传输:

export OUTLOOK_MCP_TRANSPORT=streamable-http
export OUTLOOK_MCP_HTTP_HOST=127.0.0.1   # default 127.0.0.1
export OUTLOOK_MCP_HTTP_PORT=8000      # default 8000
export OUTLOOK_MCP_HTTP_TOKEN=...      # python -c "import secrets; print(secrets.token_urlsafe(32))"
outlook-mcp serve

然后,客户端连接到 https://<your proxy>/mcp,并发送 Authorization: Bearer <token>。

OUTLOOK_MCP_TRANSPORT 可设为 stdio(默认值,未设置或为空时也使用此值)或 streamable-http。其他任何值、超出 1–65535 范围的端口、格式错误的 OUTLOOK_MCP_HTTP_ALLOWED_HOSTS,或缺失或格式错误的令牌,都会导致服务器在启动时停止并说明原因,且不会绑定任何地址。

对于容器,请明确设置 OUTLOOK_MCP_HTTP_HOST=0.0.0.0 和 OUTLOOK_MCP_HTTP_ALLOWED_HOSTS=mcp.example.com,其中主机名应为代理转发到的公网主机名。每次绑定公网地址时,服务器都会在启动前输出纯 HTTP 警告。若使用通配符地址(0.0.0.0 或 ::)绑定,却未设置允许的主机名,服务器也会警告:普通客户端 Host 标头将收到 421,因为通配符地址本身并不是客户端使用的主机名或地址。令牌可防范其他操作系统用户和浏览器页面;以你的操作系统用户身份运行的代码则可以读取客户端配置或自行启动服务器。服务器不会信任转发的标头。 机密文件可以替代环境令牌:将 OUTLOOK_MCP_HTTP_TOKEN_FILE 设置为一个不超过 4096 字节、仅包含令牌的普通文件(末尾可以有换行符),并取消设置 OUTLOOK_MCP_HTTP_TOKEN。两者同时设置时会被拒绝。在 POSIX 系统上,该文件必须归服务器用户所有,且组用户和其他用户均无权限(chmod 600);不允许使用符号链接。在 Windows 上,请自行将文件 ACL 限制为仅服务器账户可访问;服务器不会验证 Windows ACL。令牌文件错误中绝不会包含文件内容或路径。

容器机密挂载也必须满足相同的文件保护要求。

  • **Kubernetes:**投射的 Secret 键是符号链接,因此通常的卷路径会被拒绝。使用 subPath 挂载文件可避免该符号链接,但文件仍必须归服务器 UID 所有,且权限为 0400 或 0600;仅使用 subPath 并不能解决所有权问题。对于非 root 服务器,init 容器可以将投射的键以服务器 UID 复制到可写的 emptyDir 中,并设置权限为 0400,然后由应用以只读方式挂载该准备好的目录。轮换后请重新创建 Pod,以刷新副本或 subPath 挂载;subPath 挂载不会接收 Secret 更新。
  • Docker:Swarm secrets 默认创建归 root 所有且对所有用户可读的文件,因此会被拒绝。请将 Secret 的 uid 设置为服务器 UID,将 gid 设置为其组,并将 mode 设置为 0400。对于由本地文件提供的 Compose secrets,uid、gid 和 mode 会被忽略:请准备一个普通主机文件,使其容器 UID 匹配,并将权限设为 0400,然后以只读方式挂载。将 OUTLOOK_MCP_HTTP_TOKEN_FILE 设置为容器内生成的文件路径。替换令牌后请重启服务器;服务器只会在启动时读取该文件。

**这会改变可访问邮箱的对象。**使用 stdio 时,只有启动服务器的进程可以访问。使用 HTTP 时,任何持有令牌的对象只需向端口发送一个请求即可访问,因此令牌就是全部访问控制:

  • 每次绑定都必须使用令牌,包括回环绑定。 若未从 OUTLOOK_MCP_HTTP_TOKEN 或 OUTLOOK_MCP_HTTP_TOKEN_FILE 获取令牌,服务将拒绝启动。在回环地址上,如果端口没有令牌,其他操作系统用户或浏览器页面只需发送一个 HTTP 请求,就能读取邮箱。每个请求都必须携带 Authorization: Bearer <token>,否则将收到 401。令牌必须是至少 32 个字符的单个值,字符限于 A–Z a–z 0–9 -._~+/,且至少包含 8 个不同字符(末尾允许使用 = 填充)。这只能拒绝明显缺乏多样性的值,并不能防住所有可预测的令牌;请使用上方的生成器。要更换令牌,请使用新令牌重启服务。
  • 普通 HTTP 会明文发送令牌。 服务不会终止 TLS。在其他机器可访问的任何绑定地址上,令牌和工具返回的所有内容都会以可读形式通过网络传输,除非服务前方的反向代理终止了 TLS。请将服务置于反向代理之后;如果有多个客户端会连接,还应让代理对调用方进行身份验证。
  • 每次绑定都会执行 Host 和 Origin 检查。 回环绑定仅接受回环主机和来源。OUTLOOK_MCP_HTTP_ALLOWED_HOSTS 可选用于添加以逗号分隔的主机名或 IP,可带可选端口(例如 mcp.example.com 或 mcp.example.com:8443)。在公共地址上绑定时,此设置用于选择允许的主机;未设置时,仅允许字面意义上的绑定地址。不带端口的名称和 :* 条目允许任意端口,包括默认 HTTP/HTTPS 端口上的不带端口的 Host。无效的 Host 将被拒绝并返回 421;如果请求提供了 Origin,则必须通过 HTTP 或 HTTPS 与某个允许的主机匹配,否则将返回 403。不带 Origin 的客户端可以正常使用。同主机代理可以发送 Host: 127.0.0.1:<port>。
  • 文件路径位于服务端。 附加文件以及发送带附件的邮件时使用的路径,都会解析到服务端的 attachments_dir 内;远程客户端无法传入自己的本地路径。下载的文件和 saved_to 都保留在服务端,路径拒绝信息中也可能包含服务端附件目录的绝对路径。改用内联 attachments 和 as_content=True,即可在调用中直接传递字节(参见附件)。
  • 服务是无状态的。 服务不会发放 Mcp-Session-Id,而是以 JSON(而非事件流)响应每个请求。没有工具会在调用过程中向客户端发送内容,因此不会丢失任何内容。
  • 单个进程仍只服务于一个账户。 与 stdio 一样,请配合 OUTLOOK_MCP_CONFIG_DIR 使用(每个邮箱使用一个进程、一个端口和一个设置目录),并在运行服务的环境中执行 outlook-mcp auth。容器通常没有密钥环;请参见令牌缓存未加密存储(Linux)。
  • 不会记录令牌、请求 URL 或请求行。
read_only 的作用与局限

read_only: true 会阻止 outlook-mcp 的写入工具运行。让它发送邮件,它会拒绝。

这不会让你的 Microsoft 凭据变成只读。 即使配置中设置了 read_only: true,首次登录时仍会同意完整的读写权限集——首次同意时未包含的权限,以后无法添加,除非重新登录(之后每次刷新都会使用 .default——即“此帐户已同意的所有权限”——因此,如果某个会话只获准使用读取权限,那么无论配置如何设置,所有写入操作都会失败并返回 403)。无论 read_only 开启还是关闭,已存储的令牌都可以发送邮件;而在你开启 read_only 之前已同意的会话仍保留其写入权限。

请注意以下两个后果:

  • read_only 只是文本文件中的一行设置。任何能够编辑 ~/.outlook-mcp/config.json 的对象都可以关闭它,并立即获得写入权限——无需重新验证身份,也无需新的同意提示。
  • 强制执行该设置的是此服务的 Python 代码。任何持有缓存令牌的其他进程都不受影响。

因此,应将 read_only 视为防止 Agent 轻率操作的防护栏,而不是安全边界。如果你需要真正无法写入的凭据,应让 Microsoft 来强制执行,而不是由我们来做:

  1. 注册一个第二个 Azure 应用,并仅授予它读取权限:Mail.Read、Calendars.Read、Contacts.Read、Tasks.Read、MailboxSettings.Read、User.Read。此应用必须是该帐户从未授予过写入权限的应用。Microsoft 会按应用记住同意情况,刷新时会返回该应用曾获授的所有权限。

  2. 将 client_id 指向该应用,并设置以下两个键:

    { "client_id": "<the read-only app>", "read_only": true, "read_only_consent": true }
    
  3. 运行 outlook-mcp auth。设置 read_only_consent 后,同意屏幕只会列出读取权限。如果不设置,登录时此应用也会请求读写权限集。

如果没有设置 read_only: true,系统会拒绝 read_only_consent:仅请求读取权限的登录无法写入,因此需要执行写入操作的服务会在每次操作时失败。登录会话与创建它时使用的应用绑定。更改 client_id 后,服务将不再使用旧应用——在你再次运行 outlook-mcp auth 之前,outlook-mcp status 和 outlook_auth_status 都会对此进行提示。

细粒度写入权限(可选)

默认情况下,read_only: false 会解锁所有写入工具。如需更精细地控制权限,可设置 allow_categories,将写入权限限制为特定类别。读取工具(list、search、get)始终允许使用——allow_categories 仅缩小写入范围。

可用类别:

类别工具风险
mail_drafts创建/更新/删除草稿,向草稿添加附件/从草稿移除附件安全——仅处理草稿,不会发送
mail_triage移动、删除(软删除)、标记、分类、标记为已读、复制、批量处理、重新分类,以及设置/删除重点收件箱覆盖项中等——可撤销,硬删除除外
mail_folders创建/重命名/删除文件夹中等
mail_send发送、回复、转发、发送草稿、发送带附件的邮件危险——会代表你发送邮件
calendar_write创建/更新/删除事件、回复邀请、添加/移除事件文件中等——操作的是你自己的日历,但 outlook_attach_to_event 会从 attachments_dir 读取本地文件,并将其字节内容推送到 Graph。邮件中包含 Agent 撰写内容且会发送给他人的操作也需要 mail_send:邀请参与者、更改已有参与者的事件中的内容(主题、正文、地点)、为此类事件添加附件(参与者会在收到下一次更新时获取附件),以及在回复邀请时添加消息。单纯回复邀请、更改时间和取消事件仍会通知相关人员,但通知中不包含 Agent 撰写的内容
contacts_write创建/更新/删除联系人中等
todo_write创建/更新/完成/删除任务和清单项;上传/删除任务附件中等——操作的是你自己的任务列表,但 outlook_upload_task_attachment 会从 attachments_dir 读取本地文件,并将其字节内容推送到 Graph;删除任务、清单项和附件无法撤销。列出和下载附件属于纯读取操作,和其他读取操作一样不受权限限制,并且限制在 attachments_dir 内

策略示例:

仅限草稿(Agent 可以撰写草稿,由你审核并发送):

{ "read_only": false, "allow_categories": ["mail_drafts", "mail_triage", "todo_write"] }

(请注意,todo_write 包含任务附件的写入类工具——从 attachments_dir 读取文件、上传到 Graph,以及无法撤销的删除。列出和下载任务附件属于读取操作,不受写入权限限制,与邮件附件读取操作一样——见上表。)

仅限日历(Agent 可以管理你的日程,不能执行其他操作):

{ "read_only": false, "allow_categories": ["calendar_write"] }

(它无法邀请任何人。邀请属于邮件,因此邀请参与者也需要 mail_send——如果希望 Agent 为你与他人安排会议,而不只是占用你自己的时间,请添加此项。)

完整写入权限(Agent 可以执行所有操作):

{ "read_only": false }

只读(最安全的默认设置,不允许写入):

{ "read_only": true }

设置 allow_categories 后,任何属于未允许类别的工具都会返回权限拒绝错误(PermissionDeniedError),并指出被阻止的类别。allow_categories 为空(或未设置)且 read_only 为 false 时,所有写入工具均获准使用。read_only: true 始终优先——如果设置了该项,无论 allow_categories 如何配置,所有写入操作都会被阻止。未知类别名称会在加载配置时被拒绝,并触发验证错误;仅接受上述七个名称。


隐私与安全

  • 零遥测。 不进行分析、不追踪、不收集使用数据。
  • 零本地缓存。 每次调用都直接发送到 Microsoft Graph。不在本地存储邮件或日历数据。(有一项例外:每个进程会解析一次 To Do 默认列表 ID,并在会话期间保留——这是一个 ID,而非内容;请参阅 outlook_list_tasks。)
  • 零第三方调用。 服务只与 graph.microsoft.com 和 login.microsoftonline.com 通信。
  • 令牌存储。 OAuth 令牌通过 azure-identity 的 TokenCachePersistenceOptions 持久化。在 macOS 上使用系统钥匙串;在 Windows 上使用 DPAPI;在具备 PyGObject/libsecret 的 Linux 上使用 gnome-keyring。在没有 libsecret 的 Linux 上(例如通过 uv tool install 创建的隔离 venv),除非 allow_unencrypted_token_cache 为 true,否则服务会拒绝持久化令牌;启用后,令牌会改存为 ~/.IdentityService/ 下权限为 0600 的明文文件,MCP 会在启动时发出一次性警告。若要在 Linux 上使用加密存储,请安装 python3-gi gnome-keyring libsecret-1-0,并通过 --system-site-packages 重新创建 venv。
  • 不记录敏感数据。 不会记录邮件正文、收件人地址或令牌。
  • 配置权限。 在 macOS 和 Linux 上,配置目录会以 0700 权限创建,配置文件会以 0600 权限创建;加载时会修复权限过于宽松的文件。在 Windows 上无法强制执行这些 POSIX 权限——os.chmod 在那里只会设置只读属性,因此访问权限由路径的 Windows ACL 控制,包括从创建该路径的目录继承的任何权限;本服务既不会设置,也不会验证这些权限。所有平台都会拒绝符号链接配置文件。
  • 输入验证。 所有用户输入(电子邮件地址、Graph ID、OData 筛选器、KQL 查询、日期时间)在发送到 Graph API 前都会经过验证和清理。
  • HTTP 传输(选择启用)。 它会改变可访问邮箱的人员范围:每次绑定都需要提供 bearer token,并且每个请求都会检查该令牌;服务使用纯 HTTP,因此 TLS 应由前置代理负责。完整的安全说明请参阅远程 / HTTP 传输。

开发

# Install dev dependencies and the documents extra, as CI does (without it the PDF/XLSX tests skip)
uv sync --all-extras

# Run tests
uv run pytest

# Lint
uv run ruff check src/ tests/ scripts/

# Format (CI fails if `ruff format --check` would change a file)
uv run ruff format src/ tests/ scripts/

# Run server locally (stdio)
uv run outlook-mcp

要求: Python 3.10+


路线图

  • 高级邮件 -- 原始 MIME 导出、Internet 邮件标头
  • 日历 -- 取消事件(并通知与会者)
  • 仅限工作或学校账户的工具 -- 空闲/忙碌状态、会议时间、自动回复、共享邮箱:目前暂无计划(#133)。如果日后添加其中任何功能,它们将作为选择启用的功能组提供,个人账户永远不会加载

已确定的方向,以及经过调查并排除的内容(收件箱规则、邮箱设置),请参阅 ROADMAP.md。


许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。