Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
作者提供的说明(英文原文)
The deterministic attack-surface perception layer for AI security agents
这三项永远不会合并成一个分数:意见、测量和人气是不同的东西。
我们还没有为它写通俗的介绍。下面是我们从注册中心读取到的事实。
选择你使用的 AI 应用,然后复制设置。
你需要
你用的是哪个应用?
在上方选择你的应用。我们会记住它,下次按钮会显示“安装到 …”。
打开 Claude Desktop → Settings → Developer → Edit Config,把下面的内容粘贴到 claude_desktop_config.json
{
"mcpServers": {
"zerodom": {
"command": "npx",
"args": [
"-y",
"@vexralabs/zerodom"
]
}
}
}在终端中运行这条命令
claude mcp add zerodom -- npx -y @vexralabs/zerodom粘贴到项目中的 .cursor/mcp.json,或 ~/.cursor/mcp.json
{
"mcpServers": {
"zerodom": {
"command": "npx",
"args": [
"-y",
"@vexralabs/zerodom"
]
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
粘贴到项目中的 .vscode/mcp.json
{
"servers": {
"zerodom": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@vexralabs/zerodom"
]
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
这个服务器在你的电脑上运行,而 ChatGPT 只能连接互联网上的服务器。请选择其他应用。
你的选择通过 Cookie 保存在这台设备上,无需账户。
这些设置是根据作者在注册中心的条目生成的。如果 README 的写法不同,请以 README 为准。
它在你的电脑上运行;安装后,工具列表会显示在你的 AI 应用中。
我们检查的是任何人都能看到的信息;我们没有阅读代码。不适用的检查项不计入总数。 · 检查于 2026年11月6日
注册名称已通过 GitHub 账户 DevHusnainAi 验证,该账户拥有此仓库
我们还没有从 GitHub 读取这个仓库
我们还没有从 GitHub 读取这个仓库
它在你的电脑上运行,没有互联网端点
在你的电脑上运行,改用本地设置
它在你的电脑上运行;我们只能读取互联网端点的工具列表
与注册中心里这个分类中所有活跃的服务器比较。只有当发布者拥有该仓库时,星标数才计入。
它在 1 项适用的基础检查中通过了 1 项。我们没有阅读代码。在添加密钥或令牌之前,请先看看这个服务器要求哪些权限,并使用只具备所需权限的密钥。
注册中心没有列出必需的密钥,不过有些服务器会在首次使用时要求你登录。
它在你的电脑上运行。你的 AI 应用会在需要时启动它,数据不会经过作者的服务器(除非它自己调用在线服务)。
GitHub 仓库最后更新于–,最新版本(0.1.5)于4天前进入注册中心。
支持 MCP 的应用,例如 Claude Desktop、Claude Code、Cursor 和 VS Code。你的电脑上还需要有 Python (uv), Node.js。
同一分类中有:Spec Driven Development, Remote Desktop Commander, zanadir
同一分类中其他作者的服务器,按星标数排序。
如何看卡片:★ GitHub 星标i三大支柱:评价 · 检查 · 使用情况i更新 = 最新版本发布到注册中心的时间i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Find what a repository's CI is missing, and which security checks cannot fail the build.
按原文从作者的仓库复制。PopNx MCP 没有审查或背书其内容。HTML、图片和脚本已被移除。链接会离开本站。
ZeroDOM drives your real, logged-in browser as two identities, replays the same requests as each, and flags where one user reaches what another can't — IDOR / broken access control, caught deterministically. Open-core, runs local, no account, no API key, nothing leaves your machine.
Under the hunt is a deterministic, token-lean perception engine for AI agents — the same core powers scan , crawl and any browser-driving task. IDOR is just where it bites hardest.
[Site](https://zerodom.vexralabs.com) · [Docs](https://zerodom.vexralabs.com/docs) · [Playground](https://zerodom.vexralabs.com/playground) · [Discord](https://discord.gg/tVRznUb5Ez) · [Quickstart ↓](#quickstart)
A normal user is denied the admin console (401) — then walks in by flipping one client-controlled cookie. ZeroDOM proves it: same request, two identities, 401 vs 200 . Full recording (mp4) .
compare & sweepTwo audiences, one engine:
scan --js adds DOM-XSS sinks, the callable API surface and header posture; repeat / probe / race turn recon into verification (Repeater, mass-assignment diff, and a TOCTOU burst).aria_snapshot, with handles that resolve 1:1 and don't drift when the page re-renders.Broken access control is the #1 web vulnerability (OWASP A01) and the one automated scanners miss — because catching it means knowing *who should be allowed to do what*, not just fuzzing one session. The usual answer is a human in Burp, clicking through the app as one user, then again as another, diffing by eye.
ZeroDOM does that mechanically. Give it two logged-in sessions; it replays the same request as each and reports the deterministic tells:
200, the other 401/403 on an identical request. If the only difference between them is client-controllable (a cookie, header or param), that's broken access control.No LLM guessing, no "the AI thinks maybe." ZeroDOM surfaces the tell with the exact replay that proves it — a reviewable diff you drop straight into a bug report. You confirm the bug.
It drives your real Chrome (relay mode) over chrome.debugger, so your cookies, MFA and SSO are already done — or a throwaway browser (--stealth) if you'd rather not touch your session. Either way the page's markup never leaves your machine, and it's read-only by default: destructive actions and out-of-scope hosts are refused.
It works equally well as a one-line CLI, a recon pipeline stage, or a native tool an
AI agent drives through MCP. Same deterministic primitives, three front doors.
See it run in 10 seconds — no account, no browser download (bare zerodom is a static fetch, no Chromium needed):
pip install zerodom # or: uvx zerodom · npm i @vexralabs/zerodom
zerodom https://news.ycombinator.com # the interaction graph + a token report
That's the perception engine — a flat, 1:1-addressable graph instead of 12k tokens of HTML.
Now the flagship — find an IDOR. Save two logged-in sessions as Playwright storage_state files (one per account), then diff a protected endpoint across both:
zerodom compare https://app.example.com/api/admin/dashboard \
--as user=user.json --as admin=admin.json
{
"identities": { "user": { "status": 401, "bytes": 2616 }, "admin": { "status": 200, "bytes": 3469 } }, "only_admin": ["Manage users", "Billing & plans", "Overview"], "note": "admin authorized (200) where user denied (401) — broken access control if the only difference is client-controllable" }
That's the whole loop: same request, two identities, a 401-vs-200 split → a lead to confirm. only_admin lists the privileged controls the normal user should never see.
Don't have storage-state files? Capture one with context.storage_state(path="user.json") in Playwright, or export cookies from a logged-in session. Want the whole app, not one URL? → zerodom sweep.
compare & sweepzerodom compare — one endpoint, across identitiesFetch one URL under each saved session and diff the responses. Byte-identical content across two users on a private resource is a cross-tenant IDOR; a 401-vs-200 split is a broken boundary. only_ lists the actionable nodes each identity sees that the other doesn't.
# Sweep a range of object ids through two identities:
seq 1 500 | sed 's#^#https://app.example.com/api/invoice/#' \ | zerodom compare - --as alice=alice.json --as bob=bob.json \ | jq 'select(.identical_body_pairs | length > 0)'
zerodom sweep — the whole app, one commandcompare tests one URL. `sweep` does the entire app: it crawls as one identity to map the GET surface (pages + the API calls the JS fires), then replays every in-scope URL under *all* your identities and reports only the deterministic tells.
zerodom sweep https://app.example.com --as user=user.json --as admin=admin.json --format md
| severity | rule | url |
| -------- | ---------------------- | ------------------------------------- | | medium | access-boundary-split | https://app.example.com/api/admin/... |
Read-only throughout: only GET is replayed, destructive URLs are dropped (--deny). --format md emits a report-ready table (default is JSONL). This is the "point it at an app with two logins and it finds the broken access control" pass.
Both take --proxy (route through Burp/Caido), --header (a program's WAF-bypass token), and a scope you can lock. Challenge pages (Cloudflare / Turnstile / reCAPTCHA / hCaptcha) are detected and climbed by a scope-gated clearance ladder; a wall nothing clears is reported as an honest blocked, never worked around outside an authorized target.
repeat / probe / raceMapping an app surfaces the endpoints; these verbs act on them. repeat is a Repeater over the session (--save writes HAR/.http evidence for a report). probe replays an endpoint with a tampered body and diffs it against the baseline — an accepted, reflected field is a mass-assignment lead. race fires a concurrent burst (one body, or a mix of operations via repeated --body) to flag a check-then-act race (TOCTOU); the stdlib engine is always available, and --engine http2 multiplexes the burst over one connection via the optional zerodom[race] extra.
zerodom race https://app.example.com/api/coupon --body '{"code":"SAVE20"}' -n 30 \
--setup setup.json --check https://app.example.com/api/cart
All three are exposed to agents over MCP as zerodom_repeat / zerodom_probe / zerodom_race.
Standard MCP browser tools hand the model raw pixels (slow, stale on scroll) or an accessibility tree (no stable handles — repeated controls collide). zerodom-mcp gives your agent a flat, token-frugal graph where every click [45] resolves deterministically over CDP to exactly one element — and the same tools do cross-identity IDOR hunting the others can't. Why ↓
ZeroDOM is a native MCP server, so Claude, Cursor or any MCP agent can hunt with the same primitives. Run zerodom setup for a guided first-run (checks Chromium, prints the extension path + chrome://extensions steps, emits the config below, reports relay reachability — print-and-guide, no account, nothing leaves your machine).
// Claude Desktop: claude_desktop_config.json · Cursor: .cursor/mcp.json
{ "mcpServers": { "zerodom": { "command": "uvx", "args": ["--from", "zerodom", "zerodom-mcp"] } } }
Once before first use (so the server never downloads mid-tool-call): uvx --from zerodom playwright install chromium.
Using LangGraph, CrewAI, OpenAI Agents SDK, Pydantic AI, LlamaIndex, Google ADK or AutoGen? Ready-to-run MCP examples — same server, a few lines each — are in examples/integrations/.
The full tool set (click to expand)
| tool | what it does |
|---|---|
zerodom_parse_url(url, verbose=False, frames=False, viewport_only=False, check_occlusion=False) | navigate, return the compact graph; frames=True also reads same- and cross-origin iframes (auth portals, payment fields) |
zerodom_read_page(verbose=False) | re-read the live DOM without navigating |
zerodom_find(query) | return only the nodes matching a phrase |
zerodom_click_node(node_id) | click, then return what changed — flags a same-page no-op shortly after navigation as a possible hydration miss |
zerodom_fill_node(node_id, text) | type via real keystrokes — works in contenteditable editors (Notion, Slack, Discord, Jira) |
zerodom_hover(node_id) | hover, revealing hover-triggered menus/tooltips |
zerodom_press_key(node_id, key) | press a key on a focused node (Enter, Escape, Tab, …) |
zerodom_upload_file(node_id, path) | set a file input's value to a local path |
zerodom_drag(source_node_id, target_node_id) | drag one node onto another |
zerodom_scroll(direction, amount=800) | scroll, return what's newly visible |
zerodom_new_tab(url=None) | open a tab and make it active |
zerodom_list_tabs() | list every open tab, marking the active one |
zerodom_switch_tab(tab_id) | make another open tab active |
zerodom_close_tab(tab_id=None) | close a tab (the active one by default) |
zerodom_screenshot(path=None) | full-page screenshot of the active tab, saved to disk |
| `zerodom_set_viewport(wi
只显示了开头部分;其余内容请在仓库中阅读