内容
# Apple-notes-mcp
一款 [模型上下文协议(MCP)](https://modelcontextprotocol.io) 服务器,为 Claude Desktop 提供对您的 Apple Notes 的完全访问权限 - 读取、写入、搜索、组织等。
使用 TypeScript、AppleScript 和官方 MCP SDK 构建。无需 API 密钥。无需云服务。所有操作都在您的 Mac 上本地运行。
---
## 为什么选择这个官方连接器?
官方 Anthropic Apple Notes 连接器有 4 个工具,而这个连接器有 **13 个工具**。
| 工具 | 这个连接器 | 官方连接器 |
|---|:---:|:---:|
| `list_notes` (包括文件夹信息) | ✅ | ✅ |
| `search_notes` (可选文件夹筛选) | ✅ | ❌ |
| `read_note` | ✅ | ✅ |
| `create_note` | ✅ | ✅ |
| `update_note` | ✅ | ✅ |
| `delete_note` | ✅ | ❌ |
| `append_to_note` | ✅ | ❌ |
| `list_folders` (带笔记数量) | ✅ | ❌ |
| `list_notes_in_folder` | ✅ | ❌ |
| `create_folder` | ✅ | ❌ |
| `delete_folder` | ✅ | ❌ |
| `move_note` | ✅ | ❌ |
| `get_note_metadata` | ✅ | ❌ |
---
## 要求
- macOS(AppleScript 仅在 Mac 上运行)
- [Node.js](https://nodejs.org) v18 或更高版本
- [Claude Desktop](https://claude.ai/download)
- Apple Notes 应用(内置于 macOS)
---
## 安装
```bash
# 1. 克隆仓库
git clone https://github.com/your-username/apple-notes-mcp.git
cd apple-notes-mcp
# 2. 安装依赖
npm install
# 3. 构建
npm run build
```
---
## 连接到 Claude Desktop
编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"apple-notes": {
"command": "node",
"args": ["/absolute/path/to/apple-notes-mcp/dist/index.js"]
}
}
}
```
替换 `/absolute/path/to/apple-notes-mcp` 为实际路径。您可以通过在项目文件夹中运行 `pwd` 来获取它。
然后 **重启 Claude Desktop**。您应该看到 `apple-notes` 在连接器下被列出,并且所有 13 个工具都处于活动状态。
> **提示:** 如果 Claude Desktop 找不到 `node`,请使用完整路径。 在终端中运行 `which node` 并使用该路径代替 `"node"`。
---
## 工具
### `list_notes`
列出所有文件夹中的每个笔记。
**返回:** `{ id, name, folder }` 数组
**示例提示:**
> "列出我所有的 Apple 笔记"
---
### `search_notes`
按标题或正文内容搜索笔记,可选地限定在某个文件夹中。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `query` | 字符串 | ✅ | 要搜索的文本 |
| `folder` | 字符串 | ❌ | 限制搜索在此文件夹中 |
**示例提示:**
> "在我的笔记中搜索 '项目截止日期'"
> "仅在我的工作文件夹中查找有关 '预算' 的笔记"
---
### `read_note`
按 ID 读取笔记的全文纯文本内容。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
**示例提示:**
> "读取我的 '会议笔记' 笔记" *(Claude 将首先搜索,然后读取)*
---
### `create_note`
创建新笔记,可选地在特定文件夹中。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `title` | 字符串 | ✅ | 笔记标题 |
| `body` | 字符串 | ✅ | 笔记正文内容 |
| `folder` | 字符串 | ❌ | 创建笔记的文件夹 |
**示例提示:**
> "创建一个名为 '想法' 的笔记,包含我的创业想法列表"
> "在我的工作文件夹中创建一个名为 '冲刺计划' 的笔记"
---
### `update_note`
更新现有笔记的标题和/或正文。仅更改您提供的字段。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
| `title` | 字符串 | ❌ | 新标题 |
| `body` | 字符串 | ❌ | 新正文(替换现有正文) |
**示例提示:**
> "将我的 '草稿' 笔记标题更新为 '最终版本'"
---
### `append_to_note`
在不覆盖原有内容的情况下,将内容追加到笔记的末尾。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
| `content` | 字符串 | ✅ | 要追加的文本 |
**示例提示:**
> "在我的会议笔记中追加 '下周一跟进'"
---
### `delete_note`
永久删除笔记。**无法撤销。**
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
**示例提示:**
> "删除我的 '临时' 笔记"
---
### `list_folders`
列出所有文件夹及其笔记数量。
**返回:** `{ name, noteCount }` 数组
**示例提示:**
> "列出我所有的笔记文件夹"
> "每个文件夹中有多少笔记?"
---
### `list_notes_in_folder`
列出特定文件夹中的所有笔记。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `folder` | 字符串 | ✅ | 文件夹名称 |
**示例提示:**
> "显示我个人文件夹中的所有笔记"
---
### `create_folder`
在 Apple Notes 中创建新文件夹。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `name` | 字符串 | ✅ | 文件夹名称 |
**示例提示:**
> "创建一个名为 '存档 2026' 的文件夹"
---
### `delete_folder`
永久删除文件夹及其中的所有笔记。**无法撤销。**
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `name` | 字符串 | ✅ | 文件夹名称 |
**示例提示:**
> "删除 '旧草稿' 文件夹"
---
### `move_note`
将笔记移动到不同文件夹。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
| `folder` | 字符串 | ✅ | 目标文件夹名称 |
**示例提示:**
> "将我的 '想法' 笔记移动到工作文件夹"
---
### `get_note_metadata`
获取笔记的元数据:标题、文件夹、创建时间、上次修改时间。
**输入:**
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
| `noteId` | 字符串 | ✅ | 笔记的唯一 ID |
**示例提示:**
> "我的 '会议笔记' 笔记上次修改时间是什么时候?"
---
## 示例多步骤提示
这些提示会自动链接多个工具:
> "查找所有关于 '预算' 的笔记,读取最相关的笔记,然后追加今日日期作为页脚"
> "列出我所有的文件夹,然后显示笔记数量最多的文件夹中的笔记"
> "创建一个名为 '项目' 的文件夹,然后在其中创建一个名为 '项目 Alpha' 的笔记"
> "在我的财务文件夹中搜索包含 '发票' 的笔记,然后读取每个笔记"
---
## 项目结构
```
apple-notes-mcp/
├── src/
│ ├── index.ts # 入口点 - 连接传输
│ ├── server.ts # 将所有工具连接到 McpServer
│ ├── helpers.ts # escapeAppleScriptString, stripHtml, parseNoteLines
│ └── tools/
│ ├── list-notes.ts
│ ├── search-notes.ts
│ ├── read-note.ts
│ ├── create-note.ts
│ ├── update-note.ts
│ ├── delete-note.ts
│ ├── append-to-note.ts
│ ├── list-folders.ts
│ ├── list-notes-in-folder.ts
│ ├── create-folder.ts
│ ├── delete-folder.ts
│ ├── move-note.ts
│ └── get-note-metadata.ts
├── tests/
│ ├── unit/
│ │ ├── helpers.test.ts
│ │ └── tools/ # 每个工具一个测试文件
│ ├── integration/
│ │ └── server.test.ts
│ └── utils/
│ └── mock-server.ts
├── __mocks__/
│ └── run-applescript.ts # CJS 模拟 ESM-only 包
├── dist/ # 编译输出(git-ignored)
├── package.json
├── tsconfig.json
├── tsconfig.test.json
├── jest.config.ts
└── eslint.config.ts
```
---
## 开发
```bash
npm run build # 编译 TypeScript → dist/
npm run lint # 检查 lint 错误
npm run lint:fix # 自动修复 lint 错误
npm run dev # 直接使用 ts-node 运行(无需构建)
npm test # 运行所有测试
npm run test:unit # 仅运行单元测试
npm run test:integration # 仅运行集成测试
npm run test:coverage # 运行测试并生成覆盖率报告
```
---
## 安全
- 所有用户提供的数值都通过 `escapeAppleScriptString()` 进行净化,以防止注入攻击。
- 所有调试/错误输出仅发送到 `stderr` - `stdout` 保留用于 MCP JSON-RPC 通道。
- 无数据离开您的机器。所有操作通过 AppleScript 在本地运行。
---
## 许可证
MIT