DEV Community

SRKDAN
SRKDAN

Posted on

Give your AI agent a brand: on-brand images from Claude or Cursor via MCP

AI-assisted draft. I wrote and verified the setup against the current Brandiseer MCP endpoint and developer docs.

Disclosure: I work on Brandiseer. This whole post uses its MCP server, so read it with that in mind.

Ask Cursor for a hero image for a landing page and you'll get something back. Usually it's a decent picture that has nothing to do with your brand. When I tried it for an old bakery site I got a croissant on grey marble with teal accents. The bakery's boxes are orange. Every follow-up prompt drifted a little further, because the agent has no idea what the brand looks like and guesses fresh each time.

What fixed it for me was moving the brand out of the prompt. The agent still decides when it needs an image and what goes in it. The look comes from a server that already knows the brand. That split is a good fit for MCP: the agent gets a few tools, and the rules live behind them.

What the server is

URL:        https://brandiseer.com/api/mcp
Transport:  streamable-http
Header:     Authorization: Bearer bds_...
Enter fullscreen mode Exit fullscreen mode

API keys start with bds_. The same key works for the REST API, but the header is different there (more on that below, it's the most common mistake).

The tools

brandiseer_list_brands

Returns your saved brands with id, name and creation date. Ids look like bds_c_42. The agent needs one before it can generate anything, so this is usually its first call.

brandiseer_check_credits

Returns your credit balance. I have the agent call it before anything batch-shaped.

brandiseer_generate_image

Generates one still image and returns it inline, so it shows up right in the chat. Under the hood it calls POST /api/v2/generate. The exception is mode: "design", which goes through the async endpoint (POST /api/v2/generate/async, then polling GET /api/v2/jobs/:jobId). The MCP server does that polling for you. From the agent's side it's still one tool call, it just takes longer.

Since it wraps v2, you're working with the v2 knobs:

Option Values
brand id from brandiseer_list_brands
prompt what's in the frame (see the prompting section)
aspect ratio 1:1, 16:9, 9:16, 4:3
resolution 1K, 2K, 4K
mode fast, design, pro
useLogo true / false

If you open the live manifest at https://brandiseer.com/.well-known/mcp/manifest.json you'll also see brandiseer_create_brand and brandiseer_check_brand_creation_job. Those are newer (API v2.2). You give it a website URL, it starts an async job, and you poll until it hands back a brandId. It costs 20 credits, charged only if the brand actually gets created. Handy if you don't have a brand yet, but I'm leaving them out of this walkthrough.

What you need

  • A Brandiseer account with at least one brand saved
  • An API key from Settings > API (https://brandiseer.com/settings/api)
  • Cursor, or a Claude host that supports remote MCP servers
  • A few credits. A fast 1K image is 4.

Wire it into Cursor

Cursor reads MCP config from .cursor/mcp.json in a project, or ~/.cursor/mcp.json for every project. Remote servers take a url and headers:

{
  "mcpServers": {
    "brandiseer": {
      "url": "https://brandiseer.com/api/mcp",
      "headers": {
        "Authorization": "Bearer bds_YOUR_KEY"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

I'd rather not have a real key in a file that can end up in git, though. Cursor interpolates ${env:NAME} inside url and headers, so this works too:

{
  "mcpServers": {
    "brandiseer": {
      "url": "https://brandiseer.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${env:BRANDISEER_API_KEY}"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Put BRANDISEER_API_KEY in your shell profile or system environment and restart Cursor. Don't bother with a .env file here. envFile only works for stdio servers, remote ones ignore it.

Then open Customize in the sidebar and check the server is on and lists its tools. If it shows an error instead, the Output panel has an "MCP Logs" entry with the actual message.

Claude Code and Claude Desktop

This post is Cursor-first, but Claude Code takes the same two values:

claude mcp add --transport http brandiseer https://brandiseer.com/api/mcp \
  --header "Authorization: Bearer bds_YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

Or check it into the project as .mcp.json:

{
  "mcpServers": {
    "brandiseer": {
      "type": "http",
      "url": "https://brandiseer.com/api/mcp",
      "headers": {
        "Authorization": "Bearer bds_YOUR_KEY"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Claude Desktop is the odd one. As far as I know its custom connectors go through an OAuth sign-in rather than a header you paste. The server's 401 response does mention OAuth sign-in as an option, but I haven't walked through that flow for this post, so I won't pretend to document it. Any host that lets you set a URL plus a Bearer header uses the values above.

Prompting without fighting the brand

This is where most of the bad images come from. Brandiseer keeps each brand's colors, typography and visual style in its brand memory and applies them on every generation. If your prompt also says "navy palette" or "elegant serif headline", it competes with that, and it can win. Then you get an off-brand image out of a tool whose only job is the opposite.

So the prompt describes what's in the frame and how it's laid out: the subject, the layout and composition, and any text that goes on the image. Nothing about how it should look.

Fights the brand:

Instagram post for a coffee shop, cozy warm tones, minimalist aesthetic,
soft pastel colors, elegant serif font for the headline, latte on a
wooden table by a window
Enter fullscreen mode Exit fullscreen mode

Works with it:

Instagram post for a coffee shop: a latte on a wooden table by a window,
morning light through the glass. Headline across the top: "Open from 7"
Enter fullscreen mode Exit fullscreen mode

Some words sound like style but aren't. "Golden hour" and "studio lighting" describe what's physically in the scene. "Flat illustration", "isometric" and "photorealistic" pick the medium, which the brand doesn't decide. The ones to cut are mood words like "moody" or "cinematic", vague quality words like "premium", and any named color or font. The full rules are at https://brandiseer.com/guide/image. It's written for agents, so you can point yours at it directly.

Also, aspect ratio and resolution are tool arguments. Writing "square, 4K" into the prompt text does nothing.

Agents love to "improve" prompts with "clean modern aesthetic" on the way to the tool call. A project rule stops most of that. In Cursor, .cursor/rules/brandiseer.mdc:

---
description: Rules for Brandiseer image generation
alwaysApply: false
---
When calling brandiseer_generate_image:
- Describe subject, layout, composition and on-image text only.
- Never add colors, fonts, or mood words (moody, cinematic, premium).
  The brand already sets those.
- Put aspect ratio and resolution in the tool arguments, not the prompt.
- Use mode "fast" unless I ask for design or pro. Never send proMode.
Enter fullscreen mode Exit fullscreen mode

The same text works in a CLAUDE.md for Claude Code.

Smoke test

Three messages in agent chat, in this order.

1. "List my Brandiseer brands." The agent should call brandiseer_list_brands. Cursor asks before running an MCP tool by default, and the arrow next to the tool name shows the arguments. You get back ids, names and dates. Copy the id you want.

2. "How many Brandiseer credits do I have?" That's brandiseer_check_credits. If both of these work, auth is fine and anything that breaks later is about the generate call itself.

3. A boring, layout-only image.

Use brandiseer_generate_image with brand bds_c_42, aspect ratio 1:1,
resolution 1K, mode fast, no logo.
Prompt: a flat lay of a notebook, a phone and a coffee cup on a desk,
seen from above. Text at the top: "Monday plan"
Enter fullscreen mode Exit fullscreen mode

Swap in your own brand id. Before you approve the call, expand the arguments and read the prompt the agent is actually sending. If it slipped in style words, reject it and say why. The image comes back inline.

For reference, credits per image:

Mode 1K 2K 4K
Fast 4 6 8
Design 5 6 8
Pro 6 8 10

So that smoke test costs 4.

When it breaks

401 when Cursor connects. With no auth header at all the endpoint answers:

Missing Authorization: Bearer <api-key-or-oauth-token> header. Connect via
OAuth sign-in or paste an API key from https://brandiseer.com/settings/api.
Enter fullscreen mode Exit fullscreen mode

The MCP endpoint wants Authorization: Bearer bds_.... X-API-Key is the REST header, and putting that in mcp.json is the usual mix-up. The other two I'd check are a missing Bearer prefix and an env var that only exists in one terminal session, which Cursor can't see.

Images come back off-brand. Read the prompt in the tool arguments. Usually there's a color or mood word in there that you didn't write.

Design mode looks stuck. Design takes roughly 40 to 70 seconds, and the MCP server is polling the async job for you during that time. Let it finish. Cancelling and asking again just submits a new job. For quick checks and iterating on a layout, stay on fast and switch to design once you know what you want.

When to use REST instead

MCP is for when an agent is in the loop. For a batch script, a CI step or a backend job, call the API directly. Use v2, which takes the key as X-API-Key:

curl -X POST https://brandiseer.com/api/v2/generate \
  -H "X-API-Key: $BRANDISEER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brandId": "bds_c_42",
    "prompt": "Website hero: a baker pulling a tray of bread out of an oven. Headline on the left: \"Baked before 6\"",
    "aspectRatio": "16:9",
    "resolution": "1K",
    "mode": "fast",
    "useLogo": false
  }'
Enter fullscreen mode Exit fullscreen mode

That returns { "imageUrl": "...", "creditsUsed": 4 }.

For design mode with your own timeouts, submit to the async endpoint and poll. The docs say every 3 to 5 seconds, until status is done or failed:

import os
import time

import httpx

API = "https://brandiseer.com/api/v2"
headers = {"X-API-Key": os.environ["BRANDISEER_API_KEY"]}

body = {
    "brandId": "bds_c_42",
    "prompt": 'Event poster: a long dinner table in a courtyard. Text at the top: "Supper club, Friday 8pm"',
    "aspectRatio": "4:3",
    "resolution": "2K",
    "mode": "design",
    "useLogo": True,
}

with httpx.Client(headers=headers, timeout=30) as client:
    r = client.post(f"{API}/generate/async", json=body)
    r.raise_for_status()
    job_id = r.json()["data"]["jobId"]

    deadline = time.monotonic() + 9 * 60  # jobs expire after 10 minutes
    while time.monotonic() < deadline:
        time.sleep(4)
        job = client.get(f"{API}/jobs/{job_id}").json()["data"]
        if job["status"] == "done":
            print(job["imageUrl"], job["creditsUsed"])
            break
        if job["status"] == "failed":
            raise RuntimeError(job["error"])
        # anything else: still running, keep waiting
    else:
        raise TimeoutError(f"job {job_id} did not finish")
Enter fullscreen mode Exit fullscreen mode

A few details from the docs that matter here. Credits come off when you submit, and they're refunded automatically if the job fails. You have to poll with the same key you submitted with. Jobs expire after 10 minutes, hence the 9 minute deadline. I wrote up the general pattern (backoff, idempotency, Retry-After) in an earlier post on polling image jobs if you want more than this loop.

Full reference: https://brandiseer.com/developers/docs

Ignore proMode

The v1 API used proMode: true/false and only had fast and pro. v2 replaced it with mode. Some discovery surfaces still say proMode. As of 14 Oct 2026 that includes the description of brandiseer_generate_image in the MCP manifest itself, which says it "costs 4-10 credits depending on resolution and proMode".

Agents read tool descriptions, so Cursor may try to send proMode: true. For MCP and v2, use mode with fast, design or pro. That's why the rule file above says "never send proMode". /api/v1/generate still accepts proMode for old integrations, but don't mix the two. Not every surface is cleaned up yet, so if you see proMode in a doc, an OpenAPI file or a tool description, you're looking at the old API.

Top comments (0)