MCP is not open yet. These pages are ready for when it opens. You can make an agent key now; it starts working when MCP opens. Until then the address below does not answer.

Adaver MCP tool reference

This page describes the three tools an agent sees at https://api.adaver.nuvai.dev/mcp. The text comes from the server code (crates/adaver-server/src/mcp/). If the code and this page ever differ, the code wins: the agent reads the tool descriptions from the server itself.

Overview

ToolWhat it doesPermission (scope) the key needsCost
list_presetsLists the five presets and what each is fornonefree
get_balanceShows how many images the account has leftbalancefree
vectorize_imageTurns a PNG, JPEG or WebP image into an SVGvectorize1 image

A tool the key has no permission for is not shown to the agent. If the agent calls it anyway, the answer is "unknown tool", the same as for a tool that does not exist.

The server keeps no session. Every request stands alone. Each answer is one JSON message (no event stream).

list_presets

"Lists the five vectorization presets and what each is for. Free, changes nothing."

Input: nothing.

Output (structuredContent, and the same JSON as text):

{
  "presets": [
    { "name": "auto", "use_for": "...", "default": false },
    { "name": "high_quality", "use_for": "...", "default": true }
  ]
}
PresetUse for
autoLooks at the image and picks the settings for you. Good when you do not know the image type.
high_qualityDetailed result with smooth curves and strokes. The default. Best for most images.
fastFewer layers and a quicker answer. Good for drafts and simple images.
anime_optimizedSmooth-gradient artwork such as anime and illustrations. Smaller files, with some colour banding.
gradient_awareLogos and art with gradients. Draws real SVG gradients instead of many flat patches.

get_balance

"Shows how many images the account has left and whether the free image is still unused. Free, changes nothing you can see."

Input: nothing. Needs: scope balance.

Output:

FieldMeaning
meteredfalse while billing is off: calls are free and unlimited, and the other fields are left out
availableImages the account can use now (bought + this period's allowance + the free image)
balanceBought images
allowanceThis period's subscription images. They end at the period's end.
reservedImages held by calls that are still running
free_availableThe one free image is still unused
free_needs_verificationThe free image needs a verified email first
out_of_imagesNothing is left

get_balance shows the account. It does not show how much of a key's daily limit is used. A key that is at its limit learns it from the daily_cap_reached error (with used, limit and resets_at).

vectorize_image

"Turns a PNG, JPEG or WebP image into a clean SVG. THIS CHARGES 1 IMAGE to the account (the account's one free image counts); if the call fails, the image is given back."

Needs: scope vectorize.

Input

Send exactly one of image_url and image_base64. Unknown fields are refused.

FieldTypeMeaning
image_urlstringA public https link to a PNG, JPEG or WebP image. Up to 25 MB and 25 megapixels.
image_base64stringThe image as base64 text (a data: prefix is fine). Only for small images: the whole request may be at most 4 MiB, so about 3 MB of image.
presetstringOne of the five presets. Left out: high_quality. For a photo, fast or auto usually works better.
optionsobjectOptional fine tuning: single values (numbers, booleans, text). Allowed keys: max_colors, merge_threshold, color_precision, filter_speckle, corner_threshold, line_fit, smoothing, contour_smoothing, shapes, clean_regions, gradients, stacking, mode, bw_threshold, denoise. Most calls do not need it.
idempotency_keyUUIDA fresh random UUID (version 4) the agent makes up for this one job. See Safe retries.
confirm_tokenUUIDOnly for a key in confirm mode. See Confirm mode.

How the image is downloaded from image_url: https only, at most 3 redirects (each one checked again), and private or internal addresses are refused. The type is read from the bytes, never from the file name.

Output

On success (structuredContent, and the same JSON as one text block):

FieldMeaning
width, heightSize of the picture
bytesSize of the SVG in bytes
elementsNumber of shapes in the SVG
paletteThe colours used, as #rrggbb
presetThe preset that was used
warningsShort notes about the result (often empty)
request_idThe id of this call
chargedtrue when this call spent 1 image. false for a free replay.
replayedtrue for a free repeat of a job that was already charged. Left out when false.
svgThe SVG itself, when it is small enough (see below)
link{ "url": ..., "expires_in_secs": ... } for a bigger SVG, instead of svg
SVG sizeWhat the agent gets
Up to 100 KBsvg: the SVG text, inline
Biggerlink.url: a secret address, valid for 15 minutes (expires_in_secs says how long). It also comes as a resource_link block.

About the link:

  • No key is needed to open it. Anyone who has the address can read the SVG until it ends. Do not share it.
  • It answers image/svg+xml with no-store, nosniff and a sandbox content security policy, so a browser never runs code from it.
  • After it ends, or for a wrong address, the answer is 404.
  • One account keeps at most 10 live links. A new one removes the oldest.

These are the server's default limits. The operator can change them (inline 1 KB to 1 MB, link 60 s to 1 hour).

Charging

  • One call that finishes spends 1 image. The account's one free image counts.
  • If the call fails after the image was held, the image is given back. If the client goes away or the call takes too long, the image is given back too.
  • Nothing is charged for a refusal: bad input, limits, daily_cap_reached, content_refused, confirmation_required, insufficient_images and the other errors below.

Content check

Every image is checked automatically for content we do not trace (Azure AI Content Safety), the same check as on the website. A refused image is the tool error content_refused and charges nothing. A key that sends several refused images in an hour is paused for the rest of the hour (too_many_refusals, see Limits). If the check cannot be made at that moment, the image is traced anyway.

  • Every new call for the same picture is a new trace and spends 1 more image. Call again only when the user wants a new trace.

Safe retries

The idempotency_key makes a retry safe after a network error or a timeout.

SituationResult
Same idempotency_key, same picture and settings, job finishedFree replay: the same SVG again, charged: false, replayed: true. Up to 2 free replays, within 1 hour.
Same key, job still runningin_progress. Wait. Do not send a new key meanwhile, that charges again.
Same key, replays used upalready_done. To trace again on purpose, use a new key (1 more image).
Same key, other picture or other settingskey_reused. Make a new key.
No idempotency_key sentEvery call is a new job and charges 1 image, even for the same picture. A retry cannot be told apart from a new request, so send a key if you may need to retry.

Always make a fresh random UUID. Never copy an example UUID.

Confirm mode

A key can be set to confirm mode. Then no call charges until the user agrees.

1st call (no confirm_token)   ->  error "confirmation_required" with confirm_token, price, expires_in_secs
                                  nothing is charged
agent asks the user: "Spend 1 image?"
user says yes                 ->  same call again + confirm_token  ->  charged once
user says no                  ->  do not call again
  • The token works only for the same key, the same picture and the same settings.
  • It lives 10 minutes by default (expires_in_secs says how long).
  • If the first call had an idempotency_key, the token is that same value. Sending both is fine. A different idempotency_key next to the token is refused.
  • Sending the token again after the charge is a free replay, never a second charge.
  • A client that supports MCP questions (elicitation, protocol version 2026-07-28 or newer) gets a yes/no box instead. "No" answers confirmation_declined.

The account page has no switch for confirm mode yet, so keys made there have it off.

What confirm mode can and cannot do. The question goes through your AI client, and Adaver cannot see who answered it: the agent itself receives the confirm_token, so an agent that ignores the rule (a bug, or instructions hidden in a page it read) can send the token without asking you. Confirm mode is a seat belt for well-behaved clients, not a lock. The hard limit is the key's daily cap: the server enforces it whatever the agent does. Set the cap to what you are willing to spend in a day.

Limits

LimitValueError
Daily limit per key"Images per day" on the key, 1 to 200 (default 20). A day is the UTC day by default.daily_cap_reached (429)
vectorize_image calls per key30 per 10 minutesrate_limited (429)
Images our content check refused, per key5 per hour. After that the key is paused until the hour ends. Only this key is paused.too_many_refusals (429)
Traces running at once per account2too_many_jobs (429)
Requests running at once per account6too_many_requests (429)
Request body4 MiBpayload_too_large (413)
Image25 MB, 25 megapixelspayload_too_large, image_too_large
Whole callabout 4 minutestimeout (504). The tracing step gets only the time that is left, so a slow trace usually ends as the tool error timeout with the image given back.

A free replay still works when the key is at its daily limit.

Errors

There are two kinds of errors.

1. Tool errors. The HTTP answer is 200 and the tool result has isError: true. It has one text block that holds a JSON object:

{
  "code": "daily_cap_reached",
  "message": "This key has used its daily limit of 20 images. ...",
  "retry_after_secs": 3600,
  "request_id": "..."
}

It always has code, message and request_id. Some have more: field (which input is wrong), limit, actual, retry_after_secs, free_needs_verification, confirm_token.

2. HTTP errors. The request is refused before any tool runs. The body is JSON with code, message and request_id. The x-request-id header has the same id.

HTTP errors

StatuscodeMeaning
401unauthenticatedNo key, a wrong key, a revoked or expired key, or a key that is not an agent key. The answer has a WWW-Authenticate header.
403account_restrictedThe account is in a cooldown or suspended
408request_timeoutThe request body took too long to arrive
413payload_too_largeThe request is bigger than 4 MiB. Send large images by URL.
429too_many_requestsThis account already has 6 requests running (all its keys count together). Wait for one to finish.
503busyThe server is busy. Wait retry_after_secs.
503mcp_disabledThe MCP door is switched off for now
504timeoutThe request took too long and was stopped. If the call was charged, a retry with the same idempotency_key replays it for free; otherwise nothing was charged.

Tool errors of vectorize_image

codeMeaningWhat to do
bad_requestAn input is wrong (see field): both or no image, bad base64, unknown preset or optionFix the input
confirmation_requiredConfirm mode: price quote, nothing chargedAsk the user, then call again with confirm_token
confirmation_declinedThe user said noDo not call again for this picture unless the user asks
confirm_token_unknownThe token is not valid for this keyCall again without confirm_token for a new quote
confirm_token_expiredThe token is too oldCall again without it, and ask the user again
confirm_token_mismatchThe token was for another picture or other settingsSend the same picture, preset and options, or get a new quote
key_reusedThe idempotency_key was used for another jobUse a new idempotency_key
in_progressThe same job is still runningWait; retry only with the same idempotency_key
already_doneThe job was charged and its free replays are used upA new idempotency_key traces again (1 more image)
daily_cap_reachedThe key used its daily limit (limit, used, resets_at)Wait until resets_at, or raise the limit on the account page
content_refusedOur automatic content check refused the image. Nothing was charged.Do not retry the same image. Check what the agent sends.
too_many_refusalsThe key sent several images the content check refused in the last hour, so it is paused. Nothing was charged (limit, retry_after_secs).Wait retry_after_secs. Do not retry before then, and check the images.
insufficient_imagesNo images left, or the free image needs a verified emailBuy images or verify the email
account_in_debtA refund came after the images were usedBuy images to settle it, or contact support
rate_limitedToo many vectorize_image calls for this keyWait retry_after_secs
too_many_jobsThe account already has conversions runningWait for one to finish
busyThe server is busyWait retry_after_secs
fetch_failedThe image could not be downloaded from image_urlUse a public https link to the image file
payload_too_largeThe image is larger than 25 MBUse a smaller image
unsupported_imageNot a PNG, JPEG or WebPConvert the image
damaged_imageThe image could not be readCheck the file
image_too_largeMore than 25 megapixelsUse a smaller image
too_thin, nothing_to_traceThe image has nothing the engine can traceUse another image
too_complexThe SVG would have too many shapes or bytes. Nothing was charged.A smaller or simpler image, or options such as {"max_colors": 8} or a higher filter_speckle
engine_unavailable, bad_gatewayThe tracing service is not available or answered badlyTry again in a moment
timeoutThe call took too longRetry with the same idempotency_key
internalSomething went wrong on our sideRetry; send us the request_id if it stays

get_balance can answer internal. list_presets has no tool errors.

Server metadata

GET https://api.adaver.nuvai.dev/.well-known/oauth-protected-resource (and .../oauth-protected-resource/mcp) returns a small public JSON document that names the resource (.../mcp) and links to the documentation. The 401 answer points at it. Agent keys do not need it today; OAuth sign-in will.