Public: anyone can read this; the crew can change it.

MCP `sync`: sync a mirror now, or reconnect its origin, with the same rules as the API #6994

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

There was nothing to merge, so I changed nothing and pushed nothing. `main` on the forge is still `d36a4a74`, which is the commit I merged last time, and it is already an ancestor of this branch. A merge of `origin/main` reports "Already up to date", with no conflicts in `docs/MCP.md` or `src/http/mcp.ts`.

shipped production is serving it deploy 93e874d

opened this

There was nothing to merge, so I changed nothing and pushed nothing. main on the forge is still d36a4a74, which is the commit I merged last time, and it is already an ancestor of this branch. A merge of origin/main reports "Already up to date", with no conflicts in docs/MCP.md or src/http/mcp.ts.

The branch is at 1e767d56, and the forge's refs/pull/6994/head points at the same commit. A plain git push says "Everything up-to-date". I didn't re-run the tests, since nothing changed since they passed.

The conflict report was probably computed against an older main, from before the merge I pushed. If it still shows on #6994, re-check the pull against the current main. If main moves again, send me back and I'll merge it then.

Continues #6994

commented

The sync MCP tool is back on the branch and pushed. It now lives where main keeps tools, so the earlier red check should clear. I couldn't confirm the push from here: it printed the new commit, but a local ref update failed (a read-only .git path). I haven't seen the forge's verdict.

The old branch had put sync in src/http/mcp.ts. Main has since moved every tool into its own file under src/http/mcp/tools/, so the merge conflicted. I merged main, took main's mcp.ts and docs/MCP.md, and re-added the tool as src/http/mcp/tools/sync.ts. I regenerated its index line and the docs row with bun scripts/mcp-tools.ts.

What it does:

  • sync { repo } runs the same action as POST …/sync, for the same caller, so the API's permission checks apply.
  • With originId it runs the reconnect action instead. That needs an admin-scope token, and a refusal names admin rather than write access.
  • A fork is refused with not_a_mirror and pointed to take_updates.
  • Each refusal says what to do next.
  • Its description is one short sentence, to keep tools/list small.

Tests: test/mcp-sync.test.ts covers an admin syncing a faked origin with no network, a non-mirror refused, a reader refused, and the reconnect and fork paths. bun x tsc --noEmit is clean. The tests that cover the change pass: mcp-sync, mcp, mcp-size and mcp-tools.

Left out: the API routes are unchanged, and I didn't run the full check.

commented

There was nothing to merge, so I changed nothing and pushed nothing. main on the forge is still d36a4a74, which is the commit I merged last time, and it is already an ancestor of this branch. A merge of origin/main reports "Already up to date", with no conflicts in docs/MCP.md or src/http/mcp.ts.

The branch is at 1e767d56, and the forge's refs/pull/6994/head points at the same commit. A plain git push says "Everything up-to-date". I didn't re-run the tests, since nothing changed since they passed.

The conflict report was probably computed against an older main, from before the merge I pushed. If it still shows on #6994, re-check the pull against the current main. If main moves again, send me back and I'll merge it then.

commented

The check failed because the new sync tool had the sentence "the origin could not be reached" written into its own refusal text. A test requires that sentence to come only from src/actions/origin_app_words.ts. I changed src/http/mcp/tools/sync.ts to import ORIGIN_UNREACHABLE from that module and append "; try again later" to it. The agent still sees the same words.

I ran origin-app-words, crew-limit-words, mcp-sync, mcp-size and mcp-tools, plus the type check. All pass. The forge's full check hasn't run on the fix yet. The push landed as 8b14e6e8.

The pull adds an MCP sync tool, in its own file under src/http/mcp/tools/. sync { repo } syncs a mirror now, and sync { repo, originId } reconnects its origin, which needs an admin token. Both call the actions behind POST …/sync and …/origin/reconnect, so the refusals match the API's. A fork is pointed to take_updates. docs/MCP.md has the tool's row, and test/mcp-sync.test.ts covers an admin sync against a faked origin, a non-mirror, a reader, reconnect and fork.

I left the API routes and the full check untouched.

Approved

Clean. sync calls the same actions as POST …/sync and …/origin/reconnect (syncRepoNow → requireWriter, reattachMirror → requireRepoAdmin plus the caller's own origin). The MCP dispatcher requires an rw scope for writes, and the tool requires an admin scope before it reconnects, which matches the API's requireScope. repoArg gives one not_found for missing and unreadable repositories. The refusal words come from the shared module, and nothing builds shell or SQL from user text. At 8b14e6e8, test/mcp-sync.test.ts covers sync, a reader, a non-mirror, a fork, rw-vs-admin scope, not_detached, an unknown origin and a real reconnect against a faked origin. mcp-sync, mcp-size and mcp-tools pass locally: 160 tests, 0 fail. The preview refuses a guest tools/call sync with the token prompt. The page and the TUI already have Sync, so this completes the agent door.

Nit, not blocking: a readable repository that is not a mirror answers "no such app or repository". That matches the API's 404, but a not_a_mirror message like the one forks get would tell an agent more.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs