Obsidian CLI MCP Server
by husitao
README.md
# Obsidian CLI MCP Server
使用 TypeScript 实现的 stdio MCP Server,通过 Obsidian 官方 CLI 为 Claude Code、Codex 等 AI Agent 提供 Vault 操作能力。
本项目不直接读写 Vault 文件,也不通过 shell 拼接命令。所有操作均以参数数组调用 Obsidian CLI,并提供 Vault 锁定、命令权限、超时、输出限制及跨进程串行保护。
## 功能
- 查询 Obsidian 及 CLI 状态
- 列出 Vault 内的文件和文件夹
- 读取、创建、覆盖、追加和前置写入笔记
- 将大段 Markdown 自动拆成 UTF-8 安全块写入
- 搜索笔记及匹配上下文
- 调用属性、链接、任务、模板、历史、插件和开发者命令
- 按配置允许删除、`command`、`eval` 等高权限操作
- 将 Server 硬锁定到指定 Vault
- 串行处理多个 Agent 或并发 MCP 请求
调用链如下:
```text
Claude Code / Codex
│ stdio MCP
▼
Obsidian CLI MCP Server
│ FIFO + 跨进程锁
▼
Obsidian.com / obsidian
│ IPC
▼
正在运行的 Obsidian
```
## 前置条件
- Node.js 20 或更高版本
- Obsidian 1.12.7 或更高版本的安装器
- 在 Obsidian 的“设置 → 常规”中启用“命令行接口”
- 调用时保持 Obsidian 桌面端运行
- 目标 Vault 已由 Obsidian 打开或管理
Windows 使用安装目录中的 `Obsidian.com` 作为终端重定向器。升级安装器后,应重新启用命令行接口并重启终端。
先验证官方 CLI:
```powershell
obsidian version
obsidian vaults verbose
```
## 安装与构建
```powershell
Set-Location D:\Document\MyMCP\ObsidianCli
npm install
npm run check
npm test
npm run build
```
构建入口为:
```text
D:\Document\MyMCP\ObsidianCli\dist\index.js
```
修改 TypeScript 源码后必须重新执行 `npm run build`,并重启 MCP 客户端会话。
## 配置 Claude Code
在 Vault 或 Claude Code 项目根目录创建 `.mcp.json`。下面是锁定到 `Dance` 且允许全部 Obsidian CLI 能力的配置:
```json
{
"mcpServers": {
"obsidian-cli": {
"command": "node",
"args": [
"D:\\Document\\MyMCP\\ObsidianCli\\dist\\index.js"
],
"env": {
"OBSIDIAN_CLI_COMMAND": "D:\\Apps\\Common\\Obsidian\\Obsidian.com",
"OBSIDIAN_DEFAULT_VAULT": "Dance",
"OBSIDIAN_LOCKED_VAULT": "Dance",
"OBSIDIAN_CLI_ALLOW_UNSAFE": "true",
"OBSIDIAN_CLI_EXTRA_COMMANDS": "*"
}
}
}
}
```
MCP 配置中的环境变量值必须全部是字符串。特别是应写成 `"true"`,不能写成 JSON 布尔值 `true`,否则 Claude Code 会忽略整个 Server 配置。
从项目根目录验证:
```powershell
claude mcp list
claude mcp get obsidian-cli
```
预期状态:
```text
obsidian-cli ... ✓ Connected
```
修改 `.mcp.json` 或重新构建 Server 后,应退出并重新启动 Claude Code。
## 配置 Codex
在受信任的项目中创建 `.codex/config.toml`:
```toml
[mcp_servers.obsidian-cli]
command = "node"
args = ['D:\Document\MyMCP\ObsidianCli\dist\index.js']
cwd = 'D:\Workspace\Ob\Dance\Dance'
enabled = true
required = true
startup_timeout_sec = 30
tool_timeout_sec = 60
default_tools_approval_mode = "approve"
[mcp_servers.obsidian-cli.env]
OBSIDIAN_CLI_COMMAND = 'D:\Apps\Common\Obsidian\Obsidian.com'
OBSIDIAN_DEFAULT_VAULT = "Dance"
OBSIDIAN_LOCKED_VAULT = "Dance"
OBSIDIAN_CLI_ALLOW_UNSAFE = "true"
OBSIDIAN_CLI_EXTRA_COMMANDS = "*"
```
Codex 只会为受信任项目加载项目级 `.codex/config.toml`。修改配置或重新构建后,以目标 Vault 为工作区新建 Codex 线程。
## 配合项目 Skill
MCP Server 负责提供操作能力,Skill 负责规定 Agent 的知识管理流程。当前 `Dance` 项目分别使用:
```text
.claude/skills/curate-dance-vault/SKILL.md
.agents/skills/curate-dance-vault/SKILL.md
```
Claude Code 与 Codex 使用相同 Skill 内容,约束 inbox、atlas、workspace、archive、system 的数据流,并要求优先使用本 MCP,而不是 shell 文件操作。
## MCP 工具
| 工具 | 主要输入 | 用途 |
| --- | --- | --- |
| `obsidian_status` | 无 | 查询 Obsidian 版本及 CLI 连通性 |
| `obsidian_help` | `command?` | 查询总帮助或指定命令帮助 |
| `obsidian_list` | `type`、`vault?`、`folder?`、`extension?` | 列出 Vault、文件或文件夹 |
| `obsidian_read_note` | `path`、`vault?` | 按 Vault 相对路径读取笔记 |
| `obsidian_write_note` | `path`、`content`、`mode`、`overwrite`、`vault?` | 创建、追加或前置写入笔记 |
| `obsidian_search` | `query`、`path?`、`limit?`、`context`、`format`、`vault?` | 搜索笔记内容 |
| `obsidian_cli` | `command`、`parameters`、`flags`、`vault?` | 执行其他允许的 Obsidian CLI 命令 |
`obsidian_write_note.mode` 支持:
- `create`
- `append`
- `prepend`
`obsidian_write_note` 会把正文拆成最多 1,024 UTF-8 字节的块,并在一个不可交错的 CLI 批次中完成写入。调用方仍只需提交一次完整正文。
`obsidian_cli` 的参数格式:
```json
{
"command": "move",
"parameters": {
"path": "inbox/source.md",
"to": "archive/source.md"
},
"flags": []
}
```
Server 会将 Vault 参数放在命令之前,并将普通参数转换为 `key=value`。Obsidian 的普通布尔开关使用裸 flag,例如 `overwrite`、`verbose`;全局复制选项使用 `--copy`。
## 环境变量
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `OBSIDIAN_CLI_COMMAND` | `obsidian` | CLI 可执行文件名或绝对路径 |
| `OBSIDIAN_DEFAULT_VAULT` | 未设置 | 工具调用未指定 Vault 时使用的默认值 |
| `OBSIDIAN_LOCKED_VAULT` | 未设置 | 将 Server 硬锁定到指定 Vault,并禁止枚举所有 Vault |
| `OBSIDIAN_CLI_TIMEOUT_MS` | `30000` | 单个进程的执行超时,范围 1–300 秒 |
| `OBSIDIAN_CLI_MAX_OUTPUT_BYTES` | `1048576` | 单次调用最大输出,最高 10 MiB |
| `OBSIDIAN_CLI_ALLOW_UNSAFE` | `false` | 允许已知高影响命令 |
| `OBSIDIAN_CLI_EXTRA_COMMANDS` | 未设置 | 额外命令名,逗号分隔;`*` 表示允许全部合法命令名 |
同时设置默认和锁定 Vault 时,两者必须一致,否则 Server 拒绝启动。
### 推荐的受限配置
```text
OBSIDIAN_DEFAULT_VAULT=Dance
OBSIDIAN_LOCKED_VAULT=Dance
OBSIDIAN_CLI_ALLOW_UNSAFE=false
```
### 完全信任配置
```text
OBSIDIAN_DEFAULT_VAULT=Dance
OBSIDIAN_LOCKED_VAULT=Dance
OBSIDIAN_CLI_ALLOW_UNSAFE=true
OBSIDIAN_CLI_EXTRA_COMMANDS=*
```
完全信任配置允许 `delete`、`eval`、`command`、插件管理、发布、恢复、主题及开发者命令,但仍不会把输入交给操作系统 shell。`eval` 和插件命令本身仍可能对 Obsidian 应用或 Vault 产生广泛影响。
## 安全与并发模型
### 命令安全
- 使用 `spawn(executable, argv, { shell: false })`
- 校验命令、参数名和 flag 格式
- 默认使用安全命令白名单
- 高影响命令需要 `OBSIDIAN_CLI_ALLOW_UNSAFE=true`
- 未知或插件命令需要显式加入额外白名单,或设置 `OBSIDIAN_CLI_EXTRA_COMMANDS=*`
- 限制进程执行时间和输出大小
- 拒绝超过安全请求头大小的通用 CLI 调用;长正文必须使用 `obsidian_write_note`
### Vault 隔离
设置 `OBSIDIAN_LOCKED_VAULT` 后:
- 所有未指定 Vault 的命令自动使用锁定值
- 显式指定其他 Vault 会返回错误
- `obsidian_list type=vaults` 和通用 `vaults` 命令被禁用
Vault 锁定只约束通过本 Server 执行的命令。高权限的 Obsidian 应用级操作,例如插件安装或 `eval`,仍需由可信 Agent 使用。
### 并发保护
Windows `Obsidian.com` 通过 IPC 与 Obsidian 主进程通信。多个 CLI 进程同时发送消息可能导致主进程 JSON 边界损坏。
Server 使用两层保护:
1. 每个 MCP Server 内部的 FIFO Promise 队列。
2. 临时目录中的跨进程锁,并使用心跳与失效锁恢复。
因此 Claude Code、Codex 和并发 MCP 工具调用会依次访问 Obsidian CLI。直接在终端运行的 `obsidian` 命令不会经过此锁,Agent 工作期间不要在其他终端并行执行大量 CLI 命令。
## 故障排查
### Claude Code 显示 `No MCP servers configured`
检查:
1. Claude Code 是否从包含 `.mcp.json` 的项目根目录启动。
2. `.mcp.json` 是否为有效 JSON。
3. `env` 下所有值是否都是字符串。
4. 项目 MCP Server 是否已获准启用。
运行:
```powershell
claude mcp list
claude mcp get obsidian-cli
```
修改后重启 Claude Code。
### Obsidian 主进程出现 `Unexpected token ... is not valid JSON`
这表示 Windows CLI IPC 收到了损坏的 JSON 请求头。已确认的触发因素包括单次 `content=` 正文过大,以及多个 CLI 进程并行发送消息。当前 Server 会自动分块正文、限制通用请求大小并串行执行。
处理步骤:
1. 确认已使用包含 FIFO 和跨进程锁的最新构建。
2. 执行 `npm run build`。
3. 完全退出 Claude Code、Codex 和 Obsidian。
4. 先重新启动 Obsidian,再启动 Agent。
5. 不要从其他终端并行运行 Obsidian CLI。
Agent 不应在 MCP 写入失败后降级到系统 `Write` 或 shell;这会绕过 Obsidian 和 Skill 的数据流规则。
跨进程锁异常退出后会自动恢复失效锁。
### CLI 提示找不到 Obsidian
```text
The CLI is unable to find Obsidian.
```
确认:
- Obsidian 正在运行
- 安装器为 1.12.7+
- 命令行接口已重新启用
- MCP 进程与 Obsidian 运行在同一 Windows 用户和会话中
- `OBSIDIAN_CLI_COMMAND` 指向正确的 `Obsidian.com`
### 修改源码后行为没有变化
MCP 客户端运行的是 `dist/`,不是 `src/`。执行:
```powershell
npm run check
npm test
npm run build
```
然后重启 Claude Code/Codex 会话。
## 开发
```powershell
npm run dev
```
项目结构:
```text
src/
commands.ts 命令白名单、参数与 flag 构造
config.ts 环境变量解析和 Vault 锁定配置
content.ts UTF-8 安全正文分块
runner.ts 进程执行、FIFO 与跨进程锁
server.ts MCP 工具注册
index.ts stdio 入口
test/
commands.test.ts
config.test.ts
content.test.ts
runner.test.ts
server.test.ts
```
stdio 的标准输出专用于 MCP 协议;Server 日志只能写入标准错误。
## 验证
```powershell
npm run check
npm test
npm run build
```
当前测试覆盖:
- 参数构造与 shell 注入边界
- 安全、危险及通配命令权限
- Vault 锁定配置
- CLI 退出码、超时与输出限制
- 单进程及跨 Runner 串行执行
- MCP 工具发现
## 参考
- [Obsidian CLI 官方文档](https://help.obsidian.md/cli)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [Codex MCP 配置](https://developers.openai.com/codex/mcp)
- [Codex 自定义与项目 Skill](https://developers.openai.com/codex/concepts/customization)
TDQS
A3.5/5.0
Scored across 7 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: listing, reading, writing, searching, status, help, and a generic escape hatch. No overlap or ambiguity.
Naming Consistency5/5
All tools follow the consistent pattern 'obsidian_<action>' with snake_case, making it predictable for the agent.
Tool Count5/5
Seven tools is well-scoped for an Obsidian CLI wrapper, covering essential operations without being excessive or insufficient.
Completeness4/5
Covers core CRUD (read, write), search, list, status, and help. Missing explicit delete or rename, but the escape hatch fills gaps.
Maintenance
ActivityInactive
ResponsivenessNo issues