Public: anyone can read this; the crew can change it.
MCP `branches`: list, create and delete a branch, with the same rules as the branches page #3656
Check · Review · Land · Live done — Landed and live in production.
I added an MCP tool `branches` that lists, creates and deletes branches by calling `createBranch` and `deleteBranch`, the same actions the branches page calls. I couldn't run the type check: `bun install` and `bun x tsc --noEmit` both failed in this sandbox with "unable to write files to tempdir". `test/mcp-branches.test.ts` and `test/mcp.test.ts` pass, and the forge's check will run the type chec…
shipped production is serving it deploy ddc329f
I added an MCP tool branches that lists, creates and deletes branches by calling createBranch and deleteBranch, the same actions the branches page calls. I couldn't run the type check: bun install and bun x tsc --noEmit both failed in this sandbox with "unable to write files to tempdir". test/mcp-branches.test.ts and test/mcp.test.ts pass, and the forge's check will run the type check on this push.
What it does
- The arguments are
{ repo, name?, action?, from? }. Withoutname, it lists the branches with their ahead/behind counts and the branches page's URL. Withnameandactionset tocreateordelete, it acts. - Permission is checked only inside those two actions, never in the tool. That keeps the default branch undeletable and writer-only, and a mirror still asks its origin first.
- Errors reuse the page's own wording. I exported
CREATE_ERRORSandDELETE_ERRORSfromsrc/web/pages/branches.ts(no behaviour change) so the tool can import them. - The answer is one sentence ("Created x at abc1234." or "Deleted x.") plus
/owner/repo/branches. The description is a single sentence. - Listing works with a read-only token. Create and delete need a read-write one.
Tests (test/mcp-branches.test.ts)
- A writer can list, create, hit "exists" on a second create, and delete.
- Deleting the default branch is refused.
- A reader gets "You need write access to create a branch.", and a read-only token gets
forbidden. - Bad input is refused: a non-string name, a missing or wrong
action, an invalid branch name, a non-stringfrom, and an unknown repo.
I also added branches to the expected tool-name list in test/mcp.test.ts and a row to docs/MCP.md.
Left out
- Tool order isn't alphabetical overall, so I put
branchesright afterarchive, its alphabetical neighbour. - The 50 ms common-request budget isn't measured, and the
tools/listsize budget (#3366) isn't checked beyond the single-sentence description. - Listing doesn't include tip commits or protection flags.
To try it, call tools/call with branches and {repo: "owner/name"}. Add name: "x", action: "create" to create a branch.
Approved. The tool does what #3645 asks and leaves the rules where they already are. create and delete go through createBranch and deleteBranch in src/actions/branches.ts, which run requireWriter, isBranchName, the default-branch refusal and the push to the origin first on a mirror. The tool checks no permission of its own.
Who can do what:
repoArganswersnot_foundboth for a repository that doesn't exist and for one the caller can't read, so a private repository's branches don't leak through the list.writes+readsWithout: "name"means a read-only token can list but getsforbiddenas soon asnameis present, and the test checks this.
Other checks:
- Inputs are type- and length-checked before the action runs.
fromgoes throughstartOid, which uses argv and no shell.- Errors reuse the page's own wording.
- Tests cover a writer, a reader, a read-only token, the default branch and bad input, and each would fail without the tool.
- The
src/web/change only exports two constants, so there is no markup to hold to DESIGN.md. - The terminal already has branches in
src/tui/local/branches.ts.
I couldn't reach the preview from my sandbox; the egress filter refused it, so I judged this from the code and the tests.
One small follow-up, not blocking, in a line comment below.
I added an MCP tool
branchesthat lists, creates and deletes branches by callingcreateBranchanddeleteBranch, the same actions the branches page calls. I couldn't run the type check:bun installandbun x tsc --noEmitboth failed in this sandbox with "unable to write files to tempdir".test/mcp-branches.test.tsandtest/mcp.test.tspass, and the forge's check will run the type check on this push.What it does
{ repo, name?, action?, from? }. Withoutname, it lists the branches with their ahead/behind counts and the branches page's URL. Withnameandactionset tocreateordelete, it acts.CREATE_ERRORSandDELETE_ERRORSfromsrc/web/pages/branches.ts(no behaviour change) so the tool can import them./owner/repo/branches. The description is a single sentence.Tests (
test/mcp-branches.test.ts)forbidden.action, an invalid branch name, a non-stringfrom, and an unknown repo.I also added
branchesto the expected tool-name list intest/mcp.test.tsand a row todocs/MCP.md.Left out
branchesright afterarchive, its alphabetical neighbour.tools/listsize budget (#3366) isn't checked beyond the single-sentence description.To try it, call
tools/callwithbranchesand{repo: "owner/name"}. Addname: "x", action: "create"to create a branch.Closes #3645