🚀 macOS Automator MCP Server
本项目提供了一个模型上下文协议(MCP)服务器 macos_automator
,它允许在 macOS 系统上执行 AppleScript 和 JavaScript for Automation (JXA) 脚本。该服务器具备一个预定义脚本知识库,可通过 ID 访问,同时支持内联脚本、脚本文件和参数传递。知识库会在首次使用时进行懒加载,以实现服务器的快速启动。
🚀 快速开始
本项目提供的 macos_automator
服务器允许通过 MCP 协议远程执行 AppleScript 和 JXA 脚本,实现对 macOS 系统的自动化控制。以下是使用该服务器的快速指南。
安装与运行
运行此服务器的主要方式是通过 npx
,这样可以确保使用的是最新版本,而无需进行全局安装。将以下配置添加到 MCP 客户端的 mcp.json
(或等效配置文件)中:
{
"mcpServers": {
"macos_automator": {
"command": "npx",
"args": [
"-y",
"@steipete/macos-automator-mcp@latest"
]
}
}
}
本地运行(开发或直接使用)
如果你想在本地开发或直接从克隆的仓库运行服务器,可以使用提供的 start.sh
脚本。这在你需要进行本地修改或运行特定版本时非常有用。
- 克隆仓库:
git clone https://github.com/steipete/macos-automator-mcp.git
cd macos-automator-mcp
npm install
- 配置 MCP 客户端:
更新 MCP 客户端的配置,使其指向克隆仓库中
start.sh
脚本的绝对路径。
示例 mcp.json
配置片段:
{
"mcpServers": {
"macos_automator_local": {
"command": "/absolute/path/to/your/cloned/macos-automator-mcp/start.sh",
"env": {
"LOG_LEVEL": "DEBUG"
}
}
}
}
重要提示:请将 /absolute/path/to/your/cloned/macos-automator-mcp/start.sh
替换为你系统上的正确绝对路径。
start.sh
脚本会在未找到编译版本时自动使用 tsx
直接运行 TypeScript 源代码,或者在可用时从 dist/
目录运行编译后的版本。它会遵循 LOG_LEVEL
环境变量。
开发者注意事项:如果修改 start.sh
脚本,在执行前删除任何现有的编译后的 dist/server.js
(例如,添加 rm -f dist/server.js
),则可以确保始终通过 tsx
运行 src/
目录中的最新 TypeScript 代码。这在开发过程中非常有用,可以避免陈旧构建带来的问题。对于生产部署(例如发布到 npm),通常会有一个构建过程来创建最终的 dist/server.js
,它将成为发布包的入口点。
✨ 主要特性
- 通过 MCP 远程执行 AppleScript/JXA 脚本。
- 利用丰富且可扩展的常见 macOS 自动化任务知识库。
- 以编程方式控制 macOS 应用程序和系统功能。
- 将 macOS 自动化集成到更大的 AI 驱动工作流中。
📦 安装指南
前提条件
- Node.js(建议版本 >=18.0.0,详见
package.json
中的 engines
字段)。
- macOS 系统。
关键权限设置
- 运行此 MCP 服务器的应用程序(例如,终端、你的 Node.js 应用程序)需要在运行服务器的 macOS 机器上获得用户的明确权限。
- 自动化权限:用于控制其他应用程序(如 Finder、Safari、Mail 等)。
- 前往:系统设置 > 隐私与安全 > 自动化。
- 在列表中找到运行服务器的应用程序(例如,终端)。
- 确保为其需要控制的所有应用程序勾选复选框。
- 示例请参考:
docs/automation-permissions-example.png
(占位图像)。
- 辅助功能权限:用于通过 “系统事件” 进行 UI 脚本编写(例如,模拟点击、按键)。
- 前往:系统设置 > 隐私与安全 > 辅助功能。
- 将运行服务器的应用程序(例如,终端)添加到列表中,并确保勾选其复选框。
- 首次尝试控制新应用程序或使用辅助功能时,即使已预先授权,仍可能会触发 macOS 确认提示。服务器本身无法授予这些权限。
💻 使用示例
基础用法
以下是一些使用 execute_script
工具的示例:
{
"toolName": "execute_script",
"input": {
"kb_script_id": "safari_get_active_tab_url",
"timeout_seconds": 10
}
}
{
"toolName": "execute_script",
"input": {
"kb_script_id": "finder_create_folder_at_path",
"input_data": {
"folder_name": "New MCP Folder",
"parent_path": "~/Desktop"
}
}
}
高级用法
使用 get_scripting_tips
工具检索知识库中的脚本提示和示例:
{
"toolName": "get_scripting_tips",
"input": {
"list_categories": true
}
}
{
"toolName": "get_scripting_tips",
"input": {
"category": "safari"
}
}
{
"toolName": "get_scripting_tips",
"input": {
"search_term": "clipboard"
}
}
📚 详细文档
提供的工具
1. execute_script
在 macOS 上执行 AppleScript 或 JavaScript for Automation (JXA) 脚本。脚本可以作为内联内容 (script_content
)、绝对文件路径 (script_path
) 提供,或者通过使用其唯一的 kb_script_id
引用内置知识库中的脚本。
- 脚本来源(互斥):
script_content
(字符串):原始脚本代码。
script_path
(字符串):脚本文件的绝对 POSIX 路径(例如,.applescript
、.scpt
、.js
)。
kb_script_id
(字符串):服务器知识库中预定义脚本的 ID。使用 get_scripting_tips
工具发现可用的脚本 ID 及其功能。
- 语言指定:
language
(枚举: 'applescript' | 'javascript',可选):指定脚本语言。
- 如果使用
kb_script_id
,语言将从知识库脚本中推断。
- 如果使用
script_content
或 script_path
且未指定 language
,则默认为 'applescript'。
- 向脚本传递输入:
arguments
(字符串数组,可选):
- 对于
script_path
:作为标准参数传递给脚本的 on run argv
(AppleScript) 或 run(argv)
(JXA) 处理程序。
- 对于
kb_script_id
:如果预定义脚本设计为接受位置字符串参数(例如,替换占位符 --MCP_ARG_1
、--MCP_ARG_2
),则使用此参数。请检查 get_scripting_tips
中脚本的 argumentsPrompt
。
input_data
(JSON 对象,可选):
- 主要用于设计为接受命名、结构化输入的
kb_script_id
脚本。
- 此对象中的值将替换脚本中的占位符(例如,
--MCP_INPUT:yourKeyName
)。请参阅 get_scripting_tips
中的 argumentsPrompt
。
- 值(字符串、数字、布尔值、简单数组/对象)将转换为其 AppleScript 字面量等效形式。
- 其他选项:
timeout_seconds
(整数,可选,默认值: 60):最大执行时间。
output_format_mode
(枚举,可选,默认值: 'auto'):控制 osascript
输出格式化标志。
'auto'
(默认):AppleScript 使用人类可读格式 (-s h
),JXA 使用直接输出(无 -s
标志)。
'human_readable'
:强制使用 -s h
(人类可读输出,主要用于 AppleScript)。
'structured_error'
:强制使用 -s s
(结构化错误报告,主要用于 AppleScript)。
'structured_output_and_error'
:强制使用 -s ss
(主要结果和错误的结构化输出,主要用于 AppleScript)。
'direct'
:不使用 -s
标志(建议用于 JXA,也是 auto
模式下 JXA 的行为)。
include_executed_script_in_output
(布尔值,可选,默认值: false):如果为 true,输出将包括完整的脚本内容(对于知识库脚本,在进行任何占位符替换后)或执行的脚本路径。这将作为输出内容数组中的额外文本部分添加。
include_substitution_logs
(布尔值,可选,默认值: false):如果为 true,知识库脚本上执行的占位符替换的详细日志将包含在输出中。这对于调试 input_data
和 arguments
如何处理和插入脚本非常有用。日志在成功时会添加到脚本输出之前,失败时会添加到错误消息之后。
report_execution_time
(布尔值,可选,默认值: false):如果为 true
,响应内容数组中将包含一条格式化的脚本执行时间的额外消息。
- 安全警告与 macOS 权限:(与之前关于任意脚本执行和 macOS 自动化/辅助功能权限的关键警告相同)
- 响应格式:
execute_script
工具返回的响应格式如下:
{
content: Array<{
type: 'text';
text: string;
}>;
isError?: boolean;
}
- `content`:包含脚本输出的文本内容项数组。
- `isError` (布尔值,可选):当脚本执行产生错误时设置为 `true`。当满足以下条件时设置此标志:
- 脚本输出(标准输出)以 "Error" 开头(不区分大小写)。
- 这有助于客户端在不解析输出文本的情况下轻松确定执行是否失败。
2. get_scripting_tips
从服务器的知识库中检索 AppleScript/JXA 提示、示例和可运行脚本的详细信息。对于发现可用脚本、其功能以及如何使用 execute_script
(特别是 kb_script_id
)非常有用。
- 参数:
list_categories
(布尔值,可选,默认值: false):如果为 true,仅返回可用知识库类别的列表及其描述。会覆盖其他参数。
category
(字符串,可选):按特定类别 ID(例如,"finder"、"safari")过滤提示。
search_term
(字符串,可选):在提示标题、描述、脚本内容、关键字或 ID 中搜索关键字。
refresh_database
(布尔值,可选,默认值: false):如果为 true,在处理请求之前强制从磁盘重新加载整个知识库。这在开发过程中非常有用,如果你正在积极修改知识库文件并希望确保使用的是最新版本,而无需重启服务器。
limit
(整数,可选,默认值: 10):返回的最大结果数。
- 输出:
返回一个 Markdown 格式的字符串,包含请求的提示,包括其标题、描述、脚本内容、语言、可运行 ID(如果适用)、参数提示和注释。
关键用例与示例
应用程序控制
{ "input": { "script_content": "tell application \"Safari\" to get URL of front document" } }
{ "input": { "script_content": "tell application \"Mail\" to get subject of messages of inbox whose read status is false" } }
文件系统操作
{ "input": { "script_content": "tell application \"Finder\" to get name of every item of desktop" } }
{ "input": { "script_content": "tell application \"Finder\" to make new folder at desktop with properties {name:\"My New Folder\"}" } }
系统交互
{ "input": { "script_content": "display notification \"Important Update!\" with title \"System Alert\"" } }
{ "input": { "script_content": "set volume output volume 50" } }
{ "input": { "script_content": "the clipboard" } }
故障排除
- 权限错误:如果脚本无法控制应用程序或执行 UI 操作,请在系统设置中仔细检查运行 MCP 服务器的应用程序(例如,终端)的自动化和辅助功能权限。
- 脚本语法错误:
osascript
错误将在 stderr
或错误消息中返回。请先使用脚本编辑器(对于 AppleScript)或 JXA 运行器在本地测试复杂脚本。
- 超时问题:如果脚本执行时间超过
timeout_seconds
(默认 60 秒),它将被终止。对于长时间运行的脚本,请增加超时时间。
- 文件未找到:确保
script_path
是运行 MCP 服务器的用户可以访问的绝对 POSIX 路径。
- 输出不正确/JXA 问题:对于 JXA 脚本,特别是那些使用 Objective-C 桥接的脚本,请确保
output_format_mode
设置为 'direct'
或 'auto'
(默认)。对 JXA 使用 AppleScript 特定的格式化标志(如 human_readable
)可能会导致错误。如果 AppleScript 输出解析不正确,请尝试 structured_output_and_error
或 structured_error
。
通过环境变量进行配置
LOG_LEVEL
:设置服务器的日志级别。
- 值:
DEBUG
、INFO
、WARN
、ERROR
- 示例:
LOG_LEVEL=DEBUG npx @steipete/macos-automator-mcp@latest
KB_PARSING
:控制知识库(脚本提示)的解析时间。
- 值:
lazy
(默认):在首次请求 get_scripting_tips
或在 execute_script
中使用 kb_script_id
时解析知识库。这允许服务器更快启动。
eager
:在服务器启动时解析知识库。这可能会略微增加启动时间,但确保知识库立即可用,并能尽早捕获任何解析错误。
- 示例(通过
start.sh
或类似方式运行时):
KB_PARSING=eager ./start.sh
- 示例(通过支持 `env` 的 MCP 运行器配置时,如 `mcp-agentify`):
{
"env": {
"LOG_LEVEL": "INFO",
"KB_PARSING": "eager"
}
}
本地知识库
你可以使用自己的本地提示和共享处理程序来补充内置知识库。创建一个与本仓库中的 knowledge_base
相同的目录结构(或其子集)。
默认情况下,应用程序将在 ~/.macos-automator/knowledge_base
中查找此本地知识库。你可以通过设置 LOCAL_KB_PATH
环境变量来自定义此路径。
示例
假设你在 /Users/yourname/my-custom-kb
有一个本地知识库。设置环境变量:
export LOCAL_KB_PATH=/Users/yourname/my-custom-kb
或者,如果你正在运行验证脚本,可以使用 --local-kb-path
参数:
npm run validate:kb -- --local-kb-path /Users/yourname/my-custom-kb
结构和覆盖规则
- 你的本地知识库应与主
knowledge_base
的类别结构一致(例如,01_applescript_core
、05_web_browsers/safari
等)。
- 你可以添加新的
.md
提示文件或 _shared_handlers
(例如,.applescript
或 .js
文件)。
- 如果本地知识库中的提示 ID(无论是来自前元数据
id:
还是从文件名/路径生成)与嵌入式知识库中的 ID 匹配,你的本地版本将覆盖嵌入式版本。
- 类似地,本地
_shared_handlers
目录中具有相同名称和语言的共享处理程序(例如,my_utility.applescript
)将覆盖同一类别中(或如果你将它们放在本地知识库的 _shared_handlers
根目录中,则全局覆盖)具有相同名称和语言的任何嵌入式处理程序。
- 本地知识库中
_category_info.md
的类别描述也可以覆盖嵌入式知识库中同一类别的描述。
这允许你在不修改核心应用程序文件的情况下个性化和扩展可用的自动化脚本和提示。
自动化能力
此服务器通过 AppleScript 和 JavaScript for Automation (JXA) 提供强大的 macOS 自动化功能。以下是一些最有用的示例:
终端自动化
{ "input": { "kb_script_id": "terminal_app_run_command_new_tab", "input_data": { "command": "ls -la" } } }
- 使用 sudo 执行命令并安全提供密码
- 捕获命令输出以进行处理
浏览器控制
{ "input": { "kb_script_id": "chrome_open_url_new_tab_profile", "input_data": { "url": "https://example.com", "profile_name": "Default" } } }
{ "input": { "kb_script_id": "safari_get_front_tab_url" } }
{ "input": { "kb_script_id": "chrome_execute_javascript", "input_data": { "javascript_code": "document.title" } } }
- 提取页面内容、操作表单和自动化工作流
- 截取网页截图
系统交互
{ "input": { "kb_script_id": "systemsettings_toggle_dark_mode_ui" } }
{ "input": { "kb_script_id": "system_clipboard_get_file_paths" } }
文件操作
{ "input": { "kb_script_id": "finder_create_new_folder_desktop", "input_data": { "folder_name": "My Project" } } }
{ "input": { "kb_script_id": "fileops_read_text_file", "input_data": { "file_path": "~/Documents/notes.txt" } } }
应用程序集成
{ "input": { "kb_script_id": "calendar_create_event", "input_data": { "title": "Meeting", "start_date": "2023-06-01 10:00", "end_date": "2023-06-01 11:00" } } }
{ "input": { "kb_script_id": "mail_send_email_direct", "input_data": { "recipient": "user@example.com", "subject": "Hello", "body_content": "Message content" } } }
{ "input": { "kb_script_id": "music_playback_controls", "input_data": { "action": "play" } } }
- 与创意应用程序(Keynote、Pages、Numbers)协作
使用 get_scripting_tips
工具按类别探索所有可用的自动化功能。
🔧 技术细节
本项目的知识库采用懒加载机制,在首次使用时进行解析,以实现服务器的快速启动。服务器使用 Node.js 运行,通过 osascript
命令执行 AppleScript 和 JXA 脚本。在处理脚本时,会根据不同的参数设置(如 output_format_mode
)控制 osascript
的输出格式,以满足不同的需求。同时,服务器支持通过环境变量进行配置,如 LOG_LEVEL
和 KB_PARSING
,以灵活控制日志级别和知识库解析时间。
📄 许可证
本项目采用 MIT 许可证。详情请参阅 LICENSE 文件。