Skip to content

feat(webmcp): expose content, navigation and comment tools to browser agents - #6

Open
priority3 wants to merge 4 commits into
mainfrom
feat/webmcp-tools
Open

priority3 wants to merge 4 commits into
mainfrom
feat/webmcp-tools

Conversation

@priority3

Copy link
Copy Markdown
Owner

把站点能力以 WebMCP 工具形式注册到 document.modelContext,让浏览器内置 AI agent 不用靠 DOM 抓取就能检索文章、导航站点、读评论。

规划文档在 .trellis/tasks/08-28-webmcp-tools/(prd / design / implement)。

8 个工具

工具 复用
内容 search-posts get-post 构建期 /search-index.json
导航 get-page-context navigate-to-post goto-section location.prose h2-h4[id]
评论 list-comments check-comment-auth draft-comment 现有 /api/comments[data-comments-input]

三条安全边界

  1. navigate-to-post 用路由白名单/keystatic/api 是「构造上排除」而非显式封禁。前缀匹配是 === prefix || startsWith(prefix + '/'),所以 /postsevil 这类混淆会被拒。
  2. draft-comment 只填草稿不提交 —— 发评论会以访客自己的 GitHub 身份不可逆地写入 Issue。工具把文本填进现有 textarea、滚动聚焦,然后交还给用户点「发表评论」。
  3. 客户端不 import @/lib/comments —— 它看着是一堆纯函数,实际会传递依赖到 @/lib/github@/lib/comments-token(读 server env)。所以 page-context.ts 里重写了 commentKey(),这个重复是刻意的,已在 spec 里标注同步要求。

渐进增强

BaseLayout 只多了 7 行。首屏仅 229 bytes 的特性检测;12KB 工具代码走动态 import(),只有存在 WebMCP 宿主时才下载;搜索索引更晚,首次内容工具调用时才 fetch。不支持 WebMCP 的浏览器完全不受影响。

已验证

项目 结果
pnpm check 1 error = baseline(预先存在的 Keystatic 类型问题),新文件零错误
pnpm build 通过,dist/search-index.json 15 篇 / 34KB
路径白名单 25 项实测:18 项攻击输入全拒(//evil.examplejavascript:/keystatic/postsevil),7 项合法路径全放行
检索逻辑 14 项实测:中英文查询、collection 过滤、limit、空查询、4 种路径形式的 findPostdisplay:false 不可检索
dev 模式 5 条路由全 200,无运行时错误
零回归 未配 token 时 HTML 无 origin-trial meta;评论区 data-* 钩子完好

索引是 15 篇不是 16 —— toy-record.mddisplay: false 被正确排除。顺带发现:posts/[...slug].astro 用的是未过滤getCollection,所以隐藏文章仍会生成页面,只是不进列表和索引。已写进 spec。

⚠️ 未验证 —— 合并前请人工确认

draft-comment 不提交表单这条只做了静态检查grep 确认代码里没有 submit() / requestSubmit() / .click()),没有浏览器实测。工具的实际调用需要 Chrome 149+ 带 origin trial token 或 flag,或 ChatGPT Desktop。

需要实测的清单:

  • (await document.modelContext.getTools()).map(t => t.name) 列出 8 个工具
  • search-posts({ query: 'vue' }) 命中 vue3-contribution
  • navigate-to-post({ path: 'https://evil.example' }) 被拒
  • draft-comment({ text: '测试' }) 后文本入框、滚动到评论区、GitHub 无新增评论

注意 deploy preview 的域名(deploy-preview-N--*.netlify.app)与 origin trial token 绑定的 razet.me 不匹配,所以 preview 上只能用带 flag 的 Chrome 测。

前置项(合并后)

未完成这些也可以合并 —— 不配 token 就不输出 meta 标签,工具保持休眠,站点不受影响。

回滚

BaseLayout.astro 删掉 <WebMcp /> 和 origin-trial meta 两行即完全禁用,其余文件成为死代码,不影响运行。

… agents

Register 8 tools on document.modelContext so browser-integrated AI agents can
search and read posts, navigate the site, and read comments without DOM scraping.

- content:    search-posts, get-post (backed by build-time /search-index.json)
- navigation: get-page-context, navigate-to-post, goto-section
- comments:   list-comments, check-comment-auth, draft-comment

Safety boundaries:
- navigate-to-post uses a route allowlist, so /keystatic and /api are excluded by
  construction; prefix matching rejects /postsevil-style confusions
- draft-comment only fills the existing textarea and scrolls to it — publishing to
  GitHub Issues stays a user action
- client code re-implements commentKey() instead of importing @/lib/comments,
  which transitively pulls server-only env readers into the browser bundle

Progressive enhancement: BaseLayout ships a 229-byte feature check; the 12KB tool
chunk loads via dynamic import only when a WebMCP host exists, and the search index
is fetched only on first content-tool use. Browsers without WebMCP are untouched.

Origin trial token comes from PUBLIC_WEBMCP_ORIGIN_TRIAL_TOKEN; unset emits no meta
tag. Register at https://developer.chrome.com/origintrials before deploying.
@netlify

netlify Bot commented Aug 28, 2026

Copy link
Copy Markdown

Deploy Preview for priority-me ready!

Name Link
🔨 Latest commit da01d0f
🔍 Latest deploy log https://app.netlify.com/projects/priority-me/deploys/6a92241ed2c95b0008b9e89b
😎 Deploy Preview https://deploy-preview-6--priority-me.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant