For AI agents & MCP clients

BananaBanana MCP Server

Generate AI images and videos directly from Claude Desktop, Claude Code and any other MCP client — billed per generation from your BananaBanana balance. No subscription.

Create an API keyImages from $0.03 · video from $0.10
01WHAT IT IS

One endpoint, every model

A remote Model Context Protocol server exposing the full BananaBanana generation stack as agent tools: Google Nano Banana 2 Lite / 2 / Pro images (from $0.03), Veo 3.1 / Fast / Lite video and Gemini Omni Flash with sound (flat $1.00). Your agent sees live prices, confirms costs before expensive runs, and every generation lands in the same history and balance as the website.

  • Endpoint: https://bananabanana.pro/api/mcp (Streamable HTTP)
  • Auth: Bearer API key from your profile (OAuth 2.1 support is planned)
  • Rate limit: 20 tool calls per minute per key; optional per-key daily spend cap
  • No MCP client? The same endpoint is plain JSON-RPC over HTTPS — call it from curl, Python or TypeScript without any SDK
  • Failed or filtered generations are refunded automatically
  • Open docs, server.json and copy-paste client examples in the bananabanana-mcp GitHub repository
MCP clientClaude Code / Desktop, Cursor,VS Code, Codex, any agentBearer key/api/mcpbananabanana.proStreamable HTTP · 7 toolsgenerateModel poolNano Banana · Veo 3.1Omni Flashper unitYour balancepay per generationauto-refund on failure
02QUICK START

Connected in three steps

1. Create an account and top up the balance. 2. In Profile → MCP API Keys create a key (shown once). 3. Add the server to your client:

Claude Code

claude mcp add --transport http bananabanana https://bananabanana.pro/api/mcp \
  --header "Authorization: Bearer bb_live_YOUR_KEY"

Claude Desktop

Add to claude_desktop_config.json (Settings → Developer → Edit Config); requires Node.js for the mcp-remote bridge:

{
  "mcpServers": {
    "bananabanana": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://bananabanana.pro/api/mcp",
        "--header", "Authorization: Bearer bb_live_YOUR_KEY"
      ]
    }
  }
}

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in the project; to keep the key out of the file, use ${env:BB_API_KEY} instead of the literal value:

{
  "mcpServers": {
    "bananabanana": {
      "url": "https://bananabanana.pro/api/mcp",
      "headers": {
        "Authorization": "Bearer bb_live_YOUR_KEY"
      }
    }
  }
}

Full Cursor walkthrough, including quirks and a live-key demo: Generate Images in Cursor.

VS Code / GitHub Copilot

Add to .vscode/mcp.json in the workspace (or your user settings.json); VS Code prompts for the key once and stores it encrypted:

{
  "servers": {
    "bananabanana": {
      "type": "http",
      "url": "https://bananabanana.pro/api/mcp",
      "headers": {
        "Authorization": "Bearer ${input:bb-api-key}"
      }
    }
  },
  "inputs": [
    {
      "type": "promptString",
      "id": "bb-api-key",
      "description": "BananaBanana API key (bb_live_…)",
      "password": true
    }
  ]
}

Full VS Code / Copilot walkthrough, including quirks and a live-key demo: Generate Images in VS Code: Copilot MCP Setup Guide.

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "bananabanana": {
      "serverUrl": "https://bananabanana.pro/api/mcp",
      "headers": {
        "Authorization": "Bearer bb_live_YOUR_KEY"
      }
    }
  }
}

Any other MCP client (raw JSON-RPC)

POST https://bananabanana.pro/api/mcp
Authorization: Bearer bb_live_YOUR_KEY
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc":"2.0","id":1,"method":"tools/list"}

Prefer a walkthrough? The tutorial Generate Images in Claude Code covers the Claude setup end to end, with four real use cases and their actual costs.

03WORKS WITH

Client compatibility

MCP is an open protocol: any client that speaks Streamable HTTP and can attach an Authorization header connects. Current state, verified against each vendor's official docs (last checked July 2026):

ClientWorks today?How
Claude Codeyesclaude mcp add --transport http … --header
Claude Desktop / claude.aiyescustom connector with a request header (beta, rolling out) or the mcp-remote bridge
Cursoryes.cursor/mcp.json: url + headers, secrets via ${env:…} — see the snippet above
VS Code / GitHub Copilotyes.vscode/mcp.json: type: "http" + url + headers; store the key as a promptString input — VS Code asks once and keeps it encrypted
ChatGPT desktop / Codex CLI / IDEyesshared ~/.codex/config.toml: url + bearer_token_env_var (put the key in the env var). ChatGPT web connectors are the exception — they authenticate via OAuth, not pasted keys
Gemini CLIyeshttpUrl + headers in settings.json
xAI API (Grok)yesMCP tool with server_url and an authorization value sent to the server
grok.com (web)partiallycustom connectors take a server URL (Connectors → New Connector → Custom); the docs don't state whether a pasted API-key header is supported, so this path may need our upcoming OAuth 2.1
ZCode (GLM-5.2)yesSettings → MCP Servers → type HTTP + Authorization header; GLM-5.2 inside Claude Code inherits the Claude Code config
Anything elseyesraw JSON-RPC over HTTPS — see Call it from code below

Codex example — add to ~/.codex/config.toml and export BB_API_KEY=bb_live_…:

[mcp_servers.bananabanana]
url = "https://bananabanana.pro/api/mcp"
bearer_token_env_var = "BB_API_KEY"

Full Codex walkthrough — CLI, IDE extension and ChatGPT desktop from one config, with quirks and a live-key demo: Codex MCP Setup: Images and Video from One config.toml.

04NO SDK NEEDED

Call it from code

Don't use an MCP client? You don't need one — and you don't need an SDK either. The server is plain JSON-RPC 2.0 over HTTPS: one POST endpoint, a Bearer header, a single JSON response. It is stateless, so there is no session handshake to manage — tools/call works as the very first request from curl, Python, TypeScript or anything else that can send HTTP.

curl

# start an image generation (charges one image, $0.06 on the default model)
curl -s https://bananabanana.pro/api/mcp \
  -H "Authorization: Bearer bb_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
        "name":"generate_image",
        "arguments":{"prompt":"studio photo of a ceramic mug on linen, soft daylight"}}}'

# → result.structuredContent.job_id = "cmxy…"

# fetch the result (long-polls server-side up to 30 s; free)
curl -s https://bananabanana.pro/api/mcp \
  -H "Authorization: Bearer bb_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
        "name":"get_result",
        "arguments":{"job_id":"cmxy…","wait_seconds":30}}}'

Python

Only requests — no MCP library:

import requests

MCP = "https://bananabanana.pro/api/mcp"
HEADERS = {"Authorization": "Bearer bb_live_YOUR_KEY"}

def call(tool, **args):
    r = requests.post(MCP, headers=HEADERS, json={
        "jsonrpc": "2.0", "id": 1, "method": "tools/call",
        "params": {"name": tool, "arguments": args},
    })
    r.raise_for_status()
    return r.json()["result"]["structuredContent"]

job = call("generate_image", prompt="watercolor painting of a lighthouse at dawn")

result = call("get_result", job_id=job["job_id"], wait_seconds=30)
while result["status"] == "processing":
    result = call("get_result", job_id=job["job_id"], wait_seconds=30)

print(result["files"][0]["url"], "cost:", result["cost_charged_usd"])

TypeScript / Node.js

Zero dependencies — built-in fetch (Node 18+, Deno, Bun, browsers):

const MCP = "https://bananabanana.pro/api/mcp";

async function call(tool: string, args: Record<string, unknown>) {
  const res = await fetch(MCP, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BB_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      jsonrpc: "2.0", id: 1, method: "tools/call",
      params: { name: tool, arguments: args },
    }),
  });
  const { result } = await res.json();
  return result.structuredContent;
}

const job = await call("generate_image", {
  prompt: "isometric 3D render of a tiny greenhouse at golden hour",
});

let out = await call("get_result", { job_id: job.job_id, wait_seconds: 30 });
while (out.status === "processing") {
  out = await call("get_result", { job_id: job.job_id, wait_seconds: 30 });
}
console.log(out.files[0].url, "cost:", out.cost_charged_usd);

Details that matter when you script it:

  • Every tool response carries the same JSON twice: machine-readable result.structuredContent and a text block in result.content — parse whichever is easier.
  • Video (and multi-image batches) are a two-step call: the first generate_video returns a quote and charges nothing; repeat it with confirm_cost set to the quoted amount to start.
  • Pass an idempotency_key on generation calls — network retries will never double-charge.
  • tools/list works without a key, so you can explore the full schemas before creating an account. Tool calls are limited to 20 per minute per key.
05TOOLS

Seven task-shaped tools

ToolCostWhat it does
list_modelsfreeAll models with live per-unit prices, resolutions and constraints.
get_accountfreeBalance, key spend cap and today's usage.
generate_image$0.03–$0.20Text-to-image on Nano Banana 2 Lite / 2 / Pro, up to 4K. Returns a job_id.
edit_imageprice of one imageRefine a finished image with a text instruction (multi-turn editing).
generate_video$0.10–$4.40Veo 3.1 family or Omni Flash (always with sound). Always quotes the exact cost first.
get_resultfreePoll a job: hosted media URLs (24 h links), cost charged, balance left, inline image preview.
list_generationsfreeRecent generation history — shared with the website.
06PRICING

Cost transparency, built in

  • Prices are served live by list_models — the same source the website uses.
  • Every video (and multi-image batch) call first returns a quote and charges nothing; the agent repeats the call with confirm_cost to start.
  • Every result includes cost_charged_usd and balance_remaining_usd.
  • Upstream failures and content-filter rejections are refunded automatically — same policy as the web app.
  • Optional idempotency_key guarantees retries never double-charge.
07EXAMPLE

A real conversation

→ generate_video {"prompt": "drone shot over a misty pine forest", "model": "veo-3.1-fast"}
← {"status": "confirmation_required", "quoted_cost_usd": 0.70, ...}
→ generate_video {..., "confirm_cost": 0.70}
← {"job_id": "cmxy…", "status": "processing", "cost_charged_usd": 0.70, "balance_remaining_usd": 12.40}
→ get_result {"job_id": "cmxy…"}
← {"status": "completed", "files": [{"url": "https://…"}], "cost_charged_usd": 0.70}
08SECURITY

Media URLs & security

  • Result URLs are signed and valid for 24 hours; the media itself stays in your account — call get_result again for fresh links, or download from the website.
  • API keys are stored hashed and shown only once at creation; revoke them any time in your profile.
  • Per-key usage log (tool, model, cost, prompt preview) is visible in Profile → MCP API Keys.
  • MCP generations appear in the same generation history and analytics as web generations.

Ready to plug your agent in?

Create a key, add one config line — your agent generates studio-grade media in minutes.

Get your API key