Vesta MCP Server
Deploys and runs the Vesta arcade on the user's own Cloudflare account, using Cloudflare Workers, D1, and R2 to host game pages, store game files and covers, and support publishing, feedback collection, and dashboards on the free plan.
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.
Why
Making a browser game with Claude Code, Cursor or Codex takes an afternoon now. What happens next is the hard part. You paste a link somewhere, a few people click it, and you never learn that it crashed on Safari, that half of them quit in the first ten seconds, or that level 3 is impossible.
Vesta closes that loop:
your agent ──publish──▶ playable link ──▶ people play
▲ │
└──── errors, drop-off, comments ◀─────────┘Publish from the editor. One command, or one MCP tool call from your agent. Every publish is a new version with a changelog.
Feedback an agent can act on. Uncaught errors with stack traces, grouped and counted. How long sessions last. How far players get. What they wrote. One Markdown report, made to be pasted into an agent, or fetched by one.
Yours. It deploys to your Cloudflare account in one command and fits in the free plan. No platform cut, no AI-content policies, no one else's terms.
Related MCP server: web-artefacts
Quick start
You need Node 20+ and a free Cloudflare account.
npx vesta-cli setup # deploys your arcade (~2 minutes, opens a browser to sign in to Cloudflare)
npx vesta-cli publish # run in any folder with an index.html, or a built dist/▲ Hug of Death v1 is live (new game)
https://vesta.you.workers.dev/g/hug-of-death
1 files · 31.6 KB · cover: screenshotWant it on your own domain? npx vesta-cli setup --domain games.example.com (the domain must be on the same Cloudflare account). If the domain already serves a site, Vesta takes over the pages it knows and passes everything else through to the old site.
That's it. publish finds your build folder (dist/, build/, out/ or the folder itself), uploads it, screenshots the game for a cover image if you have Chrome or Playwright's Chromium, prints a QR code for your phone and saves the game's slug in vesta.json, so the next publish becomes v2.
For coding agents
Add Vesta as an MCP server, then just ask: “publish this game to Vesta”, and later, “check the Vesta feedback and fix the top error”.
claude mcp add vesta -- npx -y vesta-cli mcp # Claude CodeFor Cursor, Codex, Windsurf, Cline and other MCP clients, add this to their MCP config:
{ "mcpServers": { "vesta": { "command": "npx", "args": ["-y", "vesta-cli", "mcp"] } } }Tool | What it does |
| Uploads the project (optionally builds it first) and returns the public link |
| Markdown report: errors with stacks, session lengths, milestones, comments, versions |
| Every game on the arcade, with plays and likes |
| Sets the cover image used in the arcade and in link previews |
| Whether an arcade is configured, and where |
Every arcade also serves /llms.txt, so an agent that only has a URL knows how to publish and what the limits are.
Games can report progress. Vesta injects window.vesta into every game:
window.vesta?.milestone("reached-level-2"); // the report shows what share of plays get here
window.vesta?.error("Physics exploded"); // a game-level problem, grouped like any other error
window.vesta?.shareUrl; // the arcade page's URL, for your share button
await window.vesta?.submitScore(4210); // arcade high scores: players enter 3 initialssubmitScore shows an arcade-style "enter your initials" box inside the game (in a shadow root, so it can't clash with the game's CSS or controls), ranks the score, and resolves with { rank, rankToday, total } or null if the player skips. The game page shows the top ten.
What the agent gets back from get_feedback:
# Player feedback: Hug of Death (`hug-of-death`)
Live version: v3 · https://vesta.you.workers.dev/g/hug-of-death · last 14 days
## Players
- 412 plays, 380 sessions timed, average 2m 05s of active play
- How long sessions last on v3: <10s 8% · 10-30s 21% · 30-60s 17% · 1-3m 38% · 3-10m 14% · 10m+ 2%
## Errors on v3 (fix these first)
1. **error: TypeError: Cannot read properties of undefined (reading 'h')** at `index.html:412:18` (37×, last 2h ago)
Browser: Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) …
## Milestones on v3
- front-page: 301 sessions (73% of plays)
- rank-1: 122 sessions (30% of plays)
## What players said
- "web-2 melted the second I hit #1, then I couldn't buy anything on my phone" (sam), v3, 3h agoWhat you get
How it works
┌──────────────── your Cloudflare account (free plan) ───────────────┐
vesta publish │ │
MCP tools ───▶ │ site Worker vesta.<you>.workers.dev │
│ arcade · game pages · dashboard · API (Bearer token) │
│ │ │ │
│ ▼ ▼ │
│ D1 (SQLite) R2 (game files, covers) │
│ games, versions, ▲ │
│ daily totals, errors │ │
│ ▲ │ │
│ play Worker vesta-play.<you>.workers.dev │
players ──────▶ │ serves game files · injects the feedback script · takes beacons │
└─────────────────────────────────────────────────────────────────────┘Two Workers, one script. The same code is deployed twice with a different
ROLE. Game files are served from a separate origin, so a game's JavaScript can never read the arcade's session cookie or call its API.workers.devis on the Public Suffix List, so the two are separate sites to the browser, not just separate origins.Defence in depth on the game page. The arcade sends a strict CSP (
script-src 'self', frames only from the play origin,frame-ancestors 'none'), and the game iframe is sandboxed withoutallow-top-navigation, so a game can't redirect the arcade to a phishing page.Games load only when someone presses play. There's no autoplay audio, and a play is counted only when a person asked for one. Headless browsers and link-preview bots aren't counted.
Saves don't collide. Every game shares the play origin, so the injected script namespaces
localStorage,sessionStorageand IndexedDB per game.No raw events are stored. Telemetry lands as daily totals, a session-length histogram and errors grouped by fingerprint, so the free 5 GB of D1 lasts for years. There are no cookies or fingerprinting, and IPs are only ever stored as a salted hash, for likes and spam limits.
Uploads are checked file by file. Files go up one at a time against a manifest validated in advance: 1,000 files, 100 MB per version, 25 MB per file, no hidden files (no leaked
.envor.git/), no executables, no path tricks. A version goes live only when every file has arrived at the declared size. The newest 3 versions are kept.
More detail, including the data model and why it's built this way: docs/architecture.md.
Free plan math
Piece | Free allowance | Roughly enough for |
Workers | 100,000 requests/day | ~3,000 plays a day for a typical 20-file game |
R2 | 10 GB stored, free egress | hundreds of games (most AI-made web games are a few MB) |
D1 | 5 GB, 5M rows read/day | years of daily totals |
When you outgrow it, the Workers paid plan is $5/month. Nothing else changes.
CLI
vesta setup Deploy (or upgrade) your arcade on Cloudflare (--name, --domain, --subdomain)
vesta publish [dir] Publish; -n "notes", -b to build first, --open, --no-screenshot
vesta feedback [slug] The Markdown report (--json for raw data, --days 30)
vesta list Your games
vesta open [slug] Open the arcade or a game in your browser
vesta login [url] Connect this machine to an existing arcade (--token)
vesta delete <slug> Delete a game, every version, its stats and comments
vesta mcp Run as an MCP serverCI can publish too: set VESTA_URL and VESTA_TOKEN and run npx vesta-cli publish dist -n "$COMMIT_MESSAGE".
vesta.json
Created on first publish, next to your source. Commit it.
{
"slug": "hug-of-death",
"title": "Hug of Death",
"description": "Your side project just hit #1. You are the load balancer.",
"author": "you",
"madeWith": ["Claude Code"],
"tags": ["arcade"],
"dir": "dist",
"build": "npm run build",
"cover": "cover.png",
"aspect": "16/9",
"keyboardRequired": false,
"sourceUrl": "https://github.com/you/hug-of-death"
}madeWith is detected automatically when you publish from Claude Code, Cursor, Codex and others, or when the project has their config files (CLAUDE.md, .cursor/, …). Use "aspect": "9/16" for portrait phone games.
The games
Three original games, written with Claude Code and published with Vesta. Each is one HTML file with no dependencies, reports milestones and high scores through window.vesta, and plays itself if you add ?demo to its URL.
Your side project just hit #1 and you're the load balancer. Route traffic before servers melt, block scrapers, buy a CDN or an SRE. | |
You're the guardrail between an AI agent and the internet. Block the prompt injections (hidden text, base64, leaky image URLs) and let everything else through. | |
You are the GC. Free what no root can reach, never free what's in use, and watch for cycles. Stop the world if you must. |
Development
npm install
npm run dev # http://localhost:8787 (arcade) and http://play.localhost:8787 (games)
npm test # manifest and upload rules
npm run typecheck
npm run build # builds the CLI and bundles the Worker into itLocally, one wrangler dev process serves both roles and picks one by hostname. The local token is in worker/.dev.vars. To publish to your local arcade:
node cli/dist/cli.js login http://localhost:8787 --token dev-token-change-me
node cli/dist/cli.js publish games/hug-of-deathThe code: worker/src/play (game files, injected script, telemetry), worker/src/site (arcade, dashboard, API; server-rendered with Hono JSX, no client framework), cli/src (CLI, MCP server, Cloudflare setup).
Roadmap
Custom domain with a subdomain per game (full storage isolation between games)
Source maps: show errors at the original file and line
Remixes: “fork this game”, with credit back to the original
Signed scores, so high scores can't be posted from outside the game
Jams: a time-boxed arcade page with voting
Accounts for other creators, so an arcade can be shared by a team or a class
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Publish AI-made browser games and get a shareable URL. Update, test and read player feedback.
Publish, test and share browser games on PlayDrop from your AI agent.
Build, edit and preview browser games and web apps in your Amplify account from your AI agent.
Build browser games on gamedev.pl from your coding agent.
Related MCP Servers
FlicenseAqualityDmaintenanceEnables AI agents to deploy multiplayer web games as playable URLs with rooms, live state sync, and leaderboards, all through a single tool call.4144 npm5-- AlicenseNot gradedqualityAmaintenanceEnables coding agents to publish HTML artifacts that users can review and comment on in a sandboxed browser viewer, with feedback loop support for iterative versions.10 npmMIT
- AlicenseAqualityBmaintenanceLet coding agents play, test and tune your 2D web game. The debuff MCP server attaches to the game you have open (or runs a headless copy) and gives agents live state, explained and source-mapped errors, frame timings, typed params, deterministic replays and rewind, scenario tests and fuzz playtesting. Everything an agent does shows in your dev panel, where you can undo it.217MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to publish and manage HTML5 browser games, giving each game its own address and catalogue page with leaderboards, cloud saves, player clips, daily stats, versioning, and rollback.1MIT