@graphty/babylonjs-inspector-mcp
An MCP server that lets an LLM inspect and interact with a live BabylonJS scene over WebSocket, providing scene data, screenshots, WebGL capture, JavaScript evaluation, and optional Gemini vision analysis.
Check connection state and available tool categories with
babylonjs_connection_status.Inspect the scene with
babylonjs_scene_inspect: summary, full scene graph, or specific categories like meshes, materials, cameras, lights, animations, textures, physics, post-processing, performance, scene tree, and WebGL errors; supports name glob filters and detail targets.Run arbitrary JavaScript against the scene with
babylonjs_scene_evaluate, receiving(scene, engine, BABYLON)and returning JSON-serialized results.Capture screenshots with
babylonjs_screenshot: multiple preset views, custom camera, configurable size/format, returning saved file paths.Capture WebGL frame data with
babylonjs_spector_capture: draw calls, shader source, WebGL state, and texture bindings at summary, shaders, or full detail.Ask Gemini vision questions about the rendered scene with
babylonjs_scene_analyze(only registered whenGEMINI_API_KEYis set).
Current-implementation caveat: the browser-side client is still a stub, so only babylonjs_connection_status returns real data today; all browser-dependent tools currently report "No BabylonJS scene connected" until the browser client lands.
Provides WebGL introspection of a running BabylonJS scene via Spector.js frame captures, exposing draw calls, shader source, WebGL state, and texture bindings.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@graphty/babylonjs-inspector-mcp Take a screenshot of the current scene and check if the lighting looks correct."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
babylonjs-inspector-mcp
An MCP (Model Context Protocol) server that lets an LLM inspect a running BabylonJS 3D scene.
Status: early development (0.x). The MCP server, the tool surface, the WebSocket protocol and the HTTP server are implemented. The browser-side client that actually talks to your BabylonJS scene is still a stub, so today the tools connect and validate but return "no scene connected" until that lands. Read Implementation status for the exact breakdown before you install this.
The problem
When an LLM writes BabylonJS code -- shaders, geometry, materials, lighting, animations, post-processing -- it has no way to check the result. It cannot:
See what the scene looks like, from any angle
Tell whether two objects are actually where it intended them to be
Read back shader compilation results or WebGL state
Confirm that a material or light produces the effect it was asked for
Debug a rendering artifact it cannot observe
The LLM writes code, the human looks at the screen, and the human becomes the LLM's eyes.
Related MCP server: threejs-devtools-mcp
The solution
An MCP server that gives the LLM three kinds of access to a live scene:
Scene data -- structured JSON from BabylonJS: scene graph, meshes, materials, cameras, lights, animations, textures, physics, post-processing, performance counters.
WebGL introspection -- Spector.js frame captures: draw calls, shader source, WebGL state, texture bindings.
VLM scene understanding -- Gemini vision analysis of screenshots, depth maps and multi-view renders, combined with scene metadata (bring your own API key).
Plus a scene_evaluate escape hatch that runs arbitrary JavaScript against the scene, in the
spirit of Playwright's browser_evaluate.
Architecture
The server is a Node.js process started by your MCP host. It speaks MCP over stdio to the host and WebSocket to your browser. It does not embed a browser; your app connects to it.
+---------------------------+
| MCP client | Claude Code, Claude Desktop, or any MCP host
+---------------------------+
^
| stdio (JSON-RPC) -- MCP tool calls and results
v
+---------------------------+
| babylonjs-inspector-mcp | Node.js process spawned by the MCP host
| | - registers the MCP tools
| | - BrowserBridge: correlates requests by UUID
| | - HTTP + WebSocket server on port 9070
+---------------------------+
^
| WebSocket (ws://localhost:9070) -- commands and responses
v
+---------------------------+
| Browser | your Vite dev server, or any page
| inspector client | - discovers the BabylonJS engine
| + your BabylonJS scene | - runs commands against the live scene
+---------------------------+A tool call travels the whole chain: the host calls babylonjs_scene_inspect, the server
dispatches it to the BrowserBridge, the bridge sends a WebSocket command tagged with a UUID,
the browser client executes it against the scene, and the response comes back up the chain.
Only one browser connection is tracked at a time. Every operation has a timeout tier:
Operation | Timeout |
Scene query / inspect | 5s |
Screenshot capture | 15s |
Spector.js frame capture | 30s |
Scene evaluate | 30s |
Multi-view capture | 45s |
Scene export | 60s |
Requirements
Node.js >= 20
A BabylonJS application you can run locally
Optionally, a Gemini API key for the VLM analysis tool
Installation
npx -y babylonjs-inspector-mcp # run on demand
npm install -g babylonjs-inspector-mcp # binary on your PATH
npm install --save-dev babylonjs-inspector-mcp # Vite plugin / browser clientTo work from a checkout instead:
git clone https://github.com/apowers313/babylonjs-inspector-mcp.git
cd babylonjs-inspector-mcp
npm install
npm run buildThat produces dist/, which bin/babylonjs-inspector-mcp.js needs in order to run.
MCP client configuration
Add the server to your MCP settings, pointing at your local build. For Claude Code:
claude mcp add babylonjs-inspector -- node /path/to/babylonjs-inspector-mcp/bin/babylonjs-inspector-mcp.jsOr configure it by hand -- this is the JSON block for
claude_desktop_config.json, .mcp.json, or your host's equivalent:
{
"mcpServers": {
"babylonjs-inspector": {
"command": "node",
"args": ["/path/to/babylonjs-inspector-mcp/bin/babylonjs-inspector-mcp.js"],
"env": {
"BABYLONJS_INSPECTOR_PORT": "9070",
"GEMINI_API_KEY": "your-key-here"
}
}
}
}After the package is published, "command": "npx" with
"args": ["-y", "babylonjs-inspector-mcp"] replaces those two lines, and a global
install lets you use "command": "babylonjs-inspector-mcp" with no args. Use npx -y so
that npx's install prompt can never end up on the stdio channel the MCP protocol is using.
GEMINI_API_KEY is optional. When it is absent, the babylonjs_scene_analyze tool is not
registered at all, so it never shows up in the LLM's tool list. When it is present, the tool
appears. Everything else works without it.
Browser-side setup
The server needs your BabylonJS page to connect back to it over WebSocket. There are two supported ways to make that happen.
Vite plugin (zero instrumentation)
Add the plugin to your app's vite.config.ts. It only applies in dev mode (apply: "serve"),
so production builds are untouched, and it needs no changes to your application code.
import { defineConfig } from "vite";
import { babylonjsInspector } from "babylonjs-inspector-mcp/vite";
export default defineConfig({
plugins: [
babylonjsInspector({
port: 9070, // must match BABYLONJS_INSPECTOR_PORT; default 9070
autoConnect: true, // connect on page load; default true
}),
],
});The plugin appends a <script type="module"> tag to your HTML that imports the inspector
client from http://localhost:<port>/inspector-client.js, which the MCP server serves, and
assigns the instance to window.__babylonjsInspector.
Manual import
If you are not on Vite, or you want explicit control over when the inspector attaches:
import { InspectorClient } from "babylonjs-inspector-mcp/client";
const inspector = new InspectorClient({
port: 9070, // default 9070
autoDiscover: true, // find the BabylonJS engine automatically; default true
scene: myScene, // optional: pass the scene explicitly instead
});Both paths are wired up but not yet functional -- see below.
MCP tools
Six tools are registered. Five are always present; babylonjs_scene_analyze is registered
only when GEMINI_API_KEY is set.
Tool | Returns | Needs a live browser connection |
| Connection state, engine type, canvas size, and which tool categories are currently usable | No |
| Scene data for one of 15 categories, from a counts-only summary to a full scene graph | Yes |
| The JSON-serialized return value of a JavaScript function run against the scene | Yes |
| A map of view name to saved image file path | Yes, and the engine must be able to render |
| Spector.js WebGL frame data: draw calls, shader source, GL state | Yes, plus WebGL and Spector.js in the page |
| A Gemini vision answer to a question about the rendered scene | Yes, rendering capable, plus |
Every browser-dependent tool degrades to a plain JSON { "error": "..." } message rather than
throwing, so the LLM gets a readable reason instead of a protocol failure.
babylonjs_connection_status
No parameters. Returns connected, engineType, canRender, hasSpector, canvasSize, and
an availableTools object reporting which of sceneInspect, sceneEvaluate, screenshot,
spectorCapture and sceneAnalyze are usable right now. Every entry is false while no
browser is attached, because every one of those tools answers "No BabylonJS scene connected"
in that state. Call this first when a tool reports that nothing is connected.
babylonjs_scene_inspect
Parameter | Type | Default | Description |
| enum |
| What to inspect |
| string | -- | Name or ID of a specific mesh/material/light/texture, for the |
| string | -- | Glob pattern matched against names, e.g. |
category accepts: summary, full, meshes, mesh_detail, materials,
material_detail, cameras, lights, animations, textures, physics,
post_processing, performance, scene_tree, webgl_errors.
summary and full return an overview of the whole scene; every other category drills into
one aspect. This is deliberately one parameterized tool rather than fifteen separate ones, to
keep the host's tool list short and the LLM's choice simple.
babylonjs_scene_evaluate
Parameter | Type | Default | Description |
| string | required | A JavaScript function body receiving |
Example argument:
(scene) => scene.meshes.map((m) => ({ name: m.name, pos: m.position.asArray() }))The return value is serialized to JSON. This is a development tool with no sandbox -- the code runs with full access to the page.
babylonjs_screenshot
Parameter | Type | Default | Description |
| array of enum |
| Which views to capture |
| object | -- |
|
| number |
| Image width in pixels |
| number |
| Image height in pixels |
|
|
| Image format |
views accepts: current, front, top, side, isometric, depth, wireframe,
annotated. customCamera.projection is perspective or orthographic.
Images are written to disk and the tool returns file paths, not base64, so a multi-view capture does not flood the context window.
babylonjs_spector_capture
Parameter | Type | Default | Description |
|
|
| How much of the capture to return |
| boolean |
| Skip per-draw-call thumbnails for a faster capture |
summary returns counts and timings, shaders adds deduplicated shader source, full adds
per-draw-call WebGL state.
babylonjs_scene_analyze
Registered only when GEMINI_API_KEY is set.
Parameter | Type | Default | Description |
| string | required | A specific question about the rendered scene |
| array of enum |
| Which renders to send to the model |
| boolean |
| Send structured scene data alongside the images |
|
|
| 512, 1024 or 2048 pixels |
views accepts: current, front, top, side, isometric, depth, annotated.
Good questions are concrete: "Are the shadows rendering correctly?", "Is the sphere positioned above the plane?", "Does the PBR material look metallic?"
Configuration
All configuration is by environment variable, read once at startup.
Variable | Default | Description |
|
| Port for the HTTP + WebSocket server. Must be 1-65535 or startup fails with an explicit error. |
|
| Interface the server binds to. Loopback by default so the bridge is not reachable from other machines. Must be non-empty. |
| (none) | Comma-separated list of extra browser origins allowed to open a WebSocket. Loopback origins are always allowed. |
| (none) | Gemini API key. When unset, |
|
| Directory for screenshot output. Read with a default applied, but not validated and not yet consumed by any code path. |
|
| One of |
An invalid BABYLONJS_INSPECTOR_PORT, BABYLONJS_INSPECTOR_HOST or
BABYLONJS_INSPECTOR_LOG_LEVEL throws at startup rather than silently falling back to the
default.
Security
The inspector exists to run code you asked for inside your own page, which means anything
that can reach the bridge can run babylonjs_scene_evaluate against your scene and feed the
answer to your LLM. Two defaults keep that surface small:
Loopback only. The HTTP + WebSocket server binds
127.0.0.1. Nothing else on your network can reach it unless you setBABYLONJS_INSPECTOR_HOSTyourself.Origin-checked WebSocket upgrades. WebSockets are exempt from CORS, so the server checks the
Originheader on the upgrade itself. Origins onlocalhost,127.0.0.1or[::1](any port, any scheme) are accepted; every other origin is rejected with a 403 unless you list it inBABYLONJS_INSPECTOR_ALLOWED_ORIGINS. Requests that send noOriginat all -- curl, a native client -- are accepted, because they can only arrive over the bound interface.
The HTTP routes echo Access-Control-Allow-Origin only for an origin that passes the same
check; there is no wildcard CORS. If a second browser connects, the previously attached
socket is closed rather than silently displaced.
HTTP endpoints
Alongside the WebSocket upgrade handler, the server exposes:
Endpoint | Purpose |
| Returns |
| Serves the browser client bundle, with CORS headers echoed back to any origin that passes the WebSocket origin check, so a local dev server can load it. Currently a stub. |
Implementation status
The package is built in phases. This is what actually runs today, verified against the source rather than the design document.
Working:
MCP server over stdio, with all six tools registered and their input schemas validated by zod
Conditional registration of
babylonjs_scene_analyzebased onGEMINI_API_KEYHTTP + WebSocket server,
/healthendpoint, WebSocket upgrade handling, clean shutdown on SIGINT and SIGTERMThe WebSocket wire protocol: command/response/event/ping/pong message types, strict parsing that rejects malformed messages, UUID request correlation, per-operation timeout tiers, and rejection of all pending requests when the socket closes
Configuration loading and validation from the environment
Graceful, readable error responses from every tool when the precondition it needs is missing
Not yet working:
The browser client is a stub.
InspectorClientstores its options and does nothing else; it does not open a WebSocket, discover a BabylonJS engine, or register command handlers.GET /inspector-client.jsserves a placeholder comment, not a bundle. The Vite plugin injects a script that importsInspectorClientfrom that URL, so the injection wiring is in place but the import has nothing to resolve.Consequently every browser-dependent tool --
scene_inspect,scene_evaluate,screenshot,spector_capture,scene_analyze-- returns "No BabylonJS scene connected" in practice.babylonjs_connection_statusis the only tool that returns real data today.Spector.js is not integrated. There is no browser-side capture code, so
hasSpectoris never set true.Gemini analysis is not implemented.
GeminiClient.analyzeScenerejects, and thebabylonjs_scene_analyzehandler returns an explicit "not yet implemented" message even with a valid API key and a connected browser.Screenshots, depth maps, wireframe and annotated views have no capture implementation.
NullEngine (in-process, headless) runtime is designed for by the
BabylonJSRuntimeinterface but has no implementation;BrowserBridgeis the only runtime.BABYLONJS_INSPECTOR_SCREENSHOT_DIRandBABYLONJS_INSPECTOR_LOG_LEVELare read but unused.BABYLONJS_INSPECTOR_SCREENSHOT_DIRis not validated either -- any string, empty included, is accepted.Nothing is published to npm yet, so every
npxandnpm installroute 404s. Build from a checkout.
In short: the server half of the system is real, the browser half is scaffolding. Install this if you want to follow along or contribute; it is not yet useful for debugging a scene.
Development
npm install # install dependencies
npm run build # compile TypeScript to dist/
npm run build:watch # compile in watch mode
npm test # run tests in watch mode
npm run test:run # run tests once
npm run coverage # run tests with a coverage report
npm run lint # eslint plus a type check
npm run lint:fix # auto-fix what eslint can
npm run typecheck # tsc --noEmit only
npm run clean # remove dist/ and coverage/Coverage thresholds are 80% lines, 80% functions, 80% statements and 75% branches, and they
are enforced: npm run coverage exits non-zero below any of them, and CI gates the release
on that job. The suite currently sits around 96%.
Contributing
See CONTRIBUTING.md.
License
MIT -- see LICENSE.
Available Tools
5 toolsbabylonjs_connection_statusA
Check the current connection state of the BabylonJS inspector. Returns whether a browser is connected, the engine type, rendering capabilities, and which tool categories are available.
Inputs: no named parameters.
babylonjs_scene_evaluateA
Execute a JavaScript function against the BabylonJS scene. The function receives (scene, engine, BABYLON) as arguments. Return values are serialized to JSON. Use this for custom queries or operations not covered by other tools.
Inputs: function (required).
babylonjs_scene_inspectA
Inspect the BabylonJS scene. Use 'summary' for an overview, 'full' for complete scene graph, or drill into specific categories: meshes, mesh_detail, materials, material_detail, cameras, lights, animations, textures, physics, post_processing, performance, scene_tree, webgl_errors. Use 'target' for specific items and 'filter' for glob-based name filtering.
Inputs: filter, target, category.
babylonjs_screenshotA
Capture one or more screenshots of the BabylonJS scene. Supports multiple preset camera angles, depth maps, and custom camera positions. Screenshots are saved to the tmp/ directory and file paths are returned. Only available when a browser with rendering is connected.
Inputs: views, width, format, height, +1 more.
babylonjs_spector_captureA
Capture a WebGL frame using Spector.js for low-level rendering inspection. Returns draw call count, shader source code, WebGL state, texture bindings, and performance data. Only available when a browser with WebGL is connected.
Inputs: detailLevel, quickCapture.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 5 tools
Each tool has a distinct primary purpose: status, inspection, evaluation, screenshots, and WebGL capture. scene_inspect and scene_evaluate have some potential overlap since both query the scene, but the descriptions clearly separate structured inspection from custom JavaScript execution.
All tools share the babylonjs_ prefix, and most follow a scene/domain + action pattern, such as scene_inspect and scene_evaluate. However, babylonjs_screenshot and babylonjs_connection_status break the verb-noun pattern slightly, making the naming mostly but not fully consistent.
Five tools is a well-scoped set for an inspector-focused MCP server. Each tool covers a major capability area without unnecessary redundancy, and the count feels appropriate for the server's purpose.
The tool surface covers connection status, scene inspection, custom evaluation, screenshots, and low-level WebGL capture, which covers the core inspection workflow. Direct mutation tools are absent, but babylonjs_scene_evaluate provides a flexible escape hatch, so major workflows are not blocked.
Maintenance
Related MCP Connectors
See the rendered web: design tokens, fonts, animation timings, WebGL shaders and 3D from any URL.
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
Build and inspect browser-based 3D games: projects, scenes, Lua scripts, assets and publishing.
Blender-as-a-service for agents: search 3D assets, run Blender Python, or brief the studio agent.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to inspect and modify Three.js scenes live in the browser—objects, materials, shaders, textures, animation, lights and performance—then turn those previewed changes into code. Also supports website audits, video frame capture with Playwright and Puppeteer.5,202 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to inspect a running Three.js or React Three Fiber scene in the browser, preview material, shader, light and camera edits live, and turn approved changes into ready-to-paste source code. Also supports website performance audits, video frame capture, and Playwright/Puppeteer test hooks.5,202 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to inspect and modify live Three.js or React Three Fiber scenes in the browser and turn those live previews into ready-to-paste code. Also supports website performance audits, frame capture for video, and Playwright/Puppeteer test helpers.5,202 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to inspect Three.js scenes in real time, experiment with live previews of changes to materials, shaders, lights and cameras, and convert those changes into ready-to-paste vanilla Three.js or React Three Fiber code. Also supports website performance audits, video frame capture, and Playwright helpers with zero project changes.5,202 npmMIT