关于 office-outlook-mcp
office-outlook-mcp 向 MCP 客户端提供 Outlook 和 Microsoft 365 的邮件、日历、联系人及任务操作。它支持需确认的更改、会议安排和批量文件导出,并从已登录的浏览器会话获取令牌。
主要功能
- 01读取和管理邮件及文件夹
- 02处理邀请和日历事件
- 03查找会议时间与日程
- 04访问联系人和任务
- 05将邮件和事件导出为文件
- 06发送前确认更改
适用场景
- 01整理未读邮件和会议邀请
- 02准备回复供发送前审核
- 03为有空的参会者安排会议
- 04导出邮箱或日历记录
MCP 相关
将 Outlook 和 Microsoft 365 的邮件、日历、联系人及任务操作作为 MCP 工具提供。影响他人的变更需要确认;草稿和部分仅影响本地的操作除外。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @chrischall/office-outlook-mcpOUTLOOK_ACCESS_TOKEN密钥Pre-obtained Outlook bearer token. Overrides the browser bridge. Power users / CI only; tokens last about 25 hours.OUTLOOK_DISABLE_FETCHPROXYSet to '1' to disable browser capture, requiring OUTLOOK_ACCESS_TOKEN.OUTLOOK_API_BASEOverride the Outlook REST base URL. Defaults to https://outlook.office.com/api/v2.0.OUTLOOK_WS_PORTfetchproxy concentrator port used for token capture. Defaults to 37149, the fleet-wide shared port.OUTLOOK_CAPTURE_TIMEOUTSeconds to wait for the Outlook tab to make a request we can read a token from. Defaults to 30.OUTLOOK_TOKEN_CACHE密钥Set to 'false' to stop caching the captured token between runs. Defaults to true.OUTLOOK_TOKEN_FILE密钥Path to the cached token file. Defaults to ~/.office-outlook-mcp/token.json.OUTLOOK_OUTPUT_DIRAbsolute directory where outlook_export_messages and outlook_export_events write their files. Defaults to ~/Downloads/office-outlook-mcp. When set, a per-call dest must be inside it.FETCHPROXY_WS_HOSTBind interface for the fetchproxy concentrator, a literal IP only (default 127.0.0.1). Keep on loopback; it exists for hosted deployments that run each MCP in its own network namespace.FETCHPROXY_IDENTITY_DIRAbsolute path where the fetchproxy long-term identity keypair is stored (default ~/.fetchproxy/identity/).MCP_CONFIRM_MODEWhat outlook_send_message, outlook_reply, outlook_respond_to_invite and the other write tools do on a client that cannot show a confirmation prompt (claude.ai, Claude Desktop): "ask-user" (default: the first call returns a preview and a confirmToken, and the model must get your approval in chat before using it), "auto" (the model may use the token after reviewing the preview itself) or "refuse". An unrecognised value is treated as refuse.MCP_CONFIRM_ELICITATION"off" never shows a confirmation prompt, so every client gets the MCP_CONFIRM_MODE flow. Set it for a client that says it can show prompts but never does. Defaults to on.MCP_CONFIRM_TTL_SECONDSHow long a confirmToken stays valid, in seconds. Defaults to 600.MCP_CONFIRM_SECRET密钥Signing key for confirmTokens. Random per process by default; set it only if tokens must survive a server restart.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
28收录的工具列表 · 更新于 1 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| view | enum | 否 | 响应格式:"compact"(默认)会省略响应中其他位置已包含的字段;"full" 会返回此服务端支持的所有字段;"raw" 会返回未经投影的上游载荷。compact | full | raw |
| limit | integer | 否 | 文件夹数量上限(默认 50) |
| parent | string | 否 | 此文件夹的子文件夹(ID 或已知名称)。省略则列出顶层文件夹。 |
| nextLink | string | 否 | 继续之前的列表:原样传入其 `nextLink` 值以获取下一页。设置此项后,分页/筛选参数将从链接中获取,此处的参数会被忽略。 |
详细介绍
office-outlook-mcp
适用于 Outlook / Microsoft 365 的 MCP 服务,可处理邮件、文件夹、日历、联系人和任务,并且发送前需要确认。
本项目由 AI(Claude Code)开发并维护。请自行斟酌使用。
身份验证方式
Outlook Web 会将访问令牌保存在内存中,并通过 Authorization: Bearer … 发送。此服务通过 fetchproxy 桥接,从已登录的浏览器标签页捕获该请求头,然后通过普通的服务端请求访问 https://outlook.office.com/api/v2.0。
浏览器只在获取令牌时需要使用(有效期约 25 小时),调用时不需要。 这就是整个设计:不需要注册 Azure 应用,不需要管理员同意,请求流程中也不需要浏览器。
令牌缓存在 ~/.office-outlook-mcp/token.json(0600)中,因此重启后无需重新捕获。
安装
npm i -g @chrischall/office-outlook-mcp
需要安装 ContextMint Bridge 浏览器扩展,可从其发布页面获取:在 Chrome 中,解压 Chrome 构建版并以未打包的形式加载(chrome://extensions → 开发者模式 → 加载已解压的扩展程序)。Safari 暂不可用——它将随 ContextMint 应用一起发布,但该应用目前没有公开下载渠道——因此暂时请使用 Chrome。
ContextMint Bridge 是 fetchproxy 浏览器扩展的新名称,由同一位维护者开发——fetchproxy 自己的 README(#extension)中提供了指向它的链接。其源代码公开在 nullnet-app/contextmint-bridge:你可以自行构建,也可以使用 .sha256 文件校验发布的 zip 包(该文件与 zip 包一同发布):shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256。
此扩展、fpx 和本服务通过 fetchproxy 协议编号(当前为协议 4)保持兼容,而不是通过匹配软件包版本。请保持 Bridge 和 fpx 为最新版本——如果不匹配,会报错并指出两个协议编号。还需安装 @fetchproxy/cli:
npm i -g @fetchproxy/cli
首次捕获时,会显示一个 6 位配对码,需要在 ContextMint Bridge 弹出窗口中批准;授权会持续有效。
在 opencode 中安装
opencode 从 opencode.json(项目级)或 ~/.config/opencode/opencode.json(全局)读取 MCP 服务配置:
{
"mcp": {
"servers": {
"outlook": {
"type": "local",
"command": ["npx", "-y", "@chrischall/office-outlook-mcp"]
}
}
}
}
同一份文件适用于 opencode 2 和当前版本的 opencode 1——已在 2.0.11、1.18.31 和 1.18.28 上进行实际验证,这些版本都能通过该文件连接。
有两点值得注意,均经过实际验证,而非凭空推测:
- 不要在同一个文件中同时保留两种配置格式。 较早版本的 opencode 1 要求将服务直接放在
mcp下("mcp": { "outlook": { … } }),你可能会想同时写入两种格式,让任一版本都能找到配置。不要这样做:如果servers旁边还有其他同级键,opencode 2 会解析该文件——在opencode debug config中仍能看到它——但随后会报告 “No MCP servers configured”。没有错误,没有警告,所有服务都会静默消失。 - 如果某个旧到无法接受
servers的 opencode 1 版本,会明确报错(Configuration is invalid at …)。因此,如果看到该错误,请在该设备上切换为扁平格式,而不要将两种格式合并。
opencode 2 会与后台服务通信,因此编辑配置后,请先运行 opencode reload,再运行 opencode mcp list。
配置
所有配置均为可选项——如果不设置任何配置,服务会从浏览器捕获数据。
| 变量 | 用途 |
|---|---|
OUTLOOK_ACCESS_TOKEN | 预先获取的 bearer 令牌。优先于桥接。仅供高级用户和 CI 使用;约 25h 后过期,无法自动刷新。 |
OUTLOOK_DISABLE_FETCHPROXY | 设置为 1 可停用浏览器捕获,此时必须设置 OUTLOOK_ACCESS_TOKEN。 |
OUTLOOK_API_BASE | 覆盖 REST 基础 URL。默认为 https://outlook.office.com/api/v2.0。 |
OUTLOOK_WS_PORT | fetchproxy 集中器端口。默认为 37149,这是整个服务群共用的端口。 |
OUTLOOK_CAPTURE_TIMEOUT | 等待标签页发出可读取请求的秒数。限制整个捕获过程的时长,包括声明的两个主机。默认为 30。 |
OUTLOOK_TOKEN_CACHE | 设置为 false 可停止在不同运行之间缓存令牌。 |
OUTLOOK_TOKEN_FILE | 缓存令牌的路径。默认为 ~/.office-outlook-mcp/token.json。 |
OUTLOOK_OUTPUT_DIR | outlook_export_messages 和 outlook_export_events 写入文件的绝对目录。默认为 ~/Downloads/office-outlook-mcp。设置后,每次调用的 dest 必须位于该目录内。请参阅批量导出。 |
工具
读取 — outlook_list_folders、outlook_list_messages、
outlook_get_message、outlook_list_unread_messages、outlook_list_attachments、
outlook_get_attachment、outlook_list_events、outlook_get_event、
outlook_list_calendars、outlook_find_meeting_times、
outlook_get_schedule、outlook_get_profile、
outlook_get_mailbox_settings、outlook_list_contacts、outlook_list_people、
outlook_list_categories、outlook_list_tasks
写入(会先要求你确认——请参阅确认)—
outlook_send_message、outlook_create_draft、outlook_mark_read、
outlook_update_message、outlook_move_message、outlook_create_event、
outlook_update_event、outlook_respond_to_invite、outlook_delete_event、
outlook_reply。
有些操作不会要求确认,因为不会影响其他人:
outlook_create_draft(草稿会留在“草稿”文件夹中,直到你从
Outlook 发送),outlook_reply 设置 draftOnly: true 时(回复会留在“草稿”文件夹中),
outlook_respond_to_invite 设置 sendResponse: false 时,以及
outlook_delete_event 用于删除你自己的、没有参会者的日程,或组织者已取消的会议时
(这些操作只会更改你的日历)。
会议 — outlook_find_meeting_times 会向 Outlook 的 Scheduling
Assistant 查询所有人都有空的时段;outlook_get_schedule 会显示每个人的忙碌时段。
每个建议时段都附带 createEventArgs,可原样传给 outlook_create_event。
outlook_create_event 默认会添加 Microsoft Teams 会议,并返回加入链接;传入
teamsMeeting: false 可不添加。除非明确要求,否则
outlook_update_event 不会更改他人加入会议的方式:传入 teamsMeeting: true 可为
尚未关联 Teams 会议的日程添加 Teams 会议,确认信息也会用明白的文字说明这一点。
只有组织者
可以更新会议。outlook_respond_to_invite 可按邮件 ID 或日程 ID 接受、暂时接受
或拒绝邀请。
outlook_delete_event 会删除你组织的日程——可按单次实例的 ID 删除某次日程,
也可按系列主日程的 ID 删除整个系列——并向所有参会者发送取消通知;如果是你收到的邀请,则会拒绝删除并提示你改为拒绝邀请。
outlook_list_events 和 outlook_get_event 在所有视图中都会显示作出该决定所需的信息:
MyResponse、ResponseRequested、IsOrganizer、IsCancelled、Type(SingleInstance、Occurrence、Exception 或
SeriesMaster)、ShowAs 和 IsAllDay,完整视图还会显示 SeriesMasterId。
导出 — outlook_export_messages(邮件)和 outlook_export_events
(日历)会写入 JSONL 或 Markdown 文件,也可选择包含附件,并且只会返回文件位置;请参阅批量导出。
诊断 — outlook_healthcheck
每个读取工具都接受 view: compact | full | raw,默认为 compact。
除上述情况外,修改工具在你确认之前不会写入任何内容
——请参阅确认。预览会准确显示将要发送的内容
(操作、方法、路径和正文)。(outlook_create_event 会先读取
邮箱时区,因此其预览可以显示预订时使用的时区;这是预览所进行的唯一一次读取。)
邮件和事件文本由其他人撰写,因此 outlook_list_messages、
outlook_get_message、outlook_list_unread_messages、outlook_get_attachment、
outlook_list_events、outlook_get_event、outlook_find_meeting_times、
outlook_get_schedule、outlook_export_messages 和 outlook_export_events
会将每个结果(所有视图)都包装在不可信内容信封中——包含 untrusted_content: true,
以及一条告知模型应将文本视为数据、绝不可视为指令的 note。(如果
view: raw 记录自带 untrusted_content/note 键,则会嵌套在 data 下,
因此无法覆盖信封。)outlook_reply 会将已发送回复的主题——即原始发件人的文本——
放在同一信封中返回。
如果客户端无法显示确认提示,confirmToken 仍由模型自行传回,因此请保留
MCP_CONFIRM_MODE=ask-user(默认值),并在聊天中批准每个预览;或者使用会在运行
非只读工具前征求你同意的客户端,作为阻止意外外发的真正保障。
处理流程
Agent 无需打开 Outlook,即可从头到尾处理新邮件:
- 读取邮件批次 —
outlook_list_unread_messages会在一次调用中返回某个文件夹 (默认为收件箱)里的未读邮件,按时间从新到旧排列,并附带每封邮件的纯文本正文。 它不会将任何邮件标记为已读。每个项目都有一个kind:mail、meetingRequest、meetingCancelled或meetingResponse;请求和取消通知还会附带关联的event(时间、组织者、你当前的回复状态)——如果该会议已不在你的日历中 (已拒绝、已取消或已删除),则会附带一个hint,说明无需回复。to和cc最多列出 20 个地址;超过时会提供toCount/ccCount。 - 处理每个项目 —
- 邀请:使用邮件 ID 和
accept、tentative或decline调用outlook_respond_to_invite(可选附带评论)。回复后,Outlook 会使用新的 ID 将邀请邮件移至“已删除邮件”,因此已回复的邀请已经归档——跳过第 3 和第 4 步 (旧 ID 会返回 404); - 需要回复的邮件:使用
outlook_reply(reply、replyAll或forward), 或设置draftOnly: true,将其保存在“草稿”中供你审核; - 会议请求:对参会者调用
outlook_find_meeting_times,然后将所选时段的createEventArgs传给outlook_create_event; - 需要读取的附件:调用
outlook_get_attachment。
- 邀请:使用邮件 ID 和
- 归档 —
outlook_update_message可在一次调用中为最多 50 封邮件设置标记、 分类(分类名称来自outlook_list_categories)并标记为已读;outlook_move_message可将一封邮件移至其他文件夹。 - 标记为已处理 — 对已处理的普通邮件调用
outlook_mark_read(或在outlook_update_message中设置isRead: true),这样下一次调用outlook_list_unread_messages时,只会返回仍未处理的新邮件。已回复的邀请 已移出收件箱(见第 2 步)。
回复、转发、邀请回复和新建会议都会发送给其他人,因此每项操作都会先要求你确认——
但使用 draftOnly: true 保存的回复除外(它会留在“草稿”中,直到你发送),
以及设置 sendResponse: false 的邀请回复除外(这只会更改你的日历,不会通知组织者)。
按时间分页
outlook_list_unread_messages 和 outlook_list_messages 也会按从最早到最新的顺序,从某个时间点开始分页:将 from 设为 ISO 8601 UTC 时间
(2026-10-01T00:00:00Z)。结果中包含 next_from——下一页请求时,将其原样作为 from 传回——以及 has_more。若要回填数据,请从较早的时间开始,并持续传入 next_from,直到 has_more 为 false;随后使用最后一个 next_from 持续轮询,以获取新邮件(空页会返回相同的位置)。时间戳相同的邮件不会在分页时被跳过或重复,在分页期间将邮件标记为已读也不会导致数据丢失。from 不能与 nextLink、sinceHours、search 或 skip 组合使用。
批量导出
outlook_export_messages 会批量导出邮件,outlook_export_events 会批量导出日历,每次可导出数千条记录,且其中的文本不会进入对话。服务会对邮箱(或日历)进行分页,并将记录写入文件。工具只返回一个简短的清单:文件位置、文件大小、记录数和附件数、日期范围,以及 has_more 和 cursor。让 Agent 使用 shell 工具(jq、grep、rg、head)读取文件,而不是一次性打开整个文件。
- 邮件参数:
folder(常用名称,如inbox或sentitems,或文件夹 id;all表示导出整个邮箱;默认为inbox)、since和until(ISO 8601)、search(全文搜索,范围覆盖整个邮箱)。邮件按从最早到最新的顺序导出。 - 事件参数:
since和until(ISO 8601,均为必填,间隔最长为两年)以及calendar(日历 id;默认使用默认日历)。事件来自日历视图,因此重复系列会展开为单个事件。时间采用邮箱时区中的本地时间,每条记录都会通过time_zone标明时区。 - 两者通用:
format(jsonl,默认值,或markdown)、attachments(默认值为false)、dest、cursor、max_items(默认值为 5000,最大值为 50000)以及budget_seconds(默认值为 90,最大值为 600)。 - 文件:
part-0001.jsonl每条消息包含一条 JSON 记录(包括 id、conversation id、主题、发件人、收件人/抄送/密送、日期、标记、类别、网页链接和完整的纯文本正文)。首行为_export标头,其中注明来源、账户、参数和不可信内容说明。事件记录包含 id、iCal UID、类型和系列 id、主题、开始时间、结束时间、时区、地点、组织者、附带响应的参与者、你的响应、显示状态、类别、加入链接和完整的纯文本正文。format: "markdown"则会写入part-0001.md,生成易读的文字记录(每条消息或事件各占一个章节)。manifest.json列出数量、任何错误以及文件:磁盘存储时,列出每个分段的文件(每完成一个分段就会更新);blob zip 中则列出该 zip 文件中的文件。 - 附件: 设置
attachments: true时,大小不超过 50 MB 的每个文件附件都会保存为attachments/<short id>/<name>(文件名经过清理);记录会列出附件及其相对path,或列出skipped和原因。附加的 Outlook 项目(转发的电子邮件或事件)、云文件链接(OneDrive/SharePoint)、较大的文件和下载失败的文件都会跳过。单个附件出错不会导致导出失败。 - 续传: 每次调用会在达到
max_items或budget_seconds时停止,以先到者为准。当has_more为 true 时,将cursor原样传回。下一次调用会从同一导出的part-0002、part-0003等继续。启用附件时,会在较小批次的记录之间检查预算,因此停止位置可能在某个分页结果中间;游标会从下一条记录处继续。如果 Outlook 拒绝凭据(包括下载附件期间),或者在三次 Retry-After 等待后仍持续返回 429,调用会保留已写入的内容并返回游标。重新进行身份验证,然后继续导出。
文件的存放位置取决于服务的运行方式:
| mode | when | location in the result |
|---|---|---|
disk | 任何本地(stdio)安装,默认模式 | 一个本地绝对目录,<dir>/outlook-mail-<YYYYMMDD-HHmmss>/(或 outlook-events-…);每个文件条目都包含其绝对 path |
blob | 托管在 mcp-host 上,并由其设置 MCP_BLOB_BASE_URL 和 MCP_BLOB_SIGNING_KEY | 每次调用对应一个签名下载链接(part-NNNN.zip,其中包含 manifest.json),有效期为1 小时(url_expires_at) |
在磁盘模式下,<dir> 是每次调用的 dest,否则为 OUTLOOK_OUTPUT_DIR,再否则为
~/Downloads/office-outlook-mcp。设置了 OUTLOOK_OUTPUT_DIR 时,dest 必须位于该目录内。否则,dest 必须位于
~/Downloads、~/Documents 或 ~/Desktop 内。恢复的游标所对应的目录也会再次根据相同的根目录进行检查。
确认
每次写入操作都会在发送或更改任何内容前要求确认(新建草稿、仅创建草稿的回复和静默邀请响应除外,参见
工具)。能够显示确认提示的客户端(Claude Code)会显示提示。
无法显示确认提示的客户端会在首次调用时不执行任何操作,并返回
confirmation-required 预览以及 confirmToken;只有使用该令牌再次调用时才会执行写入操作。令牌只能使用一次,且会过期,并且绑定到精确的参数——两次调用之间只要有任何参数发生变化,就会拒绝操作(DRAFT_CHANGED),并返回新的预览。
| variable | default | |
|---|---|---|
MCP_CONFIRM_MODE | ask-user | 无法显示确认提示的客户端(claude.ai、Claude Desktop)上的写入操作行为。ask-user:分两步执行——首次调用不执行任何操作,而是返回预览和令牌;模型必须先在聊天中获得你的批准,再使用该令牌再次调用。auto:同样分两步执行,但模型在自行审核预览后可以使用令牌。refuse:此类客户端上的写入操作会被拒绝。能够显示提示的客户端(Claude Code)始终会显示实际提示,除非 MCP_CONFIRM_ELICITATION=off。无法识别的值会按 refuse 处理。 |
MCP_CONFIRM_ELICITATION | on | off 表示不显示确认提示,因此所有客户端都会采用 MCP_CONFIRM_MODE 的行为。如果客户端声称能够显示提示却从不显示(写入操作会一直挂起——opencode 2.0.x),请为其设置此项。任何其他值都会按 on 处理,并在 stderr 上显示警告。 |
MCP_CONFIRM_TTL_SECONDS | 600 | 令牌的有效时长。 |
MCP_CONFIRM_SECRET | 每个进程随机生成 | 签名密钥;只有在令牌必须跨服务器重启保留时才设置。在 mcp-host 上,主机会提供一个稳定的、按子进程区分的密钥(MCP_HOST_CONFIRM_SECRET),并在 MCP_DATA_DIR 下记录已使用的令牌,因此即使空闲重启,批准也会保留。 |
值得了解的事项
- 字段采用 PascalCase(
ReceivedDateTime、IsRead)。这是 Outlook REST API,不是 Graph——Graph 代码片段会静默返回空结果。 - 默认情况下,
outlook_get_message返回纯文本正文,其体积比 HTML 小 9.4 倍;传入html: true可获取原始内容。 outlook_list_events使用日历视图,会展开循环系列。/me/events不会,因此不会原样提供该接口。- 时区名称采用 Windows 格式(
Eastern Standard Time),而非 IANA 格式。 search和unreadOnly不能组合使用;API 不允许$search与$filter同时使用,因此工具会在发出注定失败的请求前拒绝操作。- 移动邮件会为其分配一个新 ID。
- 除非
timeZone覆盖此设置,否则outlook_list_events会以邮箱自身的时区返回时间。API 本身默认使用 UTC,因此在东部时区的邮箱中读取时会悄然产生 4 小时的误差。 - 联系人电话字段是
MobilePhone1,而不是 Graph 的MobilePhone。v2.0 Contact 类型会以 400 错误拒绝 Graph 字段名。
轻量级替代方案
如果你只需要在这台机器上通过 Claude Code 访问 Outlook,本仓库中的
skills/outlook-fpx 访问技能也能通过 fpx +
curl 完成相同的读取操作,而且完全不需要服务。需要类型化工具、
需确认的写入操作,或从 claude.ai 访问时,MCP 才更有价值。
开发
npm install
npm run build
npm test # typecheck + suite
npm run test:coverage # CI's gate
请求格式已在 docs/OUTLOOK-API.md 中固定,
并且都已通过实时邮箱验证。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。