MCP server that delegates frontend coding to agy (Antigravity/Gemini) inside an isolated git worktree
agy-frontend-mcp
An MCP server that delegates frontend coding to agy (the Antigravity / Gemini
CLI) inside an isolated git worktree — so an MCP client like Claude Code can hand
a whole frontend task to Gemini, then review the diff and decide whether to merge.
Gemini writes the files in a throwaway worktree on its own branch; nothing touches your working tree until you merge. Success is judged by the git diff, never by agy's exit code.
Why
agy is a capable agentic coder, but driving it head-less from another agent is full
of sharp edges (it hangs on an inherited stdin, writes loose filenames into its own
scratch sandbox, returns exit 0 on failure, and leaks other projects' context). This
server encapsulates all of that behind three clean tools.
Two implementations
There are two interchangeable builds with identical behavior — pick whichever fits your toolchain:
- Python (repo root) —
uv/uvx - TypeScript / Node (
ts/) —node/npx
Requirements
agyonPATHand logged in (agy modelsshould work)git- either Python ≥ 3.12 +
uv(Python build) or Node ≥ 18 (TS build)
Tools
frontend_delegate(task, model?, base_repo?, session_id?, add_dirs?, timeout_seconds?, sandbox?)Runs one agy agentic loop in a fresh worktree (or continue a prior one viasession_id). Returns{session_id, branch, worktree_path, status, summary, changed_files, diffstat, stderr_tail, elapsed_s}.statusissuccess/needs_attention(no files changed, or agy printed a failure marker) /timeout.modeldefaults to Gemini 3.1 Pro (High) for a new session, or the session's own model when continuing.add_dirspasses extra read-only context directories to agy.frontend_diff(session_id)— the worktree's git diff for review (truncated pastMAX_DIFF_BYTESwith{truncated, total_bytes, shown_bytes}).frontend_finish(session_id, action)—mergethe branch back into base (returnsstatus=conflictand keeps the worktree if the merge fails), ordiscardit. Either way the per-task agy state dir is reclaimed.
Install & register
Add the server to your MCP client config (.mcp.json for Claude Code). The
timeout (ms) should be ≥ agy's --print-timeout. Use one of the two builds:
Python (uv)
git clone https://github.com/botlong/agy-frontend-mcp && cd agy-frontend-mcp && uv sync
{
"mcpServers": {
"agy-frontend": {
"command": "uv",
"args": ["run", "--directory", "/abs/path/to/agy-frontend-mcp", "agy-frontend-mcp"],
"timeout": 1800000
}
}
}
Or with no clone, straight from GitHub:
"command": "uvx",
"args": ["--from", "git+https://github.com/botlong/agy-frontend-mcp", "agy-frontend-mcp"]
TypeScript / Node (npx)
Published on npm (agy-frontend-mcp) —
zero install, just point the client at npx:
{
"mcpServers": {
"agy-frontend": {
"command": "npx",
"args": ["-y", "agy-frontend-mcp"],
"timeout": 1800000
}
}
}
Or from a local clone — cd ts && npm install && npm run build, then use
"command": "node", "args": ["/abs/path/to/agy-frontend-mcp/ts/dist/server.js"].
See mcp.json.example (Python) and ts/README.md (TypeScript).
How it works
- Isolation — each task runs
agy --gemini_dir=<empty per-task dir>, relocating all agy state (conversations / brain / knowledge) so it can't read other projects' transcripts. OAuth is unaffected (tokens live in the system keyring). - Writing into the worktree — agy writes loose filenames into its own scratch sandbox, so the prompt is wrapped to instruct it to use absolute paths under the worktree.
- No hangs — every agy subprocess is given
stdin=DEVNULL(agy blocks on an inherited stdin) and is killed by process group on timeout. - Permissions — agy runs with
--dangerously-skip-permissions(no TTY to approve prompts); safety relies on the worktree boundary.sandbox=falseby default because frontend tasks often need the network (e.g.npm install); settrueto fail-closed.
The full design and the empirically-verified agy quirks are in
docs/superpowers/specs/.
Develop
Python:
uv sync
uv run pytest -q # unit suite (fakes agy)
AGY_SMOKE=1 uv run pytest tests/test_smoke_real_agy.py -q -s # real agy, end-to-end
TypeScript (in ts/):
npm install && npm test # vitest (fakes agy)
AGY_SMOKE=1 npm test -- tests/smoke.test.ts # real agy, end-to-end
Notes / limits
- Built for single-task-serial use; the session registry is thread-safe (atomic writes
- lock) but heavy concurrent-call orchestration is out of scope.
- Set
ENABLE_STATE_ISOLATION = Falseinisolation.py/ts/src/isolation.tsto let agy share its global~/.gemini(faster cold start, but it may pull in other projects' context).
License
MIT — see LICENSE.