Skip to Content
MCPAuthentication

Authentication

Gavana has two authentication paths, and which one you use is decided entirely by which server you connect to.

Hosted MCPLocal stdio MCP
Endpointhttps://app.gavana.ai/mcpnpx -y @gavana.ai/mcp@0.2.0 on your machine
CredentialBrowser OAuth, PKCE, no token to copyAgent Access token, or a saved CLI profile
Where it livesThe client’s own connector storageYour MCP client’s private environment, or ~/.config/gavana/agent.json
ExpiryNo automatic expiry; it remains active until you disconnect or revoke itNever by default; optionally choose a custom 1–90 day expiry when you create the token
RevocationRevoke the OAuth grantRevoke the token on the Agent Access screen

If you can use the hosted endpoint, use it. Nothing is safer than a credential you never have to handle.

Hosted: browser OAuth

You add an endpoint URL to your client, click connect, sign in to Gavana in a browser, review a consent screen, and approve. No token is ever pasted into a chat window, a config file, or a shell command.

What the flow supports

The authorization server metadata is published at https://app.gavana.ai/.well-known/oauth-authorization-server, and the hosted endpoint publishes protected-resource metadata at /.well-known/oauth-protected-resource/mcp.

Any MCP client that implements standard OAuth discovery finds everything it needs there. The declared surface is:

PropertyValue
Authorization endpointhttps://app.gavana.ai/oauth/authorize
Token endpointhttps://app.gavana.ai/oauth/token
Registration endpointhttps://app.gavana.ai/oauth/register
Revocation endpointhttps://app.gavana.ai/oauth/revoke
Grant typesauthorization_code
Response typescode
Response modesquery
PKCES256 required
Client authenticationnone — public clients with PKCE only
Bearer methodheader

Dynamic client registration is open, with real constraints: 1–10 redirect URIs, each an exact HTTPS or local-loopback callback, and a token_endpoint_auth_method of none. A registration asking for a client secret is rejected. There is no implicit grant and no password grant.

https://app.gavana.ai/mcp advertises all eight scopes: canvas:read, canvas:write, asset:read, element:read, element:write, image:generate, video:generate, job:manage. There is no partial approval on this path — the consent screen lists all eight, and approving grants all of them.

Approving grants the client the ability to write canvases, manage Elements, and start provider-backed work. Read the list before you click through. The server’s own instructions tell the model to ask for explicit current-turn approval before paid tools, but the capability is present once you approve.

Browser origins

The hosted endpoints accept browser requests from https://chatgpt.com, https://claude.ai, and the Gavana origin itself, plus anything the deployment explicitly allows. A request carrying some other Origin header is refused with 403 before authentication is even attempted. Non-browser clients that send no Origin header are unaffected.

Local: Agent Access tokens

The local stdio server has no browser, so it uses a scoped, revocable Agent Access token — or, if you have already logged in with the CLI, the profile that login saved.

Creating one

The full walkthrough is on Create an Agent Access Token. In short: open the account menu, choose Personal Access Tokens, name the token after the client that will use it, keep the default full permissions and Never expiry or make a deliberate narrower choice, then copy the value — Gavana shows it exactly once.

Two details that matter later:

  • The token’s name is written into provenance. A node created through a token named Claude · MCP records that name, so canvas history can tell your clients apart without trusting a caller-supplied label. Use one descriptively named token per client rather than sharing one.
  • Expiry defaults to Never. Choose a custom 1–90 day expiry for a temporary credential. Scopes and expiry are fixed after creation, so replace the token to change either.

Tokens begin with cba_. That prefix is a stable compatibility identifier that predates the Gavana rename — a token starting with cba_ is current, not stale.

Configuring the server

The local server reads either environment variables or the saved CLI profile:

GAVANA_BASE_URL=https://app.gavana.ai GAVANA_AGENT_TOKEN=<your Agent Access token>

or ~/.config/gavana/agent.json, written by gavana auth login.

CRAFTBOARD_BASE_URL, CRAFTBOARD_AGENT_TOKEN, and CRAFTBOARD_AGENT_CONFIG_FILE still work as transition aliases, and the legacy ~/.config/craftboard/agent.json is read when the new path does not exist. Gavana-named variables take precedence.

Put the token in your MCP client’s private environment or secret store. Never in a shared configuration file, a repository, a chat message, or a shell command that lands in history. The install pages use read -rs prompts precisely so the token never appears in your shell history.

Logging in with the CLI instead

If the CLI is already set up, the local MCP server inherits its profile and you configure no token at all:

read -rs 'GAVANA_AGENT_TOKEN?Paste Agent Access token: '; printf '\n'; printf '%s' "$GAVANA_AGENT_TOKEN" | gavana auth login --base-url 'https://app.gavana.ai' --token-stdin; unset GAVANA_AGENT_TOKEN

The token goes in over stdin, so it never becomes a command-line argument visible to other processes or to your shell history.

The six scopes

The same six scopes apply to OAuth grants and to Agent Access tokens.

ScopeGrantsDepends on
canvas:readRead canvas graphs, revisions, and node contents—
canvas:writeChange canvasescanvas:read
asset:readRead asset references—
image:generateGenerate and edit images, write image bytes into Gavana storage, and start any Recipecanvas:read, canvas:write, asset:read
video:generateDiscover connected video models and start video workcanvas:read, asset:read
job:manageObserve, resume, wait for, and cancel Runs and Jobs—

Dependencies are enforced when the token is created, not silently added at call time. Asking for image:generate without asset:read returns an error naming the missing scopes; the token creation form selects dependants for you.

image:generate is the scope that governs writing image bytes into Gavana, not just generating them. That is why save_image_to_canvas requires it even though it generates nothing. A token scoped to canvas:read and canvas:write alone cannot save an image.

job:manage is easy to leave off and painful to be without. Without it, a client can start work but cannot poll, wait for, or cancel the Run it started. Every hosted tool that waits — run_canvas_workflow, generate_image_in_canvas, generate_video — and every tool that resumes — get_canvas_workflow_run, get_video_job — requires it.

Which scopes each hosted tool needs

ToolScopes
guide_searchnone
guide_getnone
canvas_listcanvas:read
canvas_getcanvas:read
canvas_validatecanvas:read
get_canvas_imagecanvas:read
open_canvascanvas:read
canvas_apply_batchcanvas:read, canvas:write
create_canvas_workflowcanvas:read, canvas:write
save_image_to_canvascanvas:read, canvas:write, asset:read, image:generate
run_canvas_workflowcanvas:read, canvas:write, asset:read, image:generate, job:manage
generate_image_in_canvascanvas:read, canvas:write, asset:read, image:generate, job:manage
get_canvas_workflow_runcanvas:read, job:manage
find_video_modelsvideo:generate
generate_videocanvas:read, asset:read, video:generate, job:manage
get_video_jobjob:manage

The two guide tools require no scope at all, which is why an agent can always read the rules regardless of how narrowly it is provisioned.

Reading an authentication error

ResponseMeansDo this
401 invalid_tokenNo bearer token, a malformed one, or one that expired or was revokedReconnect the client. For a local token created with a custom expiry, create a replacement when that expiry passes.
403 insufficient_scopeThe token is valid but lacks a scope the tool needsThe error names the missing scopes. Reconnect or recreate the token with those added.
403 access_deniedThe browser Origin is not allowedYou are calling from an origin Gavana does not accept.

Both 401 and 403 come back with a WWW-Authenticate header pointing at the protected-resource metadata and listing the required scopes, so a well-behaved client can prompt you to reconnect rather than failing silently.

A scope error at the MCP layer is refused before the handler runs. Nothing partial happens, and no paid work starts.

Credential hygiene

  • Never paste a token into a chat, an issue, a commit, or a screenshot.
  • Never put a token in a URL — Gavana takes bearer tokens in the Authorization header only.
  • Treat a scoped preview URL as a credential. The previewUrl that get_canvas_image and successful image runs return carries a single-use token query parameter, and anyone holding that URL can fetch the image until it expires. Do not paste one into a shared document, a ticket, or a public log. Hand people an open_canvas review link instead.
  • Never expose a connected provider’s configuration — keys, endpoints, or account details — in a transcript or a report.
  • Use one named token per client so revoking one does not break the others, and so provenance stays readable.
  • Use a custom expiry for a temporary or less-trusted device; otherwise revoke the token when that client or device is no longer trusted.
  • When you report a problem to support, share the X-Request-ID value from the failing response and nothing else. It identifies the request without exposing a credential or canvas content.
  • Webhook signing secrets are deliberately kept out of MCP tool arguments so they cannot enter a model-visible transcript. If you need callbacks, use the CLI’s --webhook-secret-env option or call the API from a trusted backend.
Last updated on