Skip to content
Brand Stack
Esc
↑↓navigate↵open⌘Jpreview
Sign up
On this page

Troubleshooting

Common issues with the Brand Stack MCP connector, from OAuth flow failures to scope errors and tool errors, and how to recover.

You’re signed in but you aren’t an admin of any Brand Stack workspace. Ask a workspace admin to either:

  • Promote you to admin, or
  • Authorize the MCP connection on their own account (the token is workspace-scoped, not user-scoped: once authorized, anyone using the same client gets the same workspace’s data).

Members can still use the MCP connector on shared infrastructure once an admin has connected; what they can’t do is initiate a new connection from scratch.

“redirect_uri is not registered for this client”

Your AI client tried to use a redirect URI that wasn’t included when it registered with Brand Stack. This usually means the client re-registered against a different redirect_uri than the one it’s now passing.

Fix: remove the connection in your client (claude mcp remove brandstack, delete the entry in mcp.json, etc.), then add it again. Dynamic Client Registration creates a fresh client_id with the right URIs.

“PKCE verifier mismatch”

The authorization code was redeemed with the wrong PKCE verifier. This is usually a client-side bug or a stale tab. Close any extra browser tabs running the OAuth flow and try again from the AI client.

“Insufficient credits”

Your workspace doesn’t have enough credits for the action. Check the balance:

“Get the credits for this workspace.”

Or top up at Settings → Subscription → Plans; the rejection message itself carries a direct link to that page, and so does every get_credits response (manageCreditsUrl). Purchases happen in the browser, not through the connection. The generation tools (create_mockup, create_scene) consume credits at the same rate as the in-app studio; capture and uploads are always free, and a newly connected workspace starts with 10 free mockups.

“This token does not have the mcp scope”

Your client requested only mcp:read during the consent flow. Reconnect to grant write scope as well, or skip the write tools.

“Brand profile not found” right after adopt_repo

You are almost certainly querying the wrong entity by the right id — or running a server version from before get_brand resolved brand stacks. adopt_repo creates a brand stack; get_brand accepts a brand stack’s id or slug and answers with its generation status (queued | generating | ready | failed | needs_input), progress, and — once ready — the stack’s productId and personas. Poll it every 15–20 seconds; generation typically takes 60–90 seconds. A stack that is still generating is never reported as “not found.”

list_brands also returns both kinds (brand_stack and brand_profile entries, newest first), so the stack you just adopted is the first row.

“That URL cannot be captured”

capture_screenshot runs on Brand Stack’s servers, so it can only reach public addresses. A local dev server (localhost, 127.0.0.1, private network ranges) is only visible from your own machine. Capture those where they live:

npx playwright screenshot http://localhost:3000/dashboard ./shot.png
npx @brandstack/cli upload ./shot.png

No API key handy? The agent can move the file without one: call create_upload_link and POST the bytes to the uploadEndpoint it returns. The CLI command above is the one-step version for shells that do have a key (API keys).

If a public page times out instead, it loaded too slowly or renders only after interaction; the same client-side capture is the fallback there too.

The POST to uploadEndpoint fails with a 403 or policy error

The tool calls all work, but curl to the upload endpoint (or any direct request to brandstack.dev) is rejected by a proxy. That is a sandboxed agent runtime: environments like Claude Code on the web send MCP traffic through a dedicated channel but route general HTTP through an egress allowlist, and brandstack.dev is not on it.

Either add brandstack.dev to the environment’s network allowlist, or fall back to upload_screenshot, which carries the image base64-encoded inside the tool call itself. Compress the screenshot first (JPEG or WebP around quality 80; the inline route costs context tokens per kilobyte and caps at 3MB decoded). See Screenshots → mockups for the full flow.

Upload links from create_upload_link live for 30 minutes. Ask the agent for a fresh one; it takes a second and costs nothing.

Mockup or scene generation hangs / times out

Generation has a 120-second hard cap. If a single call hits the cap:

  • Drop image_size to 1K (cheaper, faster).
  • Remove reference images (character_reference_url, style_reference_url); they each add a fetch step.
  • Try again; model latency varies with load.

If the call returns an error after generation started, the workspace is not charged: credits are refunded on every failure path, and the mockup/scene row is marked failed in the studio.

Revoking a connection

To revoke server-side (kills every active access + refresh token immediately):

  1. Open Settings → Developer in Brand Stack.
  2. Find the client under Authorized clients.
  3. Click Revoke.

The next request from that client gets a 401 and the user has to reconnect to restore access.

To remove the connection client-side (without revoking the tokens):

  • Claude Code: claude mcp remove brandstack
  • Claude.ai web: Settings → Connectors → click the connector → Disconnect
  • Cursor / Codex: delete the entry from mcp.json / config.toml

Refresh token reuse

If a client tries to use a refresh token that has already been rotated, Brand Stack revokes the entire grant immediately. This is by design: refresh-token reuse usually indicates token theft. The legitimate client will get invalid_grant on its next refresh and trigger a fresh OAuth flow.

If you see this happen unexpectedly, check whether two copies of the same client (e.g. two Claude Code installs sharing the same config) are competing for the same grant.

Still stuck?

Open an issue with the request id (returned in error response headers) and we’ll look into it. Don’t paste tokens; Brand Stack support can find the grant from the request id alone.

Was this page helpful?