关于 Obsidian MCP Server
Obsidian MCP Server 是面向 AI Agent 和开发工具的 Go 服务,可直接读写 Obsidian vault 文件,无需运行 Obsidian。它还提供搜索、链接分析及安全编辑能力。
主要功能
- 01读写笔记与目录
- 02解析并更新 YAML 属性
- 03标签管理与反向链接
- 04全文、正则和路径搜索
- 05安全移动、删除与补丁编辑
- 06审计笔记并查看 vault 统计
适用场景
- 01在 AI 工作流中检索和编辑 vault 笔记
- 02批量整理标签、属性和笔记链接
- 03检查孤立笔记、断链及重复标题
MCP 相关
通过 MCP 工具、提示词和只读资源向客户端提供 vault 内容操作与数据;支持 Stdio 和可选的 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
obsidian-mcp-server
一个面向 Obsidian 知识库的 Go Model Context Protocol(MCP)服务。它让 AI Agent 和开发工具可以直接访问知识库文件系统,无需运行 Obsidian 实例。
功能
- 读取、写入和列出笔记与目录,通过 MCP 工具完成
- Frontmatter — 解析并更新 YAML frontmatter,同时保留原有格式
- 标签 — 提取行内
#tags、汇总整个知识库的标签数量,以及添加/移除标签 - 反向链接 — 按需生成反向链接图(wikilinks 和 Markdown 链接)
- 修改操作 — 以标题为锚点进行补丁、安全删除,以及带确认保护的移动
- 全文搜索 — 基于 BM25 Okapi 排序的搜索,并提供匹配片段
- 正则表达式/Glob 搜索 — 使用 RE2 正则表达式或文件路径 Glob 搜索路径和内容
- 路径安全 — 四层验证:词法检查、忽略项/扩展名筛选、不区分大小写的存在性查找,以及防止符号链接逃逸
- Stdio 传输 — 适用于任何 MCP 客户端(Claude Code、Claude Desktop 等)
- Streamable HTTP 传输(可选)— 默认使用 TLS 1.3 和 Bearer 令牌身份验证,仅监听环回地址,除非明确扩大范围;请参阅配置中的
--transport http和SECURITY.md§ HTTP transport - 不依赖 Obsidian — 直接操作知识库目录
- 令牌计数 — 响应包含近似令牌数量(cl100k_base)
MCP 工具
| 工具 | 描述 | 参数 |
|---|---|---|
read_note | 读取笔记内容和元数据 | path(必填),prettyPrint — 响应包含 etag |
write_note | 创建或更新笔记 | path、content(必填),mode:overwrite/append/prepend,if_match(可选 etag) |
list_directory | 列出文件和子目录 | path(为空 = 知识库根目录),prettyPrint |
get_frontmatter | 读取笔记的 YAML frontmatter | path(必填),prettyPrint |
update_frontmatter | 设置或移除 frontmatter 键(保留格式) | path(必填),updates(JSON 对象),removeKeys(JSON 数组),if_match(可选 etag) |
manage_tags | 为笔记添加或移除标签 | path、action:add/remove(必填),tag(必填),location:frontmatter/inline,if_match(可选 etag) |
list_all_tags | 汇总整个知识库中的所有标签及其数量 | prettyPrint |
get_backlinks | 查找所有链接到目标笔记的笔记 | path(必填),prettyPrint |
patch_note | 对笔记应用以标题为锚点的补丁 | path、heading、position:before/after/replace_body、content(均必填),if_match(可选 etag) |
delete_note | 将笔记移至 .obsidian-mcp/trash(需要确认);传入 permanent: true 可直接永久删除 | path、confirm(必须与 path 完全匹配)、permanent(可选,默认 false)、if_match(可选 etag) |
move_note | 在知识库内移动或重命名笔记(需要确认);默认会重写明确无歧义的入站链接 | src、dst、confirm(必须与 src 完全匹配)、updateLinks(bool,默认 true)、dryRun(bool,默认 false)、if_match(可选 etag;dryRun 为 true 时忽略) |
search_notes | 使用 BM25 进行全文搜索,返回按相关度排序的结果和匹配片段 | query(必填)、limit、maxMatchesPerFile、caseSensitive、searchContent、searchFrontmatter、pathScope、prettyPrint |
search_regex | 使用 RE2 正则表达式或 glob 模式进行搜索 | pattern(必填)、isGlob、scope、limit、maxMatchesPerFile、prettyPrint |
read_multiple_notes | 在单个请求中读取多篇笔记的内容 | paths(必填,JSON 数组)、summary(bool,默认 false)、headChars(int,默认 200)— 每个条目都包含 etag |
get_notes_info | 获取多篇笔记的元数据,而不读取完整内容 | paths(必填,JSON 数组)— 每个条目都包含 etag |
get_vault_stats | 获取整个知识库的汇总统计数据 | includeTokenCounts(bool,默认 false) |
get_periodic_note | 获取周期笔记(日、周、月、季度或年) | granularity(必填,枚举:daily/weekly/monthly/quarterly/yearly)、offset(int,默认 0)、createIfMissing(bool,默认 false) |
get_recent_periodic_notes | 获取最近的 N 篇周期笔记 | granularity(必填,枚举:daily/weekly/monthly/quarterly/yearly)、count(int,默认 5)、summary(bool,默认 true) |
get_recent_changes | 列出知识库中最近修改的笔记 | limit(int,默认 10)、since(string,ISO-8601)、summary(bool,默认 true) |
audit_notes | 检查知识库的维护问题:孤立笔记、失效链接、未添加标签的笔记、标题重复 | classes(JSON 数组:orphans/dangling-links/untagged/duplicate-titles,默认全部)、limit(每类 int,默认 20) |
get_note_outline | 返回笔记的标题树(级别、文本、行号),不包含正文 | path(必填),prettyPrint |
read_note_lines | 读取笔记中指定范围的行 | path、startLine(必填)、lineCount(int,默认 200,上限 2000) |
rename_tag | 在整个知识库的 frontmatter 和行内标签中重命名标签 | oldTag、newTag(均必填) |
replace_in_note | 在单篇笔记范围内执行限定搜索和替换,支持字面匹配或正则表达式 | path、pattern、replacement(均必填)、isRegex(bool,默认 false)、maxOccurrences(int,默认 0 = 不限) |
search_notes、search_regex、list_directory 和 get_recent_changes 的结果还会为每篇笔记包含一个 obsidian://open deepLink 字段,该字段根据 --vault-name 构建(见下文的配置)。 |
说明
patch_note 语义:position 控制 content 相对于标题的插入位置:
before— 直接插入到标题行之前after— 插入到标题正文之后(位于下一个同级或更高级标题之前)replace_body— 替换标题行与下一个同级标题之间的所有内容
search_notes 参数:
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | 字符串 | 必填 | 搜索查询。多词查询使用 OR 逻辑;完整短语会获得额外加分。 |
limit | 整数 | 20 | 结果数量上限 |
maxMatchesPerFile | 整数 | 3 | 每个结果的匹配摘要数量上限 |
caseSensitive | 布尔值 | false | 区分大小写匹配 |
searchContent | 布尔值 | true | 将笔记正文纳入评分 |
searchFrontmatter | 布尔值 | true | 将 frontmatter 值纳入评分 |
pathScope | 字符串 | — | 用于限制搜索范围的 Glob 模式(例如 Daily Notes/*) |
prettyPrint | 布尔值 | false | 使用缩进格式化 JSON |
返回:{ query, results: [{ path, score, matchCount, matches: [{line, snippet, term}], tokenCount, reason }], total }
search_regex 参数:
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
pattern | 字符串 | 必填 | RE2 正则表达式或 Glob 模式 |
isGlob | 布尔值 | false | 将模式视为文件路径 Glob(** 可跨目录匹配) |
scope | 字符串 | content | path、content 或 both |
limit | 整数 | 20 | 结果数量上限 |
maxMatchesPerFile | 整数 | 5 | 每个结果的匹配摘要数量上限 |
prettyPrint | 布尔值 | false | 使用缩进格式化 JSON |
返回:{ pattern, scope, results: [{ path, matches: [{line, snippet}] }], total }
批处理工具(read_multiple_notes、get_notes_info):paths 参数是一个 JSON 数组字符串,例如 '["Notes/foo.md","Notes/bar.md"]'。summary:true 会返回 headOf(从 headChars 开始的前 N 个字符,默认值为 200),而不是完整内容;这对于较大的笔记很有用,可以避免超出上下文限制。这两个工具都受 --max-batch 限制(默认值为 10);路径数量超出限制的请求会被静默截断,响应中会包含 "truncated": true。
乐观并发控制(if_match / etag):read_note、read_multiple_notes 和 get_notes_info 会返回笔记内容的 SHA-256 etag。将该值作为 if_match 传入 write_note、patch_note、update_frontmatter、manage_tags、delete_note 或 move_note,即可让写入变为有条件写入——如果笔记在读取后发生了更改,调用会失败并返回 REVISION_CONFLICT 错误,而不会静默覆盖其他人的编辑。所有工具中的 if_match 都是可选的;省略时会像以前一样无条件写入。有两个特殊情况:对尚不存在的笔记传入 if_match 总会导致冲突(不会创建该笔记);move_note 的 dryRun:true 预览不会检查 if_match。
周期笔记(get_periodic_note、get_recent_periodic_notes):配置(各粒度对应的文件夹和日期格式)从知识库中的 .obsidian/plugins/periodic-notes/data.json 读取。如果该文件不存在,则使用内置默认值:每日笔记使用 Daily Notes/ 中的 YYYY-MM-DD,每周笔记使用 Weekly Notes/ 中的 gggg-[W]ww,以此类推。offset=0 对应当前周期,offset=-1 对应上一个周期(昨天、上周等),offset=+1 对应下一个周期。若解析出的路径下尚无笔记,createIfMissing=true 会创建一篇空笔记。
get_vault_stats:返回 noteCount、totalBytes、totalLinks、totalTags、topTags(按数量排序的前 20 个)、oldestNote、newestNote 和 vaultRoot。设置 includeTokenCounts:true 会对每篇笔记进行令牌计数;对于大型知识库,这项操作开销较大,默认禁用。
audit_notes 类别:
orphans— 没有标签,且没有传入的 wikilink 或 Markdown 链接的笔记(完全孤立的笔记)dangling-links— 含有指向不存在的知识库路径的链接的笔记(失效引用)untagged— 没有 frontmatter 标签,也没有行内#tags的笔记duplicate-titles— 多篇笔记具有相同的文件名主体,导致 wikilink 歧义
每类结果最多包含 limit 条(默认 20 条)。结果被截断时,响应会包含 "truncated": true。
MCP 提示词
提示词是由服务端定义的对话开场内容,宿主(Claude Code、Claude Desktop)会在其界面中显示。每个提示词都会提取实时知识库数据,并构造一条可直接用于大模型的消息。
| 提示词 | 描述 | 参数 |
|---|---|---|
summarize_note | 总结一篇笔记:3 条要点、实体、未决问题 | path(必需) |
daily_note_review | 审阅一篇日记:待处理 TODO、链接建议、缺失的标签 | offset(整数,默认 0) |
weekly_review | 基于最近 7 篇日记进行每周回顾 | weekOffset(整数,默认 0) |
find_related | 按关联类型分组,建议值得建立链接的相关笔记 | path(必需) |
vault_health_check | 审查孤立笔记、失效链接、无标签笔记和重复标题;确定修复优先级 | (无) |
可在宿主的提示词选择器中调用提示词(例如,在 Claude Code 中输入 /)。它们不会修改知识库。
MCP 资源
资源是只读的知识库数据,宿主可直接将其附加到对话上下文窗口中,无需显式调用工具。
| 资源 / 模板 | URI | MIME | 描述 |
|---|---|---|---|
| 知识库统计 | obsidian://vault/stats | application/json | 笔记数量、总大小、前 10 个标签、知识库根目录 |
| 标签索引 | obsidian://vault/tags | application/json | 所有标签及其笔记数量,按频率排序 |
| 笔记内容 | obsidian://note/{path} | text/markdown | 任意知识库笔记的原始 Markdown(frontmatter + 正文) |
| 周期性笔记 | obsidian://periodic/{granularity} | text/markdown | 当前的日 / 周 / 月 / 季 / 年度笔记 |
| 反向链接 | obsidian://backlinks/{path} | application/json | 所有链接到目标笔记的笔记,附带行号和片段 |
静态资源(obsidian://vault/*)始终可在资源选择器中使用。宿主读取模板资源时才会解析它们;如果笔记不存在,资源会返回说明性空正文,而不是错误。
安装
安装脚本
下载适用于你的操作系统和架构的二进制文件,验证其校验和,并将其安装到
~/.local/bin(可通过第二个参数覆盖):
curl -fsSL https://raw.githubusercontent.com/tylern91/obsidian-mcp-server/main/install.sh | sh
固定指定版本,而不是使用 latest:
curl -fsSL https://raw.githubusercontent.com/tylern91/obsidian-mcp-server/main/install.sh | sh -s -- v0.2.0
Claude Desktop(.mcpb bundle)
从最新发布版本下载 obsidian-mcp-<version>.mcpb,然后双击即可 — Claude Desktop 会安装扩展并提示输入知识库路径。无需手动编辑 JSON。
发布版二进制文件
从最新发布版本下载预构建的二进制文件,验证其校验和,然后安装:
# macOS (Apple Silicon) — swap the asset name for your platform (darwin-amd64, linux-amd64, linux-arm64)
curl -fLO https://github.com/tylern91/obsidian-mcp-server/releases/latest/download/obsidian-mcp-<version>-darwin-arm64.tar.gz
curl -fLO https://github.com/tylern91/obsidian-mcp-server/releases/latest/download/obsidian-mcp-<version>-darwin-arm64.tar.gz.sha256
shasum -a 256 -c obsidian-mcp-<version>-darwin-arm64.tar.gz.sha256
tar -xf obsidian-mcp-<version>-darwin-arm64.tar.gz
install -m 0755 obsidian-mcp-<version>-darwin-arm64/obsidian-mcp ~/.local/bin/obsidian-mcp
Homebrew(macOS/Linux)
brew tap tylern91/obsidian-mcp
brew install obsidian-mcp
go install
需要 Go 1.27+ 才能从源代码构建。在较旧版本的 Go 上使用 GOTOOLCHAIN=local 构建,需要先升级 Go — GOTOOLCHAIN=auto(自 Go 1.21 起为默认值)会自动下载匹配的工具链。
go install github.com/tylern91/obsidian-mcp-server/cmd/obsidian-mcp@latest
从源代码构建
需要 Go 1.27+。在较旧的 Go 版本上使用 GOTOOLCHAIN=local 构建,需要先升级 Go;GOTOOLCHAIN=auto(自 Go 1.21 起的默认值)会自动下载匹配的工具链。
git clone https://github.com/tylern91/obsidian-mcp-server.git
cd obsidian-mcp-server
make build
使用
Claude Code
claude mcp add obsidian -s user \
-e OBSIDIAN_VAULT_PATH="/path/to/your/vault" \
-- obsidian-mcp
Claude Desktop
添加到 claude_desktop_config.json:
{
"mcpServers": {
"obsidian": {
"command": "obsidian-mcp",
"args": ["--vault", "/path/to/your/vault"],
"env": {}
}
}
}
Cursor
安装后编辑知识库路径——深层链接无法预先获知该路径。
VS Code
安装后编辑知识库路径——深层链接无法预先获知该路径。
直接运行
obsidian-mcp --vault /path/to/your/vault
打印版本并退出:
obsidian-mcp --version
配置
配置遵循 CLI 标志 > 环境变量 > 默认值 的优先级。
| 标志 | 环境变量 | 默认值 | 有效值 |
|---|---|---|---|
--vault | OBSIDIAN_VAULT_PATH | (必填) | 已存在目录的绝对路径或相对路径。启动时会进行验证——路径不存在或指向文件(而非目录)时会立即报错。会去除首尾空白。 |
--version | — | — | 将二进制文件的版本打印到 stdout 并退出。无需指定 --vault。 |
--extensions | OBSIDIAN_EXTENSIONS | .md,.markdown,.txt,.canvas | 以逗号分隔的列表。每个条目都应以 . 开头(例如 .md)。会去除条目首尾的空白,并丢弃空条目。只有匹配这些扩展名之一的文件才会显示给 MCP 工具。 |
--ignore | OBSIDIAN_IGNORE | .obsidian,.git,node_modules,.DS_Store,.trash | 以逗号分隔的文件名或目录名列表,遍历时会跳过这些名称。按名称匹配(不使用 glob)。会去除首尾空白,并丢弃空条目。 |
--pretty | OBSIDIAN_PRETTY | false | CLI:单独使用 --pretty 即可启用。环境变量:接受 Go 的 strconv.ParseBool 可解析的任何值——1、t、T、true、TRUE、True、0、f、F、false、FALSE、False。其他任何值都会导致启动错误。 |
--max-batch | OBSIDIAN_MAX_BATCH | 10 | 整数 ≥ 1。非整数或 <1 会导致启动错误。限制单次批处理工具调用(Phase 4)可处理的文件数量。较大的值会增加内存用量和每次响应的 token 数量——批次过大可能会超出 AI 客户端的上下文窗口,并拖慢单次工具调用。除非知识库中的文件较小,否则请将此值保持在默认值或接近默认值。 |
--max-results | OBSIDIAN_MAX_RESULTS | 20 | 整数 ≥ 1。非整数或 <1 会导致启动错误。限制返回的搜索结果数量。较大的值会增加响应的 token 数量——每次搜索返回数百条结果,可能会让低相关度条目耗尽 AI 客户端的上下文窗口。只有在精确率与召回率的权衡需要更广泛的结果集时才增加此值。 |
--log-level | OBSIDIAN_LOG_LEVEL | warn | 可选值:debug、info、warn、error(小写,区分大小写)。未知值会静默回退到 warn——不会报错,也不会记录警告。 |
--read-only | OBSIDIAN_READ_ONLY | false | CLI:单独使用 --read-only 即可启用。环境变量:与 --pretty 使用相同的 ParseBool 规则。启用后,不会注册修改数据的工具(write_note、delete_note、move_note 等)——它们绝不会出现在 tools/list 中。 |
--trash-retention-days | OBSIDIAN_TRASH_RETENTION_DAYS | 30 | 整数 ≥ 0。非整数或负数会导致启动错误。默认情况下,delete_note 会将笔记移动到 .obsidian-mcp/trash/<timestamp>/<path>,而不是永久删除;启动时会清理早于此天数的条目。 |
--vault-name | OBSIDIAN_VAULT_NAME | 知识库目录的基本名称 | 用于在 search_notes、search_regex、list_directory 和 get_recent_changes 的结果中构建 obsidian://open?vault=<name>&file=<path> 深层链接。如果知识库目录名称与 Obsidian 显示的名称不一致,请显式设置此值。 |
--transport | OBSIDIAN_TRANSPORT | stdio | stdio 或 http。http 会启动受 TLS 保护的 Streamable HTTP 监听器,而不是通过 stdio 使用 MCP——参见 SECURITY.md § HTTP transport。 |
--http-bind | OBSIDIAN_HTTP_BIND | 127.0.0.1 | --transport http 的绑定地址。除非同时设置 --allow-non-loopback,否则不接受非环回地址。 |
--http-port | OBSIDIAN_HTTP_PORT | 8443 | --transport http 的端口。 |
--allow-non-loopback | OBSIDIAN_ALLOW_NON_LOOPBACK | false | 允许 --http-bind 使用非环回地址。必须同时设置非空的 --allowed-hosts 和 --allowed-origins——这是一个需要显式确认的三标志安全门槛。 |
--allowed-hosts | OBSIDIAN_ALLOWED_HOSTS | (空) | 以逗号分隔的 Host 标头允许列表,用于 --transport http。与 --allow-non-loopback 一起使用时为必填项。 |
--allowed-origins | OBSIDIAN_ALLOWED_ORIGINS | (空) | 以逗号分隔的 Origin 标头允许列表,用于 --transport http。与 --allow-non-loopback 一起使用时为必填项。 |
--client-ca | OBSIDIAN_CLIENT_CA | (无) | 受信任客户端 CA 的 PEM 文件路径。为 --transport http 启用强制双向 TLS——不提供有效客户端证书的连接会被拒绝。 |
示例
# Override extensions to include Excalidraw drawings
obsidian-mcp --vault ./my-vault --extensions ".md,.canvas,.excalidraw"
# Add a custom ignore pattern alongside defaults (you must repeat the defaults
# you want to keep — values fully replace, not merge)
obsidian-mcp --vault ./my-vault \
--ignore ".obsidian,.git,node_modules,.DS_Store,.trash,Archive,Templates"
# Enable pretty JSON via env var (any ParseBool-compatible truthy value works)
OBSIDIAN_PRETTY=1 obsidian-mcp --vault ./my-vault
OBSIDIAN_PRETTY=true obsidian-mcp --vault ./my-vault
# Verbose logging while debugging an integration
OBSIDIAN_LOG_LEVEL=debug obsidian-mcp --vault ./my-vault
# Streamable HTTP transport instead of stdio (loopback only, TLS + bearer
# token auto-generated on first run — see SECURITY.md § HTTP transport)
obsidian-mcp --vault ./my-vault --transport http --http-port 8443
优先级示例:导出 OBSIDIAN_LOG_LEVEL=debug 后,运行 obsidian-mcp --vault ... --log-level info 时,日志级别为 info——显式标志优先。未设置的标志会继承环境变量;如果两者都未设置,则使用默认值。
安全性
执行任何文件系统操作前,所有路径都会经过 4 层安全模型验证:
- 词法检查 — 拒绝绝对路径、
..路径遍历和空字节 - 过滤 — 屏蔽忽略的模式(
.git、.obsidian等)和未经批准的扩展名 - 存在性检查 — 验证文件是否存在,并在必要时忽略大小写进行回退查找;拒绝存在歧义的匹配
- 符号链接 — 解析符号链接,并验证目标仍位于知识库根目录内
可选的 --transport http 监听器采用独立的安全措施(TLS、Bearer 身份验证、默认仅限环回地址、会话绑定)——请参阅 SECURITY.md § HTTP 传输。
项目结构
cmd/obsidian-mcp/ Entry point, transport selection (stdio/http)
internal/
config/ CLI flags, env vars, defaults
vault/ Path security, CRUD, frontmatter, tags, links, mutations
tools/ MCP tool registrations and handlers
response/ Token counting, JSON formatting
search/ BM25 ranked search, regex/glob
periodic/ Periodic note resolution (Phase 4)
prompts/ MCP Prompt templates
resources/ MCP Resource registrations
httptransport/ Streamable HTTP transport: TLS, bearer auth, session binding
testdata/vault/ Fixture vault for tests
开发
make build # compile binary
make test # go test -race ./...
make vet # go vet ./...
make fmt # gofmt + goimports
make run ARGS="--vault /path/to/vault"
make help # list all targets
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。