Back to Docs
MCP

Authentication & Scopes

Personal Access Token format, scope semantics, rate limits, credit charging, error codes, and lifecycle.

Updated 2026-10-10

Personal Access Tokens (PATs)

PATs are long-lived, per-organization bearer tokens. Every MCP request carries one in the Authorization header:

plaintext
Authorization: Bearer vbl_pat_live_<32 urlsafe chars>

Token Format

ComponentExampleMeaning
Prefixvbl_pat_live_Production. Registered with GitHub secret scanning.
Prefixvbl_pat_test_Non-production environments.
Body32 URL-safe characters24 bytes of entropy from secrets.token_urlsafe().

At creation the full token is shown once. Only a SHA256 hash of the raw value is persisted — a stolen database row cannot be replayed as a token.

Lifecycle

Step

Create

Dashboard → Settings → API & MCP → Create token. Choose a label and scopes. Up to ten active PATs per user per organization.

Step

Rotate

Create a new token, swap your client config over, then revoke the old one. Tokens have no expiry — rotation is entirely on your schedule.

Step

Revoke

Any row in the Settings list can be revoked. Rejection is immediate; in-flight requests that already passed auth complete normally.

Step

Audit

Each token row shows when it was last used and the IP address of that call (last_used_ip), so a token used from somewhere you don't recognize is easy to spot. Use Edit scopes on any row to widen or narrow a token's access without minting a new one.

OAuth Connectors

Claude.ai, Claude Desktop connectors, and ChatGPT cannot send a static token. They connect through OAuth 2.1 instead: add https://mcp.vaybel.com/ as a custom connector, sign in to Vaybel, and approve one workspace and a scope set on the consent screen. The resulting access is org-pinned exactly like a PAT, shows up under Connected apps in Settings, and can be revoked there. Details in Connectors.

Where To Store Tokens

Use one canonical local secret: VAYBEL_PAT.

For Claude Code, prefer storing the token in Claude Code settings so it is available to both the Vaybel MCP server and the official Vaybel Skills plugin:

json
{
  "env": {
    "VAYBEL_PAT": "vbl_pat_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Then reference it from MCP config instead of pasting the token into the config file:

json
{
  "mcpServers": {
    "vaybel": {
      "type": "http",
      "url": "https://mcp.vaybel.com/",
      "headers": {
        "Authorization": "Bearer ${VAYBEL_PAT}"
      }
    }
  }
}

Do Not Commit Tokens

Do not put raw vbl_pat_live_... values in project .mcp.json, example repos, screenshots, issue comments, or chat transcripts. Avoid putting long-lived Vaybel tokens in broad shell startup files like .zshrc unless you intentionally want every terminal process to inherit them.

Scopes

Every tool declares the scope(s) it requires. A PAT missing the scope gets a missing_scope tool error. The dashboard token creator selects all public scopes by default — uncheck only what you want to deny.

All scopes. The creator defaults to an All scopes switch that stores the literal ["*"] wildcard. Unlike an explicit scope list — which is fixed at mint time, so a scope added to the platform later isn't granted until you create a fresh token or edit the token's scopes — an all-scopes token grants every current scope and any scope added later, so it never needs recreating for new tools. Turn the switch off to pick an explicit subset.

Read scopes

ScopeTools
design:readworkspace.open (also needs mockup:read), design.get_generation, design.list, design.get, design.get_history
mockup:readworkspace.open (also needs design:read), mockup.get_generation, mockup.list, mockup.get, mockup.show
brand_dna:readbrand_dna.get, brand_dna.list_audience_presets
catalog:readcatalog.list_blanks, catalog.get_blank, catalog.compare_blanks
credits:readcredits.check, credits.list_costs, credits.list_usage
product_video:readproduct_video.get_generation
virtual_model:readvirtual_model.list, virtual_model.get_generation
listing:readlisting.get, listing.list, listing.get_generation, listing.list_warehouses
content:readcontent.get, content.list
social_post:readsocial_post.list, social_post.get
trend:readtrend.list, trend.get, trend.list_keywords, trend.get_keyword, trend.get_generation, trend.list_seasonal_events
insight:readinsight.get_overview, insight.list_design_performance, insight.get_guidance
integration:readintegration.list
optimize:readoptimize.list_providers, optimize.list_provider_products, optimize.check_duplicate, optimize.get_generation
drop:readdrop.list, drop.get, drop.related_trends

Write scopes

ScopeTools
brand_dna:writebrand_dna.set
design:writedesign.generate, design.edit, design.submit_feedback
mockup:writemockup.generate, mockup.update_selection, mockup.submit_feedback, mockup.retry
product_video:writeproduct_video.generate
virtual_model:writevirtual_model.generate
listing:writelisting.create, listing.update, listing.regenerate_field, listing.publish, listing.delete, listing.sync_warehouses
content:writecontent.generate, content.delete
social_post:writesocial_post.generate, social_post.update, social_post.publish
trend:writetrend.generate_concept, trend.record_outcome
optimize:writeoptimize.import_product, optimize.refresh_listing
drop:writedrop.create, drop.update, drop.attach, drop.pin_trend

PrintGen buyer scopes

Tokens for the PrintGen buyer surface carry a smaller, buyer-facing scope set:

ScopeTools
design:writedesign.generate, design.edit
design:readdesign.get_generation, design.get, design.list, design.browse (also needs mockup:read)
mockup:readdesign.browse (also needs design:read), mockup.get_generation, mockup.get, mockup.show
mockup:writemockup.generate
catalog:readshop.list_products, shop.get_product
checkout:writeshop.create_checkout
order:readshop.get_checkout, shop.list_orders, shop.get_order

Principle of Least Privilege

A monitoring agent that polls status doesn't need any :write scope — give it the :read set and nothing more. A trend-discovery agent that proposes drafts can have all reads plus design:write + mockup:write, but not listing:write or content:write. Build narrow tokens.

Plan gates

Most of the MCP surface is a paid capability. A small read-only set works on any plan, most tools require Starter or higher, and the Growth-plan feature areas are gated at Growth:

TierTools
Open (any plan)ping, catalog.*, brand_dna.get, credits.check, drop.list, drop.get, drop.related_trends
Starter+brand_dna.set, brand_dna.list_audience_presets, credits.list_costs, credits.list_usage, design.*, mockup.*, virtual_model.*, listing.*, trend.*, integration.list, workspace.open, drop.create, drop.update, drop.attach, drop.pin_trend
Growthcontent.*, insight.*, optimize.*, product_video.*, social_post.*

Gated calls fail with a clear plan_required: ... error rather than returning empty data. The error names no plan; each tool's tier is shown as a Plan chip in the Tool Reference.

Rate Limits

Rate limits apply per-PAT, per-tool, on a fixed 60-second window. Hitting one raises a rate_limited error carrying a retry after Ns hint.

ToolLimit
brand_dna.set10 / min
design.generate10 / min
design.edit10 / min
design.submit_feedback60 / min
mockup.generate20 / min
mockup.update_selection60 / min
mockup.submit_feedback60 / min
mockup.retry20 / min
product_video.generate10 / min
virtual_model.generate10 / min
listing.create10 / min
listing.update20 / min
listing.regenerate_field10 / min
listing.publish5 / min
listing.delete20 / min
listing.list_warehouses10 / min
listing.sync_warehouses10 / min
content.generate5 / min
content.delete20 / min
social_post.generate10 / min
social_post.publish10 / min
trend.generate_concept10 / min
trend.record_outcome60 / min
optimize.list_provider_products30 / min
optimize.import_product10 / min
optimize.refresh_listing20 / min
All other public toolsNo explicit MCP-layer limit (platform-level limits still apply)

Credit balance provides the finer gating for billable tools — you'll hit insufficient_credits before a rate limit on a real workload.

Credit Charging

Most tools are free. A handful charge from the same credit balance your dashboard uses — no separate developer meter.

ToolCharged forCreditsCharged
design.generateEach design5When it completes
design.editEach edit3When it completes
mockup.generateEach product photo at Pro quality, or in an environment2When it completes
mockup.generateEach print or fabric close-up2When it completes
mockup.generateEach model photo2When it completes
product_video.generateEach video20When it completes
virtual_model.generateEach model generated1When the call is accepted
listing.createEach draft listing2When the call is accepted
content.generateA video40When it completes
content.generateA slideshow12When it completes
content.generateA carousel4When it completes
content.generateA single image1When it completes
trend.generate_conceptEach new concept2When the call is accepted

Work that is charged when it completes costs nothing if it fails. Product photos from mockup.generate at quality="standard" are free, and dry_run=true returns the exact quote before anything is charged. credits.list_costs returns the same prices.

Three pre-flight gates prevent surprises:

  1. Out-of-credit calls fail fast — billable tools run a balance check before dispatching any background work.
  2. Billable tools accept an idempotency_key; sending the same key on a retry returns the cached result, so a flaky-network loop doesn't double-bill (or double-publish).
  3. trend.generate_concept short-circuits to free when the concept is already cached.

Read tools and status polls are always free.

Errors You Might See

Tool errors arrive as MCP tool results (not HTTP status codes — only authentication failures are HTTP 401). Machine-readable errors are prefixed with a stable code:

ErrorCauseFix
HTTP 401 missing bearer tokenNo Authorization headerRe-check your client config; restart after changes
HTTP 401 unknown tokenRevoked or typo'd PATRevoke from Settings, create a fresh one
missing_scope: ...PAT lacks the scope the tool needsRe-create the PAT with the missing scope
rate_limited: ... retry after NsPer-tool per-PAT limit hitWait the indicated seconds; batch where possible
insufficient_credits: requires N, available MBalance below costTop up credits, or use quality="standard" for mockups
plan_required: ...Tool needs a higher plan (trends → Starter+, insights → Growth)Upgrade the org's plan
not_found: ...Unknown id — or a UUID belonging to another orgEach PAT is pinned to one org; re-check the id
invalid_argument: ...An argument failed validationThe message names the field; fix it and call again
forbidden: ...The tool is not open to this kind of tokenCall only the tools listed in the Tool Reference
upstream_failed: ...A sales channel or publish target rejected the operationCheck the connection with integration.list, then retry
budget_exceeded: ...Session budget cap reached (internal session tokens)Raise the session budget

Errors without a code prefix are plain validation messages (e.g. prompt is required).