Skip to main content
Glama
Parker-Fawcett

rebuild-dossier

rebuild-dossier

DOI

一个 MCP 服务器,它从现有应用中逆向工程出一份可信的 重建规格 —— 一份锁定的 CLAUDE.md.claude/ 配置,以及一套经过变异测试的测试套件 —— 这样任何编码代理都可以依据该规格干净地重建应用,而不是靠猜测。

它并不重建应用。 它产出的是编码代理用来单独完成重建所需的规格、契约和测试。这个边界是有意为之的 —— 参见下面的 为什么

状态:v0。 核心循环已经工作,并已针对一个真实、混乱的仓库进行了端到端验证,包括在两个模型层级上进行了两次独立的、全新代理的交接。请阅读 docs/v0-findings.md 了解诚实的结论,包括哪些地方出了问题。

为什么

先前的研究(AgentModernize, arXiv:2605.17535)发现,如果没有经过验证的反馈循环,重建管线的行为等价性得分为 0%,而使用粗略的反馈循环也只有 9–19%。这个工具背后的赌注是:在运行测试 之前 锁定接口契约,再加上严格的“一次一个测试”的重试循环,而不是批量重新生成,会取得明显更好的效果。

任何此类管线中最危险的部分是静默地将一个 bug 验证为有意行为 —— 四种证据来源可能悄无声息地就同一个错误达成一致,而没有人解释过原因。因此,这个工具中唯一不可协商的规则是:自动解决歧义需要信号一致 以及 一个肯定的信号,表明有人确实做出了决定(一个明确的注释、一个承认 bug 的 TODO,或直接的人工回答)。仅凭静默的一致 —— 代码和观察到的行为仅仅匹配,而没有人解释过原因 —— 永远会变成一个疑问,而不是自动解决,无论表面上的置信度有多高。

Related MCP server: reforge-mcp

工作原理

六个 MCP 工具,在普通的 Claude Code(或任何兼容 MCP 的)会话中运行:

工具

作用

ingest_repo(path)

仅静态分析,不调用 LLM:路由、package.json、构建配置(通过 AST,绝不执行)、现有测试,以及结构性气味检测器(例如,仅客户端凭据检查而没有服务端验证),这些检测器即使没有人评论过,也能暴露真实的歧义。

crawl_site(url)

无头 Playwright 爬取可达路由,并带有进度通知,这样长时间爬取不会被误杀为无响应。

flag_known_bug(description)

自由文本,原样存储。对于任何匹配的内容,始终覆盖自动解决 —— 这是系统中最廉价、最权威的信号。

get_case_queue() / resolve_case(id, decision)

歧义队列。当客户端支持时,通过 MCP 引导公开问题;resolve_case 始终作为脚本化回退可用。

generate_spec()

仅在案例队列为空时才能调用。将 CLAUDE.md.claude/rules/.claude/settings.json机械地 执行纪律的钩子 —— 见下文)、spec/contracts/*.mdtests/visible/ + tests/held-out/ 以及 kickoff-prompt.txt 写入一个干净的兄弟目录 <repo>-rebuild/ —— 绝不写入原始仓库。在最终确定测试之前运行真实的变异检查:故意破坏原始代码,并确认每个生成的测试确实能捕获它,将任何不能捕获的测试降级。

机械执行而不仅仅是写下来的规则

在两个模型层级上的对比运行发现,较弱的模型会乐意阅读 CLAUDE.md,理解“只构建当前失败的,不要批量重新生成”,然后仍然悄悄违反它 —— 因为没有任何东西 检查 它。这个工具中的两条规则现在由真正的钩子强制执行,而不是散文,正是出于这个原因:

  • spec/ 是锁定的。 一个 PreToolUse 钩子阻止对 spec/ 下的任何编辑。

  • 没有测试的契约不会提前构建。 generate_spec 写入 spec/untested-contracts.json(每个没有覆盖测试的路由/契约),第二个 PreToolUse 钩子阻止对该列表上任何内容的写入 —— 与 spec/-编辑块相同的执行形状,关闭了一个曾经只是建议性的缺口。

一个 PostToolUse 钩子在每次编辑后运行可见测试套件。

快速开始

git clone https://github.com/businessfawcett-cloud/rebuild-dossier.git
cd rebuild-dossier
npm install
npx playwright install chromium   # needed for crawl_site

在 Claude Code(或任何兼容 MCP 的客户端)中将其添加为 MCP 服务器,然后在会话中:

ingest_repo({ path: "/path/to/some-app" })
get_case_queue({ repoPath: "/path/to/some-app", interactive: true })
# ...resolve whatever the queue surfaces...
generate_spec({ repoPath: "/path/to/some-app" })

这会写入一个干净的 some-app-rebuild/ 兄弟目录。cd 进入该目录,启动一个 全新的 Claude Code 会话(其他任何内容都不应在范围内),并粘贴其 kickoff-prompt.txt 的内容。

操作指南

完整的生命周期,按顺序 —— 每个步骤的实际行为,而不仅仅是调用签名。

1. 摄取仓库

ingest_repo({ path: "/absolute/path/to/some-app" })

仅静态分析 —— 不调用 LLM,不执行任何内容。解析 package.json、路由文件(目前支持 Express 和 Next.js App Router —— 参见 范围)、构建配置(Tailwind/Vite/Next,通过 AST,绝不执行)、现有测试,并扫描注释/TODO 信号以及结构性气味(例如,硬编码的客户端凭据检查而没有服务端验证 —— 这种类型的东西没有人会评论,这正是为什么它需要自己的检测器,而不是依赖现有注释)。所有内容都落在 <repo>/.dossier/ —— 这个工具自己的临时状态,位于 原始 仓库内部,绝不共享或上传到任何地方。你会收到一个摘要:

{
  "routes": 8,
  "existingTests": 0,
  "signals": 3,
  "buildConfig": ["tailwind", "next"],
  "openCases": 3,
  "savedTo": "/absolute/path/to/some-app/.dossier/evidence.json"
}

这里的 openCases 已经反映了协调结果 —— 未自动解决的注释/TODO 信号和结构性气味会自动成为案例队列条目。

如果 routes 返回 0,在假设应用没有路由之前,检查是否有 monorepoHint 字段 —— ingest_repo 需要指向实际的应用目录,而不是 monorepo 的根包装器(一个旁边有 apps/*/packages/*package.json,常见于 Turborepo/Nx/workspace 布局,包括那些从未实际声明 workspaces 字段的布局)。该提示列出了在 apps//packages/ 下找到的真实候选目录,这样你就不必自己寻找真正的应用 —— 重新运行 ingest_repo 并指向其中一个候选目录。

如果你的客户端支持 MCP 引导,你可以完全跳过手动重新运行:传递 interactive: true,当检测到带有候选目录的 monorepo 根时,ingest_repo 会询问哪个是真正的应用并直接摄取它 —— 它从不静默地自行猜测,这与 get_case_queue 的交互模式总是询问而不是在没有你的情况下解决任何内容的方式相同。拒绝、不支持的客户端,或不是真实候选之一的答案,都会回退到上面的普通提示,保持不变。

2. (可选)爬取实时站点

crawl_site({ url: "http://localhost:3000", repoPath: "/absolute/path/to/some-app" })

仅当应用实际在某个地方运行时才有用。无头 Playwright 爬取可达路由,定期发出进度通知 —— 长时间爬取会被大多数 MCP 客户端自动后台化,而没有这些通知,静默的多分钟调用可能会被误杀为无响应。

3. (可选,但在步骤 4 之前执行)标记任何你已知的损坏内容

flag_known_bug({
  repoPath: "/absolute/path/to/some-app",
  description: "The login gate secret check runs entirely client-side and is bypassable"
})

整个系统中最廉价、最权威的信号 —— 直接的人工陈述总是胜过推断。对于任何匹配的内容,它覆盖自动解决,即使 每个其他信号都静默地同意该行为看起来是有意的。在解决队列之前执行此操作,因为它会改变队列中显示的内容(并且可以完全独立地播种一个案例,零其他证据 —— 参见 docs/v0-findings.md 了解为什么这很重要)。

匹配是对每个未解决案例的文件路径和声明文本的普通 token 重叠,而不是模糊或语义匹配 —— 因此,如果你的代码库中有几个名称相似的组件,一个 bug 描述可能匹配(并自动解决)比你预期更多的未解决案例。在验证的示例中,一个关于“登录门”的 bug 匹配并关闭了 Madeline 的三个近乎重复的门组件,在一次调用中,在它们被单独审查之前。resolve_case 会覆盖案例的决策,无论其当前状态如何,所以如果这不是你的本意,请直接对过度扫过的案例调用它 —— 不要假设它触及的每个案例都是相同的决策。

4. 解决案例队列

get_case_queue({ repoPath: "/absolute/path/to/some-app", interactive: true })

interactive: true 通过 MCP 引导遍历每个未解决案例 —— 如果你的客户端支持,这是一个真实的交互式提示,并排显示证据。如果不支持(或者你在编写脚本),则一次解决一个案例:

resolve_case({ repoPath: "/absolute/path/to/some-app", id: "case:...", decision: "intentional", note: "..." })

此步骤没有捷径。 generate_spec 在任何案例仍处于打开状态时拒绝运行,这是设计使然 —— 没有部分或进行中的规格可以交给重建代理并附带注意事项;阶段 1–2 正是产生 spec/ 的过程。

5. 生成规格

generate_spec({ repoPath: "/absolute/path/to/some-app" })

仅在队列为空时可调用。将 CLAUDE.md.claude/(规则、hooks、一个 spec-auditor 子代理,以及一个 verify-against-spec 技能——全部源自项目实际的契约和测试,而非模板代码)、spec/(契约、已锁定的决策、test-dependencies.jsonuntested-contracts.json)以及 tests/ 写入一个干净的兄弟目录 some-app-rebuild/——绝不写入原始仓库。另外两个 .claude/ 工件仅在它们确实有价值时才会生成:一个 test-verifier 子代理,仅当存在需要守护的保留测试时;一个 parallel-test-fix 工作流,仅当生成的测试按共享路由文件拆分为两个或更多值得并发修复的独立集群时。一个小型应用,只有几个覆盖相同路由的测试——比如上面验证过的示例——两者都不会生成;这不是 bug,而是生成器拒绝向重建代理交付与其实际无关的工具。此步骤还会执行真实的变异检查:它在一个临时副本中故意破坏原始代码(翻转比较、删除空值检查、循环边界差一错误),并确认每个生成的测试确实能捕获它——任何无法捕获的测试会被移到 tests/weak/,而不是当作可信的测试交付。你会得到:

{
  "outputDir": "/absolute/path/to/some-app-rebuild",
  "mutationsChecked": 8,
  "weakTests": [],
  "unrunnableTests": []
}

weakTestsunrunnableTests 都落在同一个 tests/weak/ 目录中,而不是 tests/visible/,但原因不同,值得区分:弱测试运行正常,只是从未捕获到任何变异破坏;不可运行测试即使针对原始未变异代码也从未通过(导入损坏、缺少环境变量、裸仓库不具备的基础设施)——在这个区分存在之前,不可运行测试看起来与 100% 有效的测试无异,因为无论被测代码是否被变异,它都会以相同方式"失败"。两者都不是错误——这是工具在诚实告诉你某个特定测试没有赢得 tests/visible/ 中的位置,以及原因。

如果所有生成的测试都落在 tests/weak/ 中且 mutationsChecked: 0,在假设存在结构性错误之前先检查 warning 字段——更常见的原因是目标仓库尚未运行过 npm install,因此变异检查的临时副本没有目标自身的真实依赖(next@prisma/client,或应用实际需要的任何东西),每个生成的测试甚至无法导入它们。generate_spec 会直接检查这一点并明确说明,而不是让你去调试一个令人困惑的全不可运行结果。

可选:视觉辅助的页面内容分类

对于 Next.js 目标,页面路由会获得真实的 Playwright 捕获测试(截图加 DOM 文本断言),与上述 API 路由测试并列。捕获的文本片段是获得精确匹配断言(static)还是宽松形状检查(dynamic),默认由一个小型正则分类器决定——大多数时候可靠,但已确认在真实应用上可能双向出错(硬编码的下拉图例被读作实时数据;实时的、逗号格式化的数据库计数被读作固定值)。

在调用 generate_spec 之前同时设置 GROQ_API_KEYREBUILD_DOSSIER_ENABLE_VISION_CLASSIFICATION=1,会将每个捕获页面的截图和(秘密已编辑的)源代码发送给 Groq 视觉模型,该模型可以看到值实际来自哪里——源码中的字面量数组 vs. fetch/useState 调用——而不仅仅是根据渲染字符串的外观来猜测。两个变量必须同时设置是有意为之:某个无关工具遗留的环境变量 GROQ_API_KEY 绝不能静默开始将此目标仓库的代码发送给第三方。两个变量都未设置(默认情况)意味着零行为变化,零超出 generate_spec 已有行为的网络调用。

这是真实的额外成本,不是免费的:每个捕获页面一次 Groq API 调用,加上页面之间故意的 ~20 秒节奏延迟(Groq 的免费层有严格的每分钟 token 预算,连续快速发送请求会迅速耗尽它)——generate_spec 自身的响应会说明该次运行的确切额外时间。任何原因(速率限制、网络问题、无效响应)导致页面无法以这种方式分类时,仅对该页面回退到正则分类器,并在 pageVisionFallbacks 中报告——绝不会出现静默缺口或失败的运行。Groq 的免费层(无需信用卡,在 console.groq.com)足以尝试此功能。

6. 交接

cd /absolute/path/to/some-app-rebuild
claude   # or oh-my-pi, opencode — any coding agent, a genuinely fresh session

逐字粘贴 kickoff-prompt.txt 的内容。该会话的上下文中不应有其他任何内容——该目录有意完全自包含(参见 工作原理),因此重建代理没有其他可读、可漂移或可原地编辑的内容,而不是干净地构建。阅读 docs/v0-findings.md 了解对真实应用执行此操作时实际发生的情况,包括它具体卡在哪里。

从其他工具连接(oh-my-pi、opencode 等)

运行此工具有两种方式,都完全本地化——没有托管/共享实例,也不需要:

stdio(默认)——每个工具作为本地子进程生成自己的服务器副本。这是每个 MCP 客户端(Claude Code、oh-my-piopencode)添加本地 MCP 服务器的标准方式——从本仓库目录指向 npx tsx src/index.ts(或构建后的 node dist/index.js)。无需额外设置、无需认证,本节内容均不适用。

HTTP(可选)——localhost 上一个持久服务器,多个工具/会话连接到它,而不是各自生成一个。如果你希望 oh-my-pi 和 opencode(或几个 Claude Code 会话)共享一个运行实例,这很有用。仍然完全本地化——MCP_ALLOWED_HOSTS 只需包含你实际要连接的主机名(localhost),不需要真实域名,除非你故意选择将此暴露到自己的机器之外。

npm run build
PORT=8080 \
MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
MCP_ALLOWED_HOSTS=localhost,127.0.0.1 \
REBUILD_DOSSIER_ALLOWED_PATHS=/absolute/path/to/your/projects \
npm run start:http:prod

三个环境变量都是必需的——服务器有意拒绝在缺少它们时启动:MCP_AUTH_TOKEN 门控每个 /mcp 请求(bearer 认证),MCP_ALLOWED_HOSTS 防止 DNS-rebinding,REBUILD_DOSSIER_ALLOWED_PATHS(逗号分隔的绝对目录)是 ingest_repo/generate_spec 等唯一允许接触的路径——将其设置为包含你实际想要重建的仓库的父目录。

oh-my-pi.omp/mcp.json~/.omp/agent/mcp.json):

{
  "mcpServers": {
    "rebuild-dossier": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": { "Authorization": "Bearer ${REBUILD_DOSSIER_TOKEN}" }
    }
  }
}

opencodeopencode.json):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "rebuild-dossier": {
      "type": "remote",
      "url": "http://localhost:8080/mcp",
      "enabled": true,
      "oauth": false,
      "headers": { "Authorization": "Bearer {env:REBUILD_DOSSIER_TOKEN}" }
    }
  }
}

oauth: false 禁用 opencode 在 401 时的自动 OAuth 发现——此服务器仅支持上述静态 bearer token,不支持真正的 OAuth 流程。将引用的环境变量(两个示例中均为 REBUILD_DOSSIER_TOKEN)设置为与上述 MCP_AUTH_TOKEN 相同的值。

开发

npm test        # full suite
npm run typecheck

小型、单一用途的函数;全程 TDD(测试先于其所覆盖的实现编写,包括对账逻辑本身的测试——这是一个生成测试的工具,因此其自身的正确性与任何功能同等重要)。

当前范围,以及有意未构建的内容

v0 的范围是验证核心循环,而非功能完备。有意推迟,并作为真实积压事项跟踪,而非静默跳过:

  • 基于 API 形状歧义(验证规则、错误响应形状)的对账仍然真正未经测试——目前验证过的唯一一个形状不同的真实应用(catchandtrade)恰好没有需要对账的注释/TODO 信号,因此这个具体问题目前还没有答案。参见 docs/v0-findings.md

  • 视频/屏幕录制摄取和视频-LLM 标记窗口审查。

  • 原始 CLAUDE.md / 自动记忆作为证据来源。

  • 用于认证门控/多账户流程的实时 Chrome MCP 捕获(无头爬虫无法到达)。

  • 资产清单提取(二进制文件逐字节复制 + 哈希清单,锁定契约层)——已有真实设计,尚未构建。

  • 完全 no-op 处理程序的变异器(当前三个——翻转比较、删除空值检查、差一错误——无法产生"此分支从未执行"的变异体)。

参见 docs/v0-findings.md 获取完整、诚实的报告:验证过程中发现并修复的真实 bug、各模型层级的比较,以及仍然悬而未决的问题。

许可证

MIT

Available Tools

6 tools
crawl_siteCrawl siteB

Playwright headless crawl of reachable routes. Emits periodic progress notifications.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesBase URL to crawl
maxPagesNoOptional cap on how many reachable pages to visit. Unset means no limit.
repoPathYesRepo path whose .dossier/ this crawl evidence should be saved under

Output Schema

ParametersJSON Schema
NameRequiredDescription
savedToYes
openCasesYes
routesVisitedYes
routesWithConsoleErrorsYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotency, and destructive hints. The description adds some behavioral detail by noting it runs headless and emits periodic progress notifications, but it does not clarify what side effects the crawl may produce beyond visiting pages, even though readOnlyHint is false and repoPath suggests saving evidence. No contradiction with annotations was found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no filler, and the core action is front-loaded. It is concise and readable, though it could have used the extra space to provide more usage context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the schema fully documents all parameters and an output schema exists, the core technical details are covered. However, the description alone does not address when to use the tool, what side effects the crawl might have, or how it relates to the sibling tools. It is adequate but has clear gaps for an agent deciding whether to invoke it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains url, maxPages, and repoPath. The description does add a small hint that the crawl follows reachable routes from the base URL, but it does not materially improve on the parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('crawl'), the resource ('site'), and the method ('Playwright headless'), and specifies the scope as 'reachable routes.' This distinguishes it from the sibling tools, which perform different operations like ingesting, flagging, or resolving.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to choose this tool over alternatives, no prerequisites, and no exclusions. The intended context is only implied by the word 'crawl,' not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

flag_known_bugFlag known bugA

Record a known bug. Always overrides auto-resolve for any case it matches, regardless of other evidence.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path whose .dossier/ this known bug belongs to
descriptionYesFree-text description of a known bug, stored verbatim

Output Schema

ParametersJSON Schema
NameRequiredDescription
bugYes
openCasesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only indicate that this is a non-read-only, non-idempotent mutation. The description adds the crucial non-obvious behavior that a flagged known bug always wins over auto-resolve regardless of evidence. This is valuable context that annotations cannot communicate. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The primary action is front-loaded, followed immediately by the single most important behavioral rule. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter write tool, the description covers the action and the essential override behavior, and the schema documents the parameters. An output schema exists, so return-value details are not needed. The only small gap is that when-to-use guidance is implied rather than explicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and both parameters (repoPath and description) are already well documented in the schema. The main description adds no additional parameter semantics, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Record a known bug') and immediately supplies the core differentiator: it overrides auto-resolve. This distinguishes it from sibling resolution/auto-resolve tools without needing to inspect the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence gives a clear behavioral context: use this when a known bug should supersede any auto-resolve conclusion, even when other evidence points elsewhere. It does not explicitly list when not to use it or name sibling tools, but the precedence rule strongly implies the intended usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_specGenerate specA
Destructive

Write CLAUDE.md, .claude/, spec/, tests/, and kickoff-prompt.txt to -rebuild/. Only callable once the case queue is empty. Optional: if the target is a Next.js app with page routes, set GROQ_API_KEY and REBUILD_DOSSIER_ENABLE_VISION_CLASSIFICATION=1 before calling this tool to enable vision-assisted page-content classification (sends each captured page's screenshot and source code to Groq to judge static vs. dynamic content more accurately than plain regex matching) — ask the user for a Groq API key if they want more reliable generated page tests and this isn't already configured. Off by default; nothing changes if unset. Optional: pass authStorageStatePath to reach auth-gated pages during capture — see that field's own description for how to produce it.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path that was ingested; output is written to a sibling <repoPath>-rebuild/ directory
authStorageStatePathNoOptional path to a Playwright storageState JSON file (cookies/localStorage from an already-authenticated session against the target app) — load it once with `npx playwright open <url> --save-storage=state.json` after logging in by hand, or any equivalent one-time export. When set, page capture uses it to reach auth-gated pages instead of only ever seeing a login screen; this tool never logs in itself or handles credentials. The file is copied into the rebuild output (tests/fixtures/auth-storage-state.json, gitignored) so generated page tests can reach the same pages when run standalone.

Output Schema

ParametersJSON Schema
NameRequiredDescription
warningNo
outputDirYes
weakTestsYes
skippedPagesYes
capturedPagesYes
pageCaptureNoteNo
unrunnableTestsYes
mutationsCheckedYes
pageVisionFallbacksNo
pageVisionFallbackNoteNo
visionClassificationNoteNo
visionClassificationEnabledYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already marking this as destructive and non-read-only, the description adds substantial behavioral context: the tool is only callable with an empty case queue, the vision mode is off by default and changes nothing when unset, the tool never logs in or handles credentials itself, and the auth state file is copied into build output and gitignored. These details meaningfully extend beyond the annotation hints and help an agent predict side effects and prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action, then moves from precondition to optional enhancements in a logical order. Every sentence carries operational weight: the initial write target, the queue precondition, the vision-mode toggle and tradeoff, and the auth-state option. Although it is longer than a one-liner, the length is justified by the conditional behavior it must convey.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description, annotations, and rich schema collectively cover prerequisites, optional configurations, credential handling, side-effect locations, and output scope. Since an output schema exists, the description does not need to detail return values. There is no obvious gap an agent would need to guess about in order to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already fully documents repoPath and authStorageStatePath. The tool description adds only a cross-reference to authStorageStatePath and an optional storage-state usage note, but does not go beyond what the schema fields themselves say. With high schema coverage, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: it writes CLAUDE.md, .claude/, spec/, tests/, and kickoff-prompt.txt to a <repo>-rebuild/ directory. This clearly distinguishes it from sibling tools like ingest_repo or crawl_site, which perform other pipeline stages. The title alone would be vague, but the description removes all ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states an explicit precondition: 'Only callable once the case queue is empty,' which tells the agent when it may and may not be invoked. It also provides conditional guidance for two optional modes: when to set the vision-classification env vars, when to ask the user for a Groq key, and when to pass authStorageStatePath. This is direct, operational usage guidance rather than left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_case_queueGet case queueB
Destructive

Return unresolved ambiguity cases from reconciliation.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path whose .dossier/ case queue to read
interactiveNoWhen true, walk open cases via MCP elicitation instead of just listing them

Output Schema

ParametersJSON Schema
NameRequiredDescription
openYes
casesYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and readOnlyHint=false, but the description's 'Return...' reads as a safe read operation and adds no context about side effects, what may be destroyed, or why the tool is marked destructive. This mismatch makes the safety profile confusing and under-disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one short sentence with no filler. It front-loads the core purpose, and every word contributes to understanding what the tool returns.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema covers parameters and an output schema exists, so return structure is not the description's burden. However, the description is too thin to fully explain the disruptive destructive hint, the reconciliation context, or when an agent should prefer resolve_case, leaving the overall guidance minimally viable but gapped.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so repoPath and interactive are already documented in the schema. The description adds no extra parameter meaning beyond the schema and does not address the interactive behavior or its consequences.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Return unresolved ambiguity cases from reconciliation' uses a specific verb and resource, making the tool's main output clear. It is distinguishable from siblings like resolve_case, but it does not explicitly call out that distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description only implies when to use the tool: when unresolved ambiguity cases from reconciliation need to be retrieved. It gives no guidance about alternatives such as resolve_case, nor any exclusions, leaving the agent to infer selection criteria from the name and schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingest_repoIngest repoA
Idempotent

Parse package.json, tailwind/vite config, route files, and existing tests via static analysis. No LLM call.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to the repo to ingest
interactiveNoWhen true and 0 routes are found at a monorepo-shaped path, ask via elicitation which candidate directory is the real app, then ingest that instead

Output Schema

ParametersJSON Schema
NameRequiredDescription
routesYes
savedToYes
signalsYes
openCasesYes
buildConfigYes
monorepoHintNo
existingTestsYes
resolvedMonorepoChoiceNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide idempotentHint=true and destructiveHint=false. The description adds meaningful behavioral context with 'static analysis' and 'No LLM call', signaling deterministic, non-LLM execution beyond what annotations state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The first states the operation and scope, and the second adds a key behavioral constraint. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is low complexity, has full schema coverage, an output schema, and annotations covering idempotency and destructiveness. The description supplies the remaining essential facts: what files are parsed and that no LLM call is made.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both path and interactive are already well documented in the input schema. The description does not add parameter-specific meaning, which is acceptable given the schema already carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb, 'Parse', and names concrete resources: package.json, tailwind/vite config, route files, and existing tests. An agent can tell what the tool operates on, though it does not explicitly contrast itself with siblings like generate_spec or crawl_site.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The static-analysis phrasing and 'No LLM call' imply this is a deterministic, lower-cost ingestion step, but the description does not explicitly say when to use this tool versus alternatives. Sibling names provide context, yet no direct routing or exclusion guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_caseResolve caseA
DestructiveIdempotent

Resolve one open case with a human decision. Always available, no elicitation capability required.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe case id to resolve, as returned by get_case_queue (e.g. "case:...")
noteNoOptional free-text note explaining the decision
decisionYesFree-text decision, e.g. "intentional" or "bug" — stored verbatim, not a fixed enum
repoPathYesRepo path whose .dossier/ this case belongs to

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
statusYes
signalsYes
conflictNo
topicKeyYes
humanDecisionNo
autoResolutionNo
relatedCaseIdsNo
matchedKnownBugsYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry the safety profile (destructiveHint=true, idempotentHint=true), and the description adds the useful operational trait that the tool is always available and requires no elicitation capability. It does not, however, disclose what resolution actually changes (e.g., case status or removal from the queue), leaving the side effect only implied by the destructive hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with the primary purpose and followed by a concise availability note. Every word earns its place; there is no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool benefits from rich annotations, 100% parameter documentation, and an output schema, so the description need not explain return values. Still, it omits the practical effect of resolving a case (e.g., the case disappearing from get_case_queue) and provides no guidance about when to prefer this over the closely related sibling flag_known_bug, leaving a small but real completeness gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds the key semantic that the decision must be a human decision, which is not stated in the schema's decision property text and helps prevent an agent from fabricating a decision on its own. This one meaningful addition justifies a score above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'resolve one open case' with the key qualifier 'with a human decision.' It is not a tautology and clearly outlines the core action, but it does not explicitly contrast with sibling tools like flag_known_bug or get_case_queue, so it falls short of full differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Always available, no elicitation capability required' gives some operational context about when the tool can be invoked, implying it is the standard path for resolving a case. However, it never names alternatives or conditions when another sibling should be used instead, so guidance is mostly implicit rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.2.6-paper
    • Changedcrawl_site2 fields changed
      • addedInput schema / properties / maxPages / description
        Added value: +"Optional cap on how many reachable pages to visit. Unset means no limit."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "routesVisited": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "routesWithConsoleErrors": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "savedTo": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "routesVisited",
        +    "routesWithConsoleErrors",
        +    "openCases",
        +    "savedTo"
        +  ],
        +  "type": "object"
        +}
    • Changedflag_known_bug1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "bug": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "description": {
        +          "type": "string"
        +        },
        +        "flaggedAt": {
        +          "type": "string"
        +        },
        +        "id": {
        +          "type": "string"
        +        },
        +        "matchHints": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "id",
        +        "description",
        +        "matchHints",
        +        "flaggedAt"
        +      ],
        +      "type": "object"
        +    },
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "bug",
        +    "openCases"
        +  ],
        +  "type": "object"
        +}
    • Changedgenerate_spec1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "capturedPages": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "mutationsChecked": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "outputDir": {
        +      "type": "string"
        +    },
        +    "pageCaptureNote": {
        +      "type": "string"
        +    },
        +    "pageVisionFallbackNote": {
        +      "type": "string"
        +    },
        +    "pageVisionFallbacks": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "reason": {
        +            "type": "string"
        +          },
        +          "routeFile": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "routeFile",
        +          "reason"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "skippedPages": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "reason": {
        +            "type": "string"
        +          },
        +          "routeFile": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "routeFile",
        +          "reason"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "unrunnableTests": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "visionClassificationEnabled": {
        +      "type": "boolean"
        +    },
        +    "visionClassificationNote": {
        +      "type": "string"
        +    },
        +    "warning": {
        +      "type": "string"
        +    },
        +    "weakTests": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "outputDir",
        +    "mutationsChecked",
        +    "weakTests",
        +    "unrunnableTests",
        +    "capturedPages",
        +    "skippedPages",
        +    "visionClassificationEnabled"
        +  ],
        +  "type": "object"
        +}
    • Changedget_case_queue1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "cases": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "autoResolution": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decision": {
        +                "enum": [
        +                  "intentional",
        +                  "bug"
        +                ],
        +                "type": "string"
        +              },
        +              "reason": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "decision",
        +              "reason"
        +            ],
        +            "type": "object"
        +          },
        +          "conflict": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "detail": {
        +                "type": "string"
        +              },
        +              "kind": {
        +                "enum": [
        +                  "known_bug_vs_intentional_evidence",
        +                  "signal_disagreement"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "kind",
        +              "detail"
        +            ],
        +            "type": "object"
        +          },
        +          "humanDecision": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decidedAt": {
        +                "type": "string"
        +              },
        +              "decision": {
        +                "type": "string"
        +              },
        +              "note": {
        +                "type": "string"
        +              },
        +              "via": {
        +                "enum": [
        +                  "elicitation",
        +                  "resolve_case_tool"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "decision",
        +              "decidedAt",
        +              "via"
        +            ],
        +            "type": "object"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "matchedKnownBugs": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "relatedCaseIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "signals": {
        +            "items": {
        +              "additionalProperties": false,
        +              "properties": {
        +                "affirmativeIntent": {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "confidence": {
        +                      "maximum": 1,
        +                      "minimum": 0,
        +                      "type": "number"
        +                    },
        +                    "kind": {
        +                      "enum": [
        +                        "comment",
        +                        "docstring",
        +                        "todo",
        +                        "fixme"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "locator": {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "endLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        },
        +                        "file": {
        +                          "type": "string"
        +                        },
        +                        "startLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        }
        +                      },
        +                      "required": [
        +                        "file",
        +                        "startLine",
        +                        "endLine"
        +                      ],
        +                      "type": "object"
        +                    },
        +                    "text": {
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "kind",
        +                    "text",
        +                    "locator",
        +                    "confidence"
        +                  ],
        +                  "type": "object"
        +                },
        +                "claim": {
        +                  "type": "string"
        +                },
        +                "detectedAt": {
        +                  "type": "string"
        +                },
        +                "evidenceText": {
        +                  "type": "string"
        +                },
        +                "id": {
        +                  "type": "string"
        +                },
        +                "locator": {
        +                  "anyOf": [
        +                    {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "endLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        },
        +                        "file": {
        +                          "type": "string"
        +                        },
        +                        "startLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        }
        +                      },
        +                      "required": [
        +                        "file",
        +                        "startLine",
        +                        "endLine"
        +                      ],
        +                      "type": "object"
        +                    },
        +                    {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "method": {
        +                          "type": "string"
        +                        },
        +                        "path": {
        +                          "type": "string"
        +                        }
        +                      },
        +                      "required": [
        +                        "path"
        +                      ],
        +                      "type": "object"
        +                    }
        +                  ]
        +                },
        +                "source": {
        +                  "enum": [
        +                    "ingest",
        +                    "crawl",
        +                    "known_bug"
        +                  ],
        +                  "type": "string"
        +                },
        +                "topicKey": {
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "id",
        +                "source",
        +                "locator",
        +                "topicKey",
        +                "claim",
        +                "evidenceText",
        +                "detectedAt"
        +              ],
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "status": {
        +            "enum": [
        +              "auto_resolved",
        +              "open",
        +              "resolved_by_human"
        +            ],
        +            "type": "string"
        +          },
        +          "topicKey": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "topicKey",
        +          "signals",
        +          "matchedKnownBugs",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "open": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "open",
        +    "cases"
        +  ],
        +  "type": "object"
        +}
    • Changedingest_repo1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "buildConfig": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "existingTests": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "monorepoHint": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "candidates": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "message",
        +        "candidates"
        +      ],
        +      "type": "object"
        +    },
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "resolvedMonorepoChoice": {
        +      "type": "string"
        +    },
        +    "routes": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "savedTo": {
        +      "type": "string"
        +    },
        +    "signals": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "routes",
        +    "existingTests",
        +    "signals",
        +    "buildConfig",
        +    "openCases",
        +    "savedTo"
        +  ],
        +  "type": "object"
        +}
    • Changedresolve_case4 fields changed
      • addedInput schema / properties / decision / description
        Added value: +"Free-text decision, e.g. \"intentional\" or \"bug\" — stored verbatim, not a fixed enum"
      • addedInput schema / properties / id / description
        Added value: +"The case id to resolve, as returned by get_case_queue (e.g. \"case:...\")"
      • addedInput schema / properties / note / description
        Added value: +"Optional free-text note explaining the decision"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "autoResolution": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "decision": {
        +          "enum": [
        +            "intentional",
        +            "bug"
        +          ],
        +          "type": "string"
        +        },
        +        "reason": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "decision",
        +        "reason"
        +      ],
        +      "type": "object"
        +    },
        +    "conflict": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "detail": {
        +          "type": "string"
        +        },
        +        "kind": {
        +          "enum": [
        +            "known_bug_vs_intentional_evidence",
        +            "signal_disagreement"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "kind",
        +        "detail"
        +      ],
        +      "type": "object"
        +    },
        +    "humanDecision": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "decidedAt": {
        +          "type": "string"
        +        },
        +        "decision": {
        +          "type": "string"
        +        },
        +        "note": {
        +          "type": "string"
        +        },
        +        "via": {
        +          "enum": [
        +            "elicitation",
        +            "resolve_case_tool"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "decision",
        +        "decidedAt",
        +        "via"
        +      ],
        +      "type": "object"
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "matchedKnownBugs": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "relatedCaseIds": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "signals": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "affirmativeIntent": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "confidence": {
        +                "maximum": 1,
        +                "minimum": 0,
        +                "type": "number"
        +              },
        +              "kind": {
        +                "enum": [
        +                  "comment",
        +                  "docstring",
        +                  "todo",
        +                  "fixme"
        +                ],
        +                "type": "string"
        +              },
        +              "locator": {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "endLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  },
        +                  "file": {
        +                    "type": "string"
        +                  },
        +                  "startLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  }
        +                },
        +                "required": [
        +                  "file",
        +                  "startLine",
        +                  "endLine"
        +                ],
        +                "type": "object"
        +              },
        +              "text": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "kind",
        +              "text",
        +              "locator",
        +              "confidence"
        +            ],
        +            "type": "object"
        +          },
        +          "claim": {
        +            "type": "string"
        +          },
        +          "detectedAt": {
        +            "type": "string"
        +          },
        +          "evidenceText": {
        +            "type": "string"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "locator": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "endLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  },
        +                  "file": {
        +                    "type": "string"
        +                  },
        +                  "startLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  }
        +                },
        +                "required": [
        +                  "file",
        +                  "startLine",
        +                  "endLine"
        +                ],
        +                "type": "object"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "method": {
        +                    "type": "string"
        +                  },
        +                  "path": {
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "path"
        +                ],
        +                "type": "object"
        +              }
        +            ]
        +          },
        +          "source": {
        +            "enum": [
        +              "ingest",
        +              "crawl",
        +              "known_bug"
        +            ],
        +            "type": "string"
        +          },
        +          "topicKey": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "source",
        +          "locator",
        +          "topicKey",
        +          "claim",
        +          "evidenceText",
        +          "detectedAt"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "auto_resolved",
        +        "open",
        +        "resolved_by_human"
        +      ],
        +      "type": "string"
        +    },
        +    "topicKey": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "topicKey",
        +    "signals",
        +    "matchedKnownBugs",
        +    "status"
        +  ],
        +  "type": "object"
        +}
  2. 1 tool updatev0.2.2-paper
    • Changedgenerate_spec1 field changed
      • addedInput schema / properties / authStorageStatePath
        Added value: +{
        +  "description": "Optional path to a Playwright storageState JSON file (cookies/localStorage from an already-authenticated session against the target app) — load it once with `npx playwright open <url> --save-storage=state.json` after logging in by hand, or any equivalent one-time export. When set, page capture uses it to reach auth-gated pages instead of only ever seeing a login screen; this tool never logs in itself or handles credentials. The file is copied into the rebuild output (tests/fixtures/auth-storage-state.json, gitignored) so generated page tests can reach the same pages when run standalone.",
        +  "type": "string"
        +}
  3. 6 tool updatesv0.2.0
    • First observedcrawl_site
    • First observedflag_known_bug
    • First observedgenerate_spec
    • First observedget_case_queue
    • First observedingest_repo
    • First observedresolve_case

TDQS

A4/5.0
Disambiguation5/5

Each tool has a clearly distinct role in the pipeline: static repo ingestion, dynamic site crawling, recording a known bug override, listing unresolved cases, resolving a case, and generating the final dossier. There is no functional overlap or ambiguity between tool boundaries.

Naming Consistency5/5

All six tool names follow the same snake_case verb_noun convention, such as ingest_repo, crawl_site, get_case_queue, and generate_spec. The verb choices are specific and the object naming is consistent, making the set predictable and easy to navigate.

Tool Count5/5

Six tools is a well-scoped size for this workflow, covering ingestion, crawling, bug flagging, case management, and final generation without redundancy. Each tool maps to a necessary step in the rebuild-dossier process and fits comfortably within the ideal range.

Completeness4/5

The main workflow is well covered: static analysis, dynamic crawling, human-in-the-loop case resolution, and final spec generation are all present. A minor gap is that there is no tool to list or remove previously flagged known bugs, but this does not prevent completing the core pipeline.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server that spawns autonomous Claude Code agents in GitHub repos, enabling task delegation with persistent state, multi-step workflows, and job monitoring.
    47
    94
    2
    Apache 2.0
  • F
    license
    A
    quality
    D
    maintenance
    A safe, local MCP server that lets Claude drive a controlled software-development loop (inspect, read, plan, patch, apply, check, analyze, fix, summarize) on a project, using deterministic tools and real diffs/test runs.
    10
    1
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Parker-Fawcett/rebuild-dossier'

If you have feedback or need assistance with the MCP directory API, please join our Discord server