Generation belongs in an MCP server

// signals

An agent working through a task shouldn’t have to stop, switch to a design tool, click around a canvas, export a file, and carry it back. When it needs an image, it should ask for one, the same way it asks for a database row or a weather reading. Generation is a dependency, not a destination. I built RNSNB to prove that.

The break in the flow

Most image tools are places you go. That’s fine for a person composing one hero shot with intent. It’s wrong for an agent three steps into a job that happens to need a diagram, a thumbnail, a placeholder. The moment the tool is somewhere you visit, the agent has to break flow: hand off to a human, or drive a browser it was never built to drive. The image isn’t the point of the task; it’s one input the task needs. Inputs should be callable. So I made generation something an agent requests, not somewhere it has to travel.

One pipeline, two front doors

RNSNB, Randolph’s Not-So Nano Banana, is a full image studio on Google Gemini, and it has two front doors onto the same engine.

One is a browser app: a zero-build front end in vanilla JavaScript and PHP (no npm, no webpack) with an IndexedDB gallery that never fills up and offline PWA support, live at randomsynergy.com/rnsnb. A person opens it and works.

The other is a hosted MCP server, TypeScript on Node, that exposes the same generation to any agent that speaks MCP. Eight tools, feature parity with the UI. A person clicks Generate; an agent calls rnsnb_generate_image. Same backend, same models, same output. Neither path is a stripped-down version of the other.

What “a service” actually gets you

This isn’t a thin wrapper around an API. The studio runs two Gemini tiers (a Flash tier for fast drafts and iteration, and a Pro tier for text-heavy, final, client-facing renders), both up to 4K. Pro carries the controls you’d expect from a real camera: a 3D camera widget with 96 positions, 9 lighting options, depth of field, focus, and color grading. There are 20 style presets, batch generation, negative prompts, reference images, and iterative refinement that keeps a parent-child history of every edit.

The point is that an agent calling the MCP server gets all of it. Not a lesser “machine version.” The capability is identical whether a human or a model is holding the other end.

The permanent URL is the whole trick

Here’s the part that makes it agent-native. Every image RNSNB produces lands at a permanent public URL: plain HTTP GET, no auth, no token, no expiry. The agent doesn’t get back a blob it has to store or a handle that goes stale. It gets a link it can drop straight into a markdown doc, a web page, a deploy, a message.

That’s the difference between “generate an image” and “generate an image I can use in the next step.” A URL is the most composable output there is; everything downstream already knows how to read one. The agent generates, gets a link, and keeps working. It never left the flow.

Build once, expose it everywhere

This is the method, not a one-off. I built the pipeline once and put two front doors on it, so people and agents run the exact same code, models, and guardrails. When I harden the rate limits (50 generations an hour per IP on the web, per-caller ceilings on the hosted MCP side) or ship a new Gemini model, the browser and every agent get it at the same time. There’s no “AI version” quietly drifting behind the real product. Build the capability once, then expose it so people and machines call the same thing.

The lesson generalizes past images. Any capability an agent needs mid-task (a search, a generation, a lookup, a transform) is worth more as a service it can call than a place it has to visit. Stop making agents break flow to use your tools. Hand them a URL and let them keep going.