Loading...
Loading...
MCP server for real-time Three.js scene inspection, material editing, shader debugging, and performance monitoring from AI agents
npx skill4agent add aradotso/devtools-skills threejs-devtools-mcpSkill by ara.so — Devtools Skills collection.
claude mcp add threejs-devtools-mcp -- npx threejs-devtools-mcpclaude_desktop_config.json{
"mcpServers": {
"threejs-devtools-mcp": {
"command": "npx",
"args": ["-y", "threejs-devtools-mcp"]
}
}
}.cursor/mcp.json{
"mcpServers": {
"threejs-devtools-mcp": {
"command": "npx",
"args": ["-y", "threejs-devtools-mcp"]
}
}
}~/.codeium/windsurf/mcp_config.json{
"mcpServers": {
"threejs-devtools-mcp": {
"command": "npx",
"args": ["-y", "threejs-devtools-mcp"]
}
}
}.vscode/mcp.json{
"servers": {
"threejs-devtools-mcp": {
"command": "npx",
"args": ["-y", "threejs-devtools-mcp"]
}
}
}npm run devlocalhost:9222get_scene_treeget_object_detailsfind_objectsget_camerasget_lightsget_materialsupdate_materialget_shadersupdate_shaderget_texturesupdate_object_transformtoggle_object_visibilityget_object_boundsclone_objectget_performance_statsstart_performance_monitoringget_memory_infoget_render_infoget_animationsplay_animationpause_animationget_animation_stategenerate_react_componentgenerate_material_codeexport_scenetoggle_overlaycheck_common_issuesget_object_world_position// User: "My model isn't showing up"
// 1. Get scene tree to find objects
await use_mcp_tool("threejs-devtools-mcp", "get_scene_tree", {});
// 2. Check common issues
await use_mcp_tool("threejs-devtools-mcp", "check_common_issues", {});
// 3. If object found but invisible, get details
await use_mcp_tool("threejs-devtools-mcp", "get_object_details", {
objectPath: "Scene/MyModel"
});
// 4. Check if it's visible and has material
// If not visible:
await use_mcp_tool("threejs-devtools-mcp", "toggle_object_visibility", {
objectPath: "Scene/MyModel",
visible: true
});
// 5. Check if it's inside camera frustum
await use_mcp_tool("threejs-devtools-mcp", "get_object_world_position", {
objectPath: "Scene/MyModel"
});// User: "Make the car red and metallic"
// 1. Find the car object
await use_mcp_tool("threejs-devtools-mcp", "find_objects", {
name: "car"
});
// 2. Update material
await use_mcp_tool("threejs-devtools-mcp", "update_material", {
materialPath: "Scene/Car/Body/material",
properties: {
color: "#ff0000",
metalness: 0.8,
roughness: 0.2
}
});// User: "Why is my scene laggy?"
// 1. Get current performance stats
await use_mcp_tool("threejs-devtools-mcp", "get_performance_stats", {});
// 2. Check render info for draw call count
await use_mcp_tool("threejs-devtools-mcp", "get_render_info", {});
// 3. Check memory usage
await use_mcp_tool("threejs-devtools-mcp", "get_memory_info", {});
// 4. Start continuous monitoring
await use_mcp_tool("threejs-devtools-mcp", "start_performance_monitoring", {
duration: 10,
interval: 1
});
// Identify issues:
// - High draw calls → merge geometries
// - High triangle count → use LOD
// - Memory growth → check for leaks, dispose unused resources// User: "My custom shader isn't working"
// 1. List all shaders
await use_mcp_tool("threejs-devtools-mcp", "get_shaders", {});
// 2. Get shader source
// (shader details included in get_shaders response)
// 3. Update shader with fixes
await use_mcp_tool("threejs-devtools-mcp", "update_shader", {
shaderPath: "Scene/CustomMesh/material",
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float time;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv, sin(time), 1.0);
}
`,
uniforms: {
time: { value: 0.0 }
}
});// User: "Create a React component from my GLTF model"
await use_mcp_tool("threejs-devtools-mcp", "generate_react_component", {
modelPath: "/models/character.glb",
componentName: "Character",
includeAnimations: true,
includeLights: false
});
// Returns JSX code ready to use:
/*
import { useGLTF, useAnimations } from '@react-three/drei'
import { useRef, useEffect } from 'react'
export function Character(props) {
const group = useRef()
const { nodes, materials, animations } = useGLTF('/models/character.glb')
const { actions } = useAnimations(animations, group)
useEffect(() => {
actions['Idle']?.play()
}, [actions])
return (
<group ref={group} {...props} dispose={null}>
<mesh geometry={nodes.Body.geometry} material={materials.Skin} />
</group>
)
}
*/SceneScene/PlayerScene/Group/MeshScene/Car/(unnamed)/Wheel// Three.js
mesh.name = "player";
// React Three Fiber
<mesh name="player" />update_material{
color: "#ff0000", // hex color
opacity: 0.5, // 0-1
transparent: true, // boolean
metalness: 0.8, // 0-1 (MeshStandardMaterial)
roughness: 0.2, // 0-1 (MeshStandardMaterial)
emissive: "#00ff00", // hex color
emissiveIntensity: 0.5, // 0-1
wireframe: true, // boolean
side: "DoubleSide", // "FrontSide" | "BackSide" | "DoubleSide"
visible: true // boolean
}// Play animation
await use_mcp_tool("threejs-devtools-mcp", "play_animation", {
clipName: "Walk",
loop: true,
timeScale: 1.0
});
// Pause
await use_mcp_tool("threejs-devtools-mcp", "pause_animation", {
clipName: "Walk"
});
// Check state
await use_mcp_tool("threejs-devtools-mcp", "get_animation_state", {});threejs-devtools.config.json{
"port": 5173,
"chromePath": "/usr/bin/google-chrome",
"debugPort": 9222,
"autoOpenOverlay": true,
"performanceThresholds": {
"fps": 30,
"frameTime": 33,
"drawCalls": 100
}
}THREEJS_DEVTOOLS_PORTTHREEJS_DEVTOOLS_CHROME_PATHTHREEJS_DEVTOOLS_DEBUG_PORTtoggle_overlayTHREEJS_DEVTOOLS_PORT=3000 npx threejs-devtools-mcpget_scene_tree(unnamed)transparent: trueget_memory_infofind_objectsget_scene_treecheck_common_issuesrefimport { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
function Box() {
const ref = useRef()
useFrame((state, delta) => {
ref.current.rotation.x += delta
})
return (
<mesh ref={ref} name="rotating-box">
<boxGeometry />
<meshStandardMaterial color="orange" />
</mesh>
)
}// "Stop the box rotation"
await use_mcp_tool("threejs-devtools-mcp", "get_object_details", {
objectPath: "Scene/rotating-box"
});
// Developer removes useFrame hook based on AI suggestion{
"mcpServers": {
"threejs-devtools-mcp": {
"command": "npx",
"args": ["-y", "threejs-devtools-mcp", "--transport", "http"]
}
}
}http://localhost:3000THREEJS_DEVTOOLS_HTTP_PORT// User: "My 3D character model loads but is invisible and the scene is slow"
// 1. Check scene structure
const sceneTree = await use_mcp_tool("threejs-devtools-mcp", "get_scene_tree", {});
// Found: Scene/Character with multiple children
// 2. Check common issues
const issues = await use_mcp_tool("threejs-devtools-mcp", "check_common_issues", {});
// Found: Character has scale (0,0,0)
// 3. Fix scale
await use_mcp_tool("threejs-devtools-mcp", "update_object_transform", {
objectPath: "Scene/Character",
scale: { x: 1, y: 1, z: 1 }
});
// 4. Check performance
const perf = await use_mcp_tool("threejs-devtools-mcp", "get_performance_stats", {});
// FPS: 15, Draw calls: 450
// 5. Get render info to understand why
const renderInfo = await use_mcp_tool("threejs-devtools-mcp", "get_render_info", {});
// 450 draw calls → character has 450 separate meshes
// Suggestion: Merge geometries or use instancing
// Character now visible, identified performance bottleneck