agy-image
# agy-image
[](https://www.npmjs.com/package/agy-image)
[](https://www.npmjs.com/package/agy-image)
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org)
[](https://modelcontextprotocol.io)
An MCP server that generates images using the **Google AI Pro** quota already logged in to the
**Antigravity CLI** (`agy`) on your machine — without spinning up the `agy` agent loop.
It calls the image generation endpoint directly, so a picture takes seconds instead of tens of
seconds, and it works headlessly from any MCP client (Claude Code, Cursor, etc.).
> ⚠️ This targets an internal Google endpoint, not a public supported API. It reuses the
> credentials and quota of your own `agy` login. Use at your own risk.
## How it works
1. **Reads your existing login.** `agy` stores an OAuth token at
`~/.gemini/jetski-standalone-oauth-token`. That file's `refresh_token` is the only thing this
server needs from you — it's produced by logging into the Antigravity CLI once.
2. **Refreshes the access token when needed.** To do that it needs an OAuth *client* (id +
secret). It reads that pair **out of the `agy` binary installed on your machine**, verifies it
against Google's token endpoint, and caches the working pair at
`~/.cache/agy-image/credentials.json`. Nothing is bundled with this package, so no
single OAuth client gets shared by everyone who installs it.
3. **Calls the endpoint directly.**
```http
POST https://daily-cloudcode-pa.googleapis.com/v1internal:generateContent
Authorization: Bearer <access token>
Content-Type: application/json
{
"project": "aicode-consumers",
"requestId": "image_gen/<epoch_ms>/<uuid>/1",
"request": {
"contents": [{ "role": "user", "parts": [{ "text": "<prompt>" }] }],
"generationConfig": {
"candidateCount": 1,
"imageConfig": { "aspectRatio": "1:1" }
}
},
"model": "gemini-3.1-flash-image",
"userAgent": "antigravity",
"requestType": "image_gen"
}
```
4. **Writes the image to disk.** The response carries the image inline as base64, which is decoded
and saved to the path you asked for.
5. **Falls back to the agent if the direct call breaks.** If the request shape ever changes
underneath us, it runs `agy` in print mode and lets that agent generate the image instead.
Slower, but it keeps working. Disable with `AGY_FALLBACK=0`.
## Install
```json
{
"mcpServers": {
"agy-image": {
"command": "npx",
"args": ["-y", "agy-image"]
}
}
}
```
No credentials or environment variables needed — they're read from your local `agy` install.
Requirements:
- [Antigravity CLI](https://antigravity.google.com) installed and **logged in at least once**, so
`~/.gemini/jetski-standalone-oauth-token` exists and contains a `refresh_token`.
- Node.js 18+.
## Tools
| Tool | Arguments |
|---|---|
| `generate_image` | `prompt` (required), `aspect_ratio` (default `1:1`; one of `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`), `output_path` (default `generated_image.<ext>` in the current directory) |
| `antigravity_status` | none — reports config, token, credential source and the last known quota reset, without spending any quota |
## Configuration
All optional.
| Variable | Default | Purpose |
|---|---|---|
| `AGY_CLIENT_ID` / `AGY_CLIENT_SECRET` | read from the `agy` binary | Override the OAuth client, e.g. if Google rotates it |
| `AGY_PATH` | `~/.local/bin/agy` | Where to find the binary to extract credentials from, and to run as fallback |
| `AGY_TOKEN_FILE` | `~/.gemini/jetski-standalone-oauth-token` | `agy` login token |
| `AGY_FALLBACK` | `1` | Set to `0` to disable the `agy` agent fallback |
| `AGY_FALLBACK_TIMEOUT` | `300` | Fallback time limit, in seconds |
| `AGY_API_HOST` | `https://daily-cloudcode-pa.googleapis.com` | Request host |
| `AGY_IMAGE_MODEL` | `gemini-3.1-flash-image` | Image model |
| `AGY_PROJECT` | `aicode-consumers` | Value of the `project` field |
| `AGY_API_TIMEOUT` | `180` | Request timeout, in seconds |
| `AGY_QUOTA_STATE` | `~/.cache/agy-image/quota.json` | Where the last quota info is cached |
## Troubleshooting
- **`HTTP 429 QUOTA_EXHAUSTED`** — the image model's quota is spent. It's separate from chat
quota, and the error message includes the reset time. Fixed window, not a rolling one from your
last request.
- **`HTTP 403 SUBSCRIPTION_REQUIRED`** — image models other than `gemini-3.1-flash-image` require
an enterprise license.
- **`HTTP 403` on an otherwise valid request** — a malformed `requestId` is reported this way.
The server always generates it correctly; this only shows up if you craft requests by hand.
- **`Authentication error: ... token ...`** — the `agy` login is gone. Run `agy` interactively
once to log in again.
- **File is `.png` but contains JPEG** — the model returns JPEG regardless of the extension you
asked for. The response says so whenever the two disagree.
- **Prompt looks different from what you sent** — `agy` itself enriches prompts before calling the
model; this server sends yours verbatim, so results can differ slightly from the CLI.
## License
MIT
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: generate_image performs generation while antigravity_status only inspects local configuration/auth state and uses no quota. An agent can easily tell which to call, and the description of antigravity_status even directs use after generate_image fails.
generate_image follows a clear verb_noun pattern, while antigravity_status is noun_noun naming a status resource. This is a minor, readable deviation within an otherwise consistent snake_case style.
Two tools is on the thin side for a server, though the scope (quota-backed image generation plus diagnostics) is genuinely narrow. The set just barely covers the domain without feeling under-served, landing at borderline.
The core lifecycle of generating an image and diagnosing failures is covered. Minor gaps exist — no way to inspect remaining quota or explicitly refresh/reconfigure auth beyond the status check — but these are workable around for such a focused server.