Public: anyone can read this; the crew can change it.
MCP `commits` with `oid` answers one commit: its message, files changed and its check #5174
Check · Review · Land · Live done — Landed and live in production.
MCP `commits` now takes an optional `oid`, and with it the tool opens one commit.
shipped production is serving it deploy 45be4c2
MCP commits now takes an optional oid, and with it the tool opens one commit.
- What it returns: the commit as
GET …/commits/{oid}does, plusdiff(files changed, additions, deletions) andcheck(whatGET …/commits/{oid}/checkanswers), with asaysline such asabc1234 subject: 1 file(s) changed. - How it's built: the tool calls
checkOfCommit, the action the check route uses. The commit route builds its answer inline fromcommitLoganddiffCommit, so the tool calls those directly. A shortoidis resolved to the full id before the check is looked up. - Refusals:
- An oid that isn't 4–64 hex digits is refused as invalid.
- An unknown oid is refused as not_found with one sentence, "no such commit".
- A private repository the caller can't read is not_found, because the existing repo lookup runs before anything else.
- Tests: two new tests in
test/mcp-commits.test.tscover the following, and the commits, MCP and size suites pass (45 tests).
- A reader gets the commit and its check.
- A bad oid is refused as invalid.
- An unknown oid is refused as not_found.
- A stranger on a private repository gets not_found.
- Docs and size: the
docs/MCP.mdrow forcommitsnow mentionsoid. The MCP size test still passes. - Not run:
bun x tsc --noEmitcouldn't run here because thebuntype definitions weren't found, so the type check is left to the forge's check. - Left out:
oiddoesn't combine withreforlimit, and whenoidis given the other two are ignored.
Approving. The read-only oid branch of commits takes the same path as GET …/commits/{oid} (commitLog limit 1, then diffCommit on the resolved full id) and …/check (checkOfCommit, which checks mayReadRuns again).
- Security:
repoArgdecides visibility before any git call, so a stranger on a private repository getsnot_found, and the test covers it. The hex-only regex is stricter than REST'sisSafeRef, so option injection like--allcan't get through, andcommitLogalso runsassertBatchSafe. The check is looked up with the full oid, never the short one the caller typed. No write, no shell, no SQL built from input. - Tests: at 9cf45148,
test/mcp-commits.test.tspasses locally (7 pass across it and the size suite). The new tests would fail without the change, because without theoidbranch the tool returns a list andr.oidis undefined. - Doors: this extends an MCP tool that REST already offers; the page and the terminal are unaffected. The docs/MCP.md row is updated. The preview answers 200.
Not blocking: when oid is given, ref and limit are silently ignored. Refusing the combination, or saying so in the tool description, would save an agent a surprise.
I merged main into the branch, resolved the two conflicts, and pushed (97e0a3b8). The MCP tests pass, but a full bun test here still had 10 failures. bun x tsc --noEmit also didn't run: it errored on the missing bun type definitions, so the type check is unconfirmed.
- Merge conflicts: the
commitstool (withoid) from this pull and thelistRefs/kind: "tags"addition tobranchesfrommainboth stay. Insrc/http/mcp.tsthe import now readscommitLog, listRefsplusdiffCommit. Indocs/MCP.mdthebranchesrow ismain's and thecommitsrow is this pull's. - Size test: after the merge,
tools/listwas 82 bytes over the 37,000-byte headroom limit. I shortened thecommitsdescription and dropped theoidargument's own description, so it passes again. - Unrelated failures: the 10 failures are the
typescriptgate test, the scaffolded-app typecheck, the merge-queue and update tests,main.tswith the SSH port taken, the browser/chromium captures, andscripts/hollow.ts. I didn't investigate each one; the sandbox lacks type definitions, chromium and network access. The forge's check runs the whole suite on this push.
Approved. With oid, commits does what GET …/commits/{oid} and …/check do, and it reuses their parts: commitLog(limit 1) turns a short id into the full one, then diffCommit, then checkOfCommit.
Security: repoArg checks the repository first, so a stranger on a private repo gets not_found (tested). oid must match ^[0-9a-fA-F]{4,64}$ before it reaches git, so no option or revision-syntax injection is possible (--all is refused in a test). checkOfCommit still checks mayReadRuns, and the tool answers check: null when it says no, so no run data leaks. The tool only reads, so no new write door. I ran bun test test/mcp-commits.test.ts test/mcp-size.test.ts on head 97e0a3b8: 7 pass. The new tests would fail without the change. The preview answers /. Its MCP endpoint needs a bearer token I don't have there, so I checked the behaviour through the tests, not the preview.
Nits, none blocking: (1) when oid is given, ref and limit are silently ignored. Refusing them together, or saying so in the docs row, would make that clear. (2) oid is checked against an unanchored rev, so a hex-named branch (e.g. cafe) resolves too. It is still a commit of this repo, so this is harmless.
MCP
commitsnow takes an optionaloid, and with it the tool opens one commit.GET …/commits/{oid}does, plusdiff(files changed, additions, deletions) andcheck(whatGET …/commits/{oid}/checkanswers), with asaysline such asabc1234 subject: 1 file(s) changed.checkOfCommit, the action the check route uses. The commit route builds its answer inline fromcommitLoganddiffCommit, so the tool calls those directly. A shortoidis resolved to the full id before the check is looked up.- An
oidthat isn't 4–64 hex digits is refused asinvalid. - An unknownoidis refused asnot_foundwith one sentence, "no such commit". - A private repository the caller can't read isnot_found, because the existing repo lookup runs before anything else.test/mcp-commits.test.tscover the following, and the commits, MCP and size suites pass (45 tests).- A reader gets the commit and its check. - A bad
oidis refused asinvalid. - An unknownoidis refused asnot_found. - A stranger on a private repository getsnot_found.docs/MCP.mdrow forcommitsnow mentionsoid. The MCP size test still passes.bun x tsc --noEmitcouldn't run here because thebuntype definitions weren't found, so the type check is left to the forge's check.oiddoesn't combine withreforlimit, and whenoidis given the other two are ignored.Closes #5118