Turn images into clean SVG, PDF, EPS or DXF files, then edit the colours. 1 credit per image.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Optional. Bearer key from svgmill.com/account/ (5 free credits). With none: watermarked previews and a claim link.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Needs an API key. Returns a Stripe Checkout link for a credit pack, for the person to open and pay; nothing is charged until they do. Packs: pack_100 (100 credits, $25), pack_1k, pack_10k, pack_25k, pack_50k, pack_100k. Credits are added after payment and last 12 months. Prices: https://svgmill.com/pricing/.
Which pack.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http svgmill https://svgmill.com/mcp
Headers
Authorization (optional, not in the config above): Optional. Bearer key from svgmill.com/account/ (5 free credits). With none: watermarked previews and a claim link.Needs an API key. Returns a Stripe Checkout link for a credit pack, for the person to open and pay; nothing is charged until they do. Packs: pack_100 (100 credits, $25), pack_1k, pack_10k, pack_25k, pack_50k, pack_100k. Credits are added after payment and last 12 months. Prices: https://svgmill.com/pricing/.
| Argument | Type | Description |
|---|---|---|
| pack | string | Which pack. |
{
"type": "object",
"properties": {
"pack": {
"enum": [
"pack_100",
"pack_1k",
"pack_10k",
"pack_25k",
"pack_50k",
"pack_100k"
],
"type": "string",
"default": "pack_100",
"description": "Which pack."
}
},
"additionalProperties": false
}No key needed to preview: without an API key it returns a watermarked preview image (at most 512 px) and a claim_url, and no vector file. Show the preview, then ask the person to open the claim link (they sign up free and get 5 credits); then download_vector with the token returns the SVG (1 credit from their account). Without a key, pass token instead of an image to trace the same image again with other colors or preset (at most 3 times). With an API key (free to create) it converts a raster image (PNG, JPG, WebP, GIF, BMP or TIFF) into a vector file. Each call with a key costs 1 credit, and a failed conversion is not charged. Pass image_url or image_base64. Returns an image token, the credits left and a signed download link valid for 1 hour; the file itself is included when it is at most inline_max_bytes (default 16 KB; PNG up to 1 MB, as an image). Use download_vector with the token to get more formats for free. If you may retry (after a timeout, say), pass an idempotency_key: a repeat with the same key and arguments within 24 hours returns the first result and is not charged again. When images are waiting their turn, the result can instead have status "queued" with the token and retry_after_seconds, and nothing is charged yet: after that many seconds call download_vector with the token (charged then). Do not convert the image again.
| Argument | Type | Description |
|---|---|---|
| token | string | Instead of an image: an image token (img_…) to trace again with other colors or preset. |
| colors | integer | Palette size. Leave out to use the preset default. |
| format | string | Output format. |
| preset | string | logo (colour) or bw (black and white logo). |
| image_url | string | Public http(s) URL of the image. |
| image_base64 | string | The image as base64 (a data: URL works too). |
| idempotency_key | string | Any unique string, e.g. a UUID. Same key and arguments within 24 hours: the first result, charged once. The same key with other arguments is an error. |
| inline_max_bytes | integer | Largest file, in bytes, to include in the result itself (default 16384; 1048576 for PNG). Larger files come only as the download link. 0 never inlines. |
{
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Instead of an image: an image token (img_…) to trace again with other colors or preset."
},
"colors": {
"type": "integer",
"maximum": 64,
"minimum": 2,
"description": "Palette size. Leave out to use the preset default."
},
"format": {
"enum": [
"svg",
"pdf",
"eps",
"dxf",
"png"
],
"type": "string",
"default": "svg",
"description": "Output format."
},
"preset": {
"enum": [
"logo",
"bw"
],
"type": "string",
"default": "logo",
"description": "logo (colour) or bw (black and white logo)."
},
"image_url": {
"type": "string",
"description": "Public http(s) URL of the image."
},
"image_base64": {
"type": "string",
"description": "The image as base64 (a data: URL works too)."
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Any unique string, e.g. a UUID. Same key and arguments within 24 hours: the first result, charged once. The same key with other arguments is an error."
},
"inline_max_bytes": {
"type": "integer",
"maximum": 33554432,
"minimum": 0,
"description": "Largest file, in bytes, to include in the result itself (default 16384; 1048576 for PNG). Larger files come only as the download link. 0 never inlines."
}
},
"additionalProperties": false
}No key needed. Emails the person a link to create their free SVGMill account (or to sign in, if they have one) and returns a test-mode API key at once (free, watermarked results, no credits; it ends when the link is clicked, or after 24 hours). New accounts get 5 free credits when the person clicks the link; the page it opens shows their live API key. Disposable addresses are refused. Free.
| Argument | Type | Description |
|---|---|---|
| email* | string | The person's email address (ask them first). |
{
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"maxLength": 254,
"description": "The person's email address (ask them first)."
}
},
"additionalProperties": false
}No key needed for a token from a preview made without a key, once the person has claimed it (the first download costs 1 credit from their account); before that it answers status "waiting_for_claim" with the claim_url. Other tokens need an API key. Gets a file for an image token from an earlier conversion, with a fresh signed download link valid for 1 hour. Free for any format of a token you already paid for. The first download of a preview token, or of a token from a queued conversion, costs 1 credit. The file is included inline up to inline_max_bytes, as for convert_image_to_svg. If that trace is still queued or running, it answers with an error giving its place and how many seconds to wait; nothing is charged, so call it again then.
| Argument | Type | Description |
|---|---|---|
| token* | string | The image token (img_…). |
| format | string | Output format. |
| inline_max_bytes | integer | Largest file, in bytes, to include in the result itself (default 16384; 1048576 for PNG). Larger files come only as the download link. 0 never inlines. |
{
"type": "object",
"required": [
"token"
],
"properties": {
"token": {
"type": "string",
"description": "The image token (img_…)."
},
"format": {
"enum": [
"svg",
"pdf",
"eps",
"dxf",
"png"
],
"type": "string",
"default": "svg",
"description": "Output format."
},
"inline_max_bytes": {
"type": "integer",
"maximum": 33554432,
"minimum": 0,
"description": "Largest file, in bytes, to include in the result itself (default 16384; 1048576 for PNG). Larger files come only as the download link. 0 never inlines."
}
},
"additionalProperties": false
}Needs an API key. Edits a converted image, free (no credits). By colour, with only the palette from inspect_vector: mergeColours {a, b} (labels; a takes b's colour), splitColour {label}, snapPalette {rules: [{color: [r,g,b], to?: [r,g,b], drop?: true, tolerance}]} (change or drop colours; tolerance 0–2 is required, and 0.05–0.15 snaps near shades only), setColourCount {n} (fewer colours, at most the traced count). By region, with region.region from inspect_vector at a pixel of its preview image: recolor {region, color: [r,g,b]}, setTransparent {region} (cuts it out), mergeIntoNeighbour {region, neighbour}, move {region, dx, dy} (source pixels), delete {region} (shows what is beneath). Send rev, the revision you last saw (0 for a token never edited). If the token changed since, the result is a conflict error with the current rev and edits: check them, then resend. undo: n removes the last n edits. Returns the new preview image and palette, and fresh signed links to the formats already made (valid for 1 hour; earlier links stop working).
| Argument | Type | Description |
|---|---|---|
| ops | array | Edits to apply, in order. |
| rev* | integer | The revision from your last inspect_vector or edit_vector (0 for a new token). |
| undo | integer | Remove the last n edits instead of applying ops. |
| token* | string | The image token (img_…). |
| inline_max_bytes | integer | Largest edited SVG, in bytes, to include in the result (default 16384). The preview image comes up to 1048576 bytes. 0 leaves both out. |
Needs an API key. Shows your credit balance, credit grants, plan and usage this period. Free; it costs no credits.
No arguments.
{
"type": "object",
"additionalProperties": false
}No key needed for a token from a preview made without a key: then it shows the watermarked preview image and palette only (read-only). Other tokens need an API key. Shows a converted image as it is now, for editing with edit_vector: its palette (colours, their share and labels), its revision (rev) and edit log, and a watermarked preview image. Free and changes nothing. Pass x and y, a pixel of that preview image, to get the region there: its key (region.region) for region edits, colour, size and neighbours. Over a transparent pixel region is null.
| Argument | Type | Description |
|---|---|---|
| x | number | Pixel column in the preview image (0 is the left edge). |
| y | number | Pixel row in the preview image (0 is the top edge). |
| token* | string | The image token (img_…). |
| inline_max_bytes | integer | Largest preview image, in bytes, to include (default 1048576). 0 leaves the image out. |
{
"type": "object",
"required": [
"token"
],
"properties": {
"x": {
"type": "number",
"minimum": 0,
"description": "Pixel column in the preview image (0 is the left edge)."
},
"y": {
"type": "number",
"minimum": 0,
"description": "Pixel row in the preview image (0 is the top edge)."
},
"token": {
"type": "string",
"description": "The image token (img_…)."
},
"inline_max_bytes": {
"type": "integer",
"maximum": 33554432,
"minimum": 0,
"description": "Largest preview image, in bytes, to include (default 1048576). 0 leaves the image out."
}
},
"additionalProperties": false
}No key needed for tokens you already hold: pass tokens (up to 20) to see whether each is a preview waiting for its claim, claimed (download_vector works), expired or not found; this shows the state only, no files. With an API key, lists your conversions instead, newest first: token, file name, when it was made, when its files expire (30 days), the formats already made, and whether it is paid, a preview or a test. Free and read-only.
| Argument | Type | Description |
|---|---|---|
| limit | integer | With a key: how many to return. |
| cursor | string | With a key: next_cursor from the previous call. |
| tokens | array | Without a key: image tokens (img_…) to check, at most 20. Ignored when a key is sent. |
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "With a key: how many to return."
},
"cursor": {
"type": "string",
"description": "With a key: next_cursor from the previous call."
},
"tokens": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"minItems": 1,
"description": "Without a key: image tokens (img_…) to check, at most 20. Ignored when a key is sent."
}
},
"additionalProperties": false
}Needs an API key. Returns a Stripe Checkout link for a monthly or annual credit plan, for the person to open and pay; nothing is charged until they do. Credits are added each month while the plan lasts. Plans: plan_100_monthly ($17.50 a month, 100 credits a month); plan_100_annual ($168 a year, 100 credits a month); plan_1k_monthly ($140 a month, 1,000 credits a month); plan_1k_annual ($1,344 a year, 1,000 credits a month); plan_10k_monthly ($1,050 a month, 10,000 credits a month); plan_10k_annual ($10,080 a year, 10,000 credits a month); plan_25k_monthly ($1,750 a month, 25,000 credits a month); plan_25k_annual ($16,800 a year, 25,000 credits a month); plan_50k_monthly ($2,625 a month, 50,000 credits a month); plan_50k_annual ($25,200 a year, 50,000 credits a month); plan_100k_monthly ($3,500 a month, 100,000 credits a month); plan_100k_annual ($33,600 a year, 100,000 credits a month). If the account already has a plan, it is not changed: the person manages it at https://svgmill.com/account/. Prices: https://svgmill.com/pricing/.
| Argument | Type | Description |
|---|---|---|
| plan* | string | Which plan. |
{
"type": "object",
"required": [
"plan"
],
"properties": {
"plan": {
"enum": [
"plan_100_monthly",
"plan_100_annual",
"plan_1k_monthly",
"plan_1k_annual",
"plan_10k_monthly",
"plan_10k_annual",
"plan_25k_monthly",
"plan_25k_annual",
"plan_50k_monthly",
"plan_50k_annual",
"plan_100k_monthly",
"plan_100k_annual"
],
"type": "string",
"description": "Which plan."
}
},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 14, 2026.
Takes a password, API key or token as an argument, so the secret passes through the model's context and chat logs.
Fix: Read credentials from the server's own configuration (environment, OAuth) instead of a tool argument.
{
"type": "object",
"required": [
"token",
"rev"
],
"properties": {
"ops": {
"type": "array",
"items": {
"type": "object",
"required": [
"op"
],
"properties": {
"a": {
"type": "integer"
},
"b": {
"type": "integer"
},
"n": {
"type": "integer",
"minimum": 1
},
"dx": {
"type": "number"
},
"dy": {
"type": "number"
},
"op": {
"enum": [
"recolor",
"setTransparent",
"mergeIntoNeighbour",
"mergeColours",
"splitColour",
"snapPalette",
"setColourCount",
"move",
"delete"
],
"type": "string"
},
"color": {
"type": "array",
"items": {
"type": "integer",
"maximum": 255,
"minimum": 0
},
"maxItems": 3,
"minItems": 3
},
"label": {
"type": "integer"
},
"rules": {
"type": "array",
"items": {
"type": "object"
}
},
"region": {
"type": "object",
"properties": {
"x": {
"type": "integer"
},
"y": {
"type": "integer"
},
"label": {
"type": "integer"
}
},
"description": "A region key {x, y, label}: region.region from inspect_vector."
},
"neighbour": {
"type": "object",
"properties": {
"x": {
"type": "integer"
},
"y": {
"type": "integer"
},
"label": {
"type": "integer"
}
},
"description": "A region key {x, y, label}: region.region from inspect_vector."
}
}
},
"maxItems": 64,
"minItems": 1,
"description": "Edits to apply, in order."
},
"rev": {
"type": "integer",
"minimum": 0,
"description": "The revision from your last inspect_vector or edit_vector (0 for a new token)."
},
"undo": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Remove the last n edits instead of applying ops."
},
"token": {
"type": "string",
"description": "The image token (img_…)."
},
"inline_max_bytes": {
"type": "integer",
"maximum": 33554432,
"minimum": 0,
"description": "Largest edited SVG, in bytes, to include in the result (default 16384). The preview image comes up to 1048576 bytes. 0 leaves both out."
}
},
"additionalProperties": false
}