sceneview-mcp 3.4.14 → 3.5.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/sceneview-mcp?color=6c35aa)](https://www.npmjs.com/package/sceneview-mcp)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/sceneview-mcp?color=blue)](https://www.npmjs.com/package/sceneview-mcp)
7
- [![Tests](https://img.shields.io/badge/tests-612%20passing-brightgreen)](#quality)
7
+ [![Tests](https://img.shields.io/badge/tests-858%20passing-brightgreen)](#quality)
8
8
  [![MCP](https://img.shields.io/badge/MCP-v1.12-blue)](https://modelcontextprotocol.io/)
9
9
  [![Registry](https://img.shields.io/badge/MCP%20Registry-listed-blueviolet)](https://registry.modelcontextprotocol.io)
10
10
  [![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE)
@@ -12,12 +12,24 @@
12
12
 
13
13
  The official [Model Context Protocol](https://modelcontextprotocol.io/) server for **[SceneView](https://sceneview.github.io)** -- the cross-platform 3D & AR SDK for Android (Jetpack Compose + Filament), iOS/macOS/visionOS (SwiftUI + RealityKit), and Web (Filament.js + WebXR).
14
14
 
15
- Connect it to Claude, Cursor, Windsurf, or any MCP client. The assistant gets 14 specialized tools, 33 compilable code samples, a full API reference, and a code validator -- so it writes correct, working 3D/AR code on the first try.
15
+ Connect it to Claude, Cursor, Windsurf, or any MCP client. The assistant gets 22 specialized tools, 33 compilable code samples, a full API reference, and a code validator -- so it writes correct, working 3D/AR code on the first try.
16
16
 
17
17
  > **Disclaimer:** Generated code is provided "as is" without warranty. Always review before production use. See [TERMS.md](./TERMS.md) and [PRIVACY.md](./PRIVACY.md).
18
18
 
19
19
  ---
20
20
 
21
+ ## 🚀 Pro Products
22
+
23
+ | Product | Price | Description |
24
+ |---------|-------|-------------|
25
+ | [MCP Creator Kit](https://buy.polar.sh/polar_cl_tb87ROB9Xn0c5aohdn3NvkTINDF1xjW5zpkg70UwmcF) | €29 | Everything to create your own MCP server — template, CLI, docs, examples |
26
+ | [SceneView Pro Starter Kit](https://buy.polar.sh/polar_cl_tb87ROB9Xn0c5aohdn3NvkTINDF1xjW5zpkg70UwmcF) | €49 | Complete Android 3D + AR app template — 4 screens, ready to customize |
27
+ | [SceneView MCP Pro](https://buy.polar.sh/polar_cl_tb87ROB9Xn0c5aohdn3NvkTINDF1xjW5zpkg70UwmcF) | €9.99/mo | Premium MCP tools and priority support |
28
+
29
+ ⭐ [Sponsor on GitHub](https://github.com/sponsors/sceneview) — Help us build the future of 3D/AR development
30
+
31
+ ---
32
+
21
33
  ## Quick start
22
34
 
23
35
  **One command -- no install required:**
@@ -72,7 +84,7 @@ Same JSON config as above. The server communicates via **stdio** using the stand
72
84
 
73
85
  ## What you get
74
86
 
75
- ### 18 tools
87
+ ### 22 tools
76
88
 
77
89
  | Tool | What it does |
78
90
  |---|---|
@@ -80,7 +92,7 @@ Same JSON config as above. The server communicates via **stdio** using the stand
80
92
  | `list_samples` | Browse all samples, filter by tag (`ar`, `3d`, `ios`, `animation`, `geometry`, ...) |
81
93
  | `validate_code` | Checks generated code against 15+ rules before presenting it to the user |
82
94
  | `get_node_reference` | Full API reference for any of 26+ node types -- exact signatures, defaults, examples |
83
- | `list_node_types` | List every composable node type available in SceneView |
95
+ | `list_platforms` | List all supported platforms with their status, renderer, and framework |
84
96
  | `get_setup` | Gradle + manifest setup for Android 3D or AR projects |
85
97
  | `get_ios_setup` | SPM dependency, Info.plist, and SwiftUI integration for iOS/macOS/visionOS |
86
98
  | `get_web_setup` | Kotlin/JS + Filament.js (WASM) setup for browser-based 3D |
@@ -95,6 +107,9 @@ Same JSON config as above. The server communicates via **stdio** using the stand
95
107
  | `migrate_code` | Automatically migrates SceneView 2.x code to 3.x with detailed changelog |
96
108
  | `debug_issue` | Targeted debugging guide by category or auto-detected from problem description |
97
109
  | `generate_scene` | Generates a complete composable from natural language (e.g., "a room with a table and two chairs") |
110
+ | `get_animation_guide` | Guide for model animations, Spring physics, Compose property animations, SmoothTransform |
111
+ | `get_gesture_guide` | Guide for gestures: isEditable, onTouchEvent, tap-to-place, drag-to-rotate, pinch-to-scale |
112
+ | `get_performance_tips` | Performance optimization: LOD, texture compression, instancing, profiling with Systrace/AGI |
98
113
 
99
114
  ### 2 resources
100
115
 
@@ -151,7 +166,7 @@ The assistant calls `render_3d_preview` and returns an interactive link to a bro
151
166
 
152
167
  ## Quality
153
168
 
154
- The MCP server is tested with **612 unit tests** across 14 test suites covering:
169
+ The MCP server is tested with **858 unit tests** across 22 test suites covering:
155
170
 
156
171
  - Every tool response (correct output, error handling, edge cases)
157
172
  - All 33 code samples (compilable structure, correct imports, no deprecated APIs)
@@ -160,9 +175,9 @@ The MCP server is tested with **612 unit tests** across 14 test suites covering:
160
175
  - Resource responses (API reference, GitHub issues integration)
161
176
 
162
177
  ```
163
- Test Files 14 passed (14)
164
- Tests 612 passed (612)
165
- Duration 491ms
178
+ Test Files 22 passed (22)
179
+ Tests 858 passed (858)
180
+ Duration 624ms
166
181
  ```
167
182
 
168
183
  All tools work **fully offline** except `sceneview://known-issues` (GitHub API, cached 10 min).
@@ -213,7 +228,7 @@ The only network call is to the GitHub API (for known issues). All other tools w
213
228
  cd mcp
214
229
  npm install
215
230
  npm run prepare # Copy llms.txt + build TypeScript
216
- npm test # 612 tests
231
+ npm test # 858 tests
217
232
  npm run dev # Start with tsx (hot reload)
218
233
  ```
219
234
 
@@ -222,7 +237,7 @@ npm run dev # Start with tsx (hot reload)
222
237
  ```
223
238
  mcp/
224
239
  src/
225
- index.ts # MCP server entry point (18 tools, 2 resources)
240
+ index.ts # MCP server entry point (22 tools, 2 resources)
226
241
  samples.ts # 33 compilable code samples (Kotlin + Swift)
227
242
  validator.ts # Code validator (15+ rules, Kotlin + Swift)
228
243
  node-reference.ts # Node type parser (extracts from llms.txt)
@@ -239,7 +254,7 @@ mcp/
239
254
  1. Fork the repository
240
255
  2. Create a feature branch
241
256
  3. Add tests for new tools or rules
242
- 4. Run `npm test` -- all 612+ tests must pass
257
+ 4. Run `npm test` -- all 858+ tests must pass
243
258
  5. Submit a pull request
244
259
 
245
260
  See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide.
@@ -0,0 +1,806 @@
1
+ /**
2
+ * advanced-guides.ts
3
+ *
4
+ * Animation, gesture, and performance guides for SceneView developers.
5
+ */
6
+ // ─── Animation Guide ─────────────────────────────────────────────────────────
7
+ export const ANIMATION_GUIDE = `# SceneView Animation Guide
8
+
9
+ ## 1. Playing glTF Model Animations
10
+
11
+ GLB/glTF models can embed skeletal and morph-target animations. SceneView exposes them via \`Animator\` on the model instance.
12
+
13
+ \`\`\`kotlin
14
+ @Composable
15
+ fun AnimatedModelScreen() {
16
+ val engine = rememberEngine()
17
+ val modelLoader = rememberModelLoader(engine)
18
+ val modelInstance = rememberModelInstance(modelLoader, "models/character.glb")
19
+
20
+ Scene(engine = engine) {
21
+ modelInstance?.let { instance ->
22
+ ModelNode(
23
+ modelInstance = instance,
24
+ scaleToUnits = 1.0f,
25
+ // autoAnimate = true plays the first animation automatically
26
+ autoAnimate = true
27
+ )
28
+ }
29
+ }
30
+ }
31
+ \`\`\`
32
+
33
+ ### Controlling Animations Manually
34
+
35
+ \`\`\`kotlin
36
+ @Composable
37
+ fun ManualAnimationScreen() {
38
+ val engine = rememberEngine()
39
+ val modelLoader = rememberModelLoader(engine)
40
+ val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
41
+
42
+ Scene(
43
+ engine = engine,
44
+ onFrame = { frameTimeNanos ->
45
+ modelInstance?.let { instance ->
46
+ val animator = instance.animator
47
+ if (animator.animationCount > 0) {
48
+ // Update animation time
49
+ animator.applyAnimation(
50
+ animationIndex = 0,
51
+ time = (frameTimeNanos / 1_000_000_000.0).toFloat()
52
+ )
53
+ animator.updateBoneMatrices()
54
+ }
55
+ }
56
+ }
57
+ ) {
58
+ modelInstance?.let { instance ->
59
+ ModelNode(modelInstance = instance, scaleToUnits = 1.0f)
60
+ }
61
+ }
62
+ }
63
+ \`\`\`
64
+
65
+ ### Listing Available Animations
66
+
67
+ \`\`\`kotlin
68
+ modelInstance?.let { instance ->
69
+ val animator = instance.animator
70
+ for (i in 0 until animator.animationCount) {
71
+ val name = animator.getAnimationName(i)
72
+ val duration = animator.getAnimationDuration(i)
73
+ Log.d("Anim", "Animation $i: '$name' (\${duration}s)")
74
+ }
75
+ }
76
+ \`\`\`
77
+
78
+ ## 2. Spring Animations (KMP Core)
79
+
80
+ SceneView's KMP core provides spring-based animations for smooth, physics-driven motion.
81
+
82
+ \`\`\`kotlin
83
+ import io.github.sceneview.core.animation.Spring
84
+ import io.github.sceneview.core.animation.SpringAnimation
85
+
86
+ @Composable
87
+ fun SpringAnimatedNode() {
88
+ val engine = rememberEngine()
89
+ val modelLoader = rememberModelLoader(engine)
90
+ val modelInstance = rememberModelInstance(modelLoader, "models/cube.glb")
91
+
92
+ // Spring-based position animation
93
+ var targetY by remember { mutableFloatStateOf(0f) }
94
+ val springY = remember {
95
+ SpringAnimation(
96
+ spring = Spring(
97
+ stiffness = Spring.StiffnessMedium,
98
+ dampingRatio = Spring.DampingRatioMediumBouncy
99
+ ),
100
+ initialValue = 0f
101
+ )
102
+ }
103
+
104
+ Scene(
105
+ engine = engine,
106
+ onFrame = { _ ->
107
+ springY.target = targetY
108
+ springY.advance(0.016f) // ~60fps dt
109
+ }
110
+ ) {
111
+ modelInstance?.let { instance ->
112
+ ModelNode(
113
+ modelInstance = instance,
114
+ scaleToUnits = 0.5f,
115
+ position = Position(0f, springY.value, 0f)
116
+ )
117
+ }
118
+ }
119
+
120
+ // Toggle position on button press
121
+ Button(onClick = { targetY = if (targetY == 0f) 2f else 0f }) {
122
+ Text("Bounce")
123
+ }
124
+ }
125
+ \`\`\`
126
+
127
+ ### Spring Presets
128
+
129
+ | Preset | Stiffness | Damping | Use Case |
130
+ |--------|-----------|---------|----------|
131
+ | \`StiffnessHigh\` / \`DampingRatioNoBouncy\` | 10000 | 1.0 | Snappy UI, instant feel |
132
+ | \`StiffnessMedium\` / \`DampingRatioLowBouncy\` | 1500 | 0.75 | General purpose |
133
+ | \`StiffnessMediumLow\` / \`DampingRatioMediumBouncy\` | 400 | 0.5 | Playful bounce |
134
+ | \`StiffnessLow\` / \`DampingRatioHighBouncy\` | 200 | 0.2 | Heavy bounce, toy-like |
135
+
136
+ ## 3. Property Animations
137
+
138
+ Animate any node property (position, rotation, scale) over time with easing.
139
+
140
+ \`\`\`kotlin
141
+ @Composable
142
+ fun PropertyAnimationDemo() {
143
+ val engine = rememberEngine()
144
+ val modelLoader = rememberModelLoader(engine)
145
+ val modelInstance = rememberModelInstance(modelLoader, "models/sphere.glb")
146
+
147
+ // Compose animation for rotation
148
+ val infiniteTransition = rememberInfiniteTransition(label = "rotate")
149
+ val rotationY by infiniteTransition.animateFloat(
150
+ initialValue = 0f,
151
+ targetValue = 360f,
152
+ animationSpec = infiniteRepeatable(
153
+ animation = tween(durationMillis = 3000, easing = LinearEasing),
154
+ repeatMode = RepeatMode.Restart
155
+ ),
156
+ label = "rotY"
157
+ )
158
+
159
+ Scene(engine = engine) {
160
+ modelInstance?.let { instance ->
161
+ ModelNode(
162
+ modelInstance = instance,
163
+ scaleToUnits = 0.5f,
164
+ rotation = Rotation(0f, rotationY, 0f)
165
+ )
166
+ }
167
+ }
168
+ }
169
+ \`\`\`
170
+
171
+ ### Animating Scale with Compose
172
+
173
+ \`\`\`kotlin
174
+ var isExpanded by remember { mutableStateOf(false) }
175
+ val scale by animateFloatAsState(
176
+ targetValue = if (isExpanded) 2.0f else 1.0f,
177
+ animationSpec = spring(
178
+ dampingRatio = Spring.DampingRatioMediumBouncy,
179
+ stiffness = Spring.StiffnessMedium
180
+ ),
181
+ label = "scale"
182
+ )
183
+
184
+ ModelNode(
185
+ modelInstance = instance,
186
+ scaleToUnits = scale
187
+ )
188
+ \`\`\`
189
+
190
+ ## 4. Smooth Transform (KMP Core)
191
+
192
+ SmoothTransform interpolates between current and target transforms over time — ideal for following a moving target.
193
+
194
+ \`\`\`kotlin
195
+ import io.github.sceneview.core.animation.SmoothTransform
196
+
197
+ @Composable
198
+ fun SmoothFollowDemo() {
199
+ val engine = rememberEngine()
200
+ val modelLoader = rememberModelLoader(engine)
201
+ val modelInstance = rememberModelInstance(modelLoader, "models/drone.glb")
202
+
203
+ val smoothPosition = remember { SmoothTransform(smoothTime = 0.3f) }
204
+ var targetPosition by remember { mutableStateOf(Position(0f, 1f, 0f)) }
205
+
206
+ Scene(
207
+ engine = engine,
208
+ onFrame = { _ ->
209
+ smoothPosition.target = targetPosition
210
+ smoothPosition.advance(0.016f)
211
+ }
212
+ ) {
213
+ modelInstance?.let { instance ->
214
+ ModelNode(
215
+ modelInstance = instance,
216
+ scaleToUnits = 0.3f,
217
+ position = smoothPosition.current
218
+ )
219
+ }
220
+ }
221
+ }
222
+ \`\`\`
223
+
224
+ ## 5. AR Animation — Animated Model on Anchor
225
+
226
+ \`\`\`kotlin
227
+ @Composable
228
+ fun ARAnimatedModel() {
229
+ val engine = rememberEngine()
230
+ val modelLoader = rememberModelLoader(engine)
231
+ val modelInstance = rememberModelInstance(modelLoader, "models/dancing_character.glb")
232
+ var anchor by remember { mutableStateOf<Anchor?>(null) }
233
+
234
+ ARScene(
235
+ engine = engine,
236
+ modelLoader = modelLoader,
237
+ planeRenderer = true,
238
+ onTouchEvent = { event, hitResult ->
239
+ if (event.action == MotionEvent.ACTION_UP && hitResult != null) {
240
+ anchor = hitResult.createAnchor()
241
+ }
242
+ true
243
+ }
244
+ ) {
245
+ anchor?.let { a ->
246
+ AnchorNode(anchor = a) {
247
+ modelInstance?.let { instance ->
248
+ ModelNode(
249
+ modelInstance = instance,
250
+ scaleToUnits = 0.5f,
251
+ autoAnimate = true // plays embedded animation
252
+ )
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ \`\`\`
259
+
260
+ ## Key Takeaways
261
+
262
+ 1. **Embedded animations** — use \`autoAnimate = true\` or control \`Animator\` manually in \`onFrame\`.
263
+ 2. **Compose animations** — use \`animateFloatAsState\`, \`InfiniteTransition\`, \`Animatable\` — they integrate naturally with SceneView nodes.
264
+ 3. **Spring animations** — use KMP core \`SpringAnimation\` for physics-driven motion.
265
+ 4. **SmoothTransform** — use for smooth following / interpolation (camera follow, target tracking).
266
+ 5. **Threading** — all animation updates in \`onFrame\` run on the main thread (safe for Filament).
267
+ `;
268
+ // ─── Gesture Guide ───────────────────────────────────────────────────────────
269
+ export const GESTURE_GUIDE = `# SceneView Gesture Guide
270
+
271
+ ## 1. Built-in Gestures with \`isEditable\`
272
+
273
+ The simplest way to add gestures. Setting \`isEditable = true\` on a \`ModelNode\` enables:
274
+ - **Pinch to scale** — two-finger pinch scales the model
275
+ - **Drag to rotate** — single-finger drag rotates around Y axis
276
+ - **Tap to select** — tap highlights the model
277
+
278
+ \`\`\`kotlin
279
+ @Composable
280
+ fun EditableModelScreen() {
281
+ val engine = rememberEngine()
282
+ val modelLoader = rememberModelLoader(engine)
283
+ val modelInstance = rememberModelInstance(modelLoader, "models/chair.glb")
284
+
285
+ Scene(engine = engine) {
286
+ modelInstance?.let { instance ->
287
+ ModelNode(
288
+ modelInstance = instance,
289
+ scaleToUnits = 1.0f,
290
+ // Enable built-in gestures
291
+ isEditable = true
292
+ )
293
+ }
294
+ }
295
+ }
296
+ \`\`\`
297
+
298
+ ### What \`isEditable\` Provides
299
+
300
+ | Gesture | Action | Modifier |
301
+ |---------|--------|----------|
302
+ | Single tap | Select / deselect | — |
303
+ | Single-finger drag | Rotate around Y axis | — |
304
+ | Two-finger pinch | Scale up / down | Clamped to min/max |
305
+ | Two-finger drag | Pan / translate | — |
306
+
307
+ ## 2. Custom Gesture Handling with \`onTouchEvent\`
308
+
309
+ For full control, use the \`onTouchEvent\` callback on \`Scene\` or \`ARScene\`.
310
+
311
+ \`\`\`kotlin
312
+ @Composable
313
+ fun CustomGestureScreen() {
314
+ val engine = rememberEngine()
315
+ val modelLoader = rememberModelLoader(engine)
316
+ val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
317
+ var selectedNode by remember { mutableStateOf<ModelNode?>(null) }
318
+
319
+ Scene(
320
+ engine = engine,
321
+ onTouchEvent = { event, hitResult ->
322
+ when (event.action) {
323
+ MotionEvent.ACTION_DOWN -> {
324
+ // hitResult contains the node that was tapped (if any)
325
+ // Use this to detect taps on specific models
326
+ true
327
+ }
328
+ MotionEvent.ACTION_MOVE -> {
329
+ // Handle drag gestures
330
+ true
331
+ }
332
+ MotionEvent.ACTION_UP -> {
333
+ // Handle tap release
334
+ true
335
+ }
336
+ else -> false
337
+ }
338
+ }
339
+ ) {
340
+ modelInstance?.let { instance ->
341
+ ModelNode(
342
+ modelInstance = instance,
343
+ scaleToUnits = 1.0f
344
+ )
345
+ }
346
+ }
347
+ }
348
+ \`\`\`
349
+
350
+ ## 3. Tap-to-Place in AR
351
+
352
+ The most common AR gesture — tap a detected plane to place a model.
353
+
354
+ \`\`\`kotlin
355
+ @Composable
356
+ fun TapToPlaceAR() {
357
+ val engine = rememberEngine()
358
+ val modelLoader = rememberModelLoader(engine)
359
+ val modelInstance = rememberModelInstance(modelLoader, "models/furniture.glb")
360
+ var anchor by remember { mutableStateOf<Anchor?>(null) }
361
+
362
+ ARScene(
363
+ engine = engine,
364
+ modelLoader = modelLoader,
365
+ planeRenderer = true,
366
+ onTouchEvent = { event, hitResult ->
367
+ if (event.action == MotionEvent.ACTION_UP && hitResult != null) {
368
+ // Create an anchor at the tap location on the AR plane
369
+ anchor = hitResult.createAnchor()
370
+ }
371
+ true
372
+ }
373
+ ) {
374
+ anchor?.let { a ->
375
+ AnchorNode(anchor = a) {
376
+ modelInstance?.let { instance ->
377
+ ModelNode(
378
+ modelInstance = instance,
379
+ scaleToUnits = 0.5f,
380
+ isEditable = true // allow further manipulation after placement
381
+ )
382
+ }
383
+ }
384
+ }
385
+ }
386
+ }
387
+ \`\`\`
388
+
389
+ ## 4. Drag-to-Rotate with Custom Sensitivity
390
+
391
+ \`\`\`kotlin
392
+ @Composable
393
+ fun DragToRotateScreen() {
394
+ val engine = rememberEngine()
395
+ val modelLoader = rememberModelLoader(engine)
396
+ val modelInstance = rememberModelInstance(modelLoader, "models/shoe.glb")
397
+ var rotationY by remember { mutableFloatStateOf(0f) }
398
+ var lastX by remember { mutableFloatStateOf(0f) }
399
+ val sensitivity = 0.5f
400
+
401
+ Scene(
402
+ engine = engine,
403
+ onTouchEvent = { event, _ ->
404
+ when (event.action) {
405
+ MotionEvent.ACTION_DOWN -> {
406
+ lastX = event.x
407
+ true
408
+ }
409
+ MotionEvent.ACTION_MOVE -> {
410
+ val deltaX = event.x - lastX
411
+ rotationY += deltaX * sensitivity
412
+ lastX = event.x
413
+ true
414
+ }
415
+ else -> false
416
+ }
417
+ }
418
+ ) {
419
+ modelInstance?.let { instance ->
420
+ ModelNode(
421
+ modelInstance = instance,
422
+ scaleToUnits = 1.0f,
423
+ rotation = Rotation(0f, rotationY, 0f)
424
+ )
425
+ }
426
+ }
427
+ }
428
+ \`\`\`
429
+
430
+ ## 5. Pinch-to-Scale with Custom Limits
431
+
432
+ \`\`\`kotlin
433
+ @Composable
434
+ fun PinchToScaleScreen() {
435
+ val engine = rememberEngine()
436
+ val modelLoader = rememberModelLoader(engine)
437
+ val modelInstance = rememberModelInstance(modelLoader, "models/vase.glb")
438
+ var currentScale by remember { mutableFloatStateOf(1.0f) }
439
+ val minScale = 0.3f
440
+ val maxScale = 3.0f
441
+
442
+ val scaleDetector = rememberScaleGestureDetector { detector ->
443
+ currentScale = (currentScale * detector.scaleFactor).coerceIn(minScale, maxScale)
444
+ }
445
+
446
+ Scene(
447
+ engine = engine,
448
+ onTouchEvent = { event, _ ->
449
+ scaleDetector.onTouchEvent(event)
450
+ true
451
+ }
452
+ ) {
453
+ modelInstance?.let { instance ->
454
+ ModelNode(
455
+ modelInstance = instance,
456
+ scaleToUnits = currentScale
457
+ )
458
+ }
459
+ }
460
+ }
461
+ \`\`\`
462
+
463
+ ## 6. Multi-Model Selection
464
+
465
+ \`\`\`kotlin
466
+ @Composable
467
+ fun MultiModelSelectionScreen() {
468
+ val engine = rememberEngine()
469
+ val modelLoader = rememberModelLoader(engine)
470
+ val chair = rememberModelInstance(modelLoader, "models/chair.glb")
471
+ val table = rememberModelInstance(modelLoader, "models/table.glb")
472
+ var selectedModel by remember { mutableStateOf<String?>(null) }
473
+
474
+ Scene(engine = engine) {
475
+ chair?.let { instance ->
476
+ ModelNode(
477
+ modelInstance = instance,
478
+ scaleToUnits = 0.5f,
479
+ position = Position(-1f, 0f, 0f),
480
+ isEditable = true,
481
+ onTap = { selectedModel = "chair" }
482
+ )
483
+ }
484
+ table?.let { instance ->
485
+ ModelNode(
486
+ modelInstance = instance,
487
+ scaleToUnits = 0.5f,
488
+ position = Position(1f, 0f, 0f),
489
+ isEditable = true,
490
+ onTap = { selectedModel = "table" }
491
+ )
492
+ }
493
+ }
494
+
495
+ // Show selection UI
496
+ selectedModel?.let { name ->
497
+ Text("Selected: $name", modifier = Modifier.padding(16.dp))
498
+ }
499
+ }
500
+ \`\`\`
501
+
502
+ ## 7. HitResultNode — Surface Cursor
503
+
504
+ A model that follows the user's gaze / screen center on AR planes — before they tap to place.
505
+
506
+ \`\`\`kotlin
507
+ @Composable
508
+ fun SurfaceCursorAR() {
509
+ val engine = rememberEngine()
510
+ val modelLoader = rememberModelLoader(engine)
511
+ val cursorModel = rememberModelInstance(modelLoader, "models/cursor_ring.glb")
512
+
513
+ ARScene(
514
+ engine = engine,
515
+ modelLoader = modelLoader,
516
+ planeRenderer = true
517
+ ) {
518
+ // HitResultNode automatically follows the center hit on AR planes
519
+ HitResultNode(engine = engine) {
520
+ cursorModel?.let { instance ->
521
+ ModelNode(modelInstance = instance, scaleToUnits = 0.1f)
522
+ }
523
+ }
524
+ }
525
+ }
526
+ \`\`\`
527
+
528
+ ## Key Takeaways
529
+
530
+ 1. **\`isEditable = true\`** — one-liner for pinch/drag/tap on any ModelNode.
531
+ 2. **\`onTouchEvent\`** — full MotionEvent access for custom gesture logic.
532
+ 3. **AR tap-to-place** — use \`hitResult.createAnchor()\` in \`onTouchEvent\` with \`ACTION_UP\`.
533
+ 4. **Custom rotation/scale** — track touch deltas or use \`ScaleGestureDetector\`.
534
+ 5. **HitResultNode** — AR surface cursor that follows the center of the screen.
535
+ 6. **Multi-model** — use \`onTap\` callback per ModelNode for selection.
536
+ `;
537
+ // ─── Performance Tips ────────────────────────────────────────────────────────
538
+ export const PERFORMANCE_TIPS = `# SceneView Performance Optimization Guide
539
+
540
+ ## 1. Model Optimization
541
+
542
+ ### Polygon Budget
543
+
544
+ | Device Tier | Max Triangles | Max Draw Calls | Max Textures |
545
+ |-------------|--------------|----------------|--------------|
546
+ | Low-end | 50K | 20 | 8 x 512px |
547
+ | Mid-range | 100K | 50 | 16 x 1024px |
548
+ | High-end | 300K+ | 100+ | 32 x 2048px |
549
+
550
+ ### LOD (Level of Detail)
551
+
552
+ Use multiple LODs in your glTF models to reduce triangle count at distance. Filament respects glTF LOD extensions.
553
+
554
+ \`\`\`kotlin
555
+ @Composable
556
+ fun LODModelDemo() {
557
+ val engine = rememberEngine()
558
+ val modelLoader = rememberModelLoader(engine)
559
+ // Use a GLB exported with LOD levels from Blender/3ds Max
560
+ // Filament picks the appropriate LOD automatically based on screen coverage
561
+ val modelInstance = rememberModelInstance(modelLoader, "models/building_lod.glb")
562
+
563
+ Scene(engine = engine) {
564
+ modelInstance?.let { instance ->
565
+ ModelNode(
566
+ modelInstance = instance,
567
+ scaleToUnits = 5.0f
568
+ )
569
+ }
570
+ }
571
+ }
572
+ \`\`\`
573
+
574
+ ### Texture Compression
575
+
576
+ **Always use KTX2 with Basis Universal** for production builds:
577
+
578
+ \`\`\`bash
579
+ # Install KTX tools: https://github.com/KhronosGroup/KTX-Software
580
+ # Convert textures to KTX2 with Basis Universal compression
581
+ toktx --t2 --bcmp --assign_oetf srgb output.ktx2 input.png
582
+
583
+ # Or compress entire glTF with gltf-transform
584
+ npx @gltf-transform/cli optimize input.glb output.glb \\
585
+ --compress draco \\
586
+ --texture-compress ktx2
587
+ \`\`\`
588
+
589
+ **Texture size guidelines:**
590
+ - Diffuse/base color: 1024x1024 max on mobile
591
+ - Normal maps: 512x512 (hard to see detail at higher res on mobile)
592
+ - Roughness/metallic: 512x512 (pack into single texture channels)
593
+ - Environment HDR: 2K (sky_2k.hdr) is sufficient for most scenes
594
+
595
+ ### Mesh Optimization with Draco / Meshopt
596
+
597
+ \`\`\`bash
598
+ # Draco compression (lossy, smallest files, supported by Filament)
599
+ npx @gltf-transform/cli optimize model.glb compressed.glb \\
600
+ --compress draco
601
+
602
+ # Meshopt compression (lossless, good balance, supported by Filament)
603
+ npx @gltf-transform/cli optimize model.glb compressed.glb \\
604
+ --compress meshopt
605
+
606
+ # Typical savings: 60-90% file size reduction
607
+ \`\`\`
608
+
609
+ ## 2. Runtime Performance
610
+
611
+ ### Engine and Loader Reuse
612
+
613
+ \`\`\`kotlin
614
+ // CORRECT — single engine for entire app
615
+ @Composable
616
+ fun MyApp() {
617
+ val engine = rememberEngine()
618
+ val modelLoader = rememberModelLoader(engine)
619
+
620
+ // Pass engine and modelLoader to all scenes
621
+ NavHost(...) {
622
+ composable("scene1") { Scene1(engine, modelLoader) }
623
+ composable("scene2") { Scene2(engine, modelLoader) }
624
+ }
625
+ }
626
+
627
+ // WRONG — each screen creates its own engine (wastes GPU memory)
628
+ @Composable
629
+ fun BadScene() {
630
+ val engine = rememberEngine() // creates new engine each time!
631
+ Scene(engine = engine) { /* ... */ }
632
+ }
633
+ \`\`\`
634
+
635
+ ### Avoid Per-Frame Allocations
636
+
637
+ \`\`\`kotlin
638
+ // WRONG — creates new Position every frame
639
+ Scene(
640
+ engine = engine,
641
+ onFrame = { _ ->
642
+ node.position = Position(x, y, z) // allocation every frame!
643
+ }
644
+ )
645
+
646
+ // CORRECT — reuse mutable position
647
+ val position = remember { MutablePosition() }
648
+ Scene(
649
+ engine = engine,
650
+ onFrame = { _ ->
651
+ position.set(x, y, z)
652
+ node.position = position
653
+ }
654
+ )
655
+ \`\`\`
656
+
657
+ ### Limit Concurrent Model Loads
658
+
659
+ \`\`\`kotlin
660
+ // WRONG — loads 20 models at once, spikes memory
661
+ items.forEach { item ->
662
+ val model = rememberModelInstance(modelLoader, item.path)
663
+ // All 20 start loading simultaneously
664
+ }
665
+
666
+ // CORRECT — stagger or paginate model loading
667
+ val visibleItems = items.take(4) // only load visible models
668
+ visibleItems.forEach { item ->
669
+ val model = rememberModelInstance(modelLoader, item.path)
670
+ model?.let { ModelNode(modelInstance = it, scaleToUnits = 0.5f) }
671
+ }
672
+ \`\`\`
673
+
674
+ ## 3. Frustum Culling
675
+
676
+ Filament performs frustum culling automatically — objects outside the camera view are not rendered. You can improve this by:
677
+
678
+ \`\`\`kotlin
679
+ // Set accurate bounding boxes on nodes for better culling
680
+ ModelNode(
681
+ modelInstance = instance,
682
+ scaleToUnits = 1.0f
683
+ // Filament automatically computes bounding boxes from mesh data
684
+ // For custom geometry, set boundingBox explicitly
685
+ )
686
+ \`\`\`
687
+
688
+ **Tips for effective frustum culling:**
689
+ - Break large scenes into multiple ModelNodes instead of one giant mesh
690
+ - Each ModelNode has its own bounding box and can be culled independently
691
+ - Use \`scaleToUnits\` — it helps Filament compute tighter bounding boxes
692
+
693
+ ## 4. Instancing
694
+
695
+ When rendering multiple copies of the same model (e.g., trees, buildings), use instancing to share mesh data.
696
+
697
+ \`\`\`kotlin
698
+ @Composable
699
+ fun InstancedTreesScene() {
700
+ val engine = rememberEngine()
701
+ val modelLoader = rememberModelLoader(engine)
702
+ val treeInstance = rememberModelInstance(modelLoader, "models/tree.glb")
703
+
704
+ Scene(engine = engine) {
705
+ // Each ModelNode with the same modelInstance shares GPU mesh data
706
+ // Filament handles instancing internally when using the same asset
707
+ treeInstance?.let { instance ->
708
+ for (i in 0 until 10) {
709
+ val x = (i % 5) * 2.0f - 4.0f
710
+ val z = (i / 5) * 2.0f - 1.0f
711
+ ModelNode(
712
+ modelInstance = instance,
713
+ scaleToUnits = 1.5f,
714
+ position = Position(x, 0f, z)
715
+ )
716
+ }
717
+ }
718
+ }
719
+ }
720
+ \`\`\`
721
+
722
+ > **Note:** When placing the same \`modelInstance\` in multiple \`ModelNode\`s, the mesh and material data is shared on the GPU. For independent transforms, Filament handles per-instance transforms efficiently.
723
+
724
+ ## 5. Lighting Optimization
725
+
726
+ \`\`\`kotlin
727
+ // Limit shadow-casting lights — each adds a depth render pass
728
+ LightNode(
729
+ type = LightNode.Type.DIRECTIONAL,
730
+ apply = {
731
+ intensity(100_000f)
732
+ direction(0f, -1f, -1f)
733
+ castShadows(true) // adds one depth pass
734
+ }
735
+ )
736
+
737
+ // Use small HDR environments
738
+ val environment = rememberEnvironment(engine, "environments/sky_2k.hdr")
739
+ // NOT: sky_4k.hdr or sky_8k.hdr (wastes GPU memory on mobile)
740
+ \`\`\`
741
+
742
+ **Shadow optimization checklist:**
743
+ - Only 1-2 shadow-casting lights max on mobile
744
+ - Reduce shadow map resolution if needed (Filament defaults are reasonable)
745
+ - Disable shadows on objects that don't need them
746
+
747
+ ## 6. Post-Processing
748
+
749
+ \`\`\`kotlin
750
+ // Disable post-processing for simpler scenes (saves ~2ms per frame)
751
+ Scene(
752
+ engine = engine,
753
+ postProcessing = false // skips bloom, SSAO, tone mapping
754
+ ) {
755
+ // Simpler rendering, better FPS
756
+ }
757
+ \`\`\`
758
+
759
+ | Effect | Cost | Recommendation |
760
+ |--------|------|----------------|
761
+ | Tone mapping | Low | Keep enabled (visual quality) |
762
+ | FXAA | Low | Keep enabled (anti-aliasing) |
763
+ | Bloom | Medium | Disable on low-end devices |
764
+ | SSAO | High | Disable on mobile |
765
+ | Screen-space reflections | High | Disable on mobile |
766
+
767
+ ## 7. Profiling with Systrace
768
+
769
+ \`\`\`bash
770
+ # Capture a Systrace for Filament rendering
771
+ python systrace.py -t 5 -o trace.html gfx view
772
+
773
+ # Or use Android Studio Profiler:
774
+ # 1. Run app with profiling enabled
775
+ # 2. Open CPU profiler → Record trace
776
+ # 3. Look for Filament sections: "Filament::Renderer", "Filament::View"
777
+ \`\`\`
778
+
779
+ ### Key Metrics to Watch
780
+
781
+ | Metric | Target | Action if Over |
782
+ |--------|--------|----------------|
783
+ | Frame time | < 16.6ms (60fps) | Reduce polygons, textures |
784
+ | Draw calls | < 50 | Merge meshes, use instancing |
785
+ | GPU memory | < 256MB | Compress textures, reduce LOD |
786
+ | Model load time | < 2s | Use Draco/Meshopt, smaller models |
787
+
788
+ ## 8. Android GPU Inspector (AGI)
789
+
790
+ For detailed GPU profiling:
791
+
792
+ 1. Install AGI from [developer.android.com/agi](https://developer.android.com/agi)
793
+ 2. Enable GPU profiling in device developer options
794
+ 3. Capture a frame: AGI shows exact GPU time per draw call
795
+ 4. Identify bottlenecks: shader compilation, overdraw, texture sampling
796
+
797
+ ## Key Takeaways
798
+
799
+ 1. **Compress models** — Draco/Meshopt + KTX2 textures. Target 60-90% size reduction.
800
+ 2. **Reuse engines** — one \`rememberEngine()\` per app, pass it down.
801
+ 3. **Limit loads** — max 3-4 concurrent \`rememberModelInstance\` calls.
802
+ 4. **Frustum culling** — break scenes into multiple nodes for automatic culling.
803
+ 5. **Instancing** — reuse the same \`modelInstance\` for repeated objects.
804
+ 6. **Profile** — use Systrace or AGI to find real bottlenecks, don't guess.
805
+ 7. **Post-processing** — disable what you don't need (\`postProcessing = false\`).
806
+ `;
@@ -502,7 +502,7 @@ Scene(
502
502
  - Require Xcode 15.0+ (iOS 17 / visionOS targets).
503
503
  - Clean: Xcode > Product > Clean Build Folder.
504
504
  - Reset packages: File > Packages > Reset Package Caches.
505
- - URL must be exactly: \`https://github.com/SceneView/sceneview\`
505
+ - URL must be exactly: \`https://github.com/sceneview/sceneview\`
506
506
 
507
507
  ### Swift Concurrency Warnings
508
508
 
package/dist/guides.js CHANGED
@@ -60,8 +60,8 @@ Shared Kotlin Multiplatform module providing:
60
60
 
61
61
  ## How to Stay Updated
62
62
 
63
- - **GitHub:** https://github.com/SceneView/sceneview
64
- - **Releases:** https://github.com/SceneView/sceneview/releases
63
+ - **GitHub:** https://github.com/sceneview/sceneview
64
+ - **Releases:** https://github.com/sceneview/sceneview/releases
65
65
  - **Website:** https://sceneview.github.io
66
66
  `;
67
67
  // ─── Best Practices ───────────────────────────────────────────────────────────
@@ -321,7 +321,7 @@ export const TROUBLESHOOTING_GUIDE = `# SceneView Troubleshooting Guide
321
321
  **Fix:**
322
322
  - Ensure Xcode 15.0+ (required for iOS 17 / visionOS targets).
323
323
  - Clean derived data: Xcode → Product → Clean Build Folder, then File → Packages → Reset Package Caches.
324
- - Check the URL is exactly: \`https://github.com/SceneView/sceneview\`
324
+ - Check the URL is exactly: \`https://github.com/sceneview/sceneview\`
325
325
 
326
326
  ### Image Tracking Not Working (iOS)
327
327
  **Fix:**
@@ -339,7 +339,7 @@ export const AR_SETUP_GUIDE = `# SceneView AR — Complete Setup Guide (Android
339
339
  ## 1. SPM Dependency
340
340
 
341
341
  \`\`\`swift
342
- .package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")
342
+ .package(url: "https://github.com/sceneview/sceneview", from: "3.3.0")
343
343
  \`\`\`
344
344
 
345
345
  ## 2. Info.plist — Camera Permission
package/dist/index.js CHANGED
@@ -17,9 +17,11 @@ import { getPlatformSetup, PLATFORM_IDS } from "./platform-setup.js";
17
17
  import { migrateCode, formatMigrationResult } from "./migrate-code.js";
18
18
  import { getDebugGuide, autoDetectIssue, DEBUG_CATEGORIES } from "./debug-issue.js";
19
19
  import { generateScene, formatGeneratedScene } from "./generate-scene.js";
20
+ import { ANIMATION_GUIDE, GESTURE_GUIDE, PERFORMANCE_TIPS } from "./advanced-guides.js";
21
+ import { MATERIAL_GUIDE, COLLISION_GUIDE, MODEL_OPTIMIZATION_GUIDE, WEB_RENDERING_GUIDE } from "./extra-guides.js";
20
22
  const __dirname = dirname(fileURLToPath(import.meta.url));
21
23
  // ─── Legal disclaimer ─────────────────────────────────────────────────────────
22
- const DISCLAIMER = '\n\n---\n*Generated code suggestion. Review before use in production. See [TERMS.md](https://github.com/SceneView/sceneview/blob/main/mcp/TERMS.md).*';
24
+ const DISCLAIMER = '\n\n---\n*Generated code suggestion. Review before use in production. See [TERMS.md](https://github.com/sceneview/sceneview/blob/main/mcp/TERMS.md).*';
23
25
  function withDisclaimer(content) {
24
26
  if (content.length === 0)
25
27
  return content;
@@ -37,7 +39,7 @@ catch {
37
39
  API_DOCS = "SceneView API docs not found. Run `npm run prepare` to bundle llms.txt.";
38
40
  }
39
41
  const NODE_SECTIONS = parseNodeSections(API_DOCS);
40
- const server = new Server({ name: "@sceneview/mcp", version: "3.4.14" }, { capabilities: { resources: {}, tools: {} } });
42
+ const server = new Server({ name: "sceneview-mcp", version: "3.5.0" }, { capabilities: { resources: {}, tools: {} } });
41
43
  // ─── Resources ───────────────────────────────────────────────────────────────
42
44
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
43
45
  resources: [
@@ -424,6 +426,69 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
424
426
  required: [],
425
427
  },
426
428
  },
429
+ {
430
+ name: "get_animation_guide",
431
+ description: "Returns a comprehensive guide for animating 3D models in SceneView — playing embedded glTF animations, Spring physics animations (KMP core), Compose property animations (animateFloatAsState, InfiniteTransition), SmoothTransform for smooth following, and AR animated models. Includes compilable Kotlin code samples. Use this when a user asks about animation, motion, springs, smooth movement, or how to play model animations.",
432
+ inputSchema: {
433
+ type: "object",
434
+ properties: {},
435
+ required: [],
436
+ },
437
+ },
438
+ {
439
+ name: "get_gesture_guide",
440
+ description: "Returns a comprehensive guide for adding gestures to 3D objects in SceneView — isEditable for one-line pinch-to-scale/drag-to-rotate/tap-to-select, custom onTouchEvent handlers, AR tap-to-place, drag-to-rotate with sensitivity, pinch-to-scale with limits, multi-model selection, and HitResultNode surface cursor. Includes compilable Kotlin code samples. Use this when a user asks about touch, gestures, interaction, drag, pinch, tap, or editing 3D objects.",
441
+ inputSchema: {
442
+ type: "object",
443
+ properties: {},
444
+ required: [],
445
+ },
446
+ },
447
+ {
448
+ name: "get_performance_tips",
449
+ description: "Returns a comprehensive performance optimization guide for SceneView — polygon budgets per device tier, LOD, texture compression (KTX2/Basis Universal), mesh compression (Draco/Meshopt), engine reuse, per-frame allocation avoidance, frustum culling, instancing, lighting optimization, post-processing costs, and profiling with Systrace and Android GPU Inspector. Includes code samples and CLI commands. Use this when a user asks about performance, optimization, FPS, memory, profiling, or slow rendering.",
450
+ inputSchema: {
451
+ type: "object",
452
+ properties: {},
453
+ required: [],
454
+ },
455
+ },
456
+ {
457
+ name: "get_material_guide",
458
+ description: "Returns a comprehensive guide for PBR materials in SceneView — baseColor, metallic, roughness, reflectance, emissive, clearCoat, normal maps. Includes recipes for common materials (glass, chrome, gold, rubber, car paint), code samples for modifying materials on ModelNode, texture setup, and environment lighting requirements. Use this when a user asks about materials, textures, colors, shaders, appearance, or why their model looks wrong (flat, dark, too shiny).",
459
+ inputSchema: {
460
+ type: "object",
461
+ properties: {},
462
+ required: [],
463
+ },
464
+ },
465
+ {
466
+ name: "get_collision_guide",
467
+ description: "Returns a comprehensive guide for collision detection, hit testing, and physics in SceneView — node tapping (onTouchEvent), AR surface hit testing (frame.hitTest), ray-box/ray-sphere intersection (KMP core), bounding boxes, and basic rigid body physics. Use this when a user asks about tapping 3D objects, collision detection, physics simulation, ray casting, or hit testing.",
468
+ inputSchema: {
469
+ type: "object",
470
+ properties: {},
471
+ required: [],
472
+ },
473
+ },
474
+ {
475
+ name: "get_model_optimization_guide",
476
+ description: "Returns a complete guide for optimizing 3D models for SceneView — polygon budgets per device tier, file size targets, Draco/Meshopt mesh compression, KTX2 texture compression, the recommended optimization pipeline (gltf-transform CLI), texture sizing rules, LOD strategies, and quick wins. Use this when a user asks about model optimization, file size, load times, polygon count, texture compression, or preparing models for mobile.",
477
+ inputSchema: {
478
+ type: "object",
479
+ properties: {},
480
+ required: [],
481
+ },
482
+ },
483
+ {
484
+ name: "get_web_rendering_guide",
485
+ description: "Returns a comprehensive guide for SceneView Web (Filament.js WASM) — architecture, quick start (sceneview.js npm or Kotlin/JS), IBL environment lighting (critical for PBR quality), rendering quality settings (SSAO, bloom, TAA), camera exposure tuning, Filament.js vs model-viewer comparison, and web performance tips. Use this when a user asks about web 3D rendering, Filament.js, browser viewing, WebGL, or wants to display 3D models in a web page.",
486
+ inputSchema: {
487
+ type: "object",
488
+ properties: {},
489
+ required: [],
490
+ },
491
+ },
427
492
  ],
428
493
  }));
429
494
  // ─── Tool handlers ────────────────────────────────────────────────────────────
@@ -654,7 +719,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
654
719
  ``,
655
720
  `In Xcode: **File → Add Package Dependencies** → paste:`,
656
721
  `\`\`\``,
657
- `https://github.com/SceneView/sceneview`,
722
+ `https://github.com/sceneview/sceneview`,
658
723
  `\`\`\``,
659
724
  `Set version rule to **"from: 3.3.0"**.`,
660
725
  ``,
@@ -667,7 +732,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
667
732
  ` name: "MyApp",`,
668
733
  ` platforms: [.iOS(.v17), .macOS(.v14), .visionOS(.v1)],`,
669
734
  ` dependencies: [`,
670
- ` .package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")`,
735
+ ` .package(url: "https://github.com/sceneview/sceneview", from: "3.3.0")`,
671
736
  ` ],`,
672
737
  ` targets: [`,
673
738
  ` .executableTarget(`,
@@ -738,7 +803,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
738
803
  `### 1. Add SPM Dependency`,
739
804
  ``,
740
805
  `\`\`\`swift`,
741
- `.package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")`,
806
+ `.package(url: "https://github.com/sceneview/sceneview", from: "3.3.0")`,
742
807
  `\`\`\``,
743
808
  ``,
744
809
  `### 2. Minimum Platform`,
@@ -1050,6 +1115,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1050
1115
  ];
1051
1116
  return { content: withDisclaimer([{ type: "text", text: lines.join("\n") }]) };
1052
1117
  }
1118
+ // ── get_animation_guide ─────────────────────────────────────────────────
1119
+ case "get_animation_guide": {
1120
+ return { content: withDisclaimer([{ type: "text", text: ANIMATION_GUIDE }]) };
1121
+ }
1122
+ // ── get_gesture_guide ────────────────────────────────────────────────────
1123
+ case "get_gesture_guide": {
1124
+ return { content: withDisclaimer([{ type: "text", text: GESTURE_GUIDE }]) };
1125
+ }
1126
+ // ── get_performance_tips ─────────────────────────────────────────────────
1127
+ case "get_performance_tips": {
1128
+ return { content: withDisclaimer([{ type: "text", text: PERFORMANCE_TIPS }]) };
1129
+ }
1130
+ // ── get_material_guide ───────────────────────────────────────────────────
1131
+ case "get_material_guide": {
1132
+ return { content: withDisclaimer([{ type: "text", text: MATERIAL_GUIDE }]) };
1133
+ }
1134
+ // ── get_collision_guide ──────────────────────────────────────────────────
1135
+ case "get_collision_guide": {
1136
+ return { content: withDisclaimer([{ type: "text", text: COLLISION_GUIDE }]) };
1137
+ }
1138
+ // ── get_model_optimization_guide ─────────────────────────────────────────
1139
+ case "get_model_optimization_guide": {
1140
+ return { content: withDisclaimer([{ type: "text", text: MODEL_OPTIMIZATION_GUIDE }]) };
1141
+ }
1142
+ // ── get_web_rendering_guide ──────────────────────────────────────────────
1143
+ case "get_web_rendering_guide": {
1144
+ return { content: withDisclaimer([{ type: "text", text: WEB_RENDERING_GUIDE }]) };
1145
+ }
1053
1146
  default:
1054
1147
  return {
1055
1148
  content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
package/dist/issues.js CHANGED
@@ -9,10 +9,10 @@ export async function fetchKnownIssues() {
9
9
  let issues = [];
10
10
  let fetchError = null;
11
11
  try {
12
- const response = await fetch("https://api.github.com/repos/SceneView/sceneview/issues?state=open&per_page=30", {
12
+ const response = await fetch("https://api.github.com/repos/sceneview/sceneview/issues?state=open&per_page=30", {
13
13
  headers: {
14
14
  Accept: "application/vnd.github+json",
15
- "User-Agent": "sceneview-mcp/3.3.0",
15
+ "User-Agent": "sceneview-mcp/3.4.14",
16
16
  "X-GitHub-Api-Version": "2022-11-28",
17
17
  },
18
18
  });
@@ -176,7 +176,7 @@ const IOS_3D = `## SceneViewSwift — iOS/macOS/visionOS 3D Setup
176
176
 
177
177
  In Xcode: **File > Add Package Dependencies** > paste:
178
178
  \`\`\`
179
- https://github.com/SceneView/sceneview
179
+ https://github.com/sceneview/sceneview
180
180
  \`\`\`
181
181
  Set version rule to **"from: 3.3.0"**.
182
182
 
@@ -189,7 +189,7 @@ let package = Package(
189
189
  name: "MyApp",
190
190
  platforms: [.iOS(.v17), .macOS(.v14), .visionOS(.v1)],
191
191
  dependencies: [
192
- .package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")
192
+ .package(url: "https://github.com/sceneview/sceneview", from: "3.3.0")
193
193
  ],
194
194
  targets: [
195
195
  .executableTarget(
@@ -251,7 +251,7 @@ const IOS_AR = `## SceneViewSwift — iOS AR Setup
251
251
  ### 1. SPM Dependency
252
252
 
253
253
  \`\`\`swift
254
- .package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")
254
+ .package(url: "https://github.com/sceneview/sceneview", from: "3.3.0")
255
255
  \`\`\`
256
256
 
257
257
  ### 2. Info.plist — Camera Permission (Required)
package/dist/samples.js CHANGED
@@ -1038,8 +1038,8 @@ fun NodeHierarchyScreen() {
1038
1038
  title: "iOS 3D Model Viewer",
1039
1039
  description: "SwiftUI 3D scene with a USDZ model, IBL environment, orbit camera, and animation playback.",
1040
1040
  tags: ["3d", "model", "environment", "camera", "animation", "ios", "swift"],
1041
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1042
- spmDependency: "https://github.com/SceneView/sceneview",
1041
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1042
+ spmDependency: "https://github.com/sceneview/sceneview",
1043
1043
  prompt: "Create a SwiftUI screen that loads a USDZ model and displays it with IBL lighting, orbit camera, and animation playback. Use SceneViewSwift.",
1044
1044
  language: "swift",
1045
1045
  code: `import SwiftUI
@@ -1077,8 +1077,8 @@ struct ModelViewerScreen: View {
1077
1077
  title: "iOS AR Tap-to-Place Model Viewer",
1078
1078
  description: "AR scene with plane detection. Tap a surface to place a 3D model using ARKit + RealityKit.",
1079
1079
  tags: ["ar", "model", "anchor", "plane-detection", "placement", "ios", "swift"],
1080
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1081
- spmDependency: "https://github.com/SceneView/sceneview",
1080
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1081
+ spmDependency: "https://github.com/sceneview/sceneview",
1082
1082
  prompt: "Create an iOS AR screen that detects surfaces and lets the user tap to place a USDZ model. Use SceneViewSwift.",
1083
1083
  language: "swift",
1084
1084
  code: `import SwiftUI
@@ -1117,8 +1117,8 @@ struct ARModelViewerScreen: View {
1117
1117
  title: "iOS AR Augmented Image",
1118
1118
  description: "Detects reference images in the camera feed and overlays 3D content above them using ARKit.",
1119
1119
  tags: ["ar", "model", "image-tracking", "ios", "swift"],
1120
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1121
- spmDependency: "https://github.com/SceneView/sceneview",
1120
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1121
+ spmDependency: "https://github.com/sceneview/sceneview",
1122
1122
  prompt: "Create an iOS AR screen that detects a printed reference image and places a 3D model above it. Use SceneViewSwift.",
1123
1123
  language: "swift",
1124
1124
  code: `import SwiftUI
@@ -1155,8 +1155,8 @@ struct AugmentedImageScreen: View {
1155
1155
  title: "iOS Procedural Geometry",
1156
1156
  description: "Procedural geometry shapes — cube, sphere, cylinder, cone, and plane — with PBR materials.",
1157
1157
  tags: ["3d", "geometry", "ios", "swift"],
1158
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1159
- spmDependency: "https://github.com/SceneView/sceneview",
1158
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1159
+ spmDependency: "https://github.com/sceneview/sceneview",
1160
1160
  prompt: "Create a SwiftUI scene showing procedural geometry shapes (cube, sphere, cylinder, cone, plane) with different materials. Use SceneViewSwift.",
1161
1161
  language: "swift",
1162
1162
  code: `import SwiftUI
@@ -1209,8 +1209,8 @@ struct GeometryShapesScreen: View {
1209
1209
  title: "iOS Lighting",
1210
1210
  description: "Directional, point, and spot lights with configurable intensity, color, and shadows.",
1211
1211
  tags: ["3d", "lighting", "environment", "ios", "swift"],
1212
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1213
- spmDependency: "https://github.com/SceneView/sceneview",
1212
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1213
+ spmDependency: "https://github.com/sceneview/sceneview",
1214
1214
  prompt: "Create a SwiftUI 3D scene with directional, point, and spot lights illuminating geometry. Use SceneViewSwift.",
1215
1215
  language: "swift",
1216
1216
  code: `import SwiftUI
@@ -1273,8 +1273,8 @@ struct LightingScreen: View {
1273
1273
  title: "iOS Physics Demo",
1274
1274
  description: "Interactive physics simulation with bouncing spheres, gravity, and configurable restitution.",
1275
1275
  tags: ["3d", "physics", "geometry", "ios", "swift"],
1276
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1277
- spmDependency: "https://github.com/SceneView/sceneview",
1276
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1277
+ spmDependency: "https://github.com/sceneview/sceneview",
1278
1278
  prompt: "Create a SwiftUI 3D scene where tapping spawns coloured spheres that fall under gravity and bounce off a floor. Use SceneViewSwift.",
1279
1279
  language: "swift",
1280
1280
  code: `import SwiftUI
@@ -1337,8 +1337,8 @@ struct PhysicsDemoScreen: View {
1337
1337
  title: "iOS 3D Text Labels",
1338
1338
  description: "Camera-facing 3D text labels using TextNode and BillboardNode for always-facing-camera behavior.",
1339
1339
  tags: ["3d", "text", "geometry", "ios", "swift"],
1340
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1341
- spmDependency: "https://github.com/SceneView/sceneview",
1340
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1341
+ spmDependency: "https://github.com/sceneview/sceneview",
1342
1342
  prompt: "Create a SwiftUI 3D scene with floating text labels that always face the camera, showing planet names. Use SceneViewSwift.",
1343
1343
  language: "swift",
1344
1344
  code: `import SwiftUI
@@ -1385,8 +1385,8 @@ struct TextLabelsScreen: View {
1385
1385
  title: "iOS Video on 3D Surface",
1386
1386
  description: "Video playback on a 3D plane using VideoNode with play/pause controls.",
1387
1387
  tags: ["3d", "video", "ios", "swift"],
1388
- dependency: "https://github.com/SceneView/sceneview — from: \"3.3.0\"",
1389
- spmDependency: "https://github.com/SceneView/sceneview",
1388
+ dependency: "https://github.com/sceneview/sceneview — from: \"3.3.0\"",
1389
+ spmDependency: "https://github.com/sceneview/sceneview",
1390
1390
  prompt: "Create a SwiftUI 3D scene with a video playing on a floating 3D plane. Include play/pause controls. Use SceneViewSwift.",
1391
1391
  language: "swift",
1392
1392
  code: `import SwiftUI
package/llms.txt CHANGED
@@ -3,11 +3,11 @@
3
3
  SceneView is a declarative 3D and AR SDK for Android (Jetpack Compose, Filament, ARCore) and Apple platforms — iOS, macOS, visionOS (SwiftUI, RealityKit, ARKit) — with shared core logic via Kotlin Multiplatform. Each platform uses its native renderer: Filament on Android, RealityKit on Apple.
4
4
 
5
5
  **Android — Maven artifacts (version 3.3.0):**
6
- - 3D only: `io.github.sceneview:sceneview:3.3.0`
7
- - AR + 3D: `io.github.sceneview:arsceneview:3.3.0`
6
+ - 3D only: `io.github.sceneview:sceneview:3.4.7`
7
+ - AR + 3D: `io.github.sceneview:arsceneview:3.4.7`
8
8
 
9
9
  **Apple (iOS 17+ / macOS 14+ / visionOS 1+) — Swift Package:**
10
- - `https://github.com/sceneview/sceneview-swift.git` (from: "3.3.0")
10
+ - `https://github.com/sceneview/sceneview-swift.git` (from: "3.4.7")
11
11
 
12
12
  **Min SDK:** 24 | **Target SDK:** 36 | **Kotlin:** 2.3.10 | **Compose BOM compatible**
13
13
 
@@ -18,8 +18,8 @@ SceneView is a declarative 3D and AR SDK for Android (Jetpack Compose, Filament,
18
18
  ### build.gradle (app module)
19
19
  ```kotlin
20
20
  dependencies {
21
- implementation("io.github.sceneview:sceneview:3.3.0") // 3D only
22
- implementation("io.github.sceneview:arsceneview:3.3.0") // AR (includes sceneview)
21
+ implementation("io.github.sceneview:sceneview:3.4.7") // 3D only
22
+ implementation("io.github.sceneview:arsceneview:3.4.7") // AR (includes sceneview)
23
23
  }
24
24
  ```
25
25
 
@@ -853,9 +853,9 @@ fun ARImageTracking(coverBitmap: Bitmap) {
853
853
 
854
854
  ## AI Integration
855
855
 
856
- MCP server: `@sceneview/mcp`. Add to `.claude/mcp.json`:
856
+ MCP server: `sceneview-mcp`. Add to `.claude/mcp.json`:
857
857
  ```json
858
- { "mcpServers": { "sceneview": { "command": "npx", "args": ["-y", "@sceneview/mcp"] } } }
858
+ { "mcpServers": { "sceneview": { "command": "npx", "args": ["-y", "sceneview-mcp"] } } }
859
859
  ```
860
860
 
861
861
  ## Why SceneView
@@ -1176,7 +1176,7 @@ React Native (Turbo Module / Fabric), KMP Compose iOS (UIKitView).
1176
1176
  ```swift
1177
1177
  // Package.swift
1178
1178
  dependencies: [
1179
- .package(url: "https://github.com/sceneview/sceneview-swift.git", from: "3.3.0")
1179
+ .package(url: "https://github.com/sceneview/sceneview-swift.git", from: "3.4.7")
1180
1180
  ]
1181
1181
  ```
1182
1182
 
@@ -2359,7 +2359,7 @@ model.enableManipulation() // look + grab + drag + rotate + scale via system ge
2359
2359
 
2360
2360
  ## MCP Server Tools
2361
2361
 
2362
- The `@sceneview/mcp` server (npm: `sceneview-mcp`) exposes 18 tools and 2 resources for AI assistants.
2362
+ The `sceneview-mcp` server exposes 18 tools and 2 resources for AI assistants.
2363
2363
 
2364
2364
  ### Setup tools
2365
2365
  | Tool | Parameters | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sceneview-mcp",
3
- "version": "3.4.14",
3
+ "version": "3.5.0",
4
4
  "mcpName": "io.github.sceneview/mcp",
5
5
  "description": "MCP server for SceneView — cross-platform 3D & AR SDK for Android and iOS. Give Claude the full SceneView SDK so it writes correct, compilable code.",
6
6
  "keywords": [
@@ -50,6 +50,7 @@
50
50
  "dist/migrate-code.js",
51
51
  "dist/debug-issue.js",
52
52
  "dist/generate-scene.js",
53
+ "dist/advanced-guides.js",
53
54
  "llms.txt"
54
55
  ],
55
56
  "engines": {
@@ -63,7 +64,7 @@
63
64
  "test": "vitest run"
64
65
  },
65
66
  "dependencies": {
66
- "@modelcontextprotocol/sdk": "^1.12.0"
67
+ "@modelcontextprotocol/sdk": "^1.28.0"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@types/node": "^22.0.0",
@@ -73,5 +74,15 @@
73
74
  },
74
75
  "overrides": {
75
76
  "picomatch": ">=4.0.4"
76
- }
77
+ },
78
+ "funding": [
79
+ {
80
+ "type": "github",
81
+ "url": "https://github.com/sponsors/sceneview"
82
+ },
83
+ {
84
+ "type": "polar",
85
+ "url": "https://polar.sh/sceneview"
86
+ }
87
+ ]
77
88
  }