Skip to main content
6 min read

Connect your AI directly

The best way to build with AI: plug the GDN toolkit into your assistant so it doesn't just write code — it scaffolds the app, renders the panel and looks at the result, fixes what it sees, validates, and generates the catalog previews. You describe the app; the AI runs the whole loop.

This works through MCP (Model Context Protocol), a standard for giving AI assistants tools. It's not Claude-only: Claude Code, Claude Desktop, OpenAI's Codex CLI, Cursor, and most modern AI tools speak it. (ChatGPT itself is the exception — see below.)

Every render below is a real panel output from a real session — this exact app was built this way, start to finish.

Rain Radar: 60-day rainfall sparkline with 0.16 IN/DAY overlay
Rain Radar — built entirely by an AI through the MCP tools. Real Open-Meteo data.

Setup

Zero setup. The repo ships a .mcp.json, so the tools register themselves:

git clone https://github.com/glance-led-dev/glance-dev-network.git
cd glance-dev-network
pip install -e .
claude

Open Claude Code inside the repo folder and approve the glance MCP server when prompted. That's it — ask for an app.

What the AI gets

ToolWhat it does
create_appScaffold a working app folder (manifest + code)
render_appRender a page and return the panel as an image — with simulate_offline to see the no-data screen
validate_appThe publish-time check, plus a no-network render to prove the fallback works
write_previewsGenerate the preview/ catalog images, same as Studio and gdn submit
measure_textPixel width of a string in a font — no more clipped text
list_fonts / list_colorsThe real font and color tables, so nothing is guessed

The renders it gets back aren't descriptions — they're images. The AI sees the panel, which is what makes the loop work.

Rendering and measuring don't change anything on disk, and the server says so, so most clients stop asking you to approve every single render once you've allowed the first.

It already knows the rules

Tools are only half of it. GDN has rules an assistant can't guess and that fail silently when broken — the panel is 32px tall, fonts are uppercase-only, http.get returns a dict you read with resp["status_code"] rather than a dot. So the server hands those over too, the moment it connects:

What it getsWhen
The rules that fail silentlyAutomatically, on connect
The full drawing API, the helper list, and the manifest schemaPulled in when it starts writing code
A complete working app to copy fromThe same files create_app scaffolds

In a coding agent like Claude Code or Codex CLI this is belt and braces — the repo is on disk, so the assistant could read the source anyway. In Claude Desktop there's no filesystem, so this is the only way it learns GDN. Which is the real reason the paste-in prompt exists: it's for chats without MCP. Connected here, you don't need it.

If your client shows prompts as slash commands, you'll also see build_an_app — pick it, describe your app in a sentence, and everything above is already loaded.

Editing files outside Claude Code

The glance tools scaffold, render, validate, and generate previews — they don't read or write your source files, because coding agents like Claude Code, Codex CLI, and Cursor already have that built in. In Claude Desktop, pair this with a filesystem MCP server so the assistant can save app.star after it writes it.

A real session, start to finish

One prompt, and the loop runs. This is the actual session that produced Rain Radar (condensed; every render is genuine):

Building Rain Radar — real session
YOU

Build me an app: average rainfall in a 100-mile radius of a ZIP code over the last 60 days, one page, draw a cool graph.

create_app{"path": "apps/rain-radar"}

Created apps/rain-radar with manifest.yaml and app.star (a working example).

measure_text{"text": "RAIN 100MI 60D", "font": "4x7"}

'RAIN 100MI 60D' in 4x7: 65px wide, 8px tall. Fits panel width 128px: yes.

AI

I'll fetch the ZIP's coordinates, then one Open-Meteo call sampling five points across the radius, and draw the 60 days as a sparkline. Writing manifest.yaml and app.star now, then rendering to check.

render_app{"app_dir": "apps/rain-radar"}

Page 1/1 (rain) — 128x32 panel.

First render: sparkline with faint fillimage returned to the AI
AI

It works — real data on the first render. But looking at it: the fill under the line is barely visible and the graph floats with no baseline. Fixing both and rendering again.

render_app{"app_dir": "apps/rain-radar"}

Page 1/1 (rain) — 128x32 panel.

Final render: brighter fill and baselineimage returned to the AI
YOU

Nice. Make the radius a setting people can change.

render_app{"app_dir": "apps/rain-radar", "inputs": {"zip": "98101", "radius": "50"}}

Page 1/1 (rain) — radius input wired up; Seattle at 50 miles.

Seattle at 50 milesimage returned to the AI
validate_app{"app_dir": "apps/rain-radar"}

PASS — 1 page renders cleanly.

write_previews{"app_dir": "apps/rain-radar"}

Wrote preview/ images: preview.png, rain.png

AI

Done — validated, with catalog previews generated. Ready to submit whenever you are.

The AI checks the failure screens too

A panel on a wall has to show something sensible when a ZIP doesn't exist, an API is down, or the data comes back empty. render_app takes a simulate_offline flag that makes every http.get fail, so the AI can look at the fallback screen the same way it looks at the happy path — and validate_app warns if an app crashes with no network instead of falling back. These two renders are the real fallback screens it checked:

ZIP NOT FOUND fallback screen
ZIP 00000 → a designed answer, not a crash.
NO DATA fallback screen
simulate_offline: true → the API-down screen.

Keep Studio open while you talk

The workflow that feels magic: Studio on one side, your AI chat on the other. The MCP tools edit the same files Studio watches, so every change the AI saves re-renders in Studio instantly — you watch the panel evolve in real time, tweak an input, and tell the AI what to change next.

Glance Dev Studio showing rain-radar: code left, live panel preview right, ZIP and radius settings below
The finished app in Studio: the AI wrote every line, and the live preview tracked each save.

Studio even referees the conversation. Mid-session — after the radius setting existed in the manifest but before the code read it — Studio flagged it in real time:

Studio flagging the radius setting as NOT USED IN CODE during iteration
Caught mid-iteration: the NOT USED IN CODE badge, before the AI wired the setting up. Validate would fail here — and the AI's validate_app call sees the same thing.

Publishing

Nothing new to learn: the AI has already run validate_app (the same check publishing runs) and write_previews (the same files Studio generates on submit). From there it's the normal flow — Validate & Submit in Studio, or:

gdn submit apps/rain-radar

and your app opens as a pull request. See Submit your app.

Next