WebMCP — In-Browser AI Tools
Captic worlds expose their own WebMCP tools from the page you have open. An AI agent connected to your browser can inspect the world you are in, place models and screens, set the lighting, write scripts, save materials, and look at the result. It all happens in your live session, with the account you are already signed in with.
There is no server to set up and no API key to paste. The tools appear when you open a page that supports them and disappear when you leave it.
WebMCP works on the world open in your browser, as you, while you watch. For scripted automation without a browser, use the REST API with an API key.
1. Setup
Requirements
| Browser | Google Chrome 144 or newer, with WebMCP enabled (see below) |
| Agent | An MCP client such as Claude Code, Claude Desktop, Cursor or Antigravity |
| Bridge | chrome-devtools-mcp, which connects the agent to your Chrome |
| Account | Signed in at w3dge.io. The building tools need the role editor or higher in that world. See User Roles. |
Step 1: Enable WebMCP in Chrome
- Open
chrome://flags/#enable-webmcp-testing, set it to Enabled, and restart Chrome. - Open
chrome://inspect/#remote-debuggingand turn on the remote debugging server. This lets the agent connect to the Chrome you already have open, with your sign-in.
Step 2: Connect your agent
Add chrome-devtools-mcp to your client's MCP configuration (for example .mcp.json or
claude_desktop_config.json):
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest",
"--categoryExperimentalWebmcp",
"--autoConnect",
"--no-usage-statistics"
]
}
}
}
--categoryExperimentalWebmcpturns on the WebMCP tools of the bridge:list_webmcp_toolsshows what the page offers andexecute_webmcp_toolruns one.--autoConnectattaches to your running Chrome.
Restart your client after saving the file.
If you would rather not connect to your everyday browser, start a separate Chrome with
--remote-debugging-port=9222 --user-data-dir=<an empty folder>, enable the WebMCP flag in
that profile, sign in to w3dge.io there, and replace --autoConnect with
--browserUrl=http://127.0.0.1:9222.
Step 3: Open w3dge.io and check the connection
Open w3dge.io, sign in, and ask your agent:
"Check the session status."
get_session_status reports whether you are signed in, which world is open, whether you can
build in it, whether the welcome screen is still showing, and what to do next. The tools add
no badges or overlays to your 3D view.
2. Which tools are available where
The page offers only the tools that make sense where you are:
| Where you are | Tools |
|---|---|
| Lobby or landing page, signed in | 6: session status, the builder guide, and the world tools (list_worlds, create_world, switch_world, delete_world) |
Inside a world where your role is below editor | 7: the six above plus enter_world |
Inside a world where you are room_owner, admin or editor | 37: everything listed below |
If you see only 6 or 7 tools inside a world, your role there is below editor. A
moderator, user or guest gets the read-only set. The
User Role System page lists the full hierarchy.
The welcome screen
Every world opens behind a welcome screen with an enter button. Until you get past it, the
scene is blurred and you are not in the multiplayer room, so nobody sees your changes live.
create_world and switch_world pass it for you. If you opened the world yourself,
get_session_status reports welcomeScreenOpen: true and the agent calls enter_world
before it builds or takes screenshots.
3. What your agent can do
Tools marked 🔒 Asks first refuse to run until the agent passes confirm: true. The
agent can only do that after checking with you. Tools marked 👁 Read-only never change
anything.
📖 Guide and session
| Tool | Description | Example prompt |
|---|---|---|
get_session_status 👁 | Who is signed in, which world is open, building rights, welcome-screen state and the next step. | "Are the building tools active?" |
get_world_builder_guide 👁 | The world architect handbook. Topics: getting_started, capelement_dsl, multiplayer_games, uix_components, recipes or all. | "Read the getting-started guide before you start." |
🌐 Worlds
| Tool | Description | Example prompt |
|---|---|---|
list_worlds 👁 | Your worlds, newest first: name, worldHashId, template, live/public flags and creation date. Pages of up to 50, searchable by name with query. | "Find my world called Launch." |
create_world | A new blank world, or a copy of a template world. Opens it unless you pass open: false. Can also set sessionOnlyChat. Free accounts can have 3 worlds. | "Create a world called Launch Venue." |
switch_world | Opens another world by worldHashId and passes its welcome screen. | "Open the world wzTeL7." |
enter_world | Passes the welcome screen of the open world, like clicking its enter button. | "Enter the world." |
delete_world 🔒 | Permanently deletes a world. | "Delete the test world I made yesterday." |
🌆 Environment and atmosphere
| Tool | Description | Example prompt |
|---|---|---|
get_world_settings 👁 | Title, description, sky, lighting, environment map, fog, ground, spawn point, chat and voice options. | "What are the current lighting settings?" |
update_world_settings | Changes any of the above, applied live to the scene and saved. See the settings reference. | "Make it a dark keynote hall and put the spawn point in the audience." |
📦 Assets and uploads
| Tool | Description | Example prompt |
|---|---|---|
list_user_assets 👁 | Searches your library of models, videos, images and audio by type, so nothing is uploaded twice. | "Do I already have a video I can put on the screen?" |
ingest_3d_model | Imports a GLB/GLTF from a URL into your library. The server compresses it with meshopt and KTX2 textures and returns an upl_… id. | "Import this model URL into my library." |
upload_model_chunk | Uploads a local file from the agent's machine (model, image, video, PDF, audio) in Base64 pieces. This avoids browser CORS and file-size limits. | "Upload this local .glb." |
check_asset_status 👁 | Checks an upload until it is ready and returns its CDN links. A model comes in three qualities, and agents place fileMediumUrl first. | "Is that model ready yet?" |
A processed model has a medium, a high (fileUrl) and a low version. Agents place
the medium version by default, because the high one can cost every visitor hundreds of MB of
graphics memory. Ask for the high version if a close-up looks too coarse.
🎨 Material library
Library materials are PBR texture sets (floors, plaster, wood, metal, fabric, artwork).
Scripts load them with this.loadMaterial(manifestUrl). The server encodes the GPU textures,
and tiling textures show at their real-world size without any manual repeat. See
PBR Materials for how materials are built.
| Tool | Description | Example prompt |
|---|---|---|
list_materials 👁 | Your materials, those shared with your organizations, the public library, or all of them. Filter by name with query. | "Which wood floors can I use?" |
get_material 👁 | One material in full: stable links, metadata, and every encoded variant with its status, size and GPU memory. | "Is the brick material ready?" |
import_material_from_urls | Imports a texture set from Poly Haven, ambientCG or Substance in one call. Map slots are read from the file names, and DirectX normal maps are converted. | "Import this Poly Haven plaster as a material." |
list_script_textures 👁 | The named textures a script entity holds (baked canvases and material textures), ready to save. | "Which textures does the artwork script make?" |
save_material | Saves textures (from a script, an image URL or a data URL) as a glTF metallic-roughness material in your library. | "Save the procedural wall as a material called Loft Brick." |
encode_material_variants | Re-encodes a material's GPU textures, for example at higher quality for a flat surface that looks patchy. Runs in the background. | "Re-encode the plaster at quality 95." |
update_material_sharing | Makes a material private, shared with an organization, unlisted or public. Only its creator and the organization's owners and admins can change this. | "Share this material with my team." |
Visibility decides who can find and reuse a material in the library. A world that uses a material can always load its texture files, for every visitor, whatever the setting.
🎯 Placing and moving things
| Tool | Description | Example prompt |
|---|---|---|
list_world_entities 👁 | Everything placed in the world, with ids, transforms and world-space bounds in metres. | "What's in this world right now?" |
spawn_media_entity | Places a 3D model, video, image, audio source or screen share (see below), in front of you or at exact coordinates. | "Put that video on a 24 m screen behind the stage." |
update_entity_transform | Moves, rotates or scales anything by id. | "Raise the screen two metres." |
remove_entity 🔒 | Permanently deletes an entity. | "Remove the old backdrop." |
undo_last_action | Reverts the last move or deletion through the Studio history. | "Undo that." |
Screen share (type: "screen_share") places the Studio's Screen/Camera Sharing screen.
It is a 5 × 2.4 m frame on which visitors share their screen or webcam live, with share
buttons below it. Set attributes.defaultMode to "webcam" or "screen", and
attributes.requireAdmin: true to let only world admins share. Every meeting or
presentation room should have one.
🎥 Camera and review
| Tool | Description | Example prompt |
|---|---|---|
capture_scene_screenshot 👁 | Renders the scene so the agent can look at its work. See the options below. | "Take a screenshot and tell me if the scale looks right." |
check_z_fighting 👁 | Finds flickering surfaces (z-fighting), which a still screenshot cannot show, and ranks the overlapping surface pairs. | "Check the new room for flicker." |
get_scene_stats 👁 | Live performance numbers: FPS, frame time, draw calls, triangles, textures, estimated GPU memory (MB), shader programs and scene-graph size. | "How heavy is this world? Check the draw calls." |
get_camera_transform 👁 | Where you are standing and which way you are looking. | "Where am I?" |
focus_camera_on | Flies the camera to frame an entity. | "Show me the podium." |
highlight_entity | Draws a coloured box around an entity, with an optional note. | "Highlight the screen so I can see which one you mean." |
capture_scene_screenshot options:
| Option | What it does |
|---|---|
projection | "perspective" (default) shows what the camera faces. "equirectangular" shows the full 360° surroundings in one image, to spot anything missing or floating. |
camera / frameEntity | Aim with { position, lookAt, fov }, or frame an entity from a raised diagonal. By default it uses your own view. |
views | Up to 4 views in one call, each with its own camera and label. |
delivery | "inline" (default) returns the image to the agent. "overlay" shows it full-screen in the page for agents that only see text output, so they can take a browser screenshot. "download" saves the file to your downloads folder. |
includeAvatar | Your own avatar is hidden by default so it does not block the view. |
width, height, format, quality | Size (default 640 × 360, or 1536 × 768 for 360°), jpeg or png, and JPEG quality. |
⚡ Scripting
Scripts are CapElement components: custom geometry, animation and interactivity. See Scripting with JavaScript.
| Tool | Description | Example prompt |
|---|---|---|
create_and_attach_script | Writes a new script and attaches it to a new entity or an existing one. The script is validated and compiled before it is attached. | "Build a control console with next/previous slide buttons." |
get_script 👁 | The source code and component name of a script entity. | "Show me the code of the rotating sign." |
edit_script | Changes only part of a script by exact text replacement, then reloads it. Much faster than rewriting the whole script. All edits apply or none do. | "Make the sign rotate twice as fast." |
update_script | Replaces a script's whole source and reloads it in place, keeping the entity and its transform. | "Rewrite the console with a dark theme." |
stage_script_chunk | Sends a very large script in pieces, for agents whose output per call is limited. | — |
get_script_diagnostics 👁 | Errors thrown by running scripts (with counts), tick cost, a snapshot of script state, and the state of any multiplayer game rooms. | "The door doesn't open. What's wrong?" |
An agent should keep one call to about 20,000 characters. It builds the main structure with
create_and_attach_script, then adds the rest with one edit_script call per part. For a
very large source it can use stage_script_chunk (up to 64 pieces of 64 KB each) or codeUrl
(a URL the page fetches the source from), then pass the result to create_and_attach_script
or update_script.
4. World settings reference
update_world_settings accepts any of the fields below. Every field is optional, and any field
you leave out keeps its current value.
await update_world_settings({
// 1. Identity and visitors
name: "Neon Keynote Arena", // Renames the world and its URL slug. The hashid stays, so old links keep working.
title: "Neon Keynote Arena", // Display title
description: "Futuristic auditorium for live keynotes",
maxUsers: 50, // Maximum concurrent visitors
instanceSize: 6, // Run the world as separate copies of 6 visitors each. 0 = one shared world.
firstPersonOnly: false, // Lock the camera to first person
joinMuted: true, // Visitors enter with their microphone muted
sessionOnlyChat: false, // Don't store chat: visitors see only what is sent while they are there. Owner/admin only.
// 2. Spawning
spawnPoint: { x: 0, y: 1.6, z: 12 }, // Where visitors arrive
spawnRotation: { x: 0, y: 180, z: 0 }, // Which way they face, in degrees
randomRadius: 2.5, // Spread arrivals over this radius (metres)
autoSpawn: true, // Respawn visitors who fall below autoSpawnPoint.y
autoSpawnPoint: { x: 0, y: -10, z: 0 },
// 3. Sun and ambient light
lighting: {
shadows: true,
sunIntensity: 2.2,
sunColor: "#fff2d6",
sunPosition: { x: -120, y: 465, z: 100 },
ambientIntensity: 0.4, // 0.0 to 2.0
ambientColor: "#221133",
hemisphereIntensity: 0.85,
hemisphereSkyColor: "#dcecff",
hemisphereGroundColor: "#918b7c",
},
lightIntensity: 1.0, // Master light multiplier (default 1.0)
toneMapping: "Neutral", // "Custom" | "Neutral" | "ACESFilmic" | "AgX" | "Reinhard" | "Cineon" | "Linear"
// 4. Sky
skybox: {
use: true,
mode: "color", // "color" (gradient) | "material" (360° panorama)
colorTop: "#0d0221",
colorBottom: "#240046",
textureSrc: "https://.../sky_360.webp", // Panorama URL, used when mode is "material"
toneMapped: true,
useGrounded: false, // Ground-projected sky dome
radius: 100,
height: 15,
},
// 5. Environment map (image-based lighting and reflections)
useEnvironment: {
use: true,
textureSrc: "paul_lobe_haus_1k.jpg", // A bundled map (see below) or an https:// .hdr/.jpg/.ktx2 panorama
environmentIntensity: 0.8, // Dark interiors 0.3–0.6, bright interiors 0.6–1, outdoors 0.8–1.2
environmentRotation: { x: 0, y: 90, z: 0 },// Turn the map to put its key light where you want it
},
// 6. Ground
ground: {
use: true,
teleport: true, // Click-to-teleport on the floor
mode: "grid", // "grid" | "color" | "material" (PBR)
chunkColor: "#111115", // Grid fill colour
voxelsColor: "#00e5ff", // Grid line colour
useFog: true, // Fade the ground into the horizon
fogDensity: 0.025, // About 63% faded at 1/fogDensity metres (minimum about 0.003)
material: { // Used when mode is "material"
color: "#ffffff",
roughness: 0.8,
metalness: 0.1,
repeat: 8,
colorMap: "https://.../albedo.ktx2",
normalMap: "https://.../normal.ktx2",
roughnessMap: "https://.../roughness.ktx2",
},
},
});
To fade the floor into the horizon, use the ground's useFog and fogDensity. The separate
world fog setting currently ignores its color and density. Any fog value, even
{ enabled: false }, turns on a fixed default fog, so leave fog out unless you want that
default.
"Custom" (the default) applies exposure only, so bright skin can blow out and blacks turn
grey. "Neutral" keeps colours true and handles highlights, which makes it the best
choice for worlds with avatars, skin or dark fabrics. ACESFilmic and AgX desaturate skin.
Bundled environment maps
Every PBR material reflects the environment map, so pick one that matches the world. A blue sky map indoors tints dark glossy materials blue. The map is not shown as the background unless you turn that on in the sky settings.
| Kind | File | Good for |
|---|---|---|
| Studio | studio_small_01_1k.jpg | Dark interiors (clubs, bars, lounges), product and character showcases |
| Studio | neutral.hdr | Model viewers and configurators: reflections without a colour cast |
| Interior | hotel_room_1k.jpg | Apartments, hotel and residential interiors, cosy meeting rooms |
| Interior | small_empty_room_4_1k.jpg | White galleries, offices, minimal showrooms |
| Interior | courtyard_1k.jpg | Cafés, terraces, warm daytime interiors |
| Interior | paul_lobe_haus_1k.jpg | Modern architecture, conference and expo halls, lobbies |
| Sky | industrial_sunset_puresky_1k.jpg | Open-air worlds. The default. |
| Sky | citrus_orchard_puresky_1k.jpg | Sunny outdoors, beaches, light and airy worlds |
| Sky | citrus_orchard_road_puresky_1k.jpg | Daytime outdoors, afternoon |
| Sky | kloofendal_43d_clear_puresky_1k.jpg | Crisp midday, sport, vehicles and shiny objects in the sun |
| Sky | kloofendal_48d_partly_cloudy_puresky_1k.jpg | Friendly daytime outdoors, parks, islands |
| Sky | sunflowers_puresky_1k.jpg | Golden hour, relaxed warm scenes |
| Sky | sky.hdr | Overcast or mild daytime |
| Sky | sky_1.hdr | Moody, rainy or northern scenes |
| Landscape | dam_wall_1k.jpg | Rural nature, parks, adventure |
| Landscape | ninomaru_teien_1k.jpg | Gardens, zen spaces, forests |
| Landscape | pizzo_pernice_1k.jpg | Mountains, alpine and hiking scenes |
| Landscape | spruit_sunrise_1k.jpg | Dawn and early morning, farmland |
| Landscape | venice_sunset_1k.jpg | Coastal towns, sunset waterfronts |
| City | portland_landing_pad_1k.jpg | Urban worlds, rooftops, business districts |
| Night | moonless_golf_1k.jpg | Night outdoors. Raise environmentIntensity or rely on scene lights. |
5. Reading the scene directly
Agents that can run JavaScript in the page (through chrome-devtools-mcp, Playwright or the
browser console) may read the live scene directly:
| What | Query |
|---|---|
| The Three.js scene | document.querySelector('a-scene, cap-scene')?.object3D |
| The camera | document.querySelector('a-scene')?.camera |
| Placed entities and scripts | document.querySelectorAll('.entityScript, [id^="cmp_"], [id^="upl_"]') |
| An entity's mesh | document.querySelector('#entityId')?.getObject3D('mesh') |
| Navmesh zones | document.querySelector('#ground')?.components['teleport-on-navmesh']?.pathfinding?.zones |
Adding or changing elements directly in the page (appendChild, createElement, setting
attributes) skips saving, the Studio undo history and multiplayer sync. The change is lost on
reload and other visitors never see it. Make every lasting change with the WebMCP tools.
6. A worked example
This is one conversation with an agent, in a world you have open:
"Build a keynote stage: a raised central podium, a large video wall behind it, curved tiered seating, a screen-share screen for presenters, and a control console with next/previous slide buttons. Put the spawn point in the audience facing the stage. Use library materials, and show me screenshots when you're done."
A capable agent will:
- Call
get_session_statusand read thegetting_started,capelement_dslanduix_componentstopics of the builder guide. - Find the room with
list_world_entitiesandget_world_settings, so it builds inside the room's bounds and in view of the spawn point. - Set the atmosphere with
update_world_settings: environment map, tone mapping, lights and ground fog. - Choose surfaces with
list_materialsand checklist_user_assetsfor a video. - Write the structure with
create_and_attach_script, then add the remaining parts withedit_script. - Place the video and a
screen_sharescreen withspawn_media_entity, and set the spawn point. - Check its work with
capture_scene_screenshot,check_z_fightingandget_scene_stats, and fix what it finds.
Useful follow-ups:
- "The seats aren't sittable. Add seat anchors so guests can sit."
- "I can't walk up to the back row. Add stairs and make the tiers walkable."
- "Make the stage and stairs click-to-teleport targets."
- "That's too many draw calls. Merge the static geometry and show me the numbers."
- "Save the stage floor as a material so I can reuse it."
7. Safety
- Destructive tools ask first.
delete_worldandremove_entityrefuse to run without an explicit confirmation, so the agent has to check with you before removing anything. - The agent acts as you. It uses your signed-in session with exactly your permissions. In
a world where your role is below
editor, the building tools are not offered at all. - Other people's text is data. World, entity, asset and material names and script code can be written by other people. Tools that return them are marked so agents treat the content as data, not as instructions.
- Nothing runs outside the page. The tools live in the browser tab. Close the world and they are gone.
- Changes are live and saved. Edits apply to the running scene and persist. Treat an agent editing a published world the way you would treat editing it yourself, and consider duplicating a live world before a large rebuild.
8. Troubleshooting
| Symptom | Cause and fix |
|---|---|
| No tools at all | Check that chrome://flags/#enable-webmcp-testing is enabled and Chrome was restarted, that chrome-devtools-mcp runs with --categoryExperimentalWebmcp, and that the page has finished loading. Then reload. |
| The agent can't connect to Chrome | Turn on remote debugging at chrome://inspect/#remote-debugging (Chrome 144+), or use --browserUrl with a separately started Chrome. Restart your MCP client afterwards. |
| Only 6 tools | You are on the lobby or landing page. Ask the agent to switch_world, or open a world yourself. |
| Only 7 tools inside a world | Your role in this world is below editor. get_session_status shows isWorldAdmin: false. |
| Screenshots are blurred, or other people don't see changes | The welcome screen is still open. Ask the agent to call enter_world. |
| The agent can't see its screenshots | Its client shows tool output as text. Ask it to use delivery: "overlay" and take a browser screenshot, or delivery: "download". |
Nothing appears after create_and_attach_script | Ask for a screenshot and get_script_diagnostics. The script compiled but may throw at runtime, or place geometry outside the room or at the wrong scale. |
| Surfaces flicker as you move | That is z-fighting. Ask the agent to run check_z_fighting and fix the overlapping surfaces it reports. |
create_world fails on a free account | Free accounts can have 3 worlds. Delete one or upgrade your plan. |
| A change vanished after reload | It was probably made by changing the page directly instead of through a tool. Ask the agent to re-list entities. If a tool change does not persist, report the world hashid to support. |