VectorAgent
Uses OpenZeppelin's hosted testnet facilitator as the x402 payment facilitator to verify and settle agent payments, configurable via the facilitator URL and API key.
Enables paid icon purchases through USDC transfers on Stellar testnet, with settlement transaction hashes stamped into delivered SVGs for provenance and license verification against Stellar Horizon.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
VectorAgent
An icon store where the buyer is an agent and the payment is the license.
An agent finds the tools over MCP, searches for free, gets an HTTP 402 when it
asks for a paid icon, signs a sub-cent USDC transfer on Stellar testnet, and
gets the SVG back with the transaction that bought it stamped into the file.
Testnet only. Every number below was measured rather than estimated.
Check it before reading the rest
None of this needs to be taken on trust. One real settlement:
Payment |
|
Receipt |
|
What it bought | 7 icons, in a 524-byte manifest whose sha256 is |
The entry's name is the first 32 characters of the payment hash, so the link between the money and the list is public too. The settlements page refetches every manifest and re-hashes it in your browser: anything that does not match the chain is dropped rather than shown, so the page cannot vouch for a list the ledger has not already committed to. Every settlement there was paid by this project's own wallet, some from the demo on the home page and some from an agent calling the MCP tools directly.
The live demo runs an actual purchase when you press the button. It is not a recording.
Related MCP server: Svg/icons MCP
What this is
A proof of one narrow thing: an agent can buy a digital asset on its own, with no human approving the purchase, and the payment can be the provenance record rather than a license file someone has to keep believing in.
Three standards stacked, none of them invented here. MCP is how agents find tools, x402 is how a server charges for a request, and Stellar settles cheaply enough that writing the receipt costs less than the icon.
The findings, including what happened when four agents met it cold and only two of them bought anything, are written up here. This README is the implementation.
Quickstart
npm install
cp .env.example .env
npm run setup-wallets # AGENT + VAULT keypairs, funded with XLM, USDC trustlines openedTwo things you have to bring yourself:
A facilitator API key. Set
FACILITATOR_API_KEYin.env. The defaultFACILITATOR_URLis OpenZeppelin's hosted testnet facilitator.Testnet USDC for the agent wallet. The Circle faucet is a web form with no public API, so this step is manual: open https://faucet.circle.com, network Stellar Testnet, token USDC, paste your
AGENT_PUBLIC_KEY. 20 USDC per request, refillable every two hours.
Then run the payment loop end to end:
npm run build:edge # copy src/ and assets/ into the function
npm run dev:edge # terminal 1: the x402 resource server on :4021
npm run test:flow shopping-cart # terminal 2: one paid fetch over plain HTTPAnd the static site, if you want the settlements page and the demo:
npm run build:previews # 1,550 watermarked PNGs into site/dist/preview
npm run build:site # settlements page, library browser
npm run build:demo # the home page
npm run serve:site # http://localhost:4180PREVIEW_BASE already defaults to that address, so the previews in a 402
challenge resolve against your own copy rather than anyone else's.
The asset library
1,550 original icons across 30 categories, built from compact specs in
assets/specs/ by npm run build:assets. Every icon is tokenized the same
way: each part carries a data-slot marker and paints through a CSS custom
property chain, so one file serves light, dark, mono and duotone without
variants.
stroke="var(--tby-accent-stroke, var(--tby-accent, var(--tok-color-secondary, #1a1f2b)))"Tier | Count | Price | What it is |
free | 1,000 | $0.000 | common UI primitives, 20 categories |
standard | 500 | $0.002 | domain-specific (dev-infra, fintech, healthcare, …) |
premium | 50 | $0.010 | animated variants of standard icons |
npm run preview:assets writes assets/qa/preview.html, a self-contained
page with every icon inlined and toggles for theme, palette and a per-region
accent override. npm run qa:assets writes per-category PNG contact sheets.
These are a test set, published under the same license as the code. They exist to make the payment flow real, not to be a product.
Pricing
Price is a property of the icon's tier, not of the route. The x402 route config takes a function, so one endpoint quotes three different prices:
price: (ctx) => getIcon(iconIdFromPath(ctx.path))?.price ?? TIERS.standard.priceThree cases resolve in order, and the first two never mint a challenge:
Request | Result |
unknown id |
|
free icon |
|
paid icon |
|
The 402 is not a dead end. Its body carries the free assessment payload
(tier, price, tags, and a watermarked 96px preview URL) while the
machine-readable requirements ride in the PAYMENT-REQUIRED header, so
the two never collide. src/preview.ts renders the watermark; it is
deliberately low-resolution and overprinted, enough to judge the icon and
useless as the asset.
Latency, and why baskets exist
A settlement costs a Stellar ledger close, and Stellar testnet closes a ledger every exactly 5.00 seconds. Measured end to end, a single paid fetch is ~8-10s, and splitting it around the ledger boundary shows where it goes:
Time | |
Request to ledger close | ~4.9-5.6s (protocol floor) |
Ledger close to response | ~1.8-4.8s (facilitator confirm, pure overhead) |
Free icon | 51 ms |
402 challenge only | 4 ms |
So roughly half the wait happens after the money has already moved, and the other half cannot be removed while we wait for settlement at all. That makes per-icon fetching a dead end for an agent building a screen: twenty icons one at a time is about three minutes.
GET /bundle/:ids buys a basket in one settlement, which is the cheapest fix
available and changes no trust assumptions. Measured:
5 icons sequentially 39.00s (7.80s each)
5 icons as one basket 7.50s 5.2x faster, same $0.010 spent
20 icons as one basket 8.06s versus roughly 180s one at a timeLatency is per settlement, not per icon, so a twenty-icon basket costs about
the same wall time as buying one. The fetch_vector_icons MCP tool says so in
its description, so a calling agent has a reason to prefer it.
The basket keeps the same three-case ordering as a single fetch: an unknown id rejects the whole basket before the middleware so nothing is billed, an all-free basket never sees a challenge, and free icons ride along inside a paid basket at no cost so the caller never has to sort them. Limit is 40.
Two things this does not fix, and they are the real roadmap: the facilitator overhead above (PayAI took x402 on Base from 1.7s to 750ms by chasing exactly this), and genuine first-contact one-off requests, which no deployed x402 pattern currently solves without pre-funding. Releasing an asset on verification alone is tempting and is what we first reached for, but it is a documented vulnerability class rather than a pattern: a production deployment measured 86.95% leakage under burst.
The license attribute
A delivered asset carries a pointer to the settlement that paid for it, so provenance survives without us:
<svg data-va-asset="vector-db"
data-va-license="standard"
data-va-tx="0a0155746e73…ccfb"
data-va-network="stellar:testnet" …>Free assets are stamped too, with data-va-license="free" and no citation.
The claim is that an audit finds zero unattributed assets, and "free"
answers "where did this come from" while a missing attribute does not.
data-va-network is load-bearing: a bare hash is meaningless without knowing
which ledger to resolve it against, and resolving it is the whole point.
The MCP server stamps this, not the resource server. The Stellar scheme's
default payment flow is authorization, which settles after the route
handler produces its body, so the server cannot know the transaction hash
when it builds the SVG. The MCP server can: it holds the wallet, it made the
payment, and it gets the settlement receipt alongside the asset. The party
that paid writes the pointer to its own payment into its own copy.
Auditing
npx tsx scripts/audit-licenses.ts ./some-app/srcWalks a tree, finds every stamped asset (including SVGs inlined into JSX),
and resolves each citation against public Horizon. It never calls the
VectorAgent registry, which is the point: the audit still works if the
company is gone. verify_vector_license is the same check as an MCP tool.
What this does and does not prove
Resolving a citation proves a settled transfer of a given amount reached a given account at a given time, and the verifier additionally checks that the amount matches the asset's tier price. It does not, on its own, prove that transfer bought this icon, because the asset id is not carried inside the transaction: that link still comes from the registry's records. Closing it needs the asset id in a Stellar memo or an asymmetric signature.
Testing
npm run dev:edge # terminal 1
npm run test:pricing # terminal 2 - HTTP + ledger
npm run test:mcp # terminal 2 - the MCP tool layer
npm run test:bundle # terminal 2 - batching, measured against sequential
npm run test:manifest # terminal 2 - canonical bytes and their digest
npm run test:attest # terminal 2 - the on-chain receipt round triptest:pricing asserts an unknown id is never billable, a free icon settles
nothing, and standard and premium are quoted and settled at $0.002 and
$0.010, checking the vault's balance on Horizon rather than trusting the
server. test:mcp spawns the MCP server over stdio and checks that an agent
sees the right tools, that search and preview cost nothing, and that only
fetch_vector_icon can spend.
Every one of these spends real testnet USDC from the agent wallet, which is the point: they fail if the money does not actually move.
Using it from Claude Code
.mcp.json at the project root registers the MCP server:
{
"mcpServers": {
"vectoragent-poc": {
"type": "stdio",
"command": "npx",
"args": ["tsx", "src/mcp-server.ts"]
}
}
}Start (or restart) a Claude Code session in this project directory. Claude Code reads
.mcp.jsonat startup, not while a session is already running.Approve the server when prompted (first time only) - it's a subprocess Claude Code starts on your machine, so it asks for consent once.
Confirm it connected: run
/mcpinside the session, orclaude mcp listfrom a terminal.Ask it to use the tools, e.g.: "Search VectorAgent for a vector database icon, preview the best paid match, then fetch it and build a React status card with it."
The six tools, and which of them can spend:
Tool | Cost | What it does |
| free | ranked matches with tier, price and |
| free | metadata + watermarked preview URL, reads the 402 without paying |
| free | catalog counts; pass a tier to list ids |
| free | resolves an SVG's |
| tier-priced | returns one SVG, settling first if the icon is not free |
| summed | a basket of up to 40 in ONE settlement; prefer this |
Watch the resource server's terminal log the 402 -> verify -> settle sequence in real time.
If you'd rather use the plain Claude Desktop chat app instead of Claude Code,
the same JSON block goes under mcpServers in claude_desktop_config.json
(Windows: %APPDATA%\Claude\claude_desktop_config.json), with cwd set to
this project's absolute path since that app doesn't infer it from where the
config file lives.
Architecture
Claude (Code or Desktop)
| MCP tool call: fetch_vector_icons([ids])
v
src/mcp-server.ts (holds AGENT's Stellar keypair)
| HTTP GET, wrapped with @x402/fetch
v
supabase/functions/vectoragent (x402 resource server; npm run dev:edge locally)
| free icon -> 200 + SVG, no challenge, stop here
| unknown id -> 404, no challenge, stop here
| paid icon -> 402 + PAYMENT-REQUIRED header (price from the icon's tier)
| + body carrying the watermarked preview URL
| <- mcp-server signs a Soroban USDC transfer, retries
v
OpenZeppelin-hosted x402 facilitator (channels.openzeppelin.com/x402/testnet)
| verifies + broadcasts the signed transfer, fees sponsored on testnet
v
Stellar testnet ledger -- AGENT -> VAULT
|
| the function returns the SVGs; mcp-server.ts stamps each one with the
| transaction that paid for it and hands them back
v
A second, independent transaction writes the receipt: sha256 of the itemised
manifest, into a manage_data entry keyed by the payment hash. Soroban payments
cannot carry a memo, which is the only reason this is two transactions.site/ is a static build with no backend of its own: the settlements page
reads Horizon and the content store straight from the browser, so it is a
second witness to the same settlements rather than this project reporting on
itself.
Why the paid route is not a Worker
Everything else here is static and could sit on one platform, so the split is worth explaining. Cloudflare Workers allow 10ms of CPU per request on the free plan. Signing one receipt transaction measures 7.5ms on its own, before the payment signing, the hashing or the catalogue search. A Supabase edge function allows 2s, so that is where the paid route runs.
Two things do not survive that runtime and are handled rather than ported:
@resvg/resvg-jsis a native binding Deno cannot load, so previews are pre-rendered into the static site bynpm run build:previewsand/preview/:fileredirects to whereverPREVIEW_BASEpoints.Express does not run on Deno, so routing is a small hand-written router. The x402 paywall itself ports cleanly, because
@x402/expressis a thin wrapper over the framework-agnostic@x402/core/server.
There is one implementation, not two. An Express server did this first and was deleted once the function worked, because two versions of ten routes drift and nothing tells you when.
Scope
Built and working: the payment loop, tiered pricing, the asset library, watermarked previews, baskets, the license attribute, the on-chain receipt, in-browser verification, and a live demo that spends real testnet money.
Still out, and deliberately so:
Binding the citation to the asset id. The license attribute ships, but the transaction itself does not carry the asset id, so the "which icon did this buy" link still depends on our records. See the section above.
Semantic search.
src/search.tsis a transparent lexical scorer, not a vector index. Good enough to exercise pricing; not good enough for "isometric 3D cloud database node". Two of the four test agents ignored its scores entirely and read the descriptions instead.Creator ingestion and payouts. The split, the publisher UI and the off-ramp are all unbuilt. Every asset here is one we authored, so there is no creator to pay yet.
Mainnet. Testnet only, with a hosted facilitator. The test agents knew it, too: one of them called the funds "valueless faucet tokens" while deciding to spend them, which is a confound no amount of testnet proves away.
License
MIT, covering the code and the 1,550 icons alike. Use any of it for anything.
This server cannot be deployed
Maintenance
Related MCP Connectors
Marketplace and payment rail for AI agents: list, buy and settle with signed receipts.
Buy private git repos and agent skills with USDC over x402. Read the manifest free, then pay.
Wallet trust scores for AI agents. Stellar, XRPL, EVM 81+ chains. OFAC sanctions. x402 payments. Multi-chain wallet trust scoring for AI agents. Score Stellar, XRPL, and EVM wallets across 81+ chains with real-time OFAC/UN/EU sanctions screening. Pay per query via x402 USDC micropayments on Stellar or Base — no accounts, no API keys required.
Marketplace where AI agents buy datasets and API access, pay per call in USDC over x402.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceVisual icon search, retrieval, and comparison for AI agents. Search 200k+ icons semantically, render side-by-side comparison grids, and retrieve raw SVG markup — all tools return images so vision-capable LLMs can see the icons.1-

Svg/icons MCPofficial
AlicenseNot gradedqualityCmaintenanceEnables AI coding tools to search, inspect, recommend, and export SVG icons from svgicons.com for use in design systems, frontend projects, and AI-assisted workflows.MIT- AlicenseCqualityDmaintenanceEnables AI-powered icon search, generation, and download from 275,000+ icons with web-based authentication and subscription plans.13 npmMIT
- FlicenseNot gradedqualityFmaintenanceEnables AI agents to query the largest CC0 database for provenance, license verification, and market data, and generate CC0 images, all via pay-per-call x402 micropayments.-