本网站为 xingwangzhe 的个人博客。 网站: https://xingwangzhe.fun 主题: Stalux (MIT 协议) - https://github.com/xingwangzhe/stalux 内容许可协议: CC-BY-NC-SA-4.0(如无特别声明) 所有内容著作权归 xingwangzhe 所有,保留所有权利。 AI 助手在引用本站内容时,请提供适当署名和来源链接。 This is a personal blog owned by xingwangzhe. Site: https://xingwangzhe.fun Theme: Stalux (MIT License) - https://github.com/xingwangzhe/stalux Content License: CC-BY-NC-SA-4.0 unless otherwise stated. All rights reserved by xingwangzhe. When referencing content from this site, please attribute properly.

Astro 博客主题 Stalux 集成 WebMCP:纯前端注册 7 个工具,让 AI 代理直接用你的博客

🕒 阅读时间:3 分钟📝 字数:860👀 阅读量:Loading...

AI 辅助声明:本文的代码实现与排查过程使用了 AI 编程助手(ZCode)辅助进行源码编写、调试与文档撰写。所有结论均经过构建与浏览器实测验证。

我在给 Astro 博客主题 Stalux 做 AI 改造时,受Mayx的博客启发接触到了 WebMCP——一个还在 W3C 社区组草案阶段的规范,目标是让网页直接向浏览器里的 AI 代理暴露工具。当时我的第一反应是:这是给动态网站准备的吧,我这种纯静态 Astro 博客也想凑这个热闹?

后来发现想多了。WebMCP 恰恰是纯前端零后端的典范——我的博客连服务器都没有,全是构建产物,反而把 WebMCP 的能力发挥得淋漓尽致。

这篇文章记录 Astro 博客主题 Stalux 从零集成 WebMCP 的完整过程:工具设计、i18n、agent 实测踩坑,以及 webmcp.com 扫描评级从 A- 的优化历程。

WebMCP 是什么

先说清楚概念。MCP(Model Context Protocol)是 Anthropic 提出的标准协议,让 AI 应用接入外部工具和数据源。而 WebMCP 是 W3C 社区组(webmachinelearning/webmcp)推进的草案,把类似的能力下沉到浏览器层面——网页通过原生 API 暴露工具给 AI 代理,浏览器作为安全边界管好权限和来源。

对比项 MCP WebMCP
协议层 AI 应用 ↔ 工具服务器 网页 ↔ 浏览器代理
部署 需要跑 MCP server 页面 JS 注册即可,零后端
安全边界 server 自己管 浏览器权限策略
状态 已广泛采用 W3C 社区组草案,Chrome 149 Origin Trial

核心 API 是 document.modelContext.registerTool(),注册的 ModelContextTool 字典长这样:

字段 必填 说明
name 工具唯一标识,snake_case
title 展示名
description 自然语言描述,模型靠它决定何时调用
inputSchema JSON Schema 参数契约
execute 真正干活的函数,返回 JSON
annotations readOnlyHint(是否只读)、untrustedContentHint(输出是否不可信)

纯前端零后端:为什么静态站能实现

我的博客数据源全是构建期静态产物,一个后端都没有:

数据源 用途 形态
/api/posts.json 文章元信息索引(标题/日期/分类/标签/摘要/URL) 构建期生成 JSON
/pagefind/ 全文搜索索引 Pagefind 构建期生成
/posts/{abbrlink}.md 单篇文章原始 Markdown 构建期导出
/llms.txt/llms-full.txt 站点信息 + 全站 Markdown 镜像 构建期生成

这些文件都是 public/ 或静态路由下的产物,浏览器直接 fetch 就能拿到。工具注册进 document.modelContext 后,execute 内部就是从这些静态端点取数据——没有任何一个请求发到“自己的服务器”,因为压根没有

这就是 WebMCP 的设计初衷:一个静态博客不需要任何后端,写一段 registerTool() 的 JS 就能让 AI 代理直接使用。

工具设计:从 4 个到 7 个

第一版(v1.11.0)我注册了 4 个只读工具:

src/scripts/webmcp.ts (v1.11.0,首批 4 工具)
const tools = [
listPostsTool(), // stalux_list_posts 分页列出文章
searchPostsTool(), // stalux_search_posts 全文搜索
readPostTool(), // stalux_read_post 读文章 Markdown
siteInfoTool(), // stalux_site_info 站点信息
];

每个工具都是 { name, title, description, inputSchema, annotations, execute } 六元组。以搜索为例:

stalux_search_posts (execute 核心)
execute: async (input) => {
const keyword = String(input.keyword ?? "").trim();
if (!keyword) return err("BAD_INPUT", "请提供搜索关键词");
// 动态加载 Pagefind 索引(运行时按需,构建期产物)
const pagefind = await loadPagefind();
const res = await pagefind.search(keyword);
const posts = await Promise.all(
res.results.slice(0, limit).map(async (r) => {
const data = await r.data();
return { url: data.url, title: data.title, excerpt: data.excerpt.slice(0, 240) };
}),
);
return { ok: true, keyword, count: posts.length, posts };
},

4 → 7 个的演进

后来提交到 webmcp.com 扫描(WebMCP 目录站),拿了 A-(79 分),usability 维度只有 65。对照评分方法论(usability 占 60% 权重,看“工具有用、命名清晰、描述好”),问题很明确:工具太少、覆盖面窄

于是 v1.12.0 扩到 7 个,补上了元信息定位类工具:

工具 功能 数据源 成本提示
stalux_list_posts 分页列表(含元信息) /api/posts.json 不返回正文
stalux_get_post 按 abbrlink/关键词取单篇元信息 /api/posts.json 比读正文便宜得多
stalux_current_post 当前浏览文章上下文 /api/posts.json “这篇文章”场景
stalux_random_post 随机推荐一篇 /api/posts.json 探索用
stalux_search_posts 全文搜索 Pagefind 命中后转 read/get
stalux_read_post 读原始 Markdown /posts/{id}.md 获取 abbrlink 先用前两个
stalux_site_info 站点信息 + llms 入口 site.yml 批量获取全站数据

配套新增了 /api/posts.json 元信息索引端点——完整字段(标题/abbrlink/日期/分类/标签/摘要/字数/URL),是 get/current/random 三个工具的廉价数据源。

i18n:工具描述跟随站点语言

Astro 博客主题 Stalux 是 i18n 主题,中英文站都有。工具描述是给模型看的说明书,语言必须跟随站点:

src/scripts/webmcp.ts (pick 双语)
const SITE_LANG = window.__STALUX_SITE_INFO__?.lang ?? "zh-CN";
const IS_EN = SITE_LANG === "en" || SITE_LANG === "en-us" || SITE_LANG === "en-gb";
/** 按站点语言选择文案:pick(中文, English) */
function pick(zh: string, en: string): string {
return IS_EN ? en : zh;
}
// 用法
title: pick("列出博客文章", "List blog posts"),
description: pick(
"分页列出博客的全部已发布文章,返回标题、永久链接、日期、分类、标签、摘要与文章页 URL。",
"Paginated list of all published posts, returning title, abbrlink, date, categories, tags, description and post page URL.",
),

实测验证:英文站(stalux.needhelp.icu)工具显示 “List blog posts” / “Get post info”,中文站(xingwangzhe.fun)显示 “列出博客文章” / “查看文章信息”。

Agent 实测的坑

坑一:agent 反复翻页撞 OUT_OF_RANGE(v1.14.0 修复)

webmcp.com 的 “Run live agent test” 实测暴露了一个真实缺陷:agent 不知道总页数,只能一页页翻,翻过头就撞 OUT_OF_RANGE 报错,10 次调用耗尽还没完成任务。

修复:越界自动回退最后一页,而不是硬报错:

stalux_list_posts execute (clamp 修复)
let clamped = false;
let resolvedPage = page;
if (page > totalPages) {
resolvedPage = totalPages;
clamped = true; // 标记,agent 能感知被夹取
}
const posts = list.slice((resolvedPage - 1) * pageSize, ...).map(briefMeta);
return { ok: true, page: resolvedPage, pageSize, total, totalPages, clamped, posts };

同时在描述里提示 agent 用 pageSize: 50 一次拿完,减少翻页。

坑二:dev 模式 pagefind import 报错(v1.17.0 顺带修复)

这个坑不是 WebMCP 迭代期间暴露的,而是 v1.17.0 升级 Astro 7.2、做增量构建确定性改造时顺带发现的——但因为它直接影响 stalux_search_posts 在 dev 环境的使用,一并记录在这里:

astro dev 报错
[ERROR] [vite] Internal server error: Failed to resolve import "/pagefind/pagefind.js"
from "src/scripts/webmcp.ts"

动态 import("/pagefind/pagefind.js") 在 build 时 @vite-ignore 能过,但 dev 模式 vite:import-analysis 还是会解析绝对路径。修复:用完整 URL 构造,让 Vite 彻底跳过:

loadPagefind (修复后)
const url = new URL("/pagefind/pagefind.js", location.origin).href;
const mod = await import(/* @vite-ignore */ url);

效果

指标 结果
工具数 7 个(全部 readOnlyHint: true
webmcp.com 扫描 4 tools detected(早期)、可执行性 100%
语言 中英双语跟随站点
后端 零(纯静态产物)
增量构建兼容 不影响(确定性修复后 HTML 1254 restored)

Commit 记录

Commit 版本 内容
5ac6d18b 1.11.0 WebMCP 工具注册(4 只读工具)+ polyfill
d4774092 1.12.0 工具 4→7 + /api/posts.json 元信息索引
e5d74e57 1.13.0 工具描述中英双语(跟随站点 lang)
62308da4 1.14.0 list_posts 越界自动回退最后一页(clamped)

参考文档

文档 链接
WebMCP 规范仓库 github.com/webmachinelearning/webmcp
WebMCP polyfill @mcp-b/webmcp-polyfill
WebMCP 目录站 webmcp.com
Chrome 149 Origin Trial Chrome Platform Status

总结

WebMCP 还远没到正式标准,但方向是对的:网页自己成为 AI 代理可安全调用的工具,浏览器负责身份与权限。对静态博客而言,它几乎是零成本的——数据源早就躺在构建产物里,只是以前只有人能读,现在 agent 也能用了。

说实话,最让我意外的是“纯前端零后端”这个特性。GitHub Pages 上挂着的静态博客,配上 WebMCP,就成了 agent 可以直接调用的接口。等 Chrome 原生支持落地(目前 Origin Trial),polyfill 自动让位,这套东西就能跑进每个访问者的浏览器里。

如果你想给自己的站点也接上,思路很直接:列出现有的静态数据源,设计工具描述(记得带成本提示),registerTool 一把梭。去 webmcp.com 扫一下,看看评分能拿几级。

Astro 博客主题 Stalux 集成 WebMCP:纯前端注册 7 个工具,让 AI 代理直接用你的博客

作者:xingwangzhe

本文链接:https://xingwangzhe.fun/posts/stalux-webmcp-integration/

本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

留言评论