Skip to main content
Glama

cove-book-forge-mcp

将 PDF 或 EPUB 转化为可复用的知识——而不是另一次一次性的对话。

cove-book-forge-mcp 是一个本地优先、开源的 MCP 服务器,可将书籍转化为结构化的 AI 分析、Obsidian 笔记、章节级 Skill,或一个完整可安装的 Agent Skill。对章节分析一次,即可在多种输出中复用结果,并将最终知识带入 Codex、Claude Code 或其他支持 MCP 的阅读系统。

你可以做什么

  • 将整本书锻造成一个 Agent Skill。 导入 PDF 或 EPUB,通过可恢复的任务分析每一章,并发布一个渐进式披露的 Skill,让 agent 无需将整本书加载到每个提示中即可使用。

  • 为每一章选择正确的输出。 将同一份已分析的章节发送到受保护的 Obsidian 知识库,或将其转化为可复用的章节 Skill。

  • 分析一次,而不是付费两次。 稳定的指纹会缓存已验证的章节分析,因此 Obsidian、章节 Skill 和整本书工作流可复用匹配的结果,且不产生额外的模型调用。

  • 在你已工作的环境中安装 Skill。 生成的 Skill 可安装到 Codex、Claude Code 或常规的通用 Agent Skills 目录中。

  • 使用你偏好的模型。 内置适配器覆盖 OpenAI、DeepSeek 及其他兼容 OpenAI 的端点,以及 Anthropic;应用程序可注入自定义 Provider,而无需更改 forge。

  • 保留或跳过内置库。 在本地存储受管副本、保留已验证的引用,或让现有阅读系统保持权威性,并通过公共边界发送完整的章节快照。

  • 围绕它构建任何阅读体验。 MCP 通过 stdio 或仅限回环的 Streamable HTTP 暴露书籍、章节、分析、输出、整本书任务、控制、状态和生成的 Skill。

Related MCP server: book-teardown-mcp

从书籍到可复用的智能

PDF / EPUB / existing reading system
                 │
                 ▼
       normalized chapters
                 │
                 ▼
    validated AI analysis + cache
          ┌──────┼───────────┐
          ▼      ▼           ▼
     Obsidian  chapter     complete-book
       notes    Skill          Skill
          └──────┼───────────┘
                 ▼
       Codex / Claude Code /
       any compatible client

它为何与众不同

这不仅仅是一个文档解析器或一次性总结书籍的提示。Forge 提供了一个可复用的应用边界:确定性章节、模式验证的分析、持久缓存、原子化受管输出,以及可重启的整本书任务。它既可用作现成的 MCP 后端,也可作为开发人员构建自有阅读界面的基础设施。

在以下场景中使用它:

  • 将一本你可能不会逐章阅读的书转化为一个完整的可复用 Skill;

  • 在现有应用中继续阅读,同时将分析和发布委托出去;

  • 构建 AI 阅读界面,而无需从头重建摄取、缓存、任务、Obsidian 输出和 Agent Skill 生成;或

  • 让多个 agent 都能使用书籍衍生的知识,而无需反复将源文本粘贴到对话中。

包含的内容

当前版本实现了符合标准的 EPUB 摄取、文本层 PDF 摄取、可选的本地 SQLite 库、外部章节快照缓存、模型 Provider 适配器、经过验证的可复用章节分析、受保护的 Obsidian 发布、持久的整本书 Agent Skill 锻造,以及通过 stdio 或回环 Streamable HTTP 提供的 MCP 工具和资源。

该仓库独立于私有 Cove/栖渡 代码,并且有意不规定阅读 UI。扫描版 PDF 仍需要外部 OCR 步骤;核心会显式失败,而不是静默上传或猜测内容。

支持的输入和安全边界

EPUB

  • 支持符合标准的 EPUB 2/3 归档。

  • 阅读顺序来自 OPF spine,而非文件名或 ZIP 成员顺序。EPUB 导航/NCX 标签在可用时提供章节标题。

  • 在读取书籍内容之前,每个 ZIP 成员都会经过预检。绝对路径、父目录遍历、反斜杠路径、加密条目、归档符号链接、嵌套归档以及配置的展开限制违规均被拒绝。

PDF

  • PDF 必须包含有意义的文本层。页面文本保持物理页面顺序,确定性章节范围使规范化书籍保持可寻址性。

  • 扫描版或纯图像 PDF 会以 OCR_REQUIRED 显式失败。核心不会下载 OCR 引擎、调用远程服务或静默调用 OCR 回退。

  • 加密和格式错误的 PDF 会以封闭的、路径安全的错误失败。

默认摄取限制为:

边界

默认值

源文件

512 MiB

PDF 页数

5,000

ZIP 成员

10,000

ZIP 展开内容总量

1 GiB

每个 ZIP 成员的展开字节数

128 MiB

ZIP 压缩比

100:1

源文件在提取前后都会进行指纹识别。在解析过程中发生变化的源文件会以 SOURCE_CHANGED 失败,且不会被部分持久化。

可选的本地库

本地缓存位于配置的 library.data_dir 下,并使用 library.sqlite3。初始化和模式迁移是显式且本地的。

  • COPY 在库数据目录下存储一份经过验证的副本。原始源文件之后可以移动或消失,而不影响受管副本。

  • REFERENCE 存储解析后的源路径及其指纹,而不复制文件。如果源文件发生变化或消失,source_available 将变为 False;已规范化的章节仍可读取。

  • 将 library.enabled: false 设置为禁用受管文件导入。完整、稳定的外部 ChapterSnapshot 仍可被 upsert 到可选的本地缓存中,并在新的库服务实例中存活。外部系统保持权威性。

使用公共 API 进行受管导入

from pathlib import Path

from cove_book_forge.config import AppConfig
from cove_book_forge.contracts import ImportMode
from cove_book_forge.library import create_book_library

data_dir = Path("/absolute/path/to/local-library")
config = AppConfig.model_validate(
    {
        "library": {"enabled": True, "data_dir": data_dir},
        "model": {"provider": "unused-local", "model": "unused-local"},
    }
)
library = create_book_library(config)
imported = library.import_book(Path("/absolute/path/to/book.epub"), ImportMode.COPY)

stored = library.get_book(imported.book)
first_chapter = library.get_chapter(imported.book, 0)
print(stored.metadata.title, first_chapter.title)

使用 ImportMode.REFERENCE 保留引用而非受管副本。在为同一数据目录构造另一个服务后,list_books()、get_book() 和 get_chapter() 读取相同的规范化契约。

在禁用受管导入时进行外部快照 upsert

from pathlib import Path

from cove_book_forge.config import AppConfig
from cove_book_forge.contracts import BookMetadata, ChapterContent, ChapterSnapshot
from cove_book_forge.library import create_book_library

config = AppConfig.model_validate(
    {
        "library": {
            "enabled": False,
            "data_dir": Path("/absolute/path/to/optional-external-cache"),
        },
        "model": {"provider": "unused-local", "model": "unused-local"},
    }
)
library = create_book_library(config)
book = library.upsert_chapter_snapshot(
    ChapterSnapshot(
        source_system="my-reader",
        external_book_id="stable-book-id",
        book=BookMetadata(title="External Book", total_chapters=1),
        chapter=ChapterContent(
            index=0,
            title="Chapter 1",
            content="Complete normalized chapter text.",
            source_locator="my-reader:chapter:0",
        ),
    )
)
print(library.get_chapter(book, 0).content)

可复用的章节分析

ChapterAnalyzer 通过注入的异步 ModelProvider 将一个规范化的 ChapterSnapshot 转化为严格的公共 ChapterAnalysis 契约。它根据契约模式验证每个结构化响应,并且当 Provider 报告无效模型输出或返回的对象未通过验证时,最多允许一次额外的生成。身份验证、速率限制、可用性和配置失败不会被修复,也永远不会触发回退 Provider。

分析器在规范化章节标题/正文、高亮、笔记、注释、反思、分析配置、提示和生成器版本以及 ChapterAnalysis 模式之上计算稳定指纹。匹配的持久缓存条目在零 Provider 调用的情况下返回,包括在重新创建库和分析器之后。Provider/模型/基础身份默认被忽略,可通过 analysis.include_provider_in_fingerprint: true 显式包含。API 密钥名称和值永远不会进入指纹。

长章节在 Markdown 感知边界处无损拆分。有序块仅包含章节内容;围栏代码和 Markdown 表格保持原子性,即使单个块超过配置的限制。每个块接收经过验证的分析,随后恰好一次最终合并,接收经过验证的块分析和章节的高亮、笔记、注释和反思。完整正文不会在合并中重复,只有最终合并的分析在完整章节指纹下被缓存。

from cove_book_forge.analysis import ChapterAnalyzer

analyzer = ChapterAnalyzer(
    provider,
    library,
    config.analysis,
    config.model,
)
analyzed = await analyzer.analyze(snapshot)
print(analyzed.analysis.core_idea, analyzed.cache_hit)

同一个 AnalyzedChapter 无需重新分析即可供给两种已实现的输出。现有阅读系统提供完整的 ChapterSnapshot;其本地缓存提供匹配的 AnalyzedChapter,因此 Skill 发布不会再次调用 Provider。

持久的整本书 Skill 锻造

WholeBookForge 接受受管库的 book_id 或完整有序的外部 ChapterSnapshot 值序列。规划会创建一个无秘密的 30 分钟 ForgePlan,绑定到每个章节分析指纹、所选 Provider/模型、提示和生成器版本以及 Skill 输出配置。其估算仅报告未缓存分析的令牌和模型调用;不会虚构价格。

启动计划需要显式确认和幂等键。一个控制器在任意时刻拥有书籍的 Skill。持久化 SQLite 日志记录计划、任务和章节发布检查点。每章通过 ChapterAnalyzer 分析并通过 AgentSkillOutput 发布,因此缓存命中不产生模型调用,最终 Skill 包含完整的章节集。暂停和取消在章节边界生效;取消保留已发布的章节。中断或失败的任务可以恢复/重试,而无需重复已完成的检查点,包括在进程重启之后。

MCP 服务器

安装项目并使用以下命令启动默认 stdio 服务器:

cove-book-forge mcp --config /absolute/path/to/config.yaml

服务器暴露库导入/读取操作、章节分析和输出、整本书规划/任务/控制/状态、生成的 Skill 发现以及匹配的 cove-book-forge:// 资源。所有工具返回 Pydantic 定义的结构化结果。公共错误使用安全的 ForgeErrorDetail 数据,不揭示源路径、章节文本、Provider 响应或凭据。

还提供显式的本地 HTTP 传输:

cove-book-forge mcp --transport http --host 127.0.0.1 --port 8000 \
  --config /absolute/path/to/config.yaml

未认证的 Streamable HTTP 仅限于回环地址。服务器不提供远程未认证模式。应用程序可以使用自定义 ModelProvider 构造 AppContext;内置的 DeepSeek 配置使用现有的兼容 OpenAI 的 Provider 路由。

安全的 Obsidian 输出

ObsidianOutput 同步发布一个已分析的章节。保险库必须已存在并显式配置;磁盘根目录、主目录、当前工作目录及其广泛祖先、符号链接路径和不可写位置均会关闭失败。发布不会调用 Provider 或修复分析。

此应用层函数是公共异步分析边界和同步输出边界的类型有效组合:

from cove_book_forge.analysis import ChapterAnalyzer
from cove_book_forge.config import AppConfig
from cove_book_forge.contracts import ChapterSnapshot, ObsidianPublishResult
from cove_book_forge.library import BookLibrary
from cove_book_forge.outputs import ObsidianOutput
from cove_book_forge.providers import ModelProvider


async def publish_chapter_to_obsidian(
    provider: ModelProvider,
    library: BookLibrary,
    config: AppConfig,
    snapshot: ChapterSnapshot,
) -> ObsidianPublishResult:
    analyzer = ChapterAnalyzer(provider, library, config.analysis, config.model)
    analyzed = await analyzer.analyze(snapshot)
    return ObsidianOutput(config.outputs.obsidian).publish(snapshot, analyzed)

匹配的持久输入指纹使 analyzer.analyze(...) 成为零调用缓存命中,包括在应用程序重新创建其库、分析器和输出服务之后。发布未更改的结果不会执行文件重写。Provider/模型/基础身份默认从指纹中排除;当应用程序要求 Provider 更改使缓存分析失效时,设置 analysis.include_provider_in_fingerprint: true。

确定性的受管布局为:

<Vault>/
├── Books/<safe book title>--<stable book key>/
│   ├── <initial safe book title> MOC.md
│   └── Chapters/<01-based index> <safe chapter title>.md
├── Cards/<safe concept or rule title>--<stable card id>.md
└── .cove-book-forge/obsidian/<stable book key>.json

带校验和的清单在单独的章节发布和进程重启之间保留章节覆盖、索引条目、卡片、框架和主题。面向人类的标题更改更新受管显示元数据,而物理书籍根目录和 MOC 路径保持稳定。清单存储受控身份、摘要、相对路径和哈希——而非源章节正文、私人笔记、提示、Provider 响应、凭据或绝对路径。

每个受管 Markdown 文件都有固定的 cove_* frontmatter,包括其所有权身份和正文哈希。Cove Book Forge 仅更新受管标记、身份和记录的哈希仍匹配的文件。在应用程序之外编辑受管笔记会导致 EXTERNAL_MODIFICATION;v0.1 不合并任意 Markdown,也没有覆盖标志。将个人文字保留在单独的、非受管的笔记中,并链接到生成的材料。

章节笔记、相关概念/规则卡片、聚合 MOC 和清单作为一个可恢复的捆绑包暂存并提交,清单最后提交。失败的发布在能够证明所有权时恢复最后一个成功的可见捆绑包,并且永远不会采用或删除竞争文件。成功的未更改发布是逐字节的空操作。

私有 Cove 阅读界面可以调用本仓库实现的公共 MCP 应用边界。核心保持与 UI 无关:其他阅读系统可以使用相同的工具和资源,而没有现成阅读器的用户也可以围绕它们构建自己的界面。

生成的 Agent Skills

AgentSkillOutput 将一个已分析的 ChapterSnapshot 转换为受管理的单章节 Agent Skill。配置一个已有的规范目录,以及你想使用的常规发现根目录:

outputs:
  skills:
    enabled: true
    canonical_path: /absolute/path/to/generated-skills
    install_to: [codex, claude, agents]

公共同步边界镜像了 Obsidian 边界。它接受缓存的分析结果,因此绝不会调用 Provider:

from cove_book_forge.contracts import AnalyzedChapter, ChapterSnapshot
from cove_book_forge.outputs import AgentSkillOutput

result = AgentSkillOutput(config.outputs.skills).publish(snapshot, analyzed)
print(result.skill_slug, result.canonical_path)

运行 examples/publish_chapter_skill.py 获取完整的本地演示。规范根目录保持为事实来源,并具有受保护、可恢复的受管理布局。每个选定的目标在支持符号链接时作为经过验证的相对符号链接安装;如果符号链接不可用,则接收经过验证的受管理副本。现有的非受管理文件、目录和链接永远不会被覆盖:安装冲突返回 INSTALL_CONFLICT,同时保持规范 Skill 可用。重复未更改的发布会复用缓存的分析并执行逐字节的无操作。

安装后,以 $<skill-slug> 调用生成的 Skill(例如 $durable-decisions--0123abcd0123abcd),或发出与生成 Skill 描述匹配的自然语言请求。Codex 使用 ~/.codex/skills,Claude Code 使用 ~/.claude/skills,通用代理使用 ~/.agents/skills;只有 install_to 中命名的根目录会被检查或更改。

同一输出边界也被整本书锻造器使用,它通过持久化、可恢复的作业分析和发布章节。公共 MCP 服务器同时公开章节级和整本书工作流;只有私有 Cove UI 适配器仍保留在这个开源仓库之外。

模型 Provider

异步 Provider 边界支持 openai、openai-compatible、deepseek 和 anthropic 作为精确的内置名称。它返回带类型的每次调用结果以及累计的输入/输出/总 token 使用量。每次生成调用最多发出一个请求:适配器内没有自动重试、JSON 修复或回退到另一个 Provider。实现的章节分析层拥有上述所述的独立有界 schema 验证/重新生成策略。即使付费响应随后在终止、内容或 JSON 对象验证中失败,受信任的 Provider 使用量仍会被计数。

API 密钥值仅从指定的进程环境变量中读取。在 YAML 中放入变量名——而不是密钥——并通过你的 shell、服务管理器或密钥管理器提供该值。密钥、提示词、URL 和原始响应体被排除在公共错误之外,并且不会被 Provider 层记录。openai、deepseek 和 anthropic 需要配置的、非空的凭证;通用 openai-compatible 和显式注册的自定义 Provider 可以省略它。

DeepSeek

DeepSeek 使用 OpenAI 兼容的 chat-completions 协议和内置的 DeepSeek API 基础地址:

model:
  provider: deepseek
  model: deepseek-chat
  api_key_env: DEEPSEEK_API_KEY

OpenAI 兼容或自托管网关

需要显式的 base_url。对于本地网关,api_key_env 是可选的;配置后,其环境值必须非空。

model:
  provider: openai-compatible
  model: local-reader-model
  base_url: http://127.0.0.1:11434/v1
  # json_mode: true  # opt in only when this gateway supports native JSON Mode
  # api_key_env: LOCAL_MODEL_API_KEY

Anthropic Claude

Claude 使用 Anthropic Messages API:

model:
  provider: anthropic
  model: claude-sonnet-4-5
  api_key_env: ANTHROPIC_API_KEY

OpenAI 和 DeepSeek 默认使用原生 JSON 对象模式。通用 openai-compatible 默认使用仅提示词的 JSON;仅对支持 response_format 的网关设置可选 json_mode: true,或对 OpenAI 或 DeepSeek 设置 false 以禁用原生模式。每条路径都会添加受控的直接对象指令,并严格接受一个 JSON 对象。Anthropic 始终将原生 JSON 模式和 JSON Schema 声明为不可用,并忽略 OpenAI 风格的覆盖。输出能力上限仍然未知;default_max_output_tokens 是调用方默认值,不是供应商硬限制。领域模式验证和一次有界的无效输出再生成由 ChapterAnalyzer 提供,而非 Provider 适配器。

由一个应用程序拥有的 ProviderRegistry 创建的内置 Provider 在同一路由和凭据身份上共享配置的并发和 60 秒请求限制。每个实例保留自己的累计用量。不同的注册表相互隔离,因此嵌入应用程序应为其一个应用程序边界复用其注册表。

显式自定义 Provider 注册

应用程序可以显式注册类型化的本地或专有 Provider,无需插件发现或动态导入路径:

from your_application.providers import custom_provider_factory

from cove_book_forge.config import ModelConfig
from cove_book_forge.providers import ProviderRegistry

registry = ProviderRegistry({"deterministic-local": custom_provider_factory})
provider = registry.create(ModelConfig(provider="deterministic-local", model="reader-model"))

参见仓库/sdist 源码示例 examples/custom_provider.py 以获取完整的类型化实现。它是源材料,而不是 wheel 包命名空间;在上面的导入之前,请在您自己的应用程序包下复制或改编它。独立的 doctor 命令只识别精确的内置项;嵌入应用程序负责其显式注册的自定义 Provider 的就绪检查。

隐私默认值和诊断

  • 库数据和规范化快照保持在本地。

  • 遥测、云同步、远程日志记录和隐藏网络回退均被禁用。

  • API 密钥值来自环境变量,绝不存储在 YAML 中。

  • 配置的输出根目录需要显式授权。Obsidian 发布保持本地化,并且只写入其经过验证的受管理捆绑包。

doctor 命令是只读且无网络的。它检查配置、内置 Provider/base 就绪性、所需环境变量是否存在、PDF 解析器依赖项、配置的库目录就绪性、通过只读 SQLite 完整性检查的现有 library.sqlite3,以及启用的 Obsidian 保险库(通过与发布使用的相同的狭窄无跟踪就绪边界)。它绝不渲染或发布输出,不调用 Provider 生成或健康检查 API,也不创建目录、数据库、WAL 文件、临时文件、清单或迁移。禁用的 Obsidian 输出是非失败警告;配置的缺失、过宽或不可写的保险库是安全的无路径失败。

uv sync --group dev
uv run cove-book-forge doctor --config /absolute/path/config.yaml

如果受管理导入被禁用且外部缓存尚不存在,当其现有父目录就绪时,doctor 报告非失败警告。不安全、不可读或无效的现有数据库保持为失败。

贡献者验证

运行完整的本地验证序列:

uv lock --check
uv run --no-sync pytest --cov=cove_book_forge --cov-report=term-missing
uv run --no-sync ruff check .
uv run --no-sync ruff format --check .
uv run --no-sync mypy src/cove_book_forge
uv run --no-sync mypy examples/custom_provider.py
uv build --clear
uv run --no-sync python scripts/verify_distribution.py dist

Provider 测试仅使用模拟本地传输和确定性假 Provider;测试套件不执行实时模型请求,也不需要真实的账户或密钥。

致谢

cove-book-forge-mcp 的灵感来自 book-to-skill 的想法和工具,由 Virgilio Jr. 创建。我们感谢其文档提取工作、Agent Skill 结构和开源贡献。具体的改编 sanitizer 通知保留在 THIRD_PARTY_NOTICES.md 中。

许可证

MIT。参见 LICENSE 和 THIRD_PARTY_NOTICES.md 中捆绑的第三方条款。

Maintenance

ActivitySlowing
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers