feat(mcp): MCP v2 — deep_dive tool, fit fix, schema honesty, GITHUB_TOKEN + timeout#35
Merged
Conversation
…call GITHUB_TOKEN (mcp/github-auth.js → ghOpts) is threaded as an optional opts.githubToken into fetcher.js (fetchGitHub) and deepdive.js (fetchSource/ghJson). With no token the path is byte-for-byte the old anonymous behavior, so the extension is untouched; with one, GitHub's 60 req/hr limit becomes 5000/hr — needed for blueprint_scene/deep_dive, which make 10+ GitHub calls per run. anthropic.js now wraps the fetch in an AbortController timeout (ANTHROPIC_TIMEOUT_MS, default 60s) so a stalled connection can't hang a tool call forever — mirroring the extension's per-provider timeout.
scan_repo declared `fit` as a required output but never produced it:
parseClaudeResponse has no fit field (the extension derives it separately
via verdict.js deriveFit), so the headline verdict was always undefined.
Now buildScanResult (pure, testable) calls deriveFit and the schema
declares fit as the real {level,label,why} object; bottom_line added too.
blueprint_scene's outputSchema advertised edges as {source,target,label}
and flat nodes, but buildBlueprintScene returns engine-shaped edges
{id,from,to,rel,note,userDrawn} and nodes carrying ref/layer/pinned. Any
client trusting the declared schema would mis-handle the payload. Schema
now matches the real scene.
Both runners thread ghOpts() for the GITHUB_TOKEN pass-through.
Third tool: plain-English explanation of how a repo works, with gaps, assumptions, self-test questions, and per-claim confidence, plus the underlying atoms + lineage. Reuses deepdive.js verbatim (same module the extension's Deep Dive uses); three sequential model calls, so it is the heaviest tool. Registered in the server's multi-tool dispatcher.
Adds 8 offline tests (no key, no network) covering the previously untested runners: ghOpts env plumbing, buildScanResult fit derivation, buildDeepDiveResult assembly, and full runScanRepo/runDeepDive via a mocked global.fetch (asserting the GITHUB_TOKEN Authorization header and deep_dive's three model calls). README documents the three tools, the real output shapes, GITHUB_TOKEN, and the timeout knob.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Turns the MCP proof (#33) into something real: a third tool, two correctness fixes the survey caught, and the rate-limit + timeout hardening it needed. All extension modules are reused verbatim; only
mcp/changes plus a backward-compatible optional param on two shared fetch helpers.What's in it
New tool —
deep_dive({ repo })— plain-English explanation of how a repo works, with gaps, assumptions, self-test questions, and per-claim confidence, plus the underlying atoms + lineage. Reusesdeepdive.jsverbatim (atoms → lineage → Feynman, three model calls — the heaviest tool).Bug fix —
scan_repofitwas alwaysundefined. The schema declaredfitrequired, butparseClaudeResponsenever produces it (the extension derives it separately viaverdict.jsderiveFit). Now a purebuildScanResultcallsderiveFit, the schema declares the real{ level, label, why }object, andbottom_lineis surfaced too.Bug fix —
blueprint_sceneoutputSchema lied. It advertised edges as{ source, target, label }and flat nodes, butbuildBlueprintScenereturns engine-shaped edges{ id, from, to, rel, note, userDrawn }and nodes withref/layer/pinned. Any client trusting the declared schema would mis-parse. Schema now matches the real scene.GITHUB_TOKENpass-through — optionalopts.githubTokenthreaded intofetchGitHub(fetcher.js) andfetchSource/ghJson(deepdive.js). No token → byte-for-byte the old anonymous path, so the extension is untouched. With one, GitHub's 60 req/hr → 5000/hr (blueprint/deep_dive make 10+ calls each and would otherwise 403 mid-scan).Hard timeout on the Anthropic call —
AbortController+ANTHROPIC_TIMEOUT_MS(default 60s) so a stalled connection can't hang a tool call forever (mirrors the extension's per-provider timeout).Reuse / invariants
mcp/.fetcher.js,deepdive.js) are purely additive optional params — existing extension callers pass nothing and behave identically (confirmed: the extension's own 849 tests still pass).Test plan
npx vitest run→ 857 passed (was 849; +8 new offline MCP tests, no key/network)ghOptsenv plumbing;buildScanResultfit derivation (strong + risky);buildDeepDiveResultassemblyrunScanRepo/runDeepDivevia mockedglobal.fetch— asserts theAuthorization: Bearerheader appears only whenGITHUB_TOKENis set, anddeep_divemakes exactly three model calls{from,to}npx eslint .→ 0 errors (25 warnings, baseline)node --checkon all touched filesNot in this PR (follow-ups)
scan_repo(the fetcher already supports them — onlyrepo-input.jsis GitHub-only)providers.jsregistry)tools/liststructural smoke test