Skip to main content
Glama
README.md
# agy-mcp

> **Personal tool, published as-is.** This is not a product: it is not on npm, it is not maintained for anyone else, and there is no support. The repository is archived — read it, copy from it, fork it freely, but do not expect issues or pull requests to be answered. If you want something maintained, [`agy-bridge`](https://github.com/sshahzaiib/agy-bridge) is an actively developed alternative with a broader tool surface.

An [MCP](https://modelcontextprotocol.io) stdio server that makes the **Antigravity CLI (`agy`)** a first-class tool inside Claude Code — and verifies, on every single call, **which backend model actually answered**.

If you pay for both Claude Code and Google AI Pro, this lets you spend the cheaper subscription on the cheaper work without leaving Claude Code. Claude stays the driver; `agy` becomes a tool it can hand a task to.

```
You  →  Claude Code  →  agy_ask(tier: "trivial")  →  agy  →  Gemini Flash
                                                       ↓
                                   [verification] OK — served by "Gemini 3.7 Flash (Low)"
```

## Why not an LLM gateway or proxy

The common way to mix providers is to point Claude Code's Anthropic API traffic at a proxy that translates it to another vendor's API. That means intercepting requests, and often reusing credentials issued to a different client.

This server does none of that. There is no proxy, no API translation, no credential relay, and nothing is re-signed or intercepted. Claude Code talks to Anthropic on your Anthropic account. `agy` talks to Google on your Google account, through Google's own official CLI, exactly as if you had typed the command yourself. All this server does is let Claude spawn that CLI as a subprocess and read its output.

Check your own subscriptions' terms and decide for yourself whether this fits them. This README makes no legal claim on your behalf.

## What you get over calling `agy` through Bash

- **Backend verification on every call.** `agy`'s `--model` flag is not always honoured, and the model's own self-report will not tell you. Every result is prefixed with a `[verification]` line naming the model that really served it, parsed out of `agy`'s own log.
- **Known-broken model ids are refused** by default, rather than silently answering from the wrong model.
- **New routing bugs are detected on their own** — see [Model routing verification](#model-routing-verification).
- **Difficulty tiers, not model ids.** Claude picks `trivial` / `standard` / `hard` / `reasoning`, and the server resolves that against the live model list.
- **No shell permission prompt per call**, and no risk of the command being reshaped by a shell wrapper.
- **Long runs do not die on the tool timeout.** A deep research call hands back a `job_id`; the run continues in the background and Claude collects it with `agy_result`.
- **The dangerous capability is a separate tool** (`agy_exec`), so the rest can be allowlisted safely. See [Security model](#security-model).

## Requirements

- Node.js **≥ 18** (zero dependencies)
- The Google Antigravity CLI (`agy`) installed, on `PATH`, and signed in
- Claude Code

Built and tested against `agy` 1.1.13, and against every release since 1.1.7.

## Install

Not published to npm, and there are no plans to. Clone it and point Claude Code at the script — there is nothing to build, and no dependencies to install.

```bash
git clone https://github.com/Sh3rm/agy-mcp.git
cd agy-mcp
npm test          # optional; needs neither agy nor network
```

## Register with Claude Code

MCP servers can be registered at three scopes. Pick the one that matches how you want to use it. Use the absolute path to `bin/agy-mcp` from your clone.

**User scope — available in every project on this machine.** Most people want this.

```bash
claude mcp add agy --scope user -- /absolute/path/to/agy-mcp/bin/agy-mcp
```

**Project scope — checked into the repo, shared with your team.** Creates or updates `.mcp.json` in the project root.

```bash
claude mcp add agy --scope project -- /absolute/path/to/agy-mcp/bin/agy-mcp
```

The resulting `.mcp.json`:

```json
{
  "mcpServers": {
    "agy": {
      "type": "stdio",
      "command": "/absolute/path/to/agy-mcp/bin/agy-mcp",
      "args": [],
      "env": {}
    }
  }
}
```

**Local scope — this project only, not shared.**

```bash
claude mcp add agy --scope local -- /absolute/path/to/agy-mcp/bin/agy-mcp
```

Then verify:

```bash
claude mcp list
```

Restart Claude Code after registering, and the seven `agy_*` tools appear.

## Tools

| Tool | Purpose | Key parameters |
| --- | --- | --- |
| `agy_ask` | General delegation: research, summarising, codegen, conversions. **Cannot** grant shell or file access. | `prompt`, `tier`, `model`, `parallel_subagents`, `effort`, `conversation_id`, `continue_conversation`, `wait_seconds` |
| `agy_research` | Web research with Google Search grounding and parallel subagents. Also exec-free. | `question`, plus the common parameters above |
| `agy_exec` | Local shell and file access on this machine. Prompts every time by design. | everything in `agy_ask`, plus `workdirs`, `sandbox` |
| `agy_result` | Collect a long run that handed back a `job_id`. | `job_id`, `wait_seconds` |
| `agy_models` | Live model list, current tier map, blocked ids, observed misroutings. | — |
| `agy_usage` | Remaining quota per limit bucket. Free: no agent turn, no tokens, no conversation. Needs agy >= 1.1.11. | — |
| `agy_selftest` | Call every model once and report which backend really served it. Run this after `agy update`. | — |

### Difficulty tiers

Tiers resolve against the **live** model list from `agy models`, by pattern — highest version wins, broken ids are skipped. A new Gemini generation is adopted with no code change.

| Tier | Resolves to | Use for |
| --- | --- | --- |
| `trivial` | Gemini Flash, low effort | single-fact lookups, formatting |
| `standard` | Gemini Flash, medium effort | everyday tasks, straightforward search |
| `hard` | Gemini Flash, high effort | multi-step work needing a capable model |
| `reasoning` | Gemini Pro | genuinely hard synthesis |
| `claude` | Claude Sonnet | when the Gemini tiers are not enough |
| `claude_max` | Claude Opus | quota-constrained, use sparingly |

## Model routing verification

`agy` has had model ids that silently routed to a different backend — the flag is accepted, the response looks normal, and the model's own claim about its identity is not reliable. From 1.1.7 through 1.1.10:

```
gemini-3.1-pro-high   →  actually served by "Gemini 3.6 Flash (High)"
gemini-3.5-flash-low  →  actually served by "Gemini 3.5 Flash (Medium)"
```

**Both were fixed in agy 1.1.11**, so nothing is blocked by default today. The cause turned out to be effort variants with no backend behind them, advertised by `agy models` regardless; 1.1.11 returns real labels for both.

That history is the argument for the check, not against it. The bug class survived four releases, and neither release note was a reliable signal: 1.1.10 shipped a `--model`/`--effort` fix that read exactly like this bug and did not fix it, while 1.1.11 fixed it without mentioning routing at all. So the verification runs on every call regardless of what is currently known to be broken.

This server runs every call with `--log-file` and parses `agy`'s own line:

```
Propagating selected model override to backend: label="..."
```

The requested id and the reported label are compared **by normalisation**, not against a lookup table:

```js
normalize(s) = s.toLowerCase().replace(/[^a-z0-9]/g, '')
match if normalize(label).startsWith(normalize(requestedId))
```

Because there is no hardcoded table, a routing bug introduced in a **future** `agy` build is caught the same way the known ones are. When a mismatch is detected the server names the model that actually answered, records it in `~/.local/state/agy-mcp/mismatches.json`, and surfaces it in `agy_models`.

Ids known to be broken are refused before the call; `force_broken_model` overrides that and returns an explicit warning instead of silent wrong-model output. The seeded list is empty as of agy 1.1.11. To block an id yourself without editing the source, set `AGY_MCP_BLOCK="id1,id2"` in the server's environment.

## Security model

The reason there is a separate `agy_exec` tool is that **MCP permission rules in Claude Code match on tool name only** — there is no argument-level matching. If local execution were a boolean parameter on `agy_ask`, allowlisting `agy_ask` would allowlist arbitrary shell access.

So the capability is split:

- `agy_ask` and `agy_research` **can never** give `agy` shell or file access, whatever arguments are passed. Safe to allowlist.
- `agy_exec` is the only path to `--dangerously-skip-permissions`. **Do not allowlist it.** Let it prompt every time.

A suggested allowlist for `~/.claude/settings.json`, deliberately excluding `agy_exec`:

```json
{
  "permissions": {
    "allow": [
      "mcp__agy__agy_ask",
      "mcp__agy__agy_research",
      "mcp__agy__agy_result",
      "mcp__agy__agy_models",
      "mcp__agy__agy_selftest"
    ]
  }
}
```

### What `agy_exec` does and does not enforce

`workdirs` is **required** and validated before agy is started. Every entry must be an absolute path to an existing directory; symlinks are resolved first, and the filesystem root, the home directory and system roots are refused outright — those are the over-scopes people reach for by accident. The first entry also becomes the working directory of the agy process, so relative paths resolve inside the scope. `sandbox` defaults to **true**, enabling agy's own terminal restrictions; the safer setting is what you get by not thinking about it.

Be blunt about the limit of all this: it constrains **the invocation**, not the agent. agy still runs with `--dangerously-skip-permissions` and has a shell. Writing "read-only" into the prompt is an *instruction to the model*, not an enforced sandbox — a request that will probably be respected, never a guarantee. This project does not claim to jail agy, and you should not describe it that way to your users.

## Configuration

| Variable | Default | Meaning |
| --- | --- | --- |
| `AGY_BIN` | `agy` | Path to the `agy` binary |

State (detected misroutings, background jobs) lives in `~/.local/state/agy-mcp/`.

## Known limitations

- **The seeded broken-model list is tied to an `agy` version.** It may be stale in either direction — it has been both. Run `agy_selftest` after `agy update` to re-map.
- **`agy models` has changed its output format before**, from bare ids to `id<TAB>Label` in 1.1.11. The parser accepts both, but a third shape would fail *silently* by falling back to the seed list. `agy_models` says which list it is showing; check it after an `agy update`. (1.1.12's release notes announced an `--output-format json` flag for the `models` subcommand, which would have made this robust — it does not exist in 1.1.13, so the text parser stays.)
- **`agy` may decline remote-host work framed as a security audit.** Describing the task accurately — your own machine, access already configured, a configuration inventory rather than a security analysis — is usually what was missing.
- **The `agy usage` subcommand still needs a real TTY.** The `/usage` *slash command* in print mode does not, as of 1.1.11, which is what `agy_usage` uses.
- **Headless `agy` cannot prompt for permission**, which is exactly why file and shell work needs `agy_exec`.
- **Parallel subagents in `--print` mode are real** — each has a conversation tree under `~/.gemini/antigravity-cli/brain/<id>/` with genuine search grounding. The mechanism is trustworthy; individual figures can still be stale, so spot-check anything load-bearing.

## Disclaimer

Unofficial and unaffiliated. Not endorsed by Google or Anthropic. "Antigravity", "Gemini", "Claude" and "Claude Code" belong to their respective owners; they are used here only to describe what this tool interoperates with.

## License

[MIT](LICENSE)