yinxiang-mcp
# yinxiang-mcp
非官方印象笔记(Yinxiang / Evernote China)MCP Server。通过 stdio 暴露笔记本、原生超级笔记、原始 ENML 和资源附件相关操作。
> 本项目不是印象笔记或 Evernote 官方项目,也不代表官方背书。
## 安装
```bash
npx -y @yanghechuan/yinxiang-mcp
```
建议锁定版本:
```bash
npx -y @yanghechuan/yinxiang-mcp@0.7.0
```
## 认证
当前版本使用 Direct Token 认证,暂未实现 OAuth。
需要配置两个环境变量:
- `YINXIANG_DEV_TOKEN`:在 <https://dev.yinxiang.com> 申请的 Developer Token
- `YINXIANG_NOTESTORE_URL`:NoteStore URL,例如 `https://app.yinxiang.com/shard/sXX/notestore`
## MCP 配置
```json
{
"mcpServers": {
"yinxiang": {
"command": "npx",
"args": ["-y", "@yanghechuan/yinxiang-mcp@0.7.0"],
"env": {
"YINXIANG_DEV_TOKEN": "<your-token>",
"YINXIANG_NOTESTORE_URL": "https://app.yinxiang.com/shard/sXX/notestore"
}
}
}
}
```
## 工具列表
### 笔记本与笔记本组
- `list-notebooks`:列出笔记本,包含 `guid`、`stack`、默认笔记本标记和更新元数据。
- `get-notebook`:按 `guid` 读取单个笔记本元数据。
- `create-notebook`:创建笔记本,可选加入笔记本组。
- `update-notebook`:重命名笔记本或更新所属笔记本组,需要 `confirm=true`。
- `delete-notebook`:删除笔记本,需要 `confirm=true` 且 `confirmGuid === guid`;非空笔记本还需要 `force=true`。
- `list-stacks`:从笔记本的 `stack` 字段反推笔记本组列表。
- `create-stack`:通过把一个已有笔记本放入 stack 来创建笔记本组,需要 `confirm=true`。
- `rename-stack`:批量更新组内笔记本的 `stack` 字段来重命名笔记本组,需要 `confirm=true`。
- `delete-stack`:清空组内笔记本的 `stack` 字段来删除笔记本组,不删除笔记本,需要 `confirm=true`。
- `move-notebook-to-stack`:将单个笔记本移入指定笔记本组,需要 `confirm=true`。
- `remove-notebook-from-stack`:将单个笔记本移出当前笔记本组,需要 `confirm=true`。
### 笔记
- `find-notes`:按 Evernote 搜索语法和/或笔记本 GUID 搜索笔记元数据。
- `get-note-raw`:读取原始 ENML、笔记本 GUID、标签和属性,不经过 Markdown 转换。
- `create-super-note`:使用原生块模型创建印象笔记超级笔记。
- `update-super-note`:使用原生块模型覆盖笔记正文,需要 `confirm=true`。
- `append-super-note-blocks`:保留已有 ENML,在末尾追加原生块,需要 `confirm=true`。
- `replace-super-note-block`:按 `blockId` 替换一个原生块,需要 `confirm=true`。
- `delete-super-note-block`:按 `blockId` 删除一个原生块,需要 `confirm=true`。
- `replace-note-enml`:用完整 ENML 或 `en-note` 内部 body 直接覆盖正文,需要 `confirm=true`。
- `clone-note`:原样克隆 ENML 正文和笔记元数据,不经过 Markdown 转换。
- `attach-file`:将本地文件追加为 Evernote Resource,并在正文追加匹配的 `<en-media>`,需要 `confirm=true`。
- `export-note-resource`:按 `resourceGuid` 或 MD5 `hash` 导出单个资源。
- `delete-note-resource`:按 `resourceGuid` 或 MD5 `hash` 删除单个资源和匹配的 `<en-media>`,需要 `confirm=true`。
- `move-note`:移动笔记到另一个笔记本,不修改标题和正文,需要 `confirm=true`。
- `clear-note-content`:清空笔记正文,保留标题和所在笔记本,需要 `confirm=true`。
- `delete-note`:将笔记移入废纸篓,需要 `confirm=true`。
- `expunge-note`:永久删除笔记,需要 `confirm=true` 且 `confirmGuid === guid`。
## 原生块模型
`create-super-note`、`update-super-note` 和 `append-super-note-blocks` 接收 `blocks` 数组。字符串会被当作普通段落;对象示例:
```json
[
{
"type": "heading",
"level": 2,
"id": "stable-block-id",
"runs": [
{ "text": "蓝色加粗标题", "bold": true, "color": "#1677ff" }
]
},
{
"type": "paragraph",
"runs": [
{ "text": "普通文字 " },
{ "text": "红色加粗", "bold": true, "color": "#d4380d" },
{ "text": " 大号文字", "fontSize": 22 },
{ "text": " 链接", "href": "https://example.com?a=1&b=2" }
]
},
{
"type": "todo",
"checked": false,
"runs": [{ "text": "待办事项" }]
},
{
"type": "table",
"id": "table-1",
"header": true,
"rows": [
[{ "text": "名称" }, { "text": "状态" }],
[{ "text": "任务 A" }, { "text": "完成", "color": "#52c41a" }]
]
}
]
```
支持的块类型:`heading`、`paragraph`、`blockquote`、`code`、`divider`、`todo`、`bulleted_list`、`numbered_list`、`table`。
支持的文字样式:`bold`、`italic`、`underline`、`strike`、`code`、`color`、`backgroundColor`、`fontSize`、`href`。
颜色必须使用 `#RRGGBB`;`fontSize` 必须是 8 到 72 的整数。正文默认字号为 16px。标题默认使用客户端标题层级,只有显式传入 `fontSize` 时才覆盖标题内部文字。
表格块必须提供稳定 `id`,便于后续用 `replace-super-note-block` 或 `delete-super-note-block` 编辑/删除整张表。
## 文件资源
`attach-file` 会读取本地文件、计算 MD5、创建 Evernote Resource,并在正文中追加匹配的 `<en-media>`。MIME 会根据扩展名自动推断,也可以显式传入。
```json
{
"guid": "note-guid",
"filePath": "/tmp/demo.png",
"fileName": "demo.png",
"confirm": true
}
```
资源可以通过 `resourceGuid` 或 MD5 `hash` 导出和删除。
## 本地开发
```bash
npm install
cp .env.example .env
npm test
npm run verify
npm start
```
`npm run verify` 是只读验证:它会通过列出笔记本来验证 token 和 NoteStore URL 是否可用。
## 发布
```bash
npm test
npm pack --dry-run
npm publish --access public
```
发布前必须确认 npm tarball 中不包含 `.env`、真实 token、日志或私人笔记内容。
## 限制
- 使用 `evernote@2.0.5`,底层是较旧的 EDAM API。
- Evernote/印象笔记的笔记本组不是独立实体,本项目通过笔记本的 `stack` 字段实现组管理。
- 原生超级笔记工具不经过 Markdown 中转,适合保留加粗、颜色、链接、待办、表格等富文本样式。
- Markdown 兼容函数仍保留在内部,但不作为 MCP 工具暴露,避免误用导致富文本样式丢失。
- 资源工具支持本地图片、音频和通用附件,可按单资源导出和删除。
- 可折叠标题依赖印象笔记超级笔记的 `other-props.blockId`、`yinxiang.superNote` 与 `yinxiang.noteLayout` 标记;旧客户端可能只显示普通标题样式。
## 安全
不要提交真实 Developer Token、绑定私人账号的 NoteStore URL、请求日志或导出的笔记内容。更多说明见 [SECURITY.md](SECURITY.md)。
## 开源协议
本项目使用 MIT License。完整协议内容见 [LICENSE](LICENSE)。
TDQS
Scored across 27 tools
Most tools have distinct purposes, but some overlap exists (e.g., delete-note vs expunge-note, append-super-note-blocks vs replace-super-note-block). Overall, agents can distinguish with care.
Tools follow snake_case with verb-noun pattern (e.g., create-notebook, delete-note). Minor inconsistencies like 'get-notebook' vs 'get-note-raw' and some verbs (expunge) are unusual but acceptable.
27 tools is on the higher side for a note-taking server. While each tool seems purposeful, the count feels heavy and could be streamlined (e.g., merge expunge-note into delete-note).
Covers core CRUD for notebooks, stacks, notes, super notes, and resources. Missing operations like rename notebook or search notebooks, but main workflows are present.