不只是我做了个爬虫,而是文档实际呈现出来的样子让我如此喜欢这个项目。

这个周末我做了个 MCP server,我对这东西运行得如此之好有点惊叹。

它叫pulpie-mcp,基本思路很简单:

给 AI 编程智能体它们自己的工具,用来把完整网页和文档抓取成干净的 Markdown。

不是摘要过的文档。不是切碎的搜索结果。不是“这是我认为你需要的重要部分”。

而是实际内容。

表格、链接、图片、代码、标题,全部转成 Markdown 并保存到智能体之后还能用的地方。

pulpie-mcp

pulpie-mcp

一个 MCP server,给 AI 智能体它们自己的工具,用来把网页转成干净的 Markdown。它在本地运行Pulpie内容提取模型,所以表格、代码块、链接和图片都能完整保留,而不是被摘要掉。

智能体可以内联读取页面,把它保存为.md文件,把整个文档章节爬取到一个文件夹里,并在再次抓取前检查它已经保存了什么。

我为什么做它

我本来就有个 Pulpie 的本地小 UI,用来把文档和文章抓成 Markdown,效果很好。但抓取的人还是我。大多数智能体抓取工具会把页面跑过一个小模型来摘要或裁剪,当智能体需要的是真正的 API 参考时,这可不是你想要的。

所以这给了智能体和我一直在用的同样的东西。它可以……

那个让我有点震撼的测试

我让 Claude 测试crawl_docs针对一个文档站点,有60 个页面。

后端当时还没运行,所以这包括了启动服务器并把提取模型加载到我的 GPU 上。

阶段 时间
后端冷启动 约 10s
爬取并保存 60 个页面 约 37s
总计 约 49s

所以不到一分钟,Claude 就从本地完全没有这些文档,变成了拥有60 个干净的 Markdown 文件可以搜索、阅读和引用。

我就觉得这太棒了。

而一旦模型已经加载好,显然那最初约 10 秒的启动成本就消失了。

我为什么构建它

我已经在本地使用Pulpie把网页转成 Markdown。

它使用一个小型内容提取模型,而不是直接抓取原始页面或试图摘要,我对结果印象非常深刻。

但有一个烦人的地方:

仍然是我在拉取文档。

如果我想让一个智能体使用某个库或框架,我可能会抓取一些文档,把它们保存到项目里,把智能体指向它们,然后让它开始工作。

这没问题。

但还有……为什么是我在做这件事?

智能体有 MCP 工具。它知道自己需要什么文档。它知道自己正在处理哪个项目。

所以我构建了一个 MCP 服务器,让它自己完成整件事。

pulpie-mcp 为智能体提供了什么

目前有四个工具:

工具 它的作用
fetch_markdown 抓取一个页面并直接将干净的 Markdown 返回给智能体
save_markdown 抓取一个页面并将其保存为 Markdown 文件
crawl_docs 爬取整个文档部分并保存到本地
list_library 检查哪些文档已经被保存

抓取和保存之间的区分结果证明特别有用。

有时智能体只需要快速阅读一个页面。

其他时候,我正在处理一个项目,希望它拉取整个文档部分并保留下来。

例如,我基本上可以告诉 Claude:

Pull the uv docs into this project's DOCS/reference folder.

然后它处理剩下的部分。

或者:

Do we already have the FastAPI docs saved somewhere?

不需要精心设计的提示词。

它不会把 60 个页面塞进上下文窗口

这部分对我来说很重要。

当crawl_docs保存文档时,它不会把每个页面的内容都返回给智能体。

那会完全疯掉。

相反,文档被写入磁盘,智能体拿回有用的元数据。每个文件还包含带有源 URL、标题和抓取时间的前置元数据。

所以智能体可以一次性抓取整个文档部分,然后只读取它实际需要的文件。

这把本地文件系统变成了一个相当不错的小型文档库。

对于项目特定的文档,智能体可以把它们保存在项目内部。

对于通用研究,pulpie-mcp 有一个全局库,位于:

~/.pulpie/library/

爬取实际上也相当智能

crawl_docs它不会盲目点击它看到的每一个链接。

它首先查找站点地图信息:

  1. robots.txt
  2. 文档路径下的站点地图
  3. 站点的根站点地图
  4. 链接爬取作为后备方案

它停留在同一主机上,并且位于你开始时的文档路径之下。

有四个并发爬取工作进程,因此网络请求可以在提取进行时重叠。

这就是它如何能如此迅速地处理完那 60 页。

该模型在本地运行

这大概是我最喜欢的部分。

pulpie-mcp 使用:

feyninc/pulpie-orange-small

它只是一个2.1 亿参数的编码器模型,在我的机器上它大约占用420 MB 显存。

MCP 进程本身不会加载 PyTorch 或模型。

取而代之的是,有一个很小的 MCP 服务器和一个独立的本地后端。

当智能体使用其中一个工具时:

Agent
  ↓
MCP server
  ↓
Local Pulpie backend
  ↓
Web page
  ↓
Clean Markdown

如果后端尚未运行,MCP 服务器会自动启动它。

一旦它运行起来,每个智能体会话都共享同一个后端,所以我不会落得 Claude、Codex 以及我那天在折腾的其他什么东西各自加载一份模型副本的下场。

在 30 分钟没有请求后,它会自行关闭并释放内存。

这就是那种小小的实现细节,把它从“精巧的实验”变成了我能真正一直装着、然后忘掉的东西。

把它添加到 Claude Code

安装它:

uv tool installgit+https://github.com/pinkpixel-dev/pulpie-mcp

然后:

claude mcp add --scope user pulpie -- pulpie-mcp

基本上就是这样。

第一次运行时,Pulpie 模型会从 Hugging Face 下载。

Codex

把这段添加到:

~/.codex/config.toml
[mcp_servers.pulpie]
command = "pulpie-mcp"

其他 MCP 客户端可以使用普通的 MCP 服务器配置。

仍然有一些限制

我目前还没遇到任何无法处理的页面,但某些完全由客户端渲染的页面可能会返回空白。而且它不处理 PDF。

到目前为止,我只在 Linux 搭配 NVIDIA/CUDA 上亲自测试过。

还有一条许可说明:pulpie-mcp 代码是 Apache 2.0,但pulpie-orange-small模型采用CC BY-NC 4.0许可,所以该模型仅供非商业用途,除非你与其创作者另有约定。

这正是我希望 MCP 被用于的场景

我觉得这就是这个项目让我如此兴奋的原因。

MCP 经常被拿来讨论如何把智能体连接到庞大的服务和 API。

但我真的很喜欢这一类更小型的 MCP 工具:

给智能体一个非常具体的能力,从我的工作流中消除一个重复性的步骤。

我以前会:

  1. 找到文档。
  2. 抓取相关页面。
  3. 清理它们。
  4. 保存到某个地方。
  5. 告诉编码智能体它们在哪里。
  6. 终于开始干活。

现在我可以基本上说:

Grab the docs you need and figure this out.

然后它就照做了。

看着它在约 49 秒内抓取60 页,把它们保存为干净的 Markdown,建立一个索引,然后立刻开始使用它们,是那种美妙的微小:

“哦。该死。这居然真的很有用。”

时刻。

而这是我最喜欢的那类项目。