Outlook日历邮件管理服务

通过模拟浏览器会话实现无需Azure注册的Outlook日历和邮件管理服务,适用于受企业策略限制的环境。

  • by benpeter
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 benpeter/owa-mcp

使用说明

owa mcp

A. 模型上下文协议(MCP) 允许Claude Code完全访问您的Microsoft Outlook日历和电子邮件的服务器-- 无需Azure应用程序注册.

运作原理

服务器通过以下方式驱动专用的、持久的谷歌Chrome浏览器 chrome开发工具mcp,使用自己的Chrome配置文件(与您的日常驱动程序Chrome分开保存),以便登录会话在重新启动后仍然有效。它将浏览器导航到OutlookWeb(Outlook.office.com),并监视它发出的网络请求。当Outlook Web加载时,它为自己的内部API调用发布Bearer令牌;此服务器拦截这些令牌并针对 outlook.office.com/api/v2.0 REST端点。

结果:满 Calendars.ReadWrite 和 Mail.ReadWrite 范围,无需OAuth应用程序注册,无需客户端ID,也无需IT参与——只要您可以在自动化浏览器中登录Microsoft 365即可。

代币在约80分钟后过期。 服务器不会在每次刷新时重新启动浏览器,而是在收购过程中保持单个chrome devtools mcp连接(及其浏览器)的活动状态,并简单地重新导航到Outlook Web以触发新的令牌请求。Chrome窗口从浏览器首次启动的那一刻起就可见(从不无头),因此您可以在需要时登录。如果在60秒内没有找到活动会话,则请求失败,并显示一条消息,要求您登录并重试——因为连接保持活动状态,您可以根据需要(包括MFA)等待多长时间,并在完成后重试,而不会丢失浏览器会话。

为什么采用这种方法

许多企业Microsoft 365租户执行条件访问策略,阻止托管设备上的第三方OAuth流(例如Azure CLI、自定义应用程序注册)。浏览器会话拦截方法之所以有效,是因为它依赖于已经满足这些策略要求的身份验证流——与Outlook Web本身使用的身份验证流程相同。这已被证实在至少一个条件访问强制的公司环境中与Chrome SSO一起工作;它是否适用于你的组织取决于你组织的具体政策。

先决条件

  • macOS(在macOS 15上测试)
  • 谷歌浏览器 已安装
  • chrome开发工具mcp 可通过 npx --验证 npx chrome-devtools-mcp@latest --version;服务器在首次使用时自动生成它,无需手动设置
  • 登录到Microsoft 365(第一个令牌请求会打开一个可见的Chrome窗口——如果系统提示,请在那里登录)
  • Node.js 20+

安装

claude mcp add owa -s user -- npx owa-mcp

就是这样。重新启动Claude Code——您应该看到可用的日历工具。

Manual installation (alternative)
git clone https://github.com/benpeter/owa-mcp
cd owa-mcp
npm install
npm run build
claude mcp add owa -s user -- node /absolute/path/to/owa-mcp/dist/index.js

可用工具

get_calendar_events

返回时间范围内的日历事件。

参数 类型 必填 说明
startDateTime string 是 ISO 8601开始
endDateTime string 是 ISO 8601结束
maxResults number no 最大事件数(默认50,最大100)
timezone string no IANA时区(默认UTC)

create_calendar_event

创建新事件。添加与会者会自动发送邀请。

参数 类型 必填 说明
subject string 是 事件标题
startDateTime string yes 不带偏移量的本地日期时间
endDateTime string yes 不带偏移量的本地日期时间
timezone string no Windows时区名称(默认“西欧标准时间”)
body string 否 事件描述
location string 否 位置名称
attendees 数组 否 [{ email, name?, type? }] --发送邀请
isAllDay boolean 否 全天事件
showAs string no 空闲、暂时、忙碌、Oof、在别处工作
isOnlineMeeting boolean 否 创建为团队会议
hideAttendees boolean 否 对其他与会者隐藏与会者列表(默认为false)
responseRequested boolean 否 向与会者请求RSVP(默认为true)
reminderMinutes number no 开始前几分钟提醒。Outlook默认省略,0禁用
recurrence object 否 将此设置为重复事件。看 复发 在......下面

update_calendar_event

更新现有事件的字段。仅包括要更改的字段。

参数 类型 必填 说明
eventId string yes 事件ID
subject string 否 新标题
startDateTime string 否 新开始时间
endDateTime string no 新结束时间
timezone string no 开始/结束时区
body string no 新建正文(注意:覆盖团队加入链接)
location string 否 新位置
showAs string no 新显示为状态
isPrivate boolean 否 标记为私有
hideAttendees boolean 否 对其他与会者隐藏与会者列表
responseRequested boolean 否 向与会者请求RSVP
reminderMinutes number no 开始前几分钟提醒。0禁用
recurrence object 否 更改重复模式。仅适用于系列主事件。看 复发 在......下面

cancel_calendar_event

取消您组织的会议。向与会者发送取消通知并说明原因。支持重复的系列操作。

参数 类型 必填 说明
eventId string yes 事件ID
reason string 否 已向与会者发送取消原因
scope string 否 single (默认), thisAndFollowing,或 allInSeries

delete_calendar_event

从日历中静默删除事件(不发送通知)。支持重复的系列操作。

参数 类型 必填 说明
eventId string yes 事件ID
scope string 否 single (默认), thisAndFollowing,或 allInSeries

respond_to_calendar_event

回复会议:接受、暂时接受或拒绝。尽可能使用OWA的内部服务.svc API,即使组织者禁用了响应请求,也能正常工作(ResponseRequested: false).如果内部API无法解决事件,则返回到标准REST API。

参数 类型 必填 说明
eventId string yes 事件ID
response string 是 accept, tentative,或 decline
comment string 否 给组织者的消息
sendResponse boolean 否 通知组织者(默认为true)
proposedStartDateTime string 否 建议替代开始(暂定/仅拒绝)
proposedEndDateTime string no 提出替代结尾

follow_calendar_event

无需RSVP即可在日历上跟踪事件。显示为免费,组织者未收到通知。

参数 类型 必填 说明
eventId string yes 事件ID
comment string no 发送给组织者的以下通知中包含可选消息
timezone string no 返回事件的时区

get_series_master

检查重复系列的主事件。返回重复模式、已取消的事件和完整的事件详细信息。接受系列中的任何事件ID。

参数 类型 必填 说明
eventId string yes 序列中的任何事件ID(自动解析)
timezone string no IANA时区(默认UTC)

list_series_instances

列出日期范围内重复序列的所有事件。接受系列中的任何事件ID。

参数 类型 必填 说明
eventId string yes 序列中的任何事件ID(自动解析)
startDateTime string 是 ISO 8601开始
endDateTime string 是 ISO 8601结束
timezone string no IANA时区(默认UTC)

list_mail_folders

列出邮箱中的所有邮件文件夹或特定文件夹的子文件夹。

参数 类型 必填 说明
parentFolderId string no 列出此文件夹的子文件夹。如果省略,则列出顶级文件夹

get_emails

使用可选筛选从特定邮箱文件夹获取电子邮件。

参数 类型 必填 说明
folderId string no 文件夹ID或已知名称(收件箱、草稿、SentItems、DeletedItems)。默认值:收件箱
filter string 否 all, unread, flagged, today, this_week
limit number no 最大结果数(默认20,最大500)
pageToken string no 来自先前响应的分页标记

search_emails

使用全文查询或结构化过滤器(互斥)搜索电子邮件。

参数 类型 必填 说明
query string no 全文搜索查询。无法与结构化筛选器组合
from string 否 按发件人电子邮件筛选
subject string no 按主题筛选(包含)
receivedAfter string no ISO 8601日期时间
receivedBefore string no ISO 8601日期时间
folderId string 否 搜索文件夹的范围
limit number no 最大结果数(默认20,最大500)

get_email

阅读一封包含全文内容和附件元数据的电子邮件。

参数 类型 必填 说明
messageId string yes 消息ID
format string 否 text (默认)或 html

get_attachment

将电子邮件附件下载到磁盘。

参数 类型 必填 说明
messageId string yes 消息ID
attachmentId string yes 来自get_email响应的附件ID

send_email

一步完成撰写和发送新电子邮件。要获得更多控制,请使用 create_draft + update_draft + send_draft.

参数 类型 必填 说明
to 数组 是 [{ email, name? }]
subject string yes 主题行
body string yes 正文内容
bodyType string 否 text (默认)或 html
cc array 无 抄送收件人 [{ email, name? }]
bcc 数组 无 密件抄送收件人
importance string no 低、正常(默认)、高
saveToSentItems boolean no 保存到已发送邮件(默认为true)

create_draft

创建保存到“草稿”文件夹的新电子邮件草稿。

参数 类型 必填 说明
to 数组 是 [{ email, name? }]
subject string yes 主题行
body string yes 正文内容
bodyType string 否 text (默认)或 html
cc array 无 抄送收件人
bcc 数组 无 密件抄送收件人
importance string no 低、正常(默认)、高

create_reply_draft

为发件人创建回复草稿。返回带有预填收件人、引用正文、“RE:”主题的草稿。

参数 类型 必填 说明
messageId string yes 消息ID

create_reply_all_draft

全部创建回复草稿。返回包含所有原始收件人、引用正文、“RE:”主题的草稿。

参数 类型 必填 说明
messageId string yes 消息ID

create_forward_draft

创建转发草稿。返回带有引用正文的草稿,主题为“FW:”,收件人为非收件人。

参数 类型 必填 说明
messageId string yes 消息ID

update_draft

发送前修改草稿。可以更改主题、正文、收件人、重要性。

参数 类型 必填 说明
messageId string yes 草稿消息ID
subject string 否 新主题
body string no 新正文内容
bodyType string 否 text 或 html
toRecipients array 否 替换所有收件人
ccRecipients array 否 替换所有抄送收件人
bccRecipients array 否 替换所有BCC收件人
importance string no 低、正常、高

send_draft

发送一条草稿消息。从草稿移动到已发送邮件。

参数 类型 必填 说明
messageId string yes 草稿消息ID

move_email

将邮件移动到其他文件夹。返回移动的邮件(具有更新的ID)。

参数 类型 必填 说明
messageId string yes 消息ID
destinationId string yes 文件夹ID或已知名称(收件箱、草稿、SentItems、已删除项、存档)

delete_email

删除邮件(移动到“已删除邮件”)。

参数 类型 必填 说明
messageId string yes 消息ID

update_email

更新电子邮件属性:标记为已读/未读,标记/取消标记。

参数 类型 必填 说明
messageId string yes 消息ID
isRead boolean no 设置为已读(true)或未读(false)
flagStatus string 否 NotFlagged, Flagged,或 Complete

示例提示:

  • “我下周有什么会议?”
  • “明天下午2点和简开一个30分钟的会议”
  • “拒绝ECCN同步,并注明我正在度假”
  • “关注分析技术电话,这样我就可以在日历上看到它”
  • “取消从下周开始的每周同步的所有后续事件”
  • “周一脱口秀的复发模式是什么?”
  • “在接下来的3个月里,每周二上午10点创建每周团队同步”
  • “显示今天未读的电子邮件”
  • “回复Sarah的电子邮件并将Bob添加到CC”
  • “将第三季度报告转发给财务团队”
  • “将时事通讯中的所有电子邮件标记为已读”

重复对象

由...使用 create_calendar_event 和 update_calendar_event 定义重复事件。

{
  "recurrence": {
    "pattern": {
      "type": "weekly",
      "interval": 1,
      "daysOfWeek": ["Monday", "Wednesday", "Friday"]
    },
    "range": {
      "type": "endDate",
      "startDate": "2026-04-07",
      "endDate": "2026-07-07"
    }
  }
}

图案类型: daily, weekly, absoluteMonthly, relativeMonthly, absoluteYearly, relativeYearly

模式字段 类型 描述
type string 必填。图案类型
interval number 必填。事件间隔(1=每一次,2=每隔一次)
daysOfWeek string[] 每周/相对模式的天数
dayOfMonth number 绝对月/绝对年的月份
month number 年度模式的月份(1-12)
index string 相对模式的周索引:第一、第二、第三、第四、最后
firstDayOfWeek string 一周的第一天(默认星期日)

范围类型: endDate, numbered, noEnd

范围字段 类型 描述
type string 必填。系列如何结束
startDate string 必填。系列开始时间(YYYY-MM-DD)
endDate string 结束日期(必填) endDate 类型)
numberOfOccurrences number 计数(必填 numbered 类型)
recurrenceTimeZone string 重复日期的时区

故障排除

令牌获取超时/未找到活动会话 自动化Chrome窗口已经打开(浏览器启动后立即可见,而不仅仅是超时),并已导航到Outlook Web。切换到它并按照自己的节奏登录(包括MFA),然后简单地重试请求——浏览器连接保持活跃,因此重复使用相同的会话,您不需要在后续调用中再次登录。

ErrorAccessDenied API日历 被拦截的令牌不包含日历范围。这是罕见的;尝试使用自动化配置文件退出任何Chrome窗口(~/Library/Application Support/owa-mcp/chrome-profile)然后重试——服务器将自动重新启动它。

许可证

Apache 2.0——请参阅 许可证.