One subscription.Two doors.

A personal, localhost-only Docker server that exposes your Google AI Pro plan as an OpenAI-compatible API at /v1 and an MCP server at /mcp, in one process.

Star on GitHub

MITNode.js 22Docker Compose127.0.0.1:8787

antigravity-connector · one processillustrative
POST /v1/chat/completions OpenAI-compatible · stream: true streaming
/mcp · web_search MCP · Streamable HTTP queued
shared queueone agy call at a time
chatrunning
web_searchwaiting
agyofficial CLI, subprocess
Google AI Proyour subscription
Login token stays inside agy.No page, no dashboard.

Same subscription, two ways in.

Point an OpenAI-compatible client at one door, or an MCP client at the other. Both end up in the same queue.

OpenAI-compatible API

/v1

Use it from anything that speaks the OpenAI chat format, including @ai-sdk/openai-compatible.

  • POST /v1/chat/completionschat
  • GET /v1/modelsmodels
  • Streaming with stream: true, SSE chunks in OpenAI formatSSE
  • Token usage in the last chunk with include_usageusage
curl http://127.0.0.1:8787/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gemini-3.8-flash",
       "reasoning_effort":"low",
       "messages":[{"role":"user",
         "content":"Say hello in one word."}]}'

MCP server

/mcp

Streamable HTTP. Progress is reported while a call waits and runs, and a cancelled call kills the agy process.

  • web_searchlinks · ~20 to 45 s
  • generate_imageone PNG · ~1 min
  • Progress during queue and run, when the client sends a progress tokenprogress
# add it to Claude Code
claude mcp add --transport http antigravity \
  http://127.0.0.1:8787/mcp \
  --header "Authorization: Bearer <API_KEY>"

Every call takes the same four steps.

  1. 01

    The request arrives

    Every route except /health needs the Bearer token. By default the server listens on 127.0.0.1 only.

    API_KEY
  2. 02

    It waits its turn

    Only one agy call runs at a time. API and MCP calls share the same queue, with a limit on how long a call may wait.

    QUEUE_MAX_WAIT_MS
  3. 03

    agy runs it

    Each call executes the official Antigravity CLI as a subprocess. The server never reads, copies or forwards the CLI login token, and never calls Google directly.

    AGY_TIMEOUT_MS
  4. 04

    The answer comes back

    SSE chunks for chat, progress notifications for MCP. If the client cancels, the agy process is stopped.

    stream: true

Small on purpose. Limits live in the server.

1call at a time Concurrency

Chat, search and image calls queue behind each other instead of racing the CLI.

24chars API_KEY minimum
300s Call timeout, default
120s Queue wait, default

Daily limits per call type (chat, search, image, research and browse) and per-minute request limits are set with DAILY_LIMIT_* variables. MCP sessions default to a maximum of 8.

Four commands, then log in once.

~/antigravity-connector
$ cp .env.example .env                 # set API_KEY, at least 24 characters
$ docker compose up -d --build
$ docker logs antigravity-connector    # prints the login block, if needed
$ curl http://127.0.0.1:8787/health

Login happens in the terminal

There is no web page. Open the link shown in the logs, sign in and copy the code. Then run docker exec -it antigravity-connector agy and paste it.

It survives restarts

The login lives in the named volume agy-gemini. docker compose down -v removes it, and you log in again.

Check it works

/health is the only route without the token. Everything else expects Authorization: Bearer.

What it does not do, and what could go wrong.

  • Not yetTool calling. The tools field returns 400.
  • Not yetresponse_format other than text, and image input.
  • Not yetThe research and browse tools, and POST /v1/images/generations.
  • Ignoredtemperature and max_tokens are accepted but have no effect.
  • PinnedThe agy binary is fixed at version 1.5.9 in the image.

Start on localhost.

Star on GitHub
Install command copied