Velven
Publish browser games, worlds, tools and wonders built with AI to Velven's hosting, and manage them.
Should I use this
Quality & Safety
Findings (1)
- LOWin rollback
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"velven": {
"url": "https://mcp.velven.ai/mcp"
}
}
}Remote endpoints
https://mcp.velven.ai/mcpstreamable-httpWhat it can do
Tool inventory
Tools (5)
🟡publish(html, files, entry, title, type, ...)
Publish a browser game, world, tool or wonder on Velven's hosting, from one HTML page or a small set of files (3 MB in all). Signed in: a private preview by default, or with prod: true the next live version, live on its Velven page within seconds. Not signed in: an unlisted page, live the same way, returned with a claim token that keeps it. A new space needs title, type and devices from the person. To update a space pass space (signed in) or claim (not signed in).
Input Schema
{
"type": "object",
"properties": {
"html": {
"description": "A whole page as one HTML string, published as index.html.",
"type": "string"
},
"files": {
"description": "Files by relative path: text as a string, binary as { \"base64\": \"...\" }. Must include the entry page (index.html unless entry says otherwise). A velven.json, a dotfile, a dot-folder or node_modules, in any folder, is left out (never published; the result names the first 10 and counts the rest): send velven.json's settings as this tool's fields.",
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"base64": {
"type": "string"
}
},
"required": [
"base64"
]
}
]
}
},
"entry": {
"description": "The page that opens first, if not index.html.",
"type": "string"
},
"title": {
"description": "The space's name. Required for a new space.",
"type": "string",
"maxLength": 80
},
"type": {
"description": "What it is. Required for a new space.",
"type": "string",
"enum": [
"game",
"world",
"tool",
"wonder"
]
},
"devices": {
"description": "Where it can be played. Required for a new space.",
"type": "array",
"items": {
"type": "string",
"enum": [
"desktop",
"mobile",
"vr"
]
}
},
"description": {
"description": "One line under the name.",
"type": "string",
"maxLength": 160
},
"engine": {
"description": "What it draws with, if one of these.",
"type": "string",
"enum": [
"three.js",
"r3f",
"babylon.js",
"playcanvas",
"a-frame",
"godot",
"unity",
"phaser",
"p5.js",
"canvas",
"webgl",
"webgpu",
"wasm",
"dom",
"marble",
"spline",
"other"
]
},
"how_made": {
"description": "How it was made, in the creator's words.",
"type": "string",
"maxLength": 2000
},
"space": {
"description": "Publish a new version of this space (yours, signed in).",
"type": "string",
"pattern": "^[a-z0-9-]{1,100}$"
},
"claim": {
"description": "The claim token of an unlisted page: publishes its next version, or claims it when signed in.",
"type": "string",
"pattern": "^vlc_[A-Za-z0-9_-]{43}$"
},
"prod": {
"description": "Go live on the space's Velven page instead of making a preview. Signed in only. Default false.",
"type": "boolean"
},
"spa": {
"description": "Serve the entry page for any unknown path (a single-page app).",
"type": "boolean"
},
"sdk": {
"description": "Add Velven's SDK script to the entry page. Default true.",
"type": "boolean"
},
"thumbnail": {
"description": "The picture on the space's tile. Give the path of one of the files sent: a JPEG, PNG or WebP, up to 2 MB and 4096 pixels on each side. It's used as soon as the version is live, and Velven takes no picture of its own. It must show the space itself.",
"type": "string"
},
"clip": {
"description": "The video the tile plays on hover, without sound. Give the path of one of the files sent: an MP4 or WebM, up to 3 MB and 5 to 10 seconds long. Velven then records no clip of its own. Without a thumbnail, the clip's first frame is the picture. It must show the space itself. A clip outside that length is refused. If the file doesn't say its length, Velven measures it once live. It keeps the first 10 seconds of a longer clip, and drops a shorter one. A later version that names neither keeps the space's.",
"type": "string"
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"space": {
"type": "string",
"description": "The space's slug."
},
"version": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "The version this publish made."
},
"status": {
"type": "string",
"description": "The version's status: preview, publishing (waiting on Velven to publish it), live or refused."
},
"reason": {
"description": "Why it was refused, naming the file when it was one.",
"type": "string"
},
"pageUrl": {
"type": "string",
"description": "The space's page on Velven."
},
"previewUrl": {
"description": "The private preview, for 24 hours (a preview only).",
"type": "string"
},
"watchUrl": {
"description": "Where to follow the version on Velven.",
"type": "string"
},
"expiresAt": {
"description": "When an unlisted page is deleted unless claimed (no account).",
"type": [
"string",
"null"
]
},
"claimToken": {
"description": "The unlisted page's claim token, shown once (no account).",
"type": "string"
},
"claimUrl": {
"description": "Open signed in to claim the page (no account).",
"type": "string"
},
"terms": {
"description": "The Terms line to show the person (no account).",
"type": "string"
},
"leftOut": {
"description": "Files not published (velven.json, dotfiles, node_modules), the first 10.",
"type": "array",
"items": {
"type": "string"
}
},
"leftOutCount": {
"description": "How many files were left out in all.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"space",
"version",
"status",
"pageUrl"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢my_spaces
List the spaces of the signed-in Velven account: slug, title, status, whether Velven hosts it, and its page. Needs sign-in; called without it, the app asks the person to sign in to Velven.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"handle": {
"type": "string"
},
"spaces": {
"type": "array",
"items": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "string",
"description": "published, processing, held, dead, unframeable."
},
"hosted": {
"type": "boolean",
"description": "Velven hosts its files (else it links a live URL)."
},
"pageUrl": {
"type": "string"
},
"createdAt": {
"type": "string"
}
},
"required": [
"slug",
"title",
"status",
"hosted",
"pageUrl",
"createdAt"
],
"additionalProperties": false
}
}
},
"required": [
"handle",
"spaces"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢versions(space)
List a hosted space's versions, newest first: number, status (uploading, preview, publishing, live, refused, unjudged, replaced), size, and whether rollback can pick it. Refused versions carry the reason. Needs sign-in.
Input Schema
{
"type": "object",
"properties": {
"space": {
"type": "string",
"pattern": "^[a-z0-9-]{1,100}$",
"description": "The space's slug, as my_spaces or publish named it, e.g. pixel-racer."
}
},
"required": [
"space"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"space": {
"type": "string"
},
"versions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"number": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"status": {
"type": "string",
"description": "uploading, preview, publishing, live, refused, unjudged or replaced."
},
"createdAt": {
"type": "string"
},
"live": {
"type": "boolean"
},
"files": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"size": {
"type": "number",
"description": "Bytes."
},
"reason": {
"description": "Why Velven refused it.",
"type": "string"
},
"liveAt": {
"type": "string"
},
"rollback": {
"type": "boolean",
"description": "It was live before, so rollback can pick it."
},
"leftBehind": {
"type": "boolean",
"description": "Made before the space moved off hosting: it can only be looked at."
}
},
"required": [
"id",
"number",
"status",
"createdAt",
"live",
"files",
"size",
"rollback",
"leftBehind"
],
"additionalProperties": false
}
}
},
"required": [
"space",
"versions"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴rollback(space, version)
Make an earlier version of a hosted space live again. Only a version that was live before (rollback: true in versions) can be picked; it goes live at once. Needs sign-in.
Input Schema
{
"type": "object",
"properties": {
"space": {
"type": "string",
"pattern": "^[a-z0-9-]{1,100}$",
"description": "The space's slug, as my_spaces or publish named it, e.g. pixel-racer."
},
"version": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991,
"description": "The version number to make live again."
}
},
"required": [
"space",
"version"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"version": {
"type": "object",
"properties": {
"number": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"number"
],
"additionalProperties": false
},
"status": {
"type": "string",
"const": "live"
},
"pageUrl": {
"type": "string"
}
},
"required": [
"version",
"status",
"pageUrl"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢search_docs(query, limit)
Search Velven's documentation: publishing and hosting, velven.json, the CLI, the SDK (sign-in, leaderboards, saves, achievements, rooms), claiming a page, the agent API and limits. Returns the best matching sections with links.
Input Schema
{
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 2,
"maxLength": 200,
"description": "What to look up, in a few words."
},
"limit": {
"description": "How many sections to return. Default 5.",
"type": "integer",
"minimum": 1,
"maximum": 10
}
},
"required": [
"query"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"query": {
"type": "string"
},
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"url": {
"type": "string"
},
"text": {
"type": "string"
}
},
"required": [
"title",
"url",
"text"
],
"additionalProperties": false
}
}
},
"required": [
"query",
"results"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}Community
Evidence