{"slug": "teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s", "title": "Teaching Google Antigravity to Paint: A Stateful Image-Editing Skill Built on Gemini's Interactions API and MCP", "summary": "A developer built a stateful image-editing skill for Google Antigravity CLI by wrapping Google's gemini-3.1-flash-lite-image model (NB2Lite) in a FastMCP server. The skill leverages Gemini's Interactions API to allow iterative edits without re-prompting the entire scene, enabling workflows like generating a cyberpunk kitchen and then adding a neon RAMEN sign to the same image. The project ships as an MCP server exposing four tools for generating and editing images, with Antigravity CLI as the client.", "body_md": "TL;DR:[nb2lite-skill-agy]wraps Google's`gemini-3.1-flash-lite-image`\n\nmodel (NB2Lite) in a FastMCP server and packages it as an Antigravity CLI skill. You type \"generate an image of a cyberpunk kitchen\" into Antigravity, and it just... does it. Then you say \"add a neon RAMEN sign\" and it editsthe same imagewithout re-prompting the whole scene. Oh, and the cover image of this article? Generated by the thing the article is about — dogfooding all the way down. More on that at the end.\n\nMost image-generation workflows are **stateless**. You send a prompt, you get pixels back, and the model immediately forgets everything. Want to tweak the result? You re-describe the *entire scene* and pray the character, lighting, and composition survive the round trip. (Narrator: they don't.)\n\nGoogle's **NB2Lite** — the friendly nickname for `gemini-3.1-flash-lite-image`\n\n— takes a different approach. It's a high-efficiency image model with sub-2-second generations, solid text rendering in 25+ languages, and — the headline feature — support for the **stateful Interactions API**, which lets you iterate on an image across multiple turns while the model keeps the visual context server-side.\n\nThis repo glues that capability directly into **Google Antigravity CLI**, so your coding agent can generate and iteratively refine images as a natural part of a pair-programming session. It ships as two things in one repo:\n\n`nb2lite-agent`\n\n, a single-file FastMCP app in `server.py`\n\n) exposing four tools.`nb2lite-image`\n\n) that teaches Antigravity The Interactions API is Gemini's stateful endpoint. The core loop looks like this:\n\n`client.interactions.create(...)`\n\nwith a prompt and `store=True`\n\n.`interaction_id`\n\n`previous_interaction_id`\n\n, and the model edits the So instead of this (stateless suffering):\n\n\"A watercolor fox in a forest at dawn, mist, soft light, wearing a red scarf, three birch trees on the left,\n\nand now alsoholding a lantern\"\n\n...you write this in Antigravity:\n\n\"Add a lantern in its paw.\"\n\nThat's it. The stored context holds the rest.\n\nA few practical details the server handles for you:\n\n`1:1`\n\n, `16:9`\n\n, `9:16`\n\n, `4:3`\n\n, `3:4`\n\n) and `low`\n\n(default, fast drafts) or `high`\n\n(complex rendering, accurate text layout, character composition). The generic API spec also lists `minimal`\n\nand `medium`\n\n, but the live API rejects them for this model with an HTTP 400 — the server saves you from discovering that the hard way.The **Model Context Protocol** is an open standard for connecting AI assistants to tools and data. Before it, giving a model access to some service meant writing a bespoke integration for each assistant — N assistants × M services, everyone reinventing the same plumbing. MCP collapses that: a tool author writes one **MCP server** that exposes typed tools, and any MCP-capable client like Antigravity CLI can discover and call them with no per-client glue code.\n\nAn MCP server is usually a small local process that speaks JSON-RPC over stdio. Antigravity launches it, asks \"what tools do you have?\", and from then on the model can call them like native functions.\n\nThe `nb2lite-agent`\n\nserver exposes four core tools:\n\n| Tool | What it does |\n|---|---|\n`generate_image` |\nText → 1k image. Saves locally, returns the path + an interaction ID. |\n`edit_image` |\nStateful edit: takes the previous interaction ID + a description of only the change. |\n`edit_local_image` |\nUploads any local image file inline (base64) and applies an edit — your entry point for existing files. |\n`get_help` |\nReports live config: API key status, active model, output directory, full tool reference. |\n\nImages land on disk as `gen_<timestamp>_<uuid8>.jpg`\n\n(or `edit_`\n\n/`edit_local_`\n\nprefixed) — the UUID suffix keeps concurrent generations from clobbering each other. Errors come back as `🔴 ...`\n\ntext strings rather than protocol errors, so Antigravity can read and react to them gracefully.\n\nIf MCP is the *hands* (the tools an agent can physically call), a **skill** is the *muscle memory* — a markdown file (`SKILL.md`\n\n) plus bundled resources that load into Antigravity's context and teach it the workflow: which tool to reach for, in what order, with which constraints.\n\nFor `nb2lite-image`\n\n, the skill encodes things like:\n\n`get_help`\n\nfirst when diagnosing setup issues — if the API key is missing, nothing else will work.`thinking_level: low`\n\nfor drafts.The skill also bundles the MCP server itself (`mcp/server.py`\n\n), its requirements, an installer script, and a vendored copy of the Interactions API developer guide — so it's fully self-contained.\n\nYou need three things: **Python 3.10+**, **Antigravity CLI**, and a **Gemini API key** (free from [Google AI Studio](https://aistudio.google.com/)). Pick *one* of the paths below.\n\nInside your Antigravity session, run:\n\n```\n/plugin marketplace add xbill9/nb2lite-skill-agy\n/plugin install nb2lite-image@nb2lite-skill-agy\n```\n\nThis installs the skill **and** auto-registers the MCP server. The plugin manifest carries no API key — the server reads `GEMINI_API_KEY`\n\nfrom your environment, so make sure it's exported before launching Antigravity CLI.\n\n```\n# 1. Get the code\ngit clone https://github.com/xbill9/nb2lite-skill-agy.git\ncd nb2lite-skill-agy\n\n# 2. One-command setup: installs deps, registers the MCP server\n#    in .mcp.json, and prompts for your API key (stored in ~/gemini.key)\n./init.sh\n\n# 3. Restart Antigravity CLI in this directory and approve the server\n#    when prompted. Verify with:\n/mcp        # should list nb2lite-agent\n```\n\n`init.sh`\n\nis idempotent and safe to rerun anytime.\n\nFrom a clone of the repo:\n\n```\nmake init TARGET=/path/to/your/project ARGS='--output-dir ./images'\n```\n\nThis copies the skill into `<project>/.gemini/antigravity-cli/skills/nb2lite-image/`\n\nand writes the `nb2lite-agent`\n\nentry into that project's `.mcp.json`\n\n. It reuses `~/gemini.key`\n\nif available. Restart Antigravity in your project, approve the server, done.\n\nThe server is published as [ xbill9/nb2lite-agent](https://hub.docker.com/r/xbill9/nb2lite-agent):\n\n```\nantigravity mcp add nb2lite-agent --env GEMINI_API_KEY=\"$(cat ~/gemini.key)\" -- \\\n  docker run --rm -i -e GEMINI_API_KEY -v \"$PWD:$PWD\" -w \"$PWD\" xbill9/nb2lite-agent\n```\n\nThe `-v \"$PWD:$PWD\" -w \"$PWD\"`\n\nmount ensures the container can save images to your workspace disk and read local files for `edit_local_image`\n\n.\n\n`/mcp`\n\ndoesn't list the server → restart Antigravity CLI in the project directory.`🔴 GEMINI_API_KEY is not set`\n\n→ run `source set_env.sh`\n\n(or export the key) and restart.`get_help`\n\n; it reports the live configuration.Once installed, you talk to Antigravity in plain English. A real flow looks like:\n\n**You:** *\"Generate a cozy cabin in a snowy forest at dusk, 16:9.\"*\n\nAntigravity calls:\n\n```\ngenerate_image(\n    prompt=\"A cozy log cabin in a snowy forest at dusk, warm light in the windows\",\n    aspect_ratio=\"16:9\",\n    thinking_level=\"low\",\n)\n# 🟢 Saved to: ./gen_1784759001_a1b2c3d4.jpg\n# Interaction ID: v1_ChdpRU5...\n```\n\n**You:** *\"Nice. Add smoke curling from the chimney.\"*\n\n```\nedit_image(\n    previous_interaction_id=\"v1_ChdpRU5...\",\n    edit_prompt=\"add gentle smoke curling from the chimney\",\n)\n# 🟢 Saved to: ./edit_1784759050_e5f6a7b8.jpg\n# Interaction ID: v1_Xk9mPq2...   ← a NEW id; the next edit chains this one\n```\n\n**You:** *\"Now make it night, with aurora in the sky.\"*\n\nSame tool, newest ID, and the cabin, trees, and chimney smoke all stay put — only the sky changes. No re-prompting, no continuity roulette.\n\nAnd for images that didn't come from the model at all:\n\n**You:** *\"Take ./whiteboard-sketch.png and render it as a clean 3D product mockup.\"*\n\n```\nedit_local_image(\n    image_path=\"./whiteboard-sketch.png\",\n    edit_prompt=\"render this hand-drawn sketch as a high-fidelity 3D product mockup\",\n    aspect_ratio=\"4:3\",\n)\n```\n\nIt returns an interaction ID too — so follow-up refinements switch to `edit_image`\n\nand go stateful from there.\n\n**\"Eating your own dog food\"** means using your own product for real work. It's the difference between \"this should work\" and \"I ship with this every day.\"\n\nThis repo dogfoods itself at every layer:\n\n`nb2lite-image`\n\nskill and `nb2lite-agent`\n\nserver are already wired up, so every development session doubles as an integration test.`make test`\n\n) drive the same four MCP tools an end user would, against the live API.\n\n```\ngenerate_image(\n    prompt=\"A wide tech blog cover illustration: a friendly AI agent with glowing antigravity elements floating alongside an easel, painting a vibrant galaxy, while a chain of connected frames behind it shows the same picture evolving step by step. Flat vector style, deep indigo background, neon cyan and magenta accents. Title text 'NB2Lite + Antigravity', subtitle 'Stateful image editing as an Antigravity skill'. Crisp, accurate lettering.\",\n    aspect_ratio=\"16:9\",\n    thinking_level=\"high\",\n)\n# 🟢 Image successfully saved!\n# • Saved to: /home/xbill/nb2lite-skill-agy/gen_1784832091_d71439ca.jpg\n# • Interaction ID: v1_ChdXbUJpYXB5aEZZYkotOFlQeC1UcG1BNBIXV21CaWFweWhGWWJKLThZUHgtVHBtQTQ\n```\n\n(That exact output is committed to the repo as [ devto-cover.jpg](https://github.com/xbill9/nb2lite-skill-agy/blob/master/devto-cover.jpg), receipts and all.)\n\nWorth noticing:\n\n`thinking_level: \"high\"`\n\nbuys you on text-heavy layouts.`edit_image`\n\nwith that interaction ID and say \"make the cyan accents emerald.\" That's the whole point.Dogfooding is the cheapest credibility there is: the tool's real output is literally the first thing you saw when you opened this article.\n\n*This is a third-party community project, not affiliated with or endorsed by Google. Bring your own Gemini API key — and remember generations are billable, so draft on low and save high for final outputs.*", "url": "https://wpnews.pro/news/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s", "canonical_source": "https://dev.to/gde/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-geminis-interactions-9g1", "published_at": "2026-07-24 12:35:53+00:00", "updated_at": "2026-07-24 13:03:05.039424+00:00", "lang": "en", "topics": ["artificial-intelligence", "generative-ai", "developer-tools", "computer-vision", "ai-products"], "entities": ["Google", "Gemini", "Antigravity CLI", "FastMCP", "MCP", "NB2Lite", "Interactions API"], "alternates": {"html": "https://wpnews.pro/news/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s", "markdown": "https://wpnews.pro/news/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s.md", "text": "https://wpnews.pro/news/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s.txt", "jsonld": "https://wpnews.pro/news/teaching-google-antigravity-to-paint-a-stateful-image-editing-skill-built-on-s.jsonld"}}