AI生成内容溯源工具

一个用于追踪Obsidian知识库中AI生成内容来源的MCP服务器,通过SQLite数据库和不可变事件日志维护输入与笔记间的完整溯源链。

  • by pascalweiss
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 pascalweiss/vault-sources-mcp

使用说明

保管库来源mcp

“这张纸条是从哪里来的?” --人工智能生成的黑曜石金库的来源分类账。

一 主控程序 跟踪服务器 哪些输入 (成绩单、文章、摘录) 其中注意到 在你的黑曜石金库里——永远不要碰金库本身。


问题

您可以使用AI代理从YouTube成绩单、书籍摘录、文章和粘贴的文本中填充黑曜石库。随着时间的推移,金库逐渐发展成为一个丰富的知识库,但 起源 这些知识消失了:

  • 聊天记录丢失。复制粘贴源已被遗忘。
  • 你不能回答 “这张纸条是从哪里来的?”
  • 没有办法审计、核对或清理人工智能生成的内容。
  • 当事情看起来不对劲时,你无法追溯到源头。

解决方案

vault-sources-mcp 是一个 来源分类账 它就在你的保险库旁边。它使任何与MCP兼容的AI代理都能够:

  • 存储原始输入 (成绩单、文章等)使用SHA-256重复数据删除
  • 将输入链接到笔记 通过frontmatter中的稳定UUID v7标识符
  • 查询来源 双向——注释的来源,注释的来源
  • 诊断问题 --查找孤立的输入、过时的笔记、缺失的链接
  • 审核一切 通过不可变的、仅可追加的事件日志

所有数据都存在于一个SQLite文件中。服务器从不读取或写入您的保管库。


运作原理

┌──────────────┐                              ┌──────────────────────┐
│   AI Agent   │◄── MCP (15 tools) ──────────►│  vault-sources-mcp   │
│              │                               │                      │
│  Reads/edits │                               │  Stores inputs,      │
│  markdown    │                               │  tracks links,       │
│  files       │                               │  logs events         │
└──────┬───────┘                               └──────────┬───────────┘
       │                                                  │
       ▼                                                  ▼
┌──────────────┐                               ┌──────────────────────┐
│  Obsidian    │                               │  SQLite database     │
│  Vault       │                               │  (single file)       │
└──────────────┘                               └──────────────────────┘

代理处理所有vault交互。MCP服务器处理所有来源数据。他们通过15种结构化工具进行沟通。


Git同步来源(事件日志)

同一个保险库经常在多个地方使用——笔记本电脑和服务器吊舱, 比如说,每个服务器都在同一个同步的git上运行自己的服务器实例 降价。单个二进制SQLite文件不能被git合并,因此并发 来自两个环境的写入会发生冲突,并悄无声息地失去来源。

为了使出处同步与纸币本身一样清晰, SQLite不再 真相的来源——它是一个可重建的投影(缓存)。 耐用, git同步的真相源是一个仅可追加的事件日志,每个写入者都有分片:

<vault>/
  .vault-sources/
    events/
      <node-id>.jsonl     # append-only; ONE writer per file → git never has to merge it
      <other-node>.jsonl
    inputs/
      <sha256>            # content-addressed input bodies, immutable, deduped
    node                  # this machine's node-id marker (gitignored, per-machine)
  .vault-sources.sqlite   # derived projection, gitignored, rebuilt from the log

为什么这是无冲突和正确的:

  1. 拆分碎片文件 --每个环境只会附加到自己的环境中 <node-id>.jsonl,所以git合并很简单(没有重叠的编辑)。
  2. 内容寻址输入 --相同的实体哈希到同一个文件,所以它们 免费重复数据消除,永不冲突。
  3. UUID v7事件ID --全球独一无二,时间有序。
  4. 确定性回放 --rebuild=读取每个分片,按事件id进行重复数据删除,排序 通过 (ts, uid),申请。无论git如何交错,结果都是相同的 碎片。

长时间运行的服务器也会监视日志(轮询+ fs.watch)并应用事件 在a之后附加另一个环境 git pull,因此它保持最新状态,没有 重新启动。

迁移是自动且经过验证的。 服务器首次打开保管库 这仍然有遗产 .vault-sources.sqlite 但没有事件日志,它会进行综合 SQLite状态的日志,将旧文件备份到 .vault-sources.sqlite.pre-migration, 并且只有在一次性内存回放被证明可以再现 传统国家。一旦不匹配,它就会中止,一切都保持不变。

承诺什么

在每个保险库回购中, 追踪 .vault-sources/events/ 和 .vault-sources/inputs/, 和 忽略 导出的缓存和每台机器的标记:

.vault-sources.sqlite*
.vault-sources/node

注意事项

  • Redaction只是工作树。 redact_input 从中删除内容文件 工作树,但git历史仍然保存着它。不要存储你必须存储的秘密 能够进行硬删除;真正的洗涤需要重写历史。
  • 节点ID在每个环境中必须是唯一的。 共享节点id的两个环境 将附加到同一分片并重新引入冲突。设置显式 VAULT_SOURCES_NODE_ID 每个环境(请参阅配置)。

安装

git clone https://github.com/your-username/vault-sources-mcp.git
cd vault-sources-mcp
npm install
npm run build

用法

1.通过 .mcp.json (克劳德代码项目)

创建一个 .mcp.json 项目根目录中的文件。Claude Code在目录中启动时会自动加载此文件。

如果你的工作目录是黑曜石保险库,不需要环境变量——服务器会自动从MCP根目录检测vault,并将数据库存储为 .vault-sources.sqlite 里面:

{
  "mcpServers": {
    "vault-sources": {
      "command": "node",
      "args": ["/path/to/vault-sources-mcp/dist/src/index.js"]
    }
  }
}

如果你的保险库在别处,设置显式路径:

{
  "mcpServers": {
    "vault-sources": {
      "command": "node",
      "args": ["/path/to/vault-sources-mcp/dist/src/index.js"],
      "env": {
        "VAULT_SOURCES_DB_PATH": "/path/to/vault-sources.sqlite"
      }
    }
  }
}

2.通过Claude CLI

claude mcp add --transport stdio \
  --env VAULT_SOURCES_DB_PATH=/path/to/vault-sources.sqlite \
  vault-sources -- node /path/to/vault-sources-mcp/dist/src/index.js

注: 所有选项(--transport, --env, --scope)一定要来 之前 服务器名称。这 -- 将服务器名称与命令和参数分开。

3.使用克劳德桌面(全球)

添加到您的Claude Desktop配置中:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • 视窗: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "vault-sources": {
      "command": "node",
      "args": ["/path/to/vault-sources-mcp/dist/src/index.js"],
      "env": {
        "VAULT_SOURCES_DB_PATH": "/path/to/vault-sources.sqlite"
      }
    }
  }
}

4.使用Gemini CLI

增添 ~/.gemini/settings.json:

{
  "mcpServers": {
    "vault-sources": {
      "command": "node",
      "args": ["/path/to/vault-sources-mcp/dist/src/index.js"],
      "env": {
        "VAULT_SOURCES_DB_PATH": "/path/to/vault-sources.sqlite"
      }
    }
  }
}

5.使用Codex CLI(OpenAI)

增添 ~/.codex/config.toml:

[mcp_servers.vault-sources]
command = "node"
args = ["/path/to/vault-sources-mcp/dist/src/index.js"]

[mcp_servers.vault-sources.env]
VAULT_SOURCES_DB_PATH = "/path/to/vault-sources.sqlite"

注: MCP是一个开放标准。任何兼容MCP的客户端都可以通过stdio传输使用此服务器。


配置

数据库路径解析

数据库路径按以下顺序解析:

  1. CLI参数 — node dist/src/index.js /path/to/db.sqlite
  2. VAULT_SOURCES_DB_PATH 环境变量
  3. VAULT_PATH 环境变量--数据库存储为 $VAULT_PATH/.vault-sources.sqlite
  4. MCP客户端根 --如果客户端支持 根,服务器使用第一个 file:// root并将数据库存储为 .vault-sources.sqlite 里面
  5. 后备方案 — ./data/vault-sources.sqlite

这意味着像Claude Code这样的MCP客户端将工作目录作为根目录公开,当从黑曜石保险库内部启动时,可以使用零配置。

环境变量

变量 描述 默认值
VAULT_SOURCES_DB_PATH SQLite投影文件的显式路径 --
VAULT_PATH 黑曜石拱顶路径(投影存储为 .vault-sources.sqlite 里面;事件日志位于 .vault-sources/ 旁边) --
VAULT_SOURCES_NODE_ID 此环境事件日志碎片的唯一id(例如。 pa-pod, mac-local).共享vault的环境之间必须不同。回退到gitignored中保存的随机id .vault-sources/node. 随机

MCP工具

数据库管理

工具 说明
db_status 检查数据库是否已初始化并获取统计信息(输入、注释、链接、事件)
db_init 创建并迁移数据库。显式——从不默默创建

输入管理

工具 说明
store_input 使用自动SHA-256重复数据删除功能存储原始文本(成绩单、文章、摘录)
get_input 按ID检索输入。返回 [REDACTED] 如果输入已被编辑
list_inputs 使用分页和状态过滤列出存储的输入(仅元数据)
redact_input 永久删除内容,但保留元数据、链接和审计跟踪

笔记管理

工具 说明
generate_note_id 生成一个UUID v7和frontmatter代码段以注入到注释中
register_note 在数据库中注册注释。Idempotent-更新 last_seen_at 重复通话
get_note 获取一条注释记录,包括其链接的输入ID列表
mark_note_deleted 软删除笔记。保存记录以供审计之用

来源链接

工具 说明
add_link 在输入和注释之间创建出处链接。多对多,幂等
remove_link 删除输入和注释之间的来源链接
get_sources_for_note 给定一张纸条,找到它的来源。 返回所有链接的输入
get_notes_for_input 给定一个来源,找到受影响的笔记。 返回所有链接的笔记

对账与诊断

工具 说明
find_stale_notes 自给定日期以来未看到的注释——代理可以检查文件是否仍然存在
find_orphaned_inputs 已存储但从未链接到任何笔记的输入
find_unlinked_notes 来源不明的笔记——未链接任何输入
get_event_log 查询仅追加事件日志。按类型、时间范围和分页进行筛选

典型工作流程

以下是与MCP连接的代理在实践中的对话:

1.  User provides a YouTube transcript
2.  Agent calls  store_input           → persists the transcript, gets input_id
3.  Agent calls  generate_note_id      → gets a UUIDv7 for the new note
4.  Agent writes the markdown file with the ID in frontmatter
5.  Agent calls  register_note         → registers the note in the provenance DB
6.  Agent calls  add_link              → links the transcript to the note

稍后,用户询问 “我的堆肥基础笔记是从哪里来的?”:

7.  Agent calls  get_sources_for_note  → returns the linked transcript metadata
8.  Agent calls  get_input             → retrieves the full original text

对于定期vault健康检查:

9.  Agent calls  find_stale_notes      → which notes haven't been seen recently?
10. Agent calls  find_orphaned_inputs  → which inputs were never used?
11. Agent calls  get_event_log         → full audit trail of every action

设计原则

原则 这意味着什么
关注点分离 服务器从不读取或写入vault文件。所有与保险库的交互都是代理人的工作。
来源,而非重复 输入在保险库外。注释不链接到输入。关系只存在于分类账中。
可审计性 每个突变都会在git同步的、只追加的日志中产生一个不可变的事件。SQLite只是该日志的可重建投影。
显性多于隐性 数据库永远不会以静默方式创建。ID需要用户批准。和解意味着——它永远不会自动修复。

项目结构

vault-sources-mcp/
├── src/
│   ├── index.ts                    # MCP server entry point (stdio transport)
│   ├── types.ts                    # Core types: Input, Note, Link, Event
│   ├── errors.ts                   # Custom error classes
│   ├── log/
│   │   ├── event-store.ts          # Append-only JSONL shards + content-addressed inputs
│   │   ├── projector.ts            # Apply one canonical event to the SQLite projection
│   │   ├── rebuild.ts              # Deterministic replay + state snapshot/diff
│   │   ├── migrate.ts              # One-time, verified legacy-SQLite → log migration
│   │   ├── node-id.ts              # Per-environment shard id resolution
│   │   └── hash.ts                 # SHA-256 content addressing
│   ├── db/
│   │   ├── database.ts             # Facade: log ↔ projection, migrate, rebuild, sync
│   │   ├── schema.ts               # Projection schema (source of truth is the log)
│   │   └── repositories/
│   │       ├── input-repository.ts # Store, deduplicate, redact inputs
│   │       ├── note-repository.ts  # Register, find stale/unlinked notes
│   │       └── link-repository.ts  # Provenance links, orphan detection
│   └── tools/
│       ├── db-tools.ts             # db_status, db_init
│       ├── id-tools.ts             # generate_note_id
│       ├── input-tools.ts          # store, get, list, redact
│       ├── note-tools.ts           # register, get, mark deleted
│       ├── link-tools.ts           # add, remove, query both directions
│       └── reconciliation-tools.ts # Diagnostics & event log queries
├── skills/                            # Claude Code skill templates
│   ├── vault-init/SKILL.md            # Database initialization workflow
│   ├── store-source/SKILL.md          # Store input sources
│   ├── new-note/SKILL.md              # Create note with provenance
│   ├── check-provenance/SKILL.md      # Trace note origins
│   └── vault-health/SKILL.md          # Diagnostic health checks
├── test/
│   ├── db/                         # Unit tests (40 tests)
│   ├── integration.test.ts         # End-to-end workflow test (4 tests)
│   └── dummy-vault/                # Sample Obsidian vault (gardening notes)
└── dist/                           # Compiled output

技能模板

该项目包括即用型 Claude代码技能 模板在 skills/ 目录。将它们复制到项目的 .claude/skills/ 为您的AI代理提供结构化的工作流程,用于追踪来源。

安装

# Copy all skills into your project
cp -r /path/to/vault-sources-mcp/skills/* .claude/skills/

或者根据需要复制个人技能。

可用技能

技能 调用 描述
保险库初始化 /vault-init 初始化来源数据库。检查数据库是否存在,请求确认,运行 db_init,并报告结果。仅手动调用——防止意外重新初始化。
存储源 /store-source 将原始输入材料(成绩单、文章、摘录)存储在出处数据库中。通过SHA-256处理重复数据删除并报告 input_id < 返回当您提供源材料时,Claude也可以自动调用此功能。
新注释 /new-note [title] 完整的笔记创建工作流:生成UUID v7,使用frontmatter写入markdown文件,在数据库中注册笔记,并将其链接到其输入源。确保在一个步骤中建立完整的来源链。
核实来源 /check-provenance [note or input] 通过追溯笔记的输入来源来回答“这个笔记从哪里来?”。也可以反向工作——给定一个输入,列出从中导出的所有注释。当出现出处问题时,Claude可以自动调用此功能。
保险库健康状况 /vault-health 运行全面的诊断:查找孤立的输入(已存储但从未链接)、未链接的笔记(无已知来源)、过时的笔记(最近看不到),并显示最近的活动。提供调查结果和建议行动——永远不要自动修复。仅限手动调用。

定制

每种技能都是独立的 SKILL.md 使用YAML frontmatter文件。你可以:

  • 编辑 description 当Claude自动调用该技能时进行微调
  • 集 disable-model-invocation: true 将技能限制为手工 /command 仅使用
  • 添加支持文件 技能目录中的(模板、示例)
  • 调整元数据字段 (例如。 source_type, title)以匹配您的工作流程

看 Claude代码技能文档 以获取完整的配置参考。


发展

npm install          # Install dependencies
npm run build        # Compile TypeScript
npm test             # Run all tests
npm run dev          # Watch mode (recompile on change)
npm run clean        # Remove compiled output

许可证

麻省理工学院