内容
# 无界面 Obsidian MCP 服务端
一个用于与 Obsidian 知识库交互的无界面 MCP(模型上下文协议)服务端。它赋予 AI 助手 Obsidian 的强大功能——全文搜索、链接图、标签和结构感知编辑——无需图形用户界面,使您的知识库成为一流的智能代理工具。
## 功能特点
- **搜索笔记**:使用 ripgrep 在 Obsidian 知识库中进行全文搜索
- **排名搜索**:BM25 排名全文搜索 - 优先显示最相关的笔记,并附有匹配的片段
- **读取笔记**:解析和提取笔记的内容、元数据和标签
- **列出笔记**:以轻量级标题发现知识库 - 为智能代理提供目录
- **列出文件**:发现非 Markdown 文件(附件、图像、PDF),可按文件夹和扩展名过滤
- **链接图**:解析 `[[wikilinks]]` 和反向链接以遍历相关笔记
- **标签索引**:聚合所有标签及其计数,并按标签检索笔记
- **相关笔记**:联想回忆 - 排名与给定笔记最相关的笔记(共享标签 + 链接图),无需嵌入
- **最近记录和元数据**:显示最近的笔记,按前置元数据过滤;读取笔记的前置元数据或获取整个知识库的统计数据
- **知识库卫生**:深入了解整个知识库的统计数据,查找孤立的笔记和损坏的 wikilinks
- **属性搜索**:发现知识库的前置元数据模式,列出属性的不同值,并按前置元数据条件查询笔记(`eq`、`ne`、`gt`、`gte`、`lt`、`lte`、`exists`、`contains`)
- **写入和编辑**(可选):创建、覆盖、追加、前置、删除笔记 - 默认禁用,需启用 `OBSIDIAN_ALLOW_WRITES`
- **结构感知编辑**:添加/删除标签,设置前置元数据,添加/删除/重命名前置元数据属性,添加/追加/替换章节,以及字面查找/替换补丁,无需重写整个笔记 - 节省智能代理令牌
- **前置元数据验证**:写入操作拒绝嵌套对象、非标量数组和字符串值中的 Markdown 语法,保持属性可查询和扁平
- **移动和重命名**:移动笔记(重写指向它们的 wikilinks)或任意附件文件
- **安全删除**:删除笔记默认移动到知识库的 `.trash`,因此可以恢复
- **Git 安全网**:可选地在每次写入之前将知识库快照到一个提交中(`OBSIDIAN_GIT_AUTOCOMMIT`)
- **跨平台**:支持 Windows、macOS 和 Linux
- **前置元数据支持**:提取 YAML 前置元数据为结构化元数据
- **标签提取**:自动识别和提取 Obsidian 标签
## 先决条件
- [Node.js](https://nodejs.org/) 18 或更新版本
- [ripgrep](https://github.com/BurntSushi/ripgrep)(`rg` 命令)
- 具有 Markdown 文件的 Obsidian 知识库
## 安装配置
1. 克隆或下载该项目
2. 安装依赖:
```bash
npm install
```
3. 编译 TypeScript 源代码:
```bash
npm run build
```
4. 设置 `OBSIDIAN_VAULT_PATH` 环境变量:
```bash
export OBSIDIAN_VAULT_PATH="/path/to/your/obsidian/vault"
```
5. 启动服务端:
```bash
# 使用 npm
npm start
# 使用 mise(如果已安装)
mise run start
```
## 开发
使用文件监听进行开发(使用 [tsx](https://github.com/privatenumber/tsx),无需构建步骤):
```bash
# 使用 npm
npm run dev
# 使用 mise
mise run dev
```
## 测试
运行自动化测试套件(使用 Node.js 内置的 `node:test` 运行器,通过 tsx - 无需额外依赖):
```bash
npm test
```
测试在临时目录中构建一个弃用夹具知识库,涵盖链接解析和反向链接、标签聚合和过滤、列表和最近记录、索引缓存失效和安全防护(路径遍历、模式限制)。
## 手动测试
您还可以使用包含的查询 CLI 工具来测试 MCP 服务端。它直接从 TypeScript 源代码运行,因此无需构建步骤:
```bash
# 搜索包含模式的笔记(默认为不区分大小写)
npm run query -- search "productivity"
# 区分大小写的搜索
npm run query -- search "TODO" --case-sensitive
# 仅搜索完整单词
npm run query -- search "test" --whole-word
# 多行搜索
npm run query -- search "pattern.*spans.*lines" --multiline
# 搜索并自定义上下文行数(默认为 5)
npm run query -- search "pattern" --context 10
# 搜索限定在文件夹、标签或前置元数据条件内
npm run query -- search "kubernetes" --tag work --match all
npm run query -- search "alpha" --where '{"status":"active"}'
# BM25 排名全文搜索(最相关的笔记优先)
npm run query -- search-ranked "kubernetes networking"
npm run query -- search-ranked "kubernetes networking" --limit 5
# 读取特定笔记(返回 { notes, errors } - 一个坏路径不会导致整个批次失败)
npm run query -- read "daily-notes/2024-01-15"
npm run query -- read "note1" "folder/note2"
# 列出笔记为轻量级标题(可选限定/限制)
npm run query -- list
npm run query -- list --folder projects --limit 20
# 显示笔记的 outbound 链接、未解析链接和反向链接
npm run query -- links "projects/alpha"
# 列出所有标签及其笔记数
npm run query -- tags
# 按标签查找笔记(默认为任意;--all 需要所有标签)
npm run query -- find-by-tag productivity
npm run query -- find-by-tag productivity project --all
# 列出最近的笔记(按修改时间或前置元数据日期字段)
npm run query -- recent --limit 10
npm run query -- recent --date-field updated --since 2024-01-01
# 查找与给定笔记最相关的笔记(排名,有原因)
npm run query -- related "projects/alpha"
npm run query -- related "projects/alpha" --limit 5
# 读取笔记的前置元数据或总结整个知识库
npm run query -- frontmatter "projects/alpha"
npm run query -- stats
# 知识库卫生:孤立的笔记和损坏的 wikilinks(从统计数据深入)
npm run query -- vault-issues orphans
npm run query -- vault-issues unresolved_links --limit 50
# 列出非 Markdown 文件(附件/图像),可选限定/过滤
npm run query -- files --folder assets --extension png
# 前置元数据模式、不同值和条件查询
npm run query -- properties
npm run query -- property-values status
npm run query -- query --where '{"status":"active","priority":{"gt":3}}'
npm run query -- get-property "projects/alpha" status
# 标题大纲和读取单个章节(索引支持的大纲;章节读取文件)
npm run query -- outline "projects/alpha"
npm run query -- read-section "projects/alpha" "Log"
npm run query -- read-section "projects/alpha" "Projects > Log" --include-subsections
# --- 写入 ---
# 创建笔记(内联、从文件或 stdin)
npm run query -- write "inbox/idea" "# Idea\n\nbody"
npm run query -- write "inbox/idea" --file draft.md --overwrite
# 追加或前置文本到笔记(前置插入在任何前置元数据之后)
npm run query -- append "daily/2026-07-22" "one more thing"
npm run query -- prepend "daily/2026-07-22" "> top banner"
# 标签和前置元数据(无需整个笔记重写)
npm run query -- add-tag "projects/alpha" project active
npm run query -- remove-tag "projects/alpha" stale
npm run query -- set-frontmatter "projects/alpha" --set status=done --unset draft
npm run query -- add-property-values "projects/alpha" aliases a2 a3
npm run query -- remove-property-values "projects/alpha" aliases a3
npm run query -- rename-property "projects/alpha" author authors
# 跨多笔记批量编辑前置元数据(一个 git 快照用于批次)
npm run query -- bulk-edit --select '{"where":{"status":"draft"}}' \
--operations '[{"op":"add_tag","tags":["review"]},{"op":"set_frontmatter","set":{"status":"active"}}]' --dry-run
# 章节(标题范围的编辑)
npm run query -- add-section "projects/alpha" "Next steps" "- ship it"
npm run query -- append-to-section "projects/alpha" "Log" "did a thing"
npm run query -- replace-section "projects/alpha" "Summary" "new summary"
# 移动/重命名笔记(重写指向它的 wikilinks)
npm run query -- move "projects/alpha" "archive/alpha"
npm run query -- move "projects/alpha" "archive/alpha" --no-update-links
# 移动任意文件(附件/图像);无需链接重写
npm run query -- move-file "assets/old.png" "assets/new.png"
# 笔记的字面查找/替换补丁
npm run query -- patch "projects/alpha" "old text" "new text"
npm run query -- patch "projects/alpha" "TODO" "DONE" --all
# 删除笔记(默认为安全删除;可恢复)
npm run query -- delete "inbox/idea"
npm run query -- delete "inbox/idea" --permanent
# 对于以 "-" 开头的內容(markdown 列表),通过 stdin 或 --file 传递
printf -- '- one\n- two' | npm run query -- add-section "projects/alpha" "Todo"
# 在写入前将知识库快照到 git 提交(参见配置)
OBSIDIAN_GIT_AUTOCOMMIT=1 npm run query -- add-tag "projects/alpha" review
# 使用详细模式查看发送的请求
npm run query -- --verbose search "pattern"
npm run query -- --verbose read "note1"
```
如果您使用 mise,相应的命令是 `mise run query -- search "productivity"` 等。
查询工具直接调用 MCP 服务端工具并返回原始 JSON 响应,使其适用于测试和调试。
## 工具
### 搜索笔记
使用 ripgrep 在知识库的 Markdown 文件中搜索。
**参数:**
- `pattern`(字符串,必填):ripgrep 的搜索模式(最大 1000 个字符)
- `case_sensitive`(布尔值,可选):区分大小写的搜索(默认:false)
- `whole_word`(布尔值,可选):仅匹配整个单词
- `multiline`(布尔值,可选):启用多行匹配
- `context_lines`(数字,可选):显示的上下文行数(默认:5,最大:100)
- `limit`(数字,可选):返回的最大文件数(默认:20,0 = 无限制 - 无硬上限)
- `max_matches_per_file`(数字,可选):每个文件返回的最大匹配数(默认:20,0 = 无限制)
- `folder`(字符串,可选):限制在该文件夹下的笔记(相对于知识库根目录)
- `tags`(数组,可选):限制包含这些标签的笔记(可选前缀 `#`)
- `match`(字符串,可选):`tags` 的语义 - `"any"`(默认)或 `"all"`
- `where`(对象,可选):限制笔记的前置元数据满足这些条件(与 `query_notes` 相同的语法)
**返回:** 一个对象,包含:
- `results`: 搜索结果数组,每个结果包含 `path`(相对路径,无 `.md` 扩展名)和 `matches`(行号 + 上下文)
- `truncated`: `true` 如果任何上限导致结果被截断
- `files_returned`: `results` 中的文件数
- `files_omitted`: 匹配的文件数超出 `limit` 且未返回
- `matches_capped_in`: 文件的路径,其匹配数被限制
当给定 `folder`/`tags`/`where` 时,首先从共享索引解析候选笔记,然后 ripgrep 只运行在这些文件上(适用于大知识库);匹配零笔记的过滤器返回空结果,不会调用 ripgrep。
### 排名搜索
基于 BM25 相关性的全文搜索 - 最相关的笔记优先,而不是每个字面匹配。补充 `search_notes`(字面/正则,不排名);它不会取代它。
**参数:**
- `query`(字符串,必填):自由文本查询(最大 1000 个字符)
- `limit`(数字,可选):结果的最大数量(默认:10,最大:100)
**返回:** 数组的笔记标题(与 `list_notes` 相同形状)扩展为:
- `score`: BM25 相关性得分(越高越相关)
- `snippet`: 一个短的匹配摘录
注意:tokenization 是 ASCII/English 导向的(小写,分成非字母数字字符,词干提取),因此非拉丁语脚本(例如 CJK)和重音字符在这里没有很好的索引 - 使用 `search_notes` 进行字面非 ASCII 匹配。
### 读取笔记
读取并解析知识库中的一个或多个笔记。
**参数:**
- `paths`(数组,必填):相对笔记路径数组(带或不带 `.md` 扩展名,最大 50)
**返回:** `{ notes, errors }`
- `notes`: 每个成功读取的笔记对象,每个笔记包含:
- `path`: 相对路径,无 `.md` 扩展名(与标题工具相同的标识符)
- `contents`: Markdown 正文(去除前置元数据;保留内联 `#tags`)
- `frontmatter`: 解析的前置元数据为 JSON 对象(与 `get_frontmatter` 相同)
- `tags`: 笔记的完整标签集 - 将前置元数据 `tags:` 与内联 `#tags` 统一
- `errors`: `[{ path, error }]` 对于无法读取的路径(丢失或太大) - 一个坏路径不再导致整个批次失败
路径遍历尝试仍然会错误整个调用;只有丢失/超大文件会单独报告每个路径的 `errors`。
### 列出笔记
列出知识库中的笔记为轻量级标题,无需完整内容。用于在搜索或读取之前发现存在的内容。
**参数:**
- `folder`(字符串,可选):限制在该文件夹下的笔记(相对于知识库根目录)
- `limit`(数字,可选):返回的最大笔记数
**返回:** 数组的笔记标题,包含 `path`、`title`(前置元数据标题或 basename)、`tags`、`headline`(第一个 Markdown 标题)、`size` 和 `modified`(ISO 时间戳)。
### 获取链接
解析笔记的 Obsidian 链接图。
**参数:**
- `path`(字符串,必填):相对笔记路径(带或不带 `.md` 扩展名)
**返回:** 一个对象,包含:
- `note`: 检查笔记的规范路径
- `outbound_links`: 解析的 `[[wikilinks]]`,每个包含原始 `target` 和解析的 `path`
- `unresolved_links`: wikilink 目标无法解析为笔记
- `backlinks`: 笔记在知识库其他地方的链接
处理 `[[note]]`、`[[note|alias]]`、`[[note#heading]]` 和 `![[embeds]]`;链接通过相对路径或 basename 解析。
### 获取大纲
笔记的标题结构 - 大纲。关闭“检查存在哪些章节,然后编辑正确的循环”而无需读取整个笔记。索引支持(无需读取文件)。
**参数:**
- `path`(字符串,必填):相对笔记路径(带或不带 `.md` 扩展名)
**返回:** `{ path, outline }`,其中每个大纲条目为 `{ heading, level, path, line, ambiguous }`。`path` 是完整的 `" > "`-joined 标题路径(例如 `Projects > Log`)- 区分歧义地址;`line` 为 1-based;`ambiguous` 为 `true` 当裸标题文本在笔记中重复。
### 获取保险库统计信息
通过一次调用汇总整个保险库,完全基于共享索引。
**参数:** 无
**返回:** `{ notes, total_size_bytes, distinct_tags, tag_assignments, tagged_notes, untagged_notes, resolved_links, unresolved_links, notes_with_links, orphan_notes, last_modified, first_modified }`。`orphan_notes` 统计既没有输入也没有输出已解析链接的笔记;时间范围是 ISO 时间戳(空保险库为 `null`)。
### 列出保险库问题
索引已经知道的保险库卫生检查结果,但 `get_vault_stats` 只统计 - 从统计数据到实际行的深入分析。
**参数:**
- `kind`(字符串,必填):`"orphans"` 或 `"unresolved_links"`
- `limit`(数字,可选):返回的行数/标题的上限
**返回:** 形状取决于 `kind`:
- `"orphans"`:笔记标题数组(与 `list_notes` 相同)- 没有输入和输出已解析链接的笔记(与 `get_vault_stats` 的 `orphan_notes` 后的谓词相同)
- `"unresolved_links"`:按源笔记分组的 `{ source, targets }` 数组 - `targets` 是该笔记中解析为无的原始 wikilink 目标
`orphans` 数组长度等于 `get_vault_stats` 的 `orphan_notes`;`unresolved_links` 下的每个 `targets` 长度之和等于 `get_vault_stats` 的 `unresolved_links` 计数(在应用 `limit` 之前)。索引支持。
### 列出文件
列出保险库中的非 markdown 文件(附件、图像、PDF)- 与 `list_notes` 相反,适用于它故意排除的所有文件。
**参数:**
- `folder`(字符串,可选):限制在该文件夹下的文件(相对于保险库根目录)
- `extension`(字符串,可选):按扩展名过滤,领先点可选且不区分大小写(例如 `png` 或 `.PNG`)
- `limit`(数字,可选):返回的最大文件数
**返回:** `{ path, size, modified, extension }` 数组 - `path` 是保留扩展名的相对于保险库的路径,`modified` 是 ISO 时间戳,`extension` 是小写且无点的。永远不会返回 markdown 文件;不涉及保险库索引。
### 列出属性
保险库的前面物质模式 - 使用中的每个属性键及其使用笔记数量和取值类型。类似于 `list_tags` 但适用于任意属性。
**参数:**
- `include_tags`(布尔值,可选):包括 `tags` 键(默认值:`true`;设为 `false` 因为它已经被 `list_tags` 覆盖)
**返回:** `{ key, count, types }` 数组,其中 `types` 是观察到的不同值类型(`string`/`number`/`boolean`/`array`/`null`/`date`),按 `count` 降序排列然后是 `key`。
### 获取属性值
一个前面物质属性的独特值,以及每个笔记的计数 - 一个键在整个保险库中取值的分面分解。
**参数:**
- `key`(字符串,必填):属性键
- `limit`(数字,可选):返回的最大值数
**返回:** `{ key, values: [{ value, count }] }`,按 `count` 降序排列。数组值属性对每个元素进行一次计数。
### 查询笔记
根据前面物质条件查找笔记 - 将 `list_recent_notes` 中的 `where` 过滤器推广为其自己的工具。
**参数:**
- `where`(对象,必填):`key -> condition` 映射。条件是裸标量(相等性/数组成员)或运算符对象 `{ eq, ne, gt, gte, lt, lte, exists, contains }`
- `match`(字符串,可选):`"all"`(默认值)或 `"any"`
- `limit`(数字,可选):返回的最大笔记数
比较是类型感知的:当两边都解析为数字时为数字,当两边都解析为日期时为时间顺序,否则为不区分大小写的字符串比较。
**返回:** 笔记标题数组(与 `list_notes` 相同)。
### 获取属性
从一个笔记中读取一个前面物质属性 - 比读取整个笔记或其完整前面物质更便宜。
**参数:**
- `path`(字符串,必填):相对笔记路径(可以带或不带 `.md` 扩展名)
- `key`(字符串,必填):属性键
**返回:** `{ path, key, value, present }` 其中 `present` 区分一个缺失的键和一个显式设置为 `null` 的键。
### 写笔记
创建笔记或覆盖现有的笔记。
**参数:**
- `path`(字符串,必填):相对笔记路径(可以带或不带 `.md` 扩展名)
- `content`(字符串,必填):完整的笔记内容(可能包括前面物质)
- `overwrite`(布尔值,可选):允许替换现有的笔记(默认值:`false` - 拒绝覆盖)
**返回:** `{ path, created }`
### 追加笔记
在笔记末尾追加文本。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `content`(字符串,必填):要追加的文本
- `create`(布尔值,可选):如果笔记不存在则创建(默认值:`false`)
**返回:** `{ path, created }`
### 在笔记开头插入
在笔记正文开头插入文本。任何前面物质块都保留,文本插入在其后(而非之前 YAML 分隔符之前)。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `content`(字符串,必填):要插入的文本
- `create`(布尔值,可选):如果笔记不存在则创建(默认值:`false`)
**返回:** `{ path, created }`
### 删除笔记
删除笔记。**默认情况下安全进入回收站:** 笔记被移动到保险库的 `.trash` 文件夹(Obsidian 的约定,被索引忽略),因此删除是可恢复的;重复进入回收站的相同名称会获得数字后缀。如果笔记不存在,则会出错。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `permanent`(布尔值,可选):直接取消链接文件而不是进入回收站(默认值:`false`)
**返回:** `{ path, deleted, trashed, trash_path?, dangled_backlinks }` - `dangled_backlinks` 列出链接到已删除笔记的笔记,并在现在有一个损坏的 `[[wikilink]]`(仅报告;这些笔记不会被修改)。
### 移动笔记
移动或重命名笔记。默认情况下,保险库中所有指向旧位置的 `[[wikilink]]` 都会被重写为新位置 - 完整路径链接变为新完整路径,裸basename 链接变为新basename,别名和 `#anchors` 保留 - 因此链接图永远不会被破坏。
**参数:**
- `from`(字符串,必填):当前相对笔记路径(可以带或不带 `.md`)
- `to`(字符串,必填):新的相对笔记路径
- `overwrite`(布尔值,可选):允许替换目标位置现有的笔记(默认值:`false`)
- `update_links`(布尔值,可选):重写指向该笔记的 wikilinks(默认值:`true`)
**返回:** `{ from, to, overwritten, updated_notes, updated_links }`
### 移动文件
移动或重命名任意文件(附件、图像或通过字面路径引用的笔记)。字面处理路径 - 不追加 `.md` 且不重写 wikilinks。
**参数:**
- `from`(字符串,必填):当前相对文件路径(带扩展名)
- `to`(字符串,必填):新的相对文件路径(带扩展名)
- `overwrite`(布尔值,可选):允许替换目标位置现有的文件(默认值:`false`)
**返回:** `{ from, to, overwritten }`
### 修补笔记
对笔记的原始文本应用字面查找/替换补丁。匹配是精确字符串(永远不是正则表达式 - 没有注入或灾难性回溯风险)。如果要查找的文本不存在,则会出错,因此过时的补丁会大声失败而不是默默地什么也不做。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `find`(字符串,必填):要查找的精确字面文本
- `replace`(字符串,必填):替换文本
- `all`(布尔值,可选):替换每个出现而不是仅第一个(默认值:`false`)
`all` 为假时,如果 `find` 出现多次,则会出错(报告计数)而不是默默修补第一个 - 设置 `all: true` 以替换每个出现,或缩小 `find` 直到它唯一。
**返回:** `{ path, replacements }`
### 添加/删除标签
在笔记的前面物质中添加或删除标签,而不重写笔记。添加是幂等的;存储规范为 `tags:` 数组。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `tags`(数组,必填):要添加/删除的标签(可以带或不带前导 `#`)
**返回:** `{ path, tags }` - 结果标签列表。
### 设置前面物质
设置和/或取消前面物质字段,同时保持正文不变。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `set`(对象,可选):要设置的字段,例如 `{ "status": "done" }`
- `unset`(数组,可选):要删除的前面物质键
**返回:** `{ path, changed }`
### 添加/删除属性值
在数组值前面物质属性中添加或删除值,而不重写整个笔记。添加是幂等的(无重复);不存在的键被创建为新数组,存在的标量被提升为 `[old, ...new]`。删除数组并在没有任何值后完全删除键。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `key`(字符串,必填):属性键
- `values`(数组,必填):要添加/删除的值
**返回:** `{ path, key, values }` - 结果列表。
### 重命名属性
在原位重命名前面物质键,保留其值及其在 YAML 中的位置。如果 `from` 不存在或 `to` 已经存在,则会出错。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `from`(字符串,必填):现有的属性键
- `to`(字符串,必填):新的属性键
**返回:** `{ path, from, to }`
### 添加章节
插入新的标题 + 内容。默认情况下追加到末尾,或在名为 `after` 的章节之后。 如果在同一级别出现重复的标题,则会出错。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `heading`(字符串,必填):标题文本(无前导 `#`)
- `content`(字符串,必填):新章节的正文
- `level`(数字,可选):标题级别 1-6(默认值:2)
- `after`(字符串,可选):在插入后 - 一个裸标题或一个 `" > "`-连接的标题路径,以与 `append_to_section` 相同的失败大声方案解析
**返回:** `{ path, heading }`
### 追加到章节
在现有标题下追加文本,在下一个标题之前(留下笔记的其余部分不变)。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `heading`(字符串,必填):要追加到的章节 - 一个裸标题或一个 `" > "`-连接的标题路径(例如 `Projects > Log`)
- `content`(字符串,必填):要追加的文本
- `create`(布尔值,可选):如果缺少章节则创建(默认值:`false`)
**返回:** `{ path, heading }`
### 替换章节
替换现有标题下的正文(保留标题行)。如果章节不存在,则会出错。
**参数:**
- `path`(字符串,必填):相对笔记路径
- `heading`(字符串,必填):要替换的章节 - 一个裸标题或一个 `" > "`-连接的标题路径,以与 `append_to_section` 相同的失败大声方案解析
- `content`(字符串,必填):新的正文
**返回:** `{ path, heading }`
### 批量编辑
对许多笔记应用一个或多个前面物质突变,在单个 git 快照下,具有每个笔记的结果报告。 将“标记这 30 个笔记”从 30 次往返(和 30 次自动快照提交)变成一次。
**参数:**
- `select`(对象,必填):要么 `paths`(显式笔记路径数组)**或** 过滤器 - `where`(类似 `query_notes` 的条件对象)和/或 `tags`(类似 `find_by_tag`),可选地限定在 `folder` 下并通过 `match` 组合(默认为 `"all"` 或 `"any"`),另外还有一个可选的 `limit`。必须提供 `paths` 或过滤器表单中的一个 - 提供两者会出错,提供两者都不会出错。
- `operations`(数组,必填):按顺序的非空前面物质变异列表应用于每个匹配的笔记(例如 `rename_property` 然后 `set_frontmatter` 在新键上,一次通过)。 支持的操作:`add_tag`、`remove_tag`、`set_frontmatter`、`add_property_values`、`remove_property_values`、`rename_property` - 与单个笔记工具形状相同。 没有章节/正文操作。
- `dry_run`(布尔值,可选):预览匹配的笔记和操作,零写入且无 git 快照。此预览仅预览选择和操作形状 - 它不解析笔记或预测每个笔记的应用结果,因此一个将提交失败的笔记(例如 `rename_property` 到现有键)仍会显示在 dry-run 匹配集中。
- `expected_count`(数字,可选):如果解析的匹配计数不同,则在任何快照或写入之前中止 - 防止过滤器在代理的预览和提交之间漂移。
**返回:** `{ dry_run, matched_count, applied_count, failed_count, results }`,其中每个 `results` 条目是 `{ path, ok: true, changed }` 或 `{ path, ok: false, error }`。每个笔记的失败是隔离和报告的;它永远不会影响其余的批次。`changed: false` 标记一个笔记,其操作都是无操作。单个 git 快照涵盖整个批次,而不是每个笔记。
> **正文 vs. 前面物质忠实度:** 章节编辑保留前面物质块字节为字节;前面物质编辑(标签,字段)以规范形式序列化 YAML(块样式列表),但留下正文不变。 封闭代码块内的标题被忽略。 所有写入路径遍历保护。
> **验证:** 每个前面物质写入拒绝嵌套对象/映射,包含非标量元素的数组和字符串值中的 markdown 语法(允许裸 URL)。 验证仅在给定写入实际触摸的键上进行,因此未受影响的键的现有违规永远不会阻止无关的编辑。
## 示例用法
连接 MCP 客户端后,您可以:
```javascript
// 搜索包含“productivity”的笔记(默认为 20 个文件,每个文件 20 个匹配)
await search_notes({
pattern: "productivity",
case_sensitive: false,
limit: 20, // 0 为无限
max_matches_per_file: 20
});
// 读取特定笔记
await read_notes({
paths: ["daily-notes/2024-01-15", "projects/my-project"]
});
// 定位:列出文件夹下的笔记
await list_notes({ folder: "projects", limit: 20 });
// 遍历:跟随链接图
await get_links({ path: "projects/my-project" });
// 回忆:什么与此笔记相关?
await get_related_notes({ path: "projects/my-project", limit: 5 });
// 检索:标记为 #project 和 #active 的笔记
await find_by_tag({ tags: ["project", "active"], match: "all" });
// 保持当前:仅限活动笔记
await list_recent_notes({ limit: 10, where: { status: "active" } });
// 创建笔记(不会覆盖,除非 overwrite: true)
await write_note({ path: "inbox/idea", content: "# Idea\n\nbody" });
// 外科编辑 - 整个笔记重写
await add_tag({ path: "projects/alpha", tags: ["review"] });
await set_frontmatter({ path: "projects/alpha", set: { status: "done" } });
await append_to_section({ path: "projects/alpha", heading: "Log", content: "shipped" });
// 批量前面物质编辑跨多个笔记,一个 git 快照
await bulk_edit({
select: { where: { status: "draft" } },
operations: [
{ op: "add_tag", tags: ["review"] },
{ op: "set_frontmatter", set: { status: "active" } }
},
dry_run: true
});
```
## 克劳德桌面集成
要将此MCP服务器与克劳德桌面一起使用,首先需要构建项目(`npm install && npm run build`),然后将其添加到克劳德配置文件中:
**macOS/Linux**: `~/.config/claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"obsidian": {
"command": "node",
"args": ["/path/to/headless-obsidian-mcp/dist/index.js"],
"env": {
"OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault"
}
}
}
}
```
**使用启动脚本(在首次运行时自动安装和构建):**
```json
{
"mcpServers": {
"obsidian": {
"command": "/path/to/headless-obsidian-mcp/start-server.sh",
"env": {
"OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault"
}
}
}
}
```
这使用包含的 `start-server.sh` 脚本,该脚本会切换到项目目录,安装依赖项并在需要时构建,然后运行 `node dist/index.js`。
将路径替换为:
- `/path/to/headless-obsidian-mcp`: 该项目目录的绝对路径
- `/path/to/your/obsidian/vault`: 您的Obsidian保险库的绝对路径
要允许代理修改您的保险库,请在上面的 `env` 块中添加 `"OBSIDIAN_ALLOW_WRITES": "1"`。要在此写入之前将保险库快照到git提交,请添加 `"OBSIDIAN_GIT_AUTOCOMMIT": "1"`。
更新配置后,重启克劳德桌面。服务器将显示为"obsidian"并提供读取工具(`search_notes`、`search_notes_ranked`、`read_notes`、`list_notes`、`get_links`、`get_outline`、`read_section`、`list_tags`、`find_by_tag`、`list_recent_notes`、`get_related_notes`、`get_frontmatter`、`get_vault_stats`、`list_vault_issues`、`list_files`、`list_properties`、`get_property_values`、`query_notes`、`get_property`)。启用 `OBSIDIAN_ALLOW_WRITES` 后,它还提供写入工具(`write_note`、`append_note`、`prepend_note`、`delete_note`、`move_note`、`move_file`、`patch_note`、`add_tag`、`remove_tag`、`set_frontmatter`、`add_property_values`、`remove_property_values`、`rename_property`、`add_section`、`append_to_section`、`replace_section`、`bulk_edit`)。
## 致谢
该项目最初是Boaz Yaniv的 [notes-mcp](https://github.com/boazy/notes-mcp) 的Node.js移植版,并且在此基础上扩展了知识库、结构感知编辑和保险库管理工具。原始代码使用MIT许可证;该许可证和版权在 [LICENSE](LICENSE) 中保留。
同时感谢 [mcpvault](https://github.com/bitbonsai/mcpvault) by bitbonsai,其Obsidian MCP服务器在塑造该项目的工具表面时是一个有用的参考。
## 许可证
在 [MIT License](LICENSE) 下发布。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器