






















我习惯用 Outlook 日历和任务记录事项,可以把日程同步到手机,手机上也装了微软 To Do。
前两天突然想能不能让 OpenClaw 来帮我操作日历记录事项,然后看了一下资料,就让 OpenCode 写了个 Python 版本,半小时不到就弄了个可用版本,确实也可以跑起来了,
Python 版本因为每一次都是要用 uv 启动一个 Python 脚本,冷启动的速度稍微慢一点。
换了 Reasonix + DeepSeek V4 Pro 重新实现个版本,用最原始的方式,没用第三方包,磕磕绊绊,修修补补,终于能跑起来了,整个过程要比用 Python 复杂了挺多,看来各个大模型还是 Python 的训练素材比较多些。
另外一方面,我个人比较喜欢 Zig 语言,成品出来发现响应速度确实有所提高,然后就是那个发布的体积真是小了很多,strip 后只有 750KB 左右。
测试通过之后,就把它发布到GitHub了
以下内容是AI辅助书写:
我是先跟DeepSeek以问答的方式商量确定了这个架构,然后再让他写。
整个项目的结构很清晰,分四层:
┌─────────────────────────────┐
│ handlers/ (MCP 接口层) │ 从 JSON-RPC 参数中提取参数,调用 Graph 层
├─────────────────────────────┤
│ graph/ (Graph API 层) │ 构造 REST 请求路径和 JSON body
├─────────────────────────────┤
│ client.zig (HTTP 传输层) │ 统一的 GET/POST/PATCH/DELETE,可 mock
├─────────────────────────────┤
│ tls.zig (HTTPS 底层) │ OpenSSL + BSD socket,TCP+TLS 全手写
│ auth/ (OAuth 认证) │ Device Code Flow + Token 持久化
│ mcp.zig (MCP 协议) │ JSON-RPC 2.0 over stdio
└─────────────────────────────┘
我查了一下,Zig 也有几个做得比较完善的 MCP 第三方包,但想着反正是让 AI 写,就没有用,选择了让 DeepSeek 自己搓。
MCP 协议本质上就是基于 stdin/stdout 的 JSON-RPC 2.0。每个消息是一行 JSON,末尾换行分隔。
核心就是事件循环:从 stdin 读一行 → 解析 JSON → 路由到对应方法 → 返回 JSON 到 stdout。
消息只分四种:
我用 Zig 的 std.json 做解析,手动构建 ObjectMap 来拼响应 JSON,没有引入第三方 JSON 库。
第一次接触微软的这个认证,用起来还是挺方便的。
这个应该是最有意思的部分。Python 版靠 azure-identity 一行代码搞定认证,但我得用 Zig 重新实现整个 OAuth Device Code Flow。
流程是这样的:
1. POST /common/oauth2/v2.0/devicecode
→ 返回 user_code, device_code, verification_uri
2. 打印到终端让用户去 https://microsoft.com/devicelogin 输验证码
3. 轮询 POSt /common/oauth2/v2.0/token
→ 每隔 5s 查一次,用户授权后拿到 access_token + refresh_token
其中最坑的是 Token 持久化。我不想每次启动都让用户重新登录,所以把 refresh_token 缓存到 ~/.config/outlook-mcp/token.json,启动时先尝试用 refresh_token 静默续期,续期失败才重新走 Device Code。
这层是直接拿 OpenSSL + BSD socket 手写的 HTTPS 请求。没有用 libcurl 之类的高层库。
为什么自己写?因为 Zig 和 cURL 的集成有点别扭,而且 MCP server 只需要很少的功能:GET、POST、form POST。我自己造个轮子更可控。
还加了 DNS 缓存和重试逻辑——弱网环境下 Graph API 偶尔会抽风,重试 3 次再加 1s 退避能让体验好很多。
| 分类 | Tool | 作用 |
|---|---|---|
| 📅 日历 | list_events | 查未来 N 天日程 |
| query_events | 查任意日期范围 | |
| search_events | 按关键词搜事件 | |
| create_event | 创建日历事件 | |
| 📧 邮件 | list_emails | 列出收件箱 |
| send_email | 发邮件 | |
| search_emails | 搜邮件 | |
| get_unread_count | 未读数 | |
| ✅ 待办 | list_task_lists | 列出任务清单 |
| list_tasks | 查看清单中的任务 | |
| create_task | 创建任务 | |
| complete_task | 标记完成 | |
| delete_task | 删除任务 |
这些 tool 都是通过 Microsoft Graph API 的 REST 接口实现的,每个 tool 对应一个或几个 Graph API 调用。
在 Claude Code 里注册这个 MCP Server 后,你可以直接说:
"看一下收件箱有没有未读邮件"
"搜索关于 '部署' 的邮件"
"给 team@xxx.com 发个邮件说今晚发版"
Agent 会调用 list_emails、search_emails、send_email 等工具完成操作。
"今天有什么会议?"
"下周一有没有空闲时间?"
"下周三下午 3 点加一个评审会议"
一句自然语言,Agent 帮你查日历、建事件。
"我的任务清单里还有哪些没完成?"
"加一个任务说「写完这篇博客」,截止这周五"
在 CI pipeline 的最后一步,可以直接调这个 MCP server 发邮件通知,不需要额外的 SMTP 配置。
# 1. 构建(需要 Zig 0.16+)
git clone https://github.com/wuchang/mcp-server-outlook
cd mcp-server-outlook
zig build -Doptimize=ReleaseSafe
# 2. 配置 Client ID
# 写入 ~/.config/outlook-mcp/config
echo 'CLIENT_ID = "你的-app-client-id"' > ~/.config/outlook-mcp/config
# 3. 运行
./zig-out/bin/mcp-server-outlook
# 首次会触发浏览器登录,之后自动复用 token
Client ID 从哪里来?去 Azure Portal → App registrations 注册一个应用。注意账户类型必须是 "Accounts in any organizational directory AND personal Microsoft accounts",然后平台选 "Mobile and desktop applications"。不需要密钥,个人账号走 Device Code Flow,免费。
然后注册到 OpenClaw:
# 方式一:环境变量(无需配置文件)
openclaw mcp set outlook \
'{"command":"/path/to/mcp-server-outlook","env":{"AZURE_CLIENT_ID":"your-client-id"}}'
# 方式二:已配好 ~/.config/outlook-mcp/config
openclaw mcp set outlook \
'{"command":"/path/to/mcp-server-outlook"}'
OAuth Device Code 的有效期默认 15 分钟。如果用户开了链接但迟迟不输入验证码,轮询会一直跑 15 分钟才报 expired_token。我在每个轮询周期检查 elapsed > expires_in 提前退出,不用等微软 API 报错。
refresh_token 保存在 ~/.config/outlook-mcp/token.json 明文。严格来说应该用系统钥匙串,但为了跨平台简单,先用文件。提供了 --logout 参数一键删除缓存文件。
代码在: https://github.com/wuchang/mcp-server-outlook
欢迎提 Issue 和 PR,一起让 AI Agent 能更好地帮我们处理日常办公事务。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。