sceneview-mcp 3.0.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { getSample, SAMPLE_IDS, SAMPLES } from "./samples.js";
9
9
  import { validateCode, formatValidationReport } from "./validator.js";
10
10
  import { MIGRATION_GUIDE } from "./migration.js";
11
11
  import { fetchKnownIssues } from "./issues.js";
12
+ import { parseNodeSections, findNodeSection, listNodeTypes } from "./node-reference.js";
12
13
  const __dirname = dirname(fileURLToPath(import.meta.url));
13
14
  let API_DOCS;
14
15
  try {
@@ -17,14 +18,15 @@ try {
17
18
  catch {
18
19
  API_DOCS = "SceneView API docs not found. Run `npm run prepare` to bundle llms.txt.";
19
20
  }
20
- const server = new Server({ name: "@sceneview/mcp", version: "3.0.2" }, { capabilities: { resources: {}, tools: {} } });
21
+ const NODE_SECTIONS = parseNodeSections(API_DOCS);
22
+ const server = new Server({ name: "@sceneview/mcp", version: "3.2.0" }, { capabilities: { resources: {}, tools: {} } });
21
23
  // ─── Resources ───────────────────────────────────────────────────────────────
22
24
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
23
25
  resources: [
24
26
  {
25
27
  uri: "sceneview://api",
26
28
  name: "SceneView API Reference",
27
- description: "Complete SceneView 3.0.0 API — Scene, ARScene, SceneScope DSL, ARSceneScope DSL, node types, resource loading, camera, gestures, math types, threading rules, and common patterns. Read this before writing any SceneView code.",
29
+ description: "Complete SceneView 3.1.1 API — Scene, ARScene, SceneScope DSL, ARSceneScope DSL, node types, resource loading, camera, gestures, math types, threading rules, and common patterns. Read this before writing any SceneView code.",
28
30
  mimeType: "text/markdown",
29
31
  },
30
32
  {
@@ -121,6 +123,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
121
123
  required: [],
122
124
  },
123
125
  },
126
+ {
127
+ name: "get_node_reference",
128
+ description: "Returns the full API reference for a specific SceneView node type or composable — parameters, types, and a usage example — parsed directly from the official llms.txt. Use this when you need the exact signature or options for a node (e.g. ModelNode, LightNode, ARScene). If the requested type is not found, the response lists all available types.",
129
+ inputSchema: {
130
+ type: "object",
131
+ properties: {
132
+ nodeType: {
133
+ type: "string",
134
+ description: 'The node type or composable name to look up, e.g. "ModelNode", "LightNode", "ARScene", "AnchorNode". Case-insensitive.',
135
+ },
136
+ },
137
+ required: ["nodeType"],
138
+ },
139
+ },
124
140
  ],
125
141
  }));
126
142
  // ─── Tool handlers ────────────────────────────────────────────────────────────
@@ -203,7 +219,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
203
219
  `### build.gradle.kts`,
204
220
  `\`\`\`kotlin`,
205
221
  `dependencies {`,
206
- ` implementation("io.github.sceneview:sceneview:3.0.0")`,
222
+ ` implementation("io.github.sceneview:sceneview:3.1.1")`,
207
223
  `}`,
208
224
  `\`\`\``,
209
225
  ``,
@@ -224,7 +240,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
224
240
  `### build.gradle.kts`,
225
241
  `\`\`\`kotlin`,
226
242
  `dependencies {`,
227
- ` implementation("io.github.sceneview:arsceneview:3.0.0")`,
243
+ ` implementation("io.github.sceneview:arsceneview:3.1.1")`,
228
244
  `}`,
229
245
  `\`\`\``,
230
246
  ``,
@@ -263,6 +279,45 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
263
279
  case "get_migration_guide": {
264
280
  return { content: [{ type: "text", text: MIGRATION_GUIDE }] };
265
281
  }
282
+ // ── get_node_reference ────────────────────────────────────────────────────
283
+ case "get_node_reference": {
284
+ const nodeType = request.params.arguments?.nodeType;
285
+ if (!nodeType || typeof nodeType !== "string") {
286
+ return {
287
+ content: [{ type: "text", text: "Missing required parameter: `nodeType`" }],
288
+ isError: true,
289
+ };
290
+ }
291
+ const section = findNodeSection(NODE_SECTIONS, nodeType);
292
+ if (!section) {
293
+ const available = listNodeTypes(NODE_SECTIONS).join(", ");
294
+ return {
295
+ content: [
296
+ {
297
+ type: "text",
298
+ text: [
299
+ `No reference found for node type \`${nodeType}\`.`,
300
+ ``,
301
+ `**Available node types:**`,
302
+ available,
303
+ ].join("\n"),
304
+ },
305
+ ],
306
+ };
307
+ }
308
+ return {
309
+ content: [
310
+ {
311
+ type: "text",
312
+ text: [
313
+ `## \`${section.name}\` — API Reference`,
314
+ ``,
315
+ section.content,
316
+ ].join("\n"),
317
+ },
318
+ ],
319
+ };
320
+ }
266
321
  default:
267
322
  return {
268
323
  content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
package/dist/migration.js CHANGED
@@ -8,8 +8,8 @@ SceneView 3.0 is a full rewrite from Android Views to **Jetpack Compose**. Nearl
8
8
 
9
9
  | 2.x | 3.0 |
10
10
  |-----|-----|
11
- | \`io.github.sceneview:sceneview:2.x.x\` | \`io.github.sceneview:sceneview:3.0.0\` |
12
- | \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.0.0\` |
11
+ | \`io.github.sceneview:sceneview:2.x.x\` | \`io.github.sceneview:sceneview:3.1.1\` |
12
+ | \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.1.1\` |
13
13
 
14
14
  ---
15
15
 
@@ -0,0 +1,73 @@
1
+ /**
2
+ * node-reference.ts
3
+ *
4
+ * Parses llms.txt to extract per-node-type API reference sections.
5
+ * Each section starts at a `###` heading and ends just before the next `###` or `##` heading.
6
+ */
7
+ // ─── Parsing ─────────────────────────────────────────────────────────────────
8
+ /**
9
+ * Extract the bare node-type name from a `###` heading line.
10
+ * Examples:
11
+ * "Scene — 3D viewport" → "Scene"
12
+ * "HitResultNode — surface cursor" → "HitResultNode"
13
+ * "Primitive geometry nodes" → "Primitive geometry nodes"
14
+ */
15
+ function headingToName(heading) {
16
+ return heading.split(/\s*[—–-]\s*/)[0].trim();
17
+ }
18
+ /**
19
+ * Parse all `###`-level sections from the full llms.txt content.
20
+ * Returns a map keyed by the bare node-type name (case-insensitive lookup
21
+ * handled separately).
22
+ */
23
+ export function parseNodeSections(llmsTxt) {
24
+ const sections = new Map();
25
+ const lines = llmsTxt.split("\n");
26
+ let i = 0;
27
+ while (i < lines.length) {
28
+ const line = lines[i];
29
+ if (line.startsWith("### ")) {
30
+ const headingText = line.slice(4).trim(); // text after "### "
31
+ const name = headingToName(headingText);
32
+ // Collect lines until the next `##` or `###` heading
33
+ const bodyLines = [line];
34
+ i++;
35
+ while (i < lines.length && !lines[i].startsWith("## ") && !lines[i].startsWith("### ")) {
36
+ bodyLines.push(lines[i]);
37
+ i++;
38
+ }
39
+ // Trim trailing blank lines
40
+ while (bodyLines.length > 1 && bodyLines[bodyLines.length - 1].trim() === "") {
41
+ bodyLines.pop();
42
+ }
43
+ sections.set(name.toLowerCase(), {
44
+ name,
45
+ heading: headingText,
46
+ content: bodyLines.join("\n"),
47
+ });
48
+ }
49
+ else {
50
+ i++;
51
+ }
52
+ }
53
+ return sections;
54
+ }
55
+ // ─── Public API ──────────────────────────────────────────────────────────────
56
+ /**
57
+ * Look up a node type section by name (case-insensitive).
58
+ *
59
+ * @param sections - The map returned by `parseNodeSections`
60
+ * @param nodeType - User-supplied name, e.g. "ModelNode", "lightnode", "ARScene"
61
+ * @returns The matching `NodeSection`, or `undefined` if not found.
62
+ */
63
+ export function findNodeSection(sections, nodeType) {
64
+ return sections.get(nodeType.toLowerCase());
65
+ }
66
+ /**
67
+ * Returns a sorted array of all known node-type names.
68
+ */
69
+ export function listNodeTypes(sections) {
70
+ return Array.from(sections.values())
71
+ .map((s) => s.name)
72
+ .sort();
73
+ }
package/dist/samples.js CHANGED
@@ -4,8 +4,8 @@ export const SAMPLES = {
4
4
  title: "3D Model Viewer",
5
5
  description: "Full-screen 3D scene with a GLB model, HDR environment, and orbit camera",
6
6
  tags: ["3d", "model", "environment", "camera"],
7
- dependency: "io.github.sceneview:sceneview:3.0.0",
8
- prompt: "Create an Android Compose screen called `ModelViewerScreen` that loads a GLB file from assets/models/my_model.glb and displays it in a full-screen 3D scene with an orbit camera (drag to rotate, pinch to zoom). Add an HDR environment from assets/environments/sky_2k.hdr for realistic lighting. Use SceneView `io.github.sceneview:sceneview:3.0.0`.",
7
+ dependency: "io.github.sceneview:sceneview:3.1.1",
8
+ prompt: "Create an Android Compose screen called `ModelViewerScreen` that loads a GLB file from assets/models/my_model.glb and displays it in a full-screen 3D scene with an orbit camera (drag to rotate, pinch to zoom). Add an HDR environment from assets/environments/sky_2k.hdr for realistic lighting. Use SceneView `io.github.sceneview:sceneview:3.1.1`.",
9
9
  code: `@Composable
10
10
  fun ModelViewerScreen() {
11
11
  val engine = rememberEngine()
@@ -38,8 +38,8 @@ fun ModelViewerScreen() {
38
38
  title: "3D Geometry Scene",
39
39
  description: "Procedural 3D scene using primitive geometry nodes (cube, sphere, plane) — no GLB required",
40
40
  tags: ["3d", "geometry", "animation"],
41
- dependency: "io.github.sceneview:sceneview:3.0.0",
42
- prompt: "Create an Android Compose screen called `GeometrySceneScreen` that renders a full-screen 3D scene with a red rotating cube, a metallic blue sphere, and a green floor plane. No model files — use SceneView built-in geometry nodes. Orbit camera. Use SceneView `io.github.sceneview:sceneview:3.0.0`.",
41
+ dependency: "io.github.sceneview:sceneview:3.1.1",
42
+ prompt: "Create an Android Compose screen called `GeometrySceneScreen` that renders a full-screen 3D scene with a red rotating cube, a metallic blue sphere, and a green floor plane. No model files — use SceneView built-in geometry nodes. Orbit camera. Use SceneView `io.github.sceneview:sceneview:3.1.1`.",
43
43
  code: `@Composable
44
44
  fun GeometrySceneScreen() {
45
45
  val engine = rememberEngine()
@@ -94,8 +94,8 @@ fun GeometrySceneScreen() {
94
94
  title: "AR Tap-to-Place",
95
95
  description: "AR scene where each tap places a GLB model on a detected surface. Placed models are pinch-to-scale and drag-to-rotate.",
96
96
  tags: ["ar", "model", "anchor", "plane-detection", "placement", "gestures"],
97
- dependency: "io.github.sceneview:arsceneview:3.0.0",
98
- prompt: "Create an Android Compose screen called `TapToPlaceScreen` that opens the camera in AR mode. Show a plane detection grid. When the user taps a detected surface, place a 3D GLB model from assets/models/chair.glb at that point. The user should be able to pinch-to-scale and drag-to-rotate after placing. Multiple taps = multiple objects. Use SceneView `io.github.sceneview:arsceneview:3.0.0`.",
97
+ dependency: "io.github.sceneview:arsceneview:3.1.1",
98
+ prompt: "Create an Android Compose screen called `TapToPlaceScreen` that opens the camera in AR mode. Show a plane detection grid. When the user taps a detected surface, place a 3D GLB model from assets/models/chair.glb at that point. The user should be able to pinch-to-scale and drag-to-rotate after placing. Multiple taps = multiple objects. Use SceneView `io.github.sceneview:arsceneview:3.1.1`.",
99
99
  code: `@Composable
100
100
  fun TapToPlaceScreen() {
101
101
  val engine = rememberEngine()
@@ -138,8 +138,8 @@ fun TapToPlaceScreen() {
138
138
  title: "AR Placement Cursor",
139
139
  description: "AR scene with a reticle that follows the surface at screen center. Tap to confirm placement.",
140
140
  tags: ["ar", "model", "anchor", "plane-detection", "placement", "camera"],
141
- dependency: "io.github.sceneview:arsceneview:3.0.0",
142
- prompt: "Create an Android Compose AR screen called `ARCursorScreen`. Show a small reticle that snaps to the nearest detected surface at the center of the screen as the user moves the camera. When the user taps, place a GLB model from assets/models/object.glb at that position and hide the reticle. Use SceneView `io.github.sceneview:arsceneview:3.0.0`.",
141
+ dependency: "io.github.sceneview:arsceneview:3.1.1",
142
+ prompt: "Create an Android Compose AR screen called `ARCursorScreen`. Show a small reticle that snaps to the nearest detected surface at the center of the screen as the user moves the camera. When the user taps, place a GLB model from assets/models/object.glb at that position and hide the reticle. Use SceneView `io.github.sceneview:arsceneview:3.1.1`.",
143
143
  code: `@Composable
144
144
  fun ARCursorScreen() {
145
145
  val engine = rememberEngine()
@@ -185,8 +185,8 @@ fun ARCursorScreen() {
185
185
  title: "AR Augmented Image",
186
186
  description: "Detects a reference image in the camera feed and overlays a 3D model above it.",
187
187
  tags: ["ar", "model", "anchor", "image-tracking"],
188
- dependency: "io.github.sceneview:arsceneview:3.0.0",
189
- prompt: "Create an Android Compose AR screen called `AugmentedImageScreen` that detects a printed reference image (from R.drawable.target_image, physical width 15 cm) and places a 3D GLB model from assets/models/overlay.glb above it, scaled to match the image width. The model should disappear when the image is lost. Use SceneView `io.github.sceneview:arsceneview:3.0.0`.",
188
+ dependency: "io.github.sceneview:arsceneview:3.1.1",
189
+ prompt: "Create an Android Compose AR screen called `AugmentedImageScreen` that detects a printed reference image (from R.drawable.target_image, physical width 15 cm) and places a 3D GLB model from assets/models/overlay.glb above it, scaled to match the image width. The model should disappear when the image is lost. Use SceneView `io.github.sceneview:arsceneview:3.1.1`.",
190
190
  code: `@Composable
191
191
  fun AugmentedImageScreen() {
192
192
  val engine = rememberEngine()
@@ -228,8 +228,8 @@ fun AugmentedImageScreen() {
228
228
  title: "AR Face Filter",
229
229
  description: "Front-camera AR that detects faces and renders a 3D mesh material over them.",
230
230
  tags: ["ar", "face-tracking", "camera"],
231
- dependency: "io.github.sceneview:arsceneview:3.0.0",
232
- prompt: "Create an Android Compose AR screen called `FaceFilterScreen` using the front camera. Detect all visible faces and apply a custom material from assets/materials/face_mask.filamat to the face mesh. Use SceneView `io.github.sceneview:arsceneview:3.0.0` with `Session.Feature.FRONT_CAMERA` and `AugmentedFaceMode.MESH3D`.",
231
+ dependency: "io.github.sceneview:arsceneview:3.1.1",
232
+ prompt: "Create an Android Compose AR screen called `FaceFilterScreen` using the front camera. Detect all visible faces and apply a custom material from assets/materials/face_mask.filamat to the face mesh. Use SceneView `io.github.sceneview:arsceneview:3.1.1` with `Session.Feature.FRONT_CAMERA` and `AugmentedFaceMode.MESH3D`.",
233
233
  code: `@Composable
234
234
  fun FaceFilterScreen() {
235
235
  val engine = rememberEngine()
package/llms.txt CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  SceneView is a Compose-first 3D and AR SDK for Android, built on Filament (Google's real-time rendering engine) and ARCore. It provides declarative composables for rendering interactive 3D scenes, loading glTF/GLB models, and building AR experiences.
4
4
 
5
- **Maven artifacts (version 3.0.0):**
6
- - 3D only: `io.github.sceneview:sceneview:3.0.0`
7
- - AR + 3D: `io.github.sceneview:arsceneview:3.0.0`
5
+ **Maven artifacts (version 3.1.1):**
6
+ - 3D only: `io.github.sceneview:sceneview:3.1.1`
7
+ - AR + 3D: `io.github.sceneview:arsceneview:3.1.1`
8
8
 
9
9
  **Min SDK:** 24 | **Target SDK:** 36 | **Kotlin:** 2.3.10 | **Compose BOM compatible**
10
10
 
@@ -15,8 +15,8 @@ SceneView is a Compose-first 3D and AR SDK for Android, built on Filament (Googl
15
15
  ### build.gradle (app module)
16
16
  ```kotlin
17
17
  dependencies {
18
- implementation("io.github.sceneview:sceneview:3.0.0") // 3D only
19
- implementation("io.github.sceneview:arsceneview:3.0.0") // AR (includes sceneview)
18
+ implementation("io.github.sceneview:sceneview:3.1.1") // 3D only
19
+ implementation("io.github.sceneview:arsceneview:3.1.1") // AR (includes sceneview)
20
20
  }
21
21
  ```
22
22
 
@@ -100,12 +100,31 @@ Scene(...) {
100
100
  position = Position(x = 0f, y = 0f, z = -2f),
101
101
  rotation = Rotation(y = 45f),
102
102
  isEditable = true,
103
- autoAnimate = true
103
+ autoAnimate = true // plays all glTF animations automatically
104
104
  )
105
105
  }
106
106
  }
107
107
  ```
108
108
 
109
+ **Reactive animation** — drive animation selection from Compose state:
110
+ ```kotlin
111
+ var isWalking by remember { mutableStateOf(false) }
112
+
113
+ Scene(...) {
114
+ instance?.let {
115
+ ModelNode(
116
+ modelInstance = it,
117
+ autoAnimate = false,
118
+ animationName = if (isWalking) "Walk" else "Idle",
119
+ animationLoop = true,
120
+ animationSpeed = 1f
121
+ )
122
+ }
123
+ }
124
+ // When animationName changes, the previous animation stops and the new one starts.
125
+ // animationName = null + autoAnimate = true plays all animations.
126
+ ```
127
+
109
128
  ### Primitive geometry nodes
110
129
  ```kotlin
111
130
  Scene(...) {
@@ -144,6 +163,28 @@ Scene(...) {
144
163
  }
145
164
  ```
146
165
 
166
+ ### VideoNode — video on a 3D plane
167
+ ```kotlin
168
+ val player = remember {
169
+ MediaPlayer().apply {
170
+ setDataSource(context, videoUri)
171
+ isLooping = true
172
+ prepare()
173
+ start()
174
+ }
175
+ }
176
+ DisposableEffect(Unit) { onDispose { player.release() } }
177
+
178
+ Scene(...) {
179
+ VideoNode(
180
+ player = player,
181
+ // size = null → auto-sized from video aspect ratio (longer edge = 1 unit)
182
+ position = Position(z = -2f)
183
+ )
184
+ }
185
+ ```
186
+ Supports `chromaKeyColor: Int?` for green-screen compositing.
187
+
147
188
  ### ViewNode — Compose UI in 3D
148
189
  ```kotlin
149
190
  val windowManager = rememberViewNodeManager()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sceneview-mcp",
3
- "version": "3.0.3",
3
+ "version": "3.2.0",
4
4
  "description": "MCP server for SceneView — 3D and AR with Jetpack Compose for Android. Give Claude the full SceneView SDK so it writes correct, compilable Kotlin.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -34,6 +34,7 @@
34
34
  "dist/index.js",
35
35
  "dist/issues.js",
36
36
  "dist/migration.js",
37
+ "dist/node-reference.js",
37
38
  "dist/samples.js",
38
39
  "dist/validator.js",
39
40
  "llms.txt"