Atlas / MCP servers / whyymj / page-agent-sdk

page-agent-sdkBLOCK

mcp/whyymj/page-agent-sdk

给网页一个会改页面的 AI 助手。一行代码挂载对话框,AI 通过工具按 schema 安全读写页面数据,实现「对话式」搭建/编辑/运维。

Verdict
BLOCK
Grade
F
Trust score
59 /100
Exposed tools
118 98r · 14w · 6d
Transport
streamable-http
License
ISC
Stars
1
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[English](https://github.com/whyymj/page-agent-sdk/blob/master/README.md) · [中文](https://github.com/whyymj/page-agent-sdk/blob/master/README.zh-CN.md)
Give your web page an AI assistant that edits the page itself. Mount a chat dialog in one line; the AI reads/writes page data safely via schema-validated tools — "conversational" building/editing/ops. A lighter, framework-agnostic alternative to CopilotKit / LangChain for in-page, schema-validated JSON-editing agents.
AI agent integration: see Agent Integration Cheat Sheet below (exports / options / extension points / built-in tools / file structure). Architecture & gotchas in `CLAUDE.md`.

[](https://www.npmjs.com/package/page-agent-sdk) [](https://github.com/whyymj/page-agent-sdk/blob/master/LICENSE) [](#self-tests)

🚀 Quick start? → 30-second quickstart · Examples · Options cheat sheet · Usage map

Usage map (task → where)

Starting point for both humans and AI agents (Claude Code / Cursor): find the feature you need, follow the link. Details live in sub-docs — doc/ index.

Read from source at commit 54d38ebc93b6OBSERVED · 2026-10-12
Advertisement
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add page-agent-sdk --env VITE_AI_API_KEY=${VITE_AI_API_KEY} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "page-agent-sdk": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "VITE_AI_API_KEY": "${VITE_AI_API_KEY}"
      }
    }
  }
}
03

Exposed tools (118)

98 read · 14 write · 6 destructive. Blast radius: 6 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
areadA
add_componentwrite追加一个组件(结构性工具,直改页面数据)
add_focuswrite追加聚焦一个组件子树(multi-focus,可同时聚焦多个相关组件)。校验 path 在 schema 内。聚焦后仅可写已聚焦的子树之一(越界 PATH_DENIED)。与 set_focus(替换全部)不同:本工具累积追加,不清除已有焦点。
added_toolreadadded
annotate_selectionread标注当前选区(测试桩)
ark-ui-specread方舟 UI 规范:色板 hex/间距/形态约束。生成 custom 组件前必读
breadB
big_resultread返回大结果
both_proberead流内同时手动通知与自动事件(测试用)
cachedread缓存测试
calcread简单计算器(支持 + - * / 与括号)
clear_focusdestructive清除当前聚焦,退出精修模式,恢复对全部组件的读写权限。
custom-designreadx
delete_componentdestructive删
demoread演示
diff_dataread对比当前主数据与某快照(默认最近)或一段 JSON(against)的差异,返回结构化 {path, from→to} 列表。供 verify 自纠/冲突诊断/操作审计(
docread文档
doc-skillreadd
dom_editwrite修改宿主页面元素(标注/内容/结构):patches 批量原子操作(任一失败整批拒绝)。op 集:set_text/set_html(内容)、set_attr/remove_attr、add_class/remove_class、set_style(样式)、insert(新建元素,before/after/prepend/append/replace)、remove、move(层级调整)、highlight(高亮+滚动定位)。纪律:selector 必须唯一命中(先 get_dom/dom_search 定位);改前自动快照,dom_restore 回滚;数据驱动页面请改数据而非 DOM。
dom_inforead读单个元素完整信息:内容(直接文本/全文本/HTML 片段)+ 计算样式(默认排障高频预设,可指定属性列表)+ 几何位置 + 事件绑定(inline on*/Vue props/addEventListener 记录;记录器仅覆盖 SDK 加载后注册的监听)。验证样式落地/排查交互绑定用。
dom_restoreread回滚最近一次 dom_edit 批操作(自动快照;可连续调用逐批回退,栈上限 20 批)。快照点被后续结构变更覆盖时如实报告未复原数。
dom_searchread搜索页面元素:CSS 选择器或可见文本两种模式,返回命中元素的 CSS 路径 + 文本片段(≤20 处)。定位元素/查渲染结果用;找到 selector 后可用 dom_info 看详情或 get_dom 看结构。
draft_commitwrite把 draft_write 累积的草稿合并 + JSON.parse + 乐观锁 + schema 校验,原子提交主数据(任一步失败不写,草稿保留可修后重试;成功清草稿 + 自动快照可回退)。仅大 JSON 从零生成用;小改用 write。
draft_writewrite分块写 JSON 草稿到 drafts 池(单次 write 受 max_tokens 限制装不下时用)。mode:
dt_probereadd
dynreadv1
dyn__queryreadd
echoread回声工具(测试用)
emptyread空结果
ephemeralread不持久化
eval_scriptread在 Worker 沙箱对主数据跑自定义 JS(无网络,超时 3s)。入参 data(深拷贝);mode:query 只读回给 LLM/transform 校验后落地(完整新值或 {patches:[...]} 增量);jsonPath 可限定子树。
failread失败
fetch_documentread以 GET 请求抓取文档/网页/接口文本。仅支持同源或已配置 CORS 的 URL;跨域会被浏览器拦截。大结果自动外存到虚拟工作区,可用 vfs_read / vfs_grep 回读。
get_domread读渲染后 DOM 结构(tag/attrs/text/children)。检查渲染效果/验证修改是否生效用;depth 控制深度(默认 3),attrs 限定返回属性。只读,大结果自动外存 vfs。
get_weatherread查询城市天气(模拟数据)
good2readd
hreadhost skill
hang2readd
hang3readd
hang_probereadd
hang_probe_e2eread挂起探针(测试看门狗)
history_dataread查看主数据快照(只读不回退):list:true 列时间线;传 id 看某次内容(默认最近),jsonPath 可只看子路径。对比差异用 diff_data;回退用 restore_data。
html-fragmentread完整 HTML 页面生成规范:代码作为 data 资产 / vfs 工作副本 / 完整自包含可独立成页 / script+CSS 集中放置 / 可引外部 JS/CSS / validate_code 自检 / 安全底线 / 可访问性
init-skillread集成方初始
inspect_contextread查看当前对话上下文的构成(供压缩决策)。返回:totalTokens(历史轮次 token 总和,与触发判断同口径)、occupancy(窗口占用比)、contextWindow、categories(分类占用)、rounds(每轮 token/工具/首句)。先调用本工具查看构成,再决定压缩策略。
inspect_envread读宿主页面环境信息(排查调试)。不传参返回摘要(URL/origin、浏览器/语言、viewport、title/readyState);传 key 读指定 window 属性值(如 key:
linear.mdreadLinear 极简
list_checkpointsread列出可用会话 checkpoint(回退点)。
list_xread列
load_skillwrite加载某个 skill 的完整指令到当前上下文(若 skill 配 exec,加载时自动执行脚本注入实时数据;若配 tools,加载后注入附带工具)。先从 system prompt 的 Skills 索引选合适的 skill,再调用此工具。skill 主文末若附「参考文档」目录,按需传 ref 单独加载某个参考(勿整包请求大 skill 的全部参考)。
mock_weatherreadmock weather
my-designread自定义品味
my-skillreadx
mySkillread测试技能描述
my_queryread自定义查询工具
mytoolreadd
nav_proberead流内模拟宿主导航(测试用)
no-storage-skillreadstorage 关闭也持久化
noop_toolread什么都不做的工具(对照:不改 bind 则基线不变)
notify_proberead流内触发宿主变更通知(测试用)
only_toolreadonly
orig_toolreadorig
otherreado
persist-skillread持久化测试
plainread无工具
preread前插
proberead回显 config
probe_inspectread轮中触发内省(测试用)
query_dataread用 JSONPath 查询主数据(只读):$ 根/.key/[n]/[*]/[?(==/!=/</<=/>/>=,&&/||)]/..key 递归。返回匹配元素 path/index/value(path 可作 write patch 的 jsonPath);大数组筛选定位用它;多条件筛选传 queries 数组一次取回。
rag-searchread多源知识检索策略:vfs 预注入文档 → 语义检索 → 指定文档加载 → 公网;综合结构化结论 + 溯源
raw_probereadd
readread读主数据(只读):不传 jsonPath 返回整体说明+格式;传 jsonPath 返回该路径当前值+hash;传 jsonPaths 一次读多个不相关路径。fields/depth 裁剪、offset/limit 数组分页减体积;详细规则见系统提示。
read_pageread读当前页面正文纯文本(自动定位 article/main 等文章容器;排除 SDK 对话框自身与脚本样式)。回答「这个页面讲了什么/某段内容在哪」类问题用;长文按 hasMore=true 时 offset+=本次返回长度 续读。只读,大结果自动外存 vfs。
remove_focusdestructive移除单个聚焦焦点(by path),保留其他焦点。移除最后一个等价退出精修。全部退出用 clear_focus。
resource_deletedestructive释放受保护资源(从资源池删除,后续 read 重新懒注册)。用于不再需要保护的字段或释放空间。
resource_getread取受保护字段(freeze/verbatim)的真实值(占位符背后的精确值)。仅受保护路径(集成方在 data.resources 声明)。read 返回 ⟦frozen:path⟧/⟦res:handle⟧ 占位符,确需真值时用此工具。传 path 或 handle。
resource_listread列出所有已注册的受保护资源(path/mode/handle/bytes)。
resource_updatewrite更新 verbatim 受保护字段的真实值(改精确原值,如刷新 token/hash)。仅 verbatim 可改;freeze 拒。更新后同步 bind + 标脏,后续 write 写回句柄即用新值。
restore_dataread把主数据回退到某个快照(不传 id 回退最近一次)。快照列表用 history_data({list:true})。
restore_last_checkpointread回退到最近一次正常状态(整体还原对话历史 + 主数据 + vfs + todos)。当本轮操作出错、页面被改坏、或走偏时调用,回到本轮起点重新来过。不传参数即回退最近一次。
run_scriptwrite跑
s1readdesc1
s2readd2
safe_toolread安全工具(应正常注入)
schema_dataread查看主数据(或子路径)的字段约束:类型/min/max/enum/必填/默认值/嵌套 shape。写前查约束,避免写错重试。不传 jsonPath 查根;传子路径(如 components.0)查该位置约束。
searchread搜索关键词(模拟数据)
search_dataread主数据内文本搜索(只读)。mode:substring(默认,不区分大小写)/regex(i 标志)/fuzzy(Levenshtein ≤ fuzzyThreshold)。递归遍历叶子值返回命中 path+value(超 200 字符截断);找名字记不清的元素用它。
set_focuswrite聚焦到指定组件子树(如 components.3)精修,替换全部已有焦点(非累积;要保留已有焦点追加用 add_focus)。聚焦后:仅可写该子树(越界 PATH_DENIED)+ 每轮只看到该组件结构。多组件页面精修其中一个时用,避免改到别处。先 read 定位 path 再聚焦;完成调 clear_focus。
sharedread共享
slow_builtinreadd
slow_proberead测试时序锚:稍等再返回
spawn_agentread委派一个独立子 agent 执行子任务,返回其最终结论(过程隔离,不占主上下文)。用于:分治大任务、专项调研、独立验证。子 agent 默认只读(不改页面)。
spawn_agentsread并行委派多个独立子 agent,聚合各自结论(子 agent 间互不通信,由你汇总)。适合:多路调研、多视角审查、批量处理。
staleread工具
stale__treadd
summarizeread摘要技能
tread带工具
take_screenshotread截取当前页面图像查看(视觉验证:布局/样式/渲染效果)。聚焦态下**不传 selector 默认截取聚焦组件**(宿主 data-path 锚定 —— 指代问句「这是啥/这里画的是啥」优先此取景,整页截图仅在用户明确要求时用)。selector 截取指定元素区域;fullPage 截整页(超长文档会被拒,改用 selector 分段);都不传且无聚焦截当前视口。只读;截图经压缩后投递(多模态主模型直看图,纯文本模型自动走识图转述)。
tool_areadA
tool_breadB
update_todowrite按 id 增量更新单个任务(改 content/status,不必重传整个清单)。id 见当前任务清单渲染(如 t-1)。执行中动态修订步骤用此工具;与 write_todos 不可同轮调用。
use_workerread委派 worker 子 agent(测试桩:恒被组件锁拒)
user-1read用户创建 1
validate_coderead校验 HTML 代码格式(标签闭合等结构合法性;DOCTYPE/html/head/body/script 均允许 —— 完整页面级)。生成/修改代码后必调;报错修正后复查直到通过。
vfs_editwrite精确替换虚拟工作区文件中的一处字符串(oldString 必须唯一)。
vfs_globread按 glob 模式匹配虚拟工作区文件名(* 匹配非斜杠,** 匹配任意)。
vfs_grepread在虚拟工作区文件内容中正则搜索。
vfs_json_patchdestructive在虚拟工作区 JSON 文件内做原子 jsonPath patch(set/remove/merge/append)。先 parse → clone 上应用全部 patches → 任一失败或 JSON 非法则整体不写回(原文件不变)。
vfs_json_readread把虚拟工作区文件当 JSON 读取:先 parse 整文件,再按 jsonPath 取子树(省略返整体)。文件非合法 JSON 报 VFS_JSON_INVALID。适合结构化读取 vfs 内大 JSON。
vfs_lsread列出虚拟工作区所有文件。
vfs_readread读取虚拟工作区文件,支持分页(offset 行号、limit 行数)。用于回读大工具结果外存的内容。
vfs_rmdestructive删除虚拟工作区文件(清理中间产物 / drafts 下草稿,补「只进不出」的闭环)。不存在返回 NOT_FOUND。
vfs_writewrite写入/覆盖虚拟工作区文件,作为中间工作记忆。jsonString=true 时校验 content 是合法 JSON(配合 vfs_json_read/vfs_json_patch 操作 JSON 文件)。
view_imageread查看一张图片 URL 的内容(页面数据里读到的图:轮播某一帧/商品图/封面等)。优先客户端物化直投(全分辨率原图,非截图渲染);问「第 N 张图/这张图画的是啥」且手里有该图 URL 时优先用它,不要截当前渲染帧(自动轮播可能已切到别的帧)。若供应商下载 URL 失败(报 Failed to download image),改用 take_screenshot 看渲染区域。参数 url 须为 http(s)。
wdereadweb 设计
writewrite恶意写入工具(应被拒绝)
write_todoswrite更新(整表替换)任务清单。用于多步任务的拆解与进度跟踪。每次传入完整的 todos 数组(状态 pending/in_progress/completed),不要增量 patch——增量改单项用 update_todo。
xreadX
04

Trust audit

BLOCKgrade F · trust 59/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)FAIL
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
declared (5 observation(s))
Shell
declared (2 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
.claude/skills/check-res-urls/scripts/check-res-urls.js:70
https.get(target, { rejectUnauthorized: false }, (res) => {
Why it matters. certificate verification is disabled
Fix. leave verification on
HIGHPrompt injection · prompt.credential_read · CWE-94, CWE-1427
.claude/skills/browser-e2e-testing/SKILL.md:40
SDK 在浏览器里执行 ReAct 循环(真跑 read/write 工具),mock 只提供 LLM 响应。**不需要 API key,可进 CI**。
Why it matters. asks the agent to read credentials
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/proxy-mock-server.ts:153
console.log(`[proxy-mock]   POST /api/refresh      → 返回新 token(演示 refreshToken)`)
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/proxy-mock-server.ts:154
console.log(`[proxy-mock] 有效 token:demo-token-xxx / demo-token-expired 触发 401 演示刷新`)
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
scripts/proxy-mock-server.ts:77
res.end(JSON.stringify({ token: 'demo-token-refreshed-' + Date.now() }))
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/core/__tests__/modules/sec-79.ts:80
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
clear_focus, delete_component, remove_focus, resource_delete, vfs_json_patch, vfs_rm
Why it matters. 6 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/core/__tests__/modules/sec-05.ts:177
assert(/脚本执行失败/.test(rr), '✓ exec 失败不缓存:跨轮重新 load → 重新执行 exec(动态 skill 可重试)')
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/core/__tests__/modules/sec-05.ts:218
await ls.invoke({ name: 'empty' })  // 未缓存 → 重跑 exec(成功空结果 __cnt=2;node 下失败重试 __cnt=0 恒不缓存)
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/core/__tests__/modules/sec-107.ts:169
Promise.resolve({ ok: true, result: new Function('data', script)(data), elapsedMs: 1 })
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/core/__tests__/modules/sec-109.ts:161
new Promise((resolve) => resolve({ ok: true, result: new Function('data', script)(data), elapsedMs: 1 }))
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/core/__tests__/modules/sec-116.ts:30
try { exprResult = new Function('data', wrapped)([1, 2, 3]) } catch { exprResult = 'THREW' }
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/runtime/_real-llm-lib.mjs:250
console.log(`  耗时 ${(scenario.elapsedMs / 1000).toFixed(0)}s | 工具×${scenario.toolCount} | token ${JSON.stringify(data.usage)}`)
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/runtime/complex-ops-real-llm.mjs:157
console.log(`  token: prompt=${data.usage.prompt ?? 0} completion=${data.usage.completion ?? 0} | 委派=${rec.delegated}`)
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/runtime/image-input-real-llm.mjs:131
console.log(`  token: prompt=${data.usage.prompt ?? 0} completion=${data.usage.completion ?? 0} | ${rec.elapsed}s`)
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
examples/docs-demo/quickAsk.ts:11
import type { ChatSdk } from '../../src/core'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
examples/docs-demo/quickAsk.ts:19
loading = import('../../src/core').then(({ createChatSdk, systemPromptHelpers }) => {
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
examples/dynamic-demo/componentSchemas.ts:1
import { z } from '../../src/core'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
examples/nested-demo/treeData.ts:1
import { z } from '../../src/core'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
examples/quick-ask-demo/main.ts:11
import type { ChatSdk } from '../../src/core'
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e/mcp.mjs:67
mcp: [{ transport: 'http', url: `http://127.0.0.1:${dead.port}/mcp`, name: 'dead', timeoutMs: 1200 }],
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e/mcp.mjs:85
mcp: [{ transport: 'http', url: `http://127.0.0.1:${dead.port}/mcp`, name: 'dead2', timeoutMs: 1200 }],
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e/mcp.mjs:105
mcp: [{ transport: 'http', url: 'http://127.0.0.1:3192/mcp', name: 'rag-mock' }],
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e/mcp.mjs:144
mcp: [{ transport: 'http', url: 'http://127.0.0.1:3195/mcp', name: 'malicious' }],
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e/mcp.mjs:201
{ transport: 'http', url: `http://127.0.0.1:${dead.port}/mcp`, name: 'dead', timeoutMs: 1200 },

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 54d38ebc93b6full audit observations/trust-audit/mcp-server/whyymj__page-agent-sdk.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-1254d38ebc93b6BLOCKF59first audit
06

Questions

What is the page-agent-sdk MCP server?

给网页一个会改页面的 AI 助手。一行代码挂载对话框,AI 通过工具按 schema 安全读写页面数据,实现「对话式」搭建/编辑/运维。

What tools does page-agent-sdk expose?

118 in total: 98 read-only, 14 that write, and 6 that can delete or overwrite (clear_focus, delete_component, remove_focus, resource_delete, vfs_json_patch). Every one is listed on this page with its risk.

Is page-agent-sdk safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (59/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 6 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does page-agent-sdk need?

It reads VITE_AI_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does page-agent-sdk run?

It speaks streamable-http, so it runs as a service you connect to over the network. It is published on npm as page-agent-sdk at 4.24.5.

How current is this page?

The grade is for one exact copy of the source (54d38ebc93b6), read on 2026-10-12. The repository is watched and re-audited when it changes.

Advertisement