我把六个站的内容,全塞进了一个 MCP
六个网站、五六十万字的内容,怎么让 ChatGPT 和 Perplexity 随时读到?我的答案是做一个只读的 MCP Hub:各站构建时吐 JSON 快照,一个零依赖的 Cloudflare Worker 做协议层,无数据库无状态,源站一部署内容自动同步。这篇讲完整架构、双域名分流的设计,和几个刻意的取舍。
本页目录

上个月我给 Onchain Diary 做了个 MCP server,316 条 Web3 安全内容,文章加词条,中英双语。做完挺得意,发给朋友试,朋友在 ChatGPT 里配好了,问了一句「permit2 钓鱼是怎么回事」,回答里真的引用了我的文章。
然后他顺手问:你其他几个站呢?
我卡住了。我有六个站在持续更新。Web3 安全教育的,SEO 工具文档的,Astro 模板商店的,AI 行业分析的,实验室 build log,还有这个博客。每个站都有内容,都有人问过类似「你写过 XX 吗」的时刻。
按当时的路子,每个站做一个 MCP server。六个端点,六份配置。用的人要配六次,我每改一处协议层要部署六次。
这不是干活的样,这是自虐的样。
所以我把它们全收进了一个 hub。一个端点,mcp.jask.dev,六个站的内容全在里面。
先说结论:hub 不聚合数据,聚合的是静态快照
最容易走弯路的地方在这。很多人一听「聚合 MCP」,第一反应是 hub 里跑一个搜索服务,各个站的内容实时灌进来,再加个向量数据库做语义检索。
别。那是给平台团队准备的架构,不是给一个人的。
我的做法是:每个源站在自己构建的时候,顺手吐两份 JSON。
一份叫 manifest.json,是目录。每条内容的 id、标题、描述、标签、链接,轻量,一个站几十 KB。一份叫 full.json,是全文。每篇文章的完整 markdown,都在里面。
构建时生成意味着什么?意味着这些 JSON 是静态文件,跟着站点一起部署到 CDN 上,零运行时成本。我用 Hugo,就写两个 output format;用 Astro 的站,就写两个 endpoint。Hugo 十几行配置,Astro 一个几十行的 ts 文件,都是一次性的活。
hub 这个 Worker 要做的,只剩下一件事:把这些 JSON 拉下来,按 MCP 协议吐出去。
拉取有缓存。Cloudflare 的边缘缓存设了 10 分钟,Worker 内存里再存一份 5 分钟。所以源站每次 git push 部署完,最迟十几分钟,hub 里的内容就是新的。零手工维护,没有同步脚本,没有 webhook,什么都不用管。
无数据库,无状态,无队列。整个 Worker 五百多行 TypeScript,还是一个文件。
三个工具,没了
协议层我手写的,没用官方 SDK。
不是标新立异。MCP 的 streamable HTTP 传输说白了就是 JSON-RPC 2.0:initialize,tools/list,tools/call,三个请求处理掉。SDK 引进来一串依赖,为了序列化三个方法,不值当。
对外只有三个工具:
list_sites(),列出所有接入的源站,各有多少条内容search(query, site?, lang?),跨站关键词搜索,中英文都行,可以限定站点或语言read(site, id),读某一条的全文,返回 markdown
搜索的实现你看了会笑:token 匹配加打分。标题命中加 3 分,标签命中加 2 分,描述命中加 1 分,所有词都命中的才进结果,按分数排,取前十。
没有向量库,没有 embedding,没有任何 ML。因为总共就几百条内容,朴素打分完全够用,而且结果可解释。你搜「wallet drainer」,它就是标题或标签里有这个词的排前面,不会给你一个语义相近但答非所问的东西。
杀鸡别用牛刀。牛刀贵,还难洗。
一个 Worker,两个门面
有个设计我觉得值得单独说。
这个 Worker 绑了两个域名。同一个代码,根据请求的域名分流。
mcp.jask.dev 是全量版。门户页加 /mcp 子路径,六个源站全在,包括这个个人博客。这是给我自己和技术朋友们用的,谁想在 ChatGPT 里配一个都行,免认证。
mcp.uzenlabs.com 是产品版。裸根端点,POST 过来就是 MCP 本体,没有门户页,没有 /mcp 子路径。关键区别:它只暴露五个产品站的内容,我的个人博客不在里面。
为什么?个人博客写的东西,投资判断也好,踩坑吐槽也好,那是「Jask 这个人」的内容,不是「UZEN Labs 这个实验室」的内容。客户或者合作方接品牌方的 MCP,不该顺带读到我个人对行业的尖锐评论。robots.txt 全 Disallow,加了 noindex 头,两个域名之间不互相链接,搜索引擎和 AI 引擎都不会把它们搞混。
一个代码库服务两个品牌,靠域名路由,这大概是 Cloudflare Workers 最被低估的玩法。同样的招我在 AI Gateway 那篇里用过,一个网关多个 provider,思路一脉相承:入口收拢,出口分流。
几个刻意的决定
只读,免认证。 MCP server 处理的是 AI 生成的输入,天然有提示词注入的面。我只读不写、无状态、不执行任何东西,攻击面基本砍没了。免认证是因为内容本来就是公开的,加个 key 只会让想用的人多一步放弃的理由。
Revolutio 的季刊没进去。 Revolutio 接进来的只有博客 collection。它的季度报告以后要收费,付费内容放进一个免认证的只读端点,等于自己拆自己的墙。代码里这个排除逻辑是写死的,还加了个防泄漏的检查。做产品的人记住这条:不是所有内容都该进 AI 的嘴。
博客全文进了快照。 有人可能会犹豫,博客全文喂给 AI,会不会被拿去训练。我的判断在 robots.txt 层面已经做了:允许 AI 搜索引用,禁止训练爬虫。MCP 是引用的通道,不是训练的通道,这个账算得过来。而且说句实话,独立开发者最大的风险从来不是内容被读,是内容没人读。
为什么值得做这件事
回到最实际的账:这东西有什么用。
我验证过。Onchain Diary 的 MCP 加上实体归并的 JSON-LD 上线之后,Perplexity 和 ChatGPT 都能沿着链路挖通我的产品线,从品牌词出发,一路读到具体文章。AI 引擎回答「XX 是什么」的时候,引用的是我的原文,不是我竞争对手转述的版本。
这就是 GEO,生成式引擎优化。llms.txt 是给 AI 看的目录,MCP 是随时能应答的图书管理员。前者是「这里有什么」,后者是「你问,我答」。两个都做,成本几乎为零,但你在 AI 搜索时代的内容定义权就拿到了。
个人站的意义我之前专门写过,当时讲的是搜索时代的逻辑。现在逻辑升级了:搜索时代你等爬虫来,AI 时代你可以递管子过去。
想复刻的话,清单很短:
- 挑一个内容最多的站先做单站 MCP,跑通 initialize / search / read 三个方法
- 给每个源站加构建时快照,manifest 加 full,静态文件扔 CDN
- 写一个 Worker 拉快照做协议层,加两层缓存,部署完事
- 门户页放好 curl 示例和配置片段,让路过的人三十秒内能用起来
我的门户页还有个小心思:一段可直接复制的 setup prompt,你把它粘给任何 AI 助手,它要么帮你配好,要么告诉你该用什么客户端。不用注册,不用看文档。
三个工具,一个端点,六个站。想试的话,mcp.jask.dev,门户页有现成的配置片段。