关于 contactsmcp
contactsmcp 是用于管理 macOS Contacts.app 通讯录的本地 MCP 服务。它通过 AppleScript 访问与系统应用同步的联系人和群组,无需 API 密钥、OAuth 或云服务。
主要功能
- 01按姓名、邮箱或电话搜索联系人
- 02读取完整联系人信息
- 03创建、更新和删除联系人
- 04导出 vCard 3.0 联系人
- 05创建和管理联系人群组
适用场景
- 01按身份信息查找联系人
- 02更新或添加通讯录条目
- 03将联系人整理到群组
MCP 相关
该服务通过 stdio 在本地运行,并向 MCP 客户端提供操作 Contacts.app 联系人和群组的工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
macos-mcp
适用于 macOS 原生应用的 MCP 服务——让 Claude Code、Claude Desktop 和任何 MCP 客户端都能原生访问 Mail、Numbers、Contacts、Calendar、Reminders 以及 FaceTime/电话。
无需 API 密钥、OAuth 或云服务。通过 AppleScript 和 URL 方案(tel://、facetime://)直接与 macOS 应用通信。在你的 Mac 上本地运行。
CUPS 打印(
printmcp)曾经属于此项目;它已移至 office-mcp,因为它是 Shell 封装,而不是 AppleScript 桥接。
服务
Mail(mailappmcp)——21 个工具
适用于 Mail.app 中配置的所有电子邮件账户——iCloud、Gmail、Outlook、Fastmail 等。
| 工具 | 描述 |
|---|---|
list-mailboxes | 列出所有账户中的邮箱及未读邮件数量 |
list-accounts | 列出已配置的邮件账户及其电子邮件地址和类型 |
list-signatures | 列出可用的电子邮件签名 |
search-messages | 按主题或发件人搜索邮件(查询为空时列出全部) |
read-message | 阅读指定邮件的完整内容 |
get-message-source | 获取邮件的原始 RFC822 源内容 |
list-attachments | 列出邮件附件及其名称、MIME 类型和大小 |
save-attachment | 将电子邮件附件保存到磁盘 |
compose-message | 在 Mail.app 中创建草稿(不会发送)——支持纯文本或通过 htmlBody 设置 HTML 正文,也支持附件 |
send-message | 立即发送电子邮件(支持 from、附件,以及通过 htmlBody 设置纯文本或 HTML 正文) |
reply-to-message | 回复或回复所有人——正确关联邮件会话,并支持带品牌标识的 htmlBody 或附件 |
forward-message | 将邮件转发给新收件人 |
redirect-message | 重定向邮件(保留原始发件人) |
move-messages | 在邮箱之间移动邮件 |
delete-messages | 按 Message-ID 删除邮件 |
mark-as-read | 将邮件标记为已读 |
mark-as-junk | 将邮件标记为垃圾邮件或取消标记 |
flag-message | 标记或取消标记邮件,支持颜色 |
set-message-color | 设置邮件列表中邮件的背景颜色 |
check-for-new-mail | 为一个或所有账户触发邮件获取 |
extract-email-address | 将 "John Doe <[email protected]>" 解析为姓名和地址 |
Numbers(numbersmcp)— 29 个工具
适用于任何已打开的 Numbers 电子表格。
| 工具 | 描述 |
|---|---|
list-spreadsheets | 列出所有已打开的 Numbers 文档 |
create-document | 创建新的 Numbers 文档 |
list-sheets | 列出文档中的工作表和表格 |
get-active-sheet | 获取当前活动工作表 |
read-range | 读取指定区域的单元格值(例如,“A1:C10”) |
read-table | 将整个表格读取为结构化数据 |
write-cell | 向指定单元格写入值 |
write-range | 向指定区域写入多个值 |
clear-range | 清除单元格区域的内容和格式 |
get-formula | 获取单元格中的公式 |
set-formula | 为单元格设置公式 |
add-row | 在表格末尾添加一行 |
delete-row | 删除表格中的一行 |
add-column | 在表格中添加一列 |
delete-column | 删除表格中的一列 |
resize-row-column | 设置行高或列宽 |
add-sheet | 在文档中添加新工作表 |
delete-sheet | 删除工作表 |
rename-sheet | 重命名工作表 |
add-table | 在工作表中添加新表格 |
delete-table | 删除工作表中的表格 |
rename-table | 重命名表格 |
sort-table | 按列对表格排序 |
transpose-table | 交换表格的行和列 |
merge-cells | 合并单元格区域 |
unmerge-cells | 取消合并之前已合并的单元格 |
set-cell-format | 设置单元格格式(数字、货币、日期、百分比等) |
set-cell-style | 设置字体、颜色、背景、粗体、斜体和对齐方式 |
export-document | 导出为 PDF、Excel 或 CSV |
联系人(@aernoud/contactsmcp)— 15 个工具
使用系统通讯录,其中包含所有已同步到 Contacts.app 的帐户。
| 工具 | 描述 |
|---|---|
search-contacts | 按姓名、电子邮件或电话号码搜索联系人 |
search-by-modification-date | 查找在指定日期之后修改的联系人 |
read-contact | 获取联系人的完整详细信息 |
get-my-card | 获取用户自己的联系人名片 |
get-vcard | 将联系人导出为 vCard 3.0 文本 |
create-contact | 创建新联系人 |
update-contact | 更新联系人字段 |
delete-contact | 删除联系人 |
list-groups | 列出所有联系人群组 |
create-group | 创建新的联系人群组 |
rename-group | 重命名联系人群组 |
delete-group | 删除联系人群组 |
add-to-group | 将联系人添加到群组 |
remove-from-group | 将联系人从群组中移除 |
list-group-members | 列出群组中的所有联系人 |
日历(calendarmcp)— 25 个工具
适用于 Calendar.app 中配置的所有日历——iCloud、Google、Exchange、本地日历等。
| 工具 | 描述 |
|---|---|
list-calendars | 列出所有日历及其名称、可写标记和描述 |
get-calendar | 按名称获取单个日历的属性(包括事件数量) |
create-calendar | 创建新日历 |
update-calendar | 重命名日历或设置其描述 |
delete-calendar | Calendar.app 不支持——返回描述性错误;必须通过 Calendar.app 界面移除日历 |
switch-view | 将 Calendar.app 切换到日/周/月视图,可选择跳转到指定日期 |
reload-calendars | 强制 Calendar.app 从账户刷新 |
list-events | 列出日历中两个 ISO 日期之间的事件 |
search-events | 在指定日期范围内按摘要子字符串搜索事件(默认范围:−30 天至 +365 天)。限定到单个日历可提高速度 |
get-event | 按 uid 获取完整事件详情 |
create-event | 创建事件,可设置摘要、开始时间、结束时间,以及可选的位置/描述/url |
update-event | 按 uid 更新事件的任意字段 |
delete-event | 按 uid 删除事件 |
move-event | 将事件移至其他日历(先删除再创建;会生成新的 uid) |
duplicate-event | 将事件复制到同一日历或其他日历 |
today-events | 列出单个日历或所有日历中的今日事件 |
upcoming-events | 列出未来 N 天内的事件 |
list-attendees | 列出事件的参加者 |
add-attendee | 添加参加者,可设置邮箱和可选的显示名称 |
remove-attendee | 按邮箱移除参加者 |
list-alarms | 列出事件的显示、邮件和声音提醒 |
add-display-alarm | 添加在事件开始前 N 分钟触发的显示提醒 |
add-sound-alarm | 添加在事件开始前 N 分钟触发的声音提醒 |
add-mail-alarm | 添加在事件开始前 N 分钟触发的邮件提醒 |
remove-alarm | 根据 list-alarms 输出中的从 1 开始的索引移除提醒 |
提醒事项(@aernoud/remindersmcp)— 22 个工具
适用于 Reminders.app 中配置的所有提醒事项列表——iCloud、Exchange、本地列表等。
| 工具 | 描述 |
|---|---|
list-accounts | 列出 Reminders.app 中所有账户及其名称和 id |
list-lists | 列出所有提醒事项列表,可限定到某个账户 |
get-list | 获取单个列表的属性(id、账户、颜色、标志、未完成和已完成数量) |
create-list | 创建新列表,可选择将其放入指定账户 |
update-list | 重命名列表 |
delete-list | 删除列表(Reminders.app 可通过 AppleScript 直接执行此操作,而 Calendar.app 不支持) |
show-list | 在 Reminders.app 中将列表置于前台 |
list-reminders | 列出指定名称列表中的提醒事项(默认不包括已完成项) |
search-reminders | 按名称子字符串搜索提醒事项;限定到单个列表可提高速度 |
get-reminder | 按 id 获取完整提醒事项详情 |
today-reminders | 列出今天到期的提醒事项,可限定到单个列表或所有列表 |
upcoming-reminders | 列出未来 N 天内到期的提醒事项 |
overdue-reminders | 列出已过期且尚未完成的提醒事项 |
create-reminder | 创建提醒事项,可设置正文、到期日期或全天到期日期、提醒日期、优先级和标记状态 |
update-reminder | 按 id 更新提醒事项的任意字段 |
delete-reminder | 按 id 删除提醒事项 |
complete-reminder | 将提醒事项标记为已完成(Reminders 会自动记录完成日期) |
uncomplete-reminder | 将先前已完成的提醒事项标记为未完成 |
move-reminder | 将提醒事项移至其他列表(使用原生 move 动词——id 会保留) |
flag-reminder | 设置或清除标记状态 |
set-priority | 将优先级设为无/高/中/低(分别映射到 Reminders 的 0/1/5/9 枚举值) |
show-reminder | 将 Reminders.app 置于前台并聚焦到指定提醒事项 |
FaceTime(facetimemcp)——3 个工具
通过将 URL 方案交给 open 来发起通话。电话通话需要通过 Continuity 配对的 iPhone(这样 macOS 才能通过手机路由通话)。
| 工具 | 描述 |
|---|---|
call-phone | 通过配对的 iPhone 发起蜂窝电话通话(tel://) |
call-facetime-audio | 向电话号码或 Apple ID 邮箱发起 FaceTime 音频通话 |
call-facetime-video | 向电话号码或 Apple ID 邮箱发起 FaceTime 视频通话 |
电话号码会规范化并验证为 E.164 格式(+15551234567);空格、连字符和括号均可接受。macOS 可能会在拨号前显示确认提示——这是设计使然,无法完全静默地拨号。
要求
- macOS(使用 AppleScript——无法在 Linux/Windows 上运行)
- Node.js 18+
安装
从 npm 安装
npm install -g mailappmcp # Mail server
npm install -g numbersmcp # Numbers server
npm install -g @aernoud/contactsmcp # Contacts server
npm install -g @aernoud/calendarmcp # Calendar server
npm install -g @aernoud/remindersmcp # Reminders server
npm install -g @aernoud/facetimemcp # FaceTime / phone calls
从源代码安装
git clone https://github.com/aernouddekker/macos-mcp.git
cd macos-mcp
npm install
npm run build
配置
Claude Code
添加到 ~/.claude/settings.json 或项目的 .mcp.json:
{
"mcpServers": {
"mailappmcp": { "command": "npx", "args": ["-y", "mailappmcp"] },
"numbersmcp": { "command": "npx", "args": ["-y", "numbersmcp"] },
"contactsmcp": { "command": "npx", "args": ["-y", "@aernoud/contactsmcp"] },
"calendarmcp": { "command": "npx", "args": ["-y", "@aernoud/calendarmcp"] },
"remindersmcp": { "command": "npx", "args": ["-y", "@aernoud/remindersmcp"] },
"facetimemcp": { "command": "npx", "args": ["-y", "@aernoud/facetimemcp"] }
}
}
Claude Desktop / Cowork
添加到 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"mailappmcp": { "command": "npx", "args": ["-y", "mailappmcp"] },
"numbersmcp": { "command": "npx", "args": ["-y", "numbersmcp"] },
"contactsmcp": { "command": "npx", "args": ["-y", "@aernoud/contactsmcp"] },
"calendarmcp": { "command": "npx", "args": ["-y", "@aernoud/calendarmcp"] },
"remindersmcp": { "command": "npx", "args": ["-y", "@aernoud/remindersmcp"] },
"facetimemcp": { "command": "npx", "args": ["-y", "@aernoud/facetimemcp"] }
}
}
工作原理
每个服务都通过 stdio 在本地运行。Mail、Numbers 和 Contacts 服务会构建 AppleScript 字符串,通过 osascript 执行,并将结构化输出解析回 JSON。Print 服务会调用 CUPS 命令(lp、lpstat、lpoptions、cancel);FaceTime 服务会将 tel:// / facetime:// URL 交给 open。共享软件包(@mailappmcp/shared)提供 AppleScript 运行器、通用命令运行器(runCommand)、字符串转义和基于分隔符的解析功能。
应用生命周期——保持原状
Mail、Calendar、Contacts 和 Reminders 需要各自的应用正在运行,才能响应 AppleScript。无需让这些应用一直保持打开状态,每个服务都会在首次使用时自动启动相应应用,并在之后进行清理:
- 首次调用会涉及某个应用的工具时,服务会检查(通过
pgrep)该应用是否已在运行。如果没有,就会在后台启动它(open -g -a),不会抢占焦点,并等待最多 5 秒,直到应用接受 AppleEvents,然后再运行工具。 - 该状态会在进程内保留,持续时间与 MCP 服务的生命周期相同。之后针对同一应用的工具调用会跳过探测并复用正在运行的应用——不会反复承担启动开销。
- 服务关闭时(SIGTERM / SIGINT / SIGHUP / 正常退出——例如 Claude Desktop 断开服务连接或聊天结束时),服务只会退出由它启动的应用。服务启动前已打开的应用会保持不变。
- 边缘情况:如果服务被强制终止(
SIGKILL),退出处理程序无法运行,因此任何自动启动的应用都会继续运行。这与从未启动过该服务的情况相同。
这意味着,你可以放心使用这些工具,不必担心会话结束后留下大量启动一半的应用,也不必担心服务会关闭你正在使用的应用。
安全性
compose-message会打开可见的草稿——发送前可先检查send-message是单独且明确的操作reply-to-message和forward-message默认以草稿模式运行(sendImmediately: false)delete-messages会将邮件移至废纸篓(Mail.app 的标准行为)
HTML 邮件
compose-message 和 send-message 接受可选的 htmlBody 参数。提供此参数时,邮件会以富文本/HTML 格式创建,收件人看到的是渲染后的格式(标题、粗体、列表、可点击链接),而不是原始标签。仍然必须提供 body,它会作为纯文本回退内容,供读取纯文本内容的客户端使用。省略 htmlBody 即采用现有的纯文本行为——完全向后兼容。
// send-message with HTML body
{
"to": ["[email protected]"],
"subject": "Weekly update",
"body": "Highlights:\n- Shipped feature X\n- Fixed bug Y",
"htmlBody": "<h2>Highlights</h2><ul><li>Shipped <b>feature X</b></li><li>Fixed bug Y — see <a href=\"https://example.com/issue/42\">#42</a></li></ul>"
}
在底层,compose-message / send-message 的 HTML 路径使用 JXA(osascript -l JavaScript)以及 Mail.app 对外发邮件运行时提供的 htmlContent setter。纯文本路径仍使用常规 AppleScript。
正确保持对话线程的品牌化回复
reply-to-message 还接受 htmlBody,可生成既带有品牌样式又能正确保持对话线程的回复。Mail 的脚本模型无法设置任意 RFC 标头,而外发回复的富文本编辑器无法通过 AppleScript content 属性写入,因此此前单独使用这两种工具都无法同时实现这两点。现在,回复工具会:
- 调用 Mail 原生的
reply动作来创建回复,并填充In-Reply-To/References标头(这些是与正文相互独立的邮件属性),然后 - 将带有品牌样式的 HTML 作为
public.html放到剪贴板上,并将其粘贴(Cmd-V)到自动引用的对话线程上方。
最终效果是:品牌样式以内嵌形式显示,保留引用的对话线程,并包含严格客户端(Outlook、Gmail web)要求的线程标头,以便将回复嵌套在对话中。
// reply-to-message with a branded HTML body
{
"account": "iCloud",
"mailbox": "INBOX",
"messageId": "<[email protected]>",
"body": "Thanks — see below.", // ignored when htmlBody is set
"htmlBody": "<p>Thanks for reaching out — here's the update:</p><ul><li><b>Status:</b> shipped</li></ul>"
}
限制:
- 回复时不能同时使用
htmlBody和attachments(Mail 在构成 MIME 多部分内容时会重新解析 HTML,导致渲染后的正文损坏)——如果同时传入两者,工具会返回错误。请先发送带有品牌样式的回复,再通过单独的回复附加文件。 - 提供
htmlBody时,会忽略纯文本body;Mail 会根据粘贴的富文本生成纯文本 MIME 替代内容。 - 粘贴时需要 Mail 短暂保持焦点;如果焦点丢失,脚本会安全中止(并恢复剪贴板内容)。
验证 HTML/品牌化回复
生成品牌化回复后,请确认这两部分都正常工作:
- 渲染检查——打开 Mail 创建的草稿。品牌样式应以格式化富文本显示(标题、粗体、链接),而不是原始的
<tags>,并位于引用的原始邮件上方。 - 线程/标头检查——将回复发送给使用严格客户端(Outlook 或 Gmail web)的收件人,并确认回复嵌套在原始对话中,而不是作为一封独立消息显示。也可以对已发送的回复运行
get-message-source,确认其中包含指向原始 Message-ID 的In-Reply-To:和References:标头。 - 剪贴板检查——确认操作完成后剪贴板仍保留之前的内容(工具会在粘贴前保存剪贴板内容,并在之后恢复)。
- 附件限制检查——同时使用
htmlBody和attachments调用reply-to-message时,应返回清晰的错误,而不是生成损坏的草稿。
已知限制
通用
- 每次调用
osascript的超时时间为 30 秒 - 首次使用时会自动启动应用;服务器关闭时,如果应用此前未运行,则会退出——请参阅应用生命周期——保持原状
- 对于接受
messageId或messageIds的 Mail 工具,建议使用search-messages返回的数字字符串id。仍支持 RFCmessageId值,但比较这些值时会加载整个邮箱中的邮件标头,即使超过 30 秒的超时时间后,Mail 也可能仍处于忙碌状态。本地 ID 仅适用于此 Mac 的 Mail 邮件库;移动邮件或重建邮件库后,请重新搜索。 - AppleScript 中的
content contains搜索在大型邮箱中可能很慢——Mail 服务器默认会搜索主题和发件人
Numbers
- Numbers 工具需要打开的文稿
日历
以下是 Calendar.app 的 AppleScript 接口本身的限制,并非 MCP 服务的限制:
- 无法通过 AppleScript 删除日历。 在所有现代 macOS 版本中,
delete calendar都会引发-10000(AppleEvent 处理程序失败)。delete-calendar工具会检查日历是否存在,然后返回描述性错误——你必须在 Calendar.app 侧边栏中手动移除日历(右键单击 → 删除)。 - 日历没有可用的 id/uid。 Calendar.app 的
calendar类不会通过 AppleScript 提供稳定的 id(uid of会引发-10000)。因此,所有日历工具都按名称识别日历——请确保日历名称唯一。 whose筛选器会对事件执行 O(n) 扫描。 AppleScript 会扫描日历中的每个事件,以评估whose start date ≥ X谓词。在繁忙的多日历存储中,即使是跨所有日历查询空的 7 天范围,也可能耗时 60 秒以上,并超过 30 秒的osascript超时时间。请尽可能始终为list-events、search-events、today-events和upcoming-events传入calendarName,以限定扫描范围。search-events还会强制限定日期范围(默认:−30 天至 +365 天)。move-event会重新分配 uid。 Calendar.app 无法在日历之间重新归属事件。该工具会删除源事件,并在目标日历中创建新事件;新事件会获得新的 uid(与oldUid一起以newUid返回)。- 重复规则以原始 RRULE 字符串形式提供(例如
FREQ=WEEKLY;INTERVAL=1)——仅支持读取和写入,不支持解析或展开。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。