sceneview-mcp 3.1.1 → 3.3.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/LICENSE +21 -0
- package/README.md +208 -66
- package/dist/guides.js +603 -0
- package/dist/index.js +346 -15
- package/dist/issues.js +2 -2
- package/dist/migration.js +3 -3
- package/dist/node-reference.js +73 -0
- package/dist/samples.js +784 -158
- package/dist/validator.js +287 -3
- package/llms.txt +1746 -19
- package/package.json +12 -5
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ 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";
|
|
13
|
+
import { PLATFORM_ROADMAP, BEST_PRACTICES, AR_SETUP_GUIDE, TROUBLESHOOTING_GUIDE } from "./guides.js";
|
|
12
14
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
15
|
let API_DOCS;
|
|
14
16
|
try {
|
|
@@ -17,14 +19,15 @@ try {
|
|
|
17
19
|
catch {
|
|
18
20
|
API_DOCS = "SceneView API docs not found. Run `npm run prepare` to bundle llms.txt.";
|
|
19
21
|
}
|
|
20
|
-
const
|
|
22
|
+
const NODE_SECTIONS = parseNodeSections(API_DOCS);
|
|
23
|
+
const server = new Server({ name: "@sceneview/mcp", version: "3.3.0" }, { capabilities: { resources: {}, tools: {} } });
|
|
21
24
|
// ─── Resources ───────────────────────────────────────────────────────────────
|
|
22
25
|
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
23
26
|
resources: [
|
|
24
27
|
{
|
|
25
28
|
uri: "sceneview://api",
|
|
26
29
|
name: "SceneView API Reference",
|
|
27
|
-
description: "Complete SceneView 3.
|
|
30
|
+
description: "Complete SceneView 3.3.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.",
|
|
28
31
|
mimeType: "text/markdown",
|
|
29
32
|
},
|
|
30
33
|
{
|
|
@@ -77,7 +80,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
77
80
|
properties: {
|
|
78
81
|
tag: {
|
|
79
82
|
type: "string",
|
|
80
|
-
description: "Optional tag to filter by (e.g. \"ar\", \"3d\", \"
|
|
83
|
+
description: "Optional tag to filter by (e.g. \"ar\", \"3d\", \"ios\", \"swift\", \"anchor\", \"geometry\", \"animation\", \"video\", \"lighting\"). Omit to list all samples.",
|
|
81
84
|
},
|
|
82
85
|
},
|
|
83
86
|
required: [],
|
|
@@ -100,13 +103,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
100
103
|
},
|
|
101
104
|
{
|
|
102
105
|
name: "validate_code",
|
|
103
|
-
description: "Checks a Kotlin SceneView snippet for common mistakes: threading violations, wrong destroy order, missing null-checks
|
|
106
|
+
description: "Checks a Kotlin or Swift SceneView snippet for common mistakes. For Kotlin: threading violations, wrong destroy order, missing null-checks, LightNode trailing-lambda bug, deprecated 2.x APIs. For Swift: missing @MainActor, async/await patterns, missing imports, RealityKit mistakes. Language is auto-detected. Always call this before presenting generated SceneView code to the user.",
|
|
104
107
|
inputSchema: {
|
|
105
108
|
type: "object",
|
|
106
109
|
properties: {
|
|
107
110
|
code: {
|
|
108
111
|
type: "string",
|
|
109
|
-
description: "The Kotlin source code to validate (composable function, class, or file).",
|
|
112
|
+
description: "The Kotlin or Swift source code to validate (composable function, SwiftUI view, class, or file). Language is auto-detected.",
|
|
110
113
|
},
|
|
111
114
|
},
|
|
112
115
|
required: ["code"],
|
|
@@ -121,6 +124,77 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
121
124
|
required: [],
|
|
122
125
|
},
|
|
123
126
|
},
|
|
127
|
+
{
|
|
128
|
+
name: "get_node_reference",
|
|
129
|
+
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.",
|
|
130
|
+
inputSchema: {
|
|
131
|
+
type: "object",
|
|
132
|
+
properties: {
|
|
133
|
+
nodeType: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: 'The node type or composable name to look up, e.g. "ModelNode", "LightNode", "ARScene", "AnchorNode". Case-insensitive.',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
required: ["nodeType"],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "get_platform_roadmap",
|
|
143
|
+
description: "Returns the SceneView multi-platform roadmap — current Android support status, planned iOS/KMP/web targets, and timeline. Use this when the user asks about cross-platform support, iOS, Kotlin Multiplatform, or future plans.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
properties: {},
|
|
147
|
+
required: [],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "get_best_practices",
|
|
152
|
+
description: "Returns SceneView performance and architecture best practices — memory management, model optimization, threading rules, Compose integration patterns, and common anti-patterns. Use this when the user asks about performance, optimization, best practices, or architecture.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {
|
|
156
|
+
category: {
|
|
157
|
+
type: "string",
|
|
158
|
+
enum: ["all", "performance", "architecture", "memory", "threading"],
|
|
159
|
+
description: 'Category to filter by. "all" returns everything. Defaults to "all" if omitted.',
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
required: [],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "get_ar_setup",
|
|
167
|
+
description: "Returns detailed AR setup instructions — AndroidManifest permissions and features, Gradle dependencies, ARCore session configuration options (depth, light estimation, instant placement, plane detection, image tracking, cloud anchors), and a complete working AR starter template. More detailed than `get_setup` for AR-specific configuration.",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {},
|
|
171
|
+
required: [],
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "get_troubleshooting",
|
|
176
|
+
description: "Returns the SceneView troubleshooting guide — common crashes (SIGABRT, model not showing), build failures, AR issues (drift, overexposure, image detection), and performance problems. Use this when a user reports something not working, a crash, or unexpected behavior.",
|
|
177
|
+
inputSchema: {
|
|
178
|
+
type: "object",
|
|
179
|
+
properties: {},
|
|
180
|
+
required: [],
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "get_ios_setup",
|
|
185
|
+
description: "Returns the complete iOS setup guide for SceneViewSwift — SPM dependency, Package.swift example, minimum platform versions, Info.plist entries for AR (camera permission), and basic SwiftUI integration code. Use this when a user wants to set up SceneView for iOS, macOS, or visionOS.",
|
|
186
|
+
inputSchema: {
|
|
187
|
+
type: "object",
|
|
188
|
+
properties: {
|
|
189
|
+
type: {
|
|
190
|
+
type: "string",
|
|
191
|
+
enum: ["3d", "ar"],
|
|
192
|
+
description: '"3d" for 3D-only scenes. "ar" for augmented reality (requires iOS, not macOS/visionOS via this path).',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
required: ["type"],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
124
198
|
],
|
|
125
199
|
}));
|
|
126
200
|
// ─── Tool handlers ────────────────────────────────────────────────────────────
|
|
@@ -141,6 +215,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
141
215
|
isError: true,
|
|
142
216
|
};
|
|
143
217
|
}
|
|
218
|
+
const isIos = sample.language === "swift";
|
|
219
|
+
const depBlock = isIos
|
|
220
|
+
? [
|
|
221
|
+
`**SPM dependency:**`,
|
|
222
|
+
`\`\`\`swift`,
|
|
223
|
+
`.package(url: "${sample.spmDependency ?? sample.dependency}", from: "3.3.0")`,
|
|
224
|
+
`\`\`\``,
|
|
225
|
+
]
|
|
226
|
+
: [
|
|
227
|
+
`**Gradle dependency:**`,
|
|
228
|
+
`\`\`\`kotlin`,
|
|
229
|
+
`implementation("${sample.dependency}")`,
|
|
230
|
+
`\`\`\``,
|
|
231
|
+
];
|
|
232
|
+
const codeLang = isIos ? "swift" : "kotlin";
|
|
233
|
+
const codeLabel = isIos ? "**Swift (SwiftUI):**" : "**Kotlin (Jetpack Compose):**";
|
|
144
234
|
return {
|
|
145
235
|
content: [
|
|
146
236
|
{
|
|
@@ -150,13 +240,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
150
240
|
``,
|
|
151
241
|
`**Tags:** ${sample.tags.join(", ")}`,
|
|
152
242
|
``,
|
|
153
|
-
|
|
154
|
-
`\`\`\`kotlin`,
|
|
155
|
-
`implementation("${sample.dependency}")`,
|
|
156
|
-
`\`\`\``,
|
|
243
|
+
...depBlock,
|
|
157
244
|
``,
|
|
158
|
-
|
|
159
|
-
|
|
245
|
+
codeLabel,
|
|
246
|
+
`\`\`\`${codeLang}`,
|
|
160
247
|
sample.code,
|
|
161
248
|
`\`\`\``,
|
|
162
249
|
``,
|
|
@@ -176,7 +263,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
176
263
|
content: [
|
|
177
264
|
{
|
|
178
265
|
type: "text",
|
|
179
|
-
text: `No samples found with tag "${filterTag}". Available tags: 3d, ar, model, geometry, animation, camera, environment, anchor, plane-detection, image-tracking,
|
|
266
|
+
text: `No samples found with tag "${filterTag}". Available tags: 3d, ar, model, geometry, animation, camera, environment, anchor, plane-detection, image-tracking, cloud-anchor, point-cloud, placement, gestures, physics, sky, fog, lines, text, reflection, post-processing, ios, swift, video, lighting`,
|
|
180
267
|
},
|
|
181
268
|
],
|
|
182
269
|
};
|
|
@@ -185,7 +272,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
185
272
|
? `## SceneView samples tagged \`${filterTag}\` (${entries.length})\n`
|
|
186
273
|
: `## All SceneView samples (${entries.length})\n`;
|
|
187
274
|
const rows = entries
|
|
188
|
-
.map((s) =>
|
|
275
|
+
.map((s) => {
|
|
276
|
+
const depLabel = s.language === "swift" ? "*SPM:*" : "*Dependency:*";
|
|
277
|
+
return `### \`${s.id}\`\n**${s.title}**${s.language === "swift" ? " (Swift/iOS)" : ""}\n${s.description}\n*Tags:* ${s.tags.join(", ")}\n${depLabel} \`${s.dependency}\`\n\nCall \`get_sample("${s.id}")\` for the full code.`;
|
|
278
|
+
})
|
|
189
279
|
.join("\n\n---\n\n");
|
|
190
280
|
return { content: [{ type: "text", text: header + rows }] };
|
|
191
281
|
}
|
|
@@ -203,7 +293,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
203
293
|
`### build.gradle.kts`,
|
|
204
294
|
`\`\`\`kotlin`,
|
|
205
295
|
`dependencies {`,
|
|
206
|
-
` implementation("io.github.sceneview:sceneview:3.
|
|
296
|
+
` implementation("io.github.sceneview:sceneview:3.3.0")`,
|
|
207
297
|
`}`,
|
|
208
298
|
`\`\`\``,
|
|
209
299
|
``,
|
|
@@ -224,7 +314,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
224
314
|
`### build.gradle.kts`,
|
|
225
315
|
`\`\`\`kotlin`,
|
|
226
316
|
`dependencies {`,
|
|
227
|
-
` implementation("io.github.sceneview:arsceneview:3.
|
|
317
|
+
` implementation("io.github.sceneview:arsceneview:3.3.0")`,
|
|
228
318
|
`}`,
|
|
229
319
|
`\`\`\``,
|
|
230
320
|
``,
|
|
@@ -263,6 +353,247 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
263
353
|
case "get_migration_guide": {
|
|
264
354
|
return { content: [{ type: "text", text: MIGRATION_GUIDE }] };
|
|
265
355
|
}
|
|
356
|
+
// ── get_node_reference ────────────────────────────────────────────────────
|
|
357
|
+
case "get_node_reference": {
|
|
358
|
+
const nodeType = request.params.arguments?.nodeType;
|
|
359
|
+
if (!nodeType || typeof nodeType !== "string") {
|
|
360
|
+
return {
|
|
361
|
+
content: [{ type: "text", text: "Missing required parameter: `nodeType`" }],
|
|
362
|
+
isError: true,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const section = findNodeSection(NODE_SECTIONS, nodeType);
|
|
366
|
+
if (!section) {
|
|
367
|
+
const available = listNodeTypes(NODE_SECTIONS).join(", ");
|
|
368
|
+
return {
|
|
369
|
+
content: [
|
|
370
|
+
{
|
|
371
|
+
type: "text",
|
|
372
|
+
text: [
|
|
373
|
+
`No reference found for node type \`${nodeType}\`.`,
|
|
374
|
+
``,
|
|
375
|
+
`**Available node types:**`,
|
|
376
|
+
available,
|
|
377
|
+
].join("\n"),
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
content: [
|
|
384
|
+
{
|
|
385
|
+
type: "text",
|
|
386
|
+
text: [
|
|
387
|
+
`## \`${section.name}\` — API Reference`,
|
|
388
|
+
``,
|
|
389
|
+
section.content,
|
|
390
|
+
].join("\n"),
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
// ── get_platform_roadmap ────────────────────────────────────────────────
|
|
396
|
+
case "get_platform_roadmap": {
|
|
397
|
+
return { content: [{ type: "text", text: PLATFORM_ROADMAP }] };
|
|
398
|
+
}
|
|
399
|
+
// ── get_best_practices ───────────────────────────────────────────────────
|
|
400
|
+
case "get_best_practices": {
|
|
401
|
+
const category = request.params.arguments?.category || "all";
|
|
402
|
+
const text = BEST_PRACTICES[category] ?? BEST_PRACTICES["all"];
|
|
403
|
+
return { content: [{ type: "text", text }] };
|
|
404
|
+
}
|
|
405
|
+
// ── get_ar_setup ─────────────────────────────────────────────────────────
|
|
406
|
+
case "get_ar_setup": {
|
|
407
|
+
return { content: [{ type: "text", text: AR_SETUP_GUIDE }] };
|
|
408
|
+
}
|
|
409
|
+
// ── get_troubleshooting ──────────────────────────────────────────────────
|
|
410
|
+
case "get_troubleshooting": {
|
|
411
|
+
return { content: [{ type: "text", text: TROUBLESHOOTING_GUIDE }] };
|
|
412
|
+
}
|
|
413
|
+
// ── get_ios_setup ─────────────────────────────────────────────────────────
|
|
414
|
+
case "get_ios_setup": {
|
|
415
|
+
const iosType = request.params.arguments?.type;
|
|
416
|
+
if (iosType === "3d") {
|
|
417
|
+
return {
|
|
418
|
+
content: [
|
|
419
|
+
{
|
|
420
|
+
type: "text",
|
|
421
|
+
text: [
|
|
422
|
+
`## SceneViewSwift — iOS/macOS/visionOS 3D Setup`,
|
|
423
|
+
``,
|
|
424
|
+
`### 1. Add SPM Dependency`,
|
|
425
|
+
``,
|
|
426
|
+
`In Xcode: **File → Add Package Dependencies** → paste:`,
|
|
427
|
+
`\`\`\``,
|
|
428
|
+
`https://github.com/SceneView/sceneview`,
|
|
429
|
+
`\`\`\``,
|
|
430
|
+
`Set version rule to **"from: 3.3.0"**.`,
|
|
431
|
+
``,
|
|
432
|
+
`Or in Package.swift:`,
|
|
433
|
+
`\`\`\`swift`,
|
|
434
|
+
`// swift-tools-version: 5.10`,
|
|
435
|
+
`import PackageDescription`,
|
|
436
|
+
``,
|
|
437
|
+
`let package = Package(`,
|
|
438
|
+
` name: "MyApp",`,
|
|
439
|
+
` platforms: [.iOS(.v17), .macOS(.v14), .visionOS(.v1)],`,
|
|
440
|
+
` dependencies: [`,
|
|
441
|
+
` .package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")`,
|
|
442
|
+
` ],`,
|
|
443
|
+
` targets: [`,
|
|
444
|
+
` .executableTarget(`,
|
|
445
|
+
` name: "MyApp",`,
|
|
446
|
+
` dependencies: [`,
|
|
447
|
+
` .product(name: "SceneViewSwift", package: "sceneview")`,
|
|
448
|
+
` ]`,
|
|
449
|
+
` )`,
|
|
450
|
+
` ]`,
|
|
451
|
+
`)`,
|
|
452
|
+
`\`\`\``,
|
|
453
|
+
``,
|
|
454
|
+
`### 2. Minimum Platform Versions`,
|
|
455
|
+
``,
|
|
456
|
+
`| Platform | Minimum Version |`,
|
|
457
|
+
`|----------|-----------------|`,
|
|
458
|
+
`| iOS | 17.0 |`,
|
|
459
|
+
`| macOS | 14.0 |`,
|
|
460
|
+
`| visionOS | 1.0 |`,
|
|
461
|
+
``,
|
|
462
|
+
`### 3. Basic SwiftUI Integration`,
|
|
463
|
+
``,
|
|
464
|
+
`\`\`\`swift`,
|
|
465
|
+
`import SwiftUI`,
|
|
466
|
+
`import SceneViewSwift`,
|
|
467
|
+
`import RealityKit`,
|
|
468
|
+
``,
|
|
469
|
+
`struct ContentView: View {`,
|
|
470
|
+
` @State private var model: ModelNode?`,
|
|
471
|
+
``,
|
|
472
|
+
` var body: some View {`,
|
|
473
|
+
` SceneView { root in`,
|
|
474
|
+
` if let model {`,
|
|
475
|
+
` root.addChild(model.entity)`,
|
|
476
|
+
` }`,
|
|
477
|
+
` }`,
|
|
478
|
+
` .cameraControls(.orbit)`,
|
|
479
|
+
` .task {`,
|
|
480
|
+
` model = try? await ModelNode.load("models/car.usdz")`,
|
|
481
|
+
` model?.scaleToUnits(1.0)`,
|
|
482
|
+
` }`,
|
|
483
|
+
` }`,
|
|
484
|
+
`}`,
|
|
485
|
+
`\`\`\``,
|
|
486
|
+
``,
|
|
487
|
+
`### 4. Model Formats`,
|
|
488
|
+
``,
|
|
489
|
+
`| Format | Support |`,
|
|
490
|
+
`|--------|---------|`,
|
|
491
|
+
`| USDZ | Native — recommended for iOS |`,
|
|
492
|
+
`| .reality | Native — RealityKit format |`,
|
|
493
|
+
`| glTF/GLB | Planned via GLTFKit2 |`,
|
|
494
|
+
``,
|
|
495
|
+
`No manifest or permission changes needed for 3D-only scenes.`,
|
|
496
|
+
].join("\n"),
|
|
497
|
+
},
|
|
498
|
+
],
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
if (iosType === "ar") {
|
|
502
|
+
return {
|
|
503
|
+
content: [
|
|
504
|
+
{
|
|
505
|
+
type: "text",
|
|
506
|
+
text: [
|
|
507
|
+
`## SceneViewSwift — iOS AR Setup`,
|
|
508
|
+
``,
|
|
509
|
+
`### 1. Add SPM Dependency`,
|
|
510
|
+
``,
|
|
511
|
+
`\`\`\`swift`,
|
|
512
|
+
`.package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")`,
|
|
513
|
+
`\`\`\``,
|
|
514
|
+
``,
|
|
515
|
+
`### 2. Minimum Platform`,
|
|
516
|
+
``,
|
|
517
|
+
`AR requires **iOS 17.0+** (ARKit + RealityKit). macOS and visionOS use different AR APIs.`,
|
|
518
|
+
``,
|
|
519
|
+
`### 3. Info.plist — Camera Permission`,
|
|
520
|
+
``,
|
|
521
|
+
`Add to your Info.plist (required for AR camera access):`,
|
|
522
|
+
`\`\`\`xml`,
|
|
523
|
+
`<key>NSCameraUsageDescription</key>`,
|
|
524
|
+
`<string>This app uses the camera for augmented reality.</string>`,
|
|
525
|
+
`\`\`\``,
|
|
526
|
+
``,
|
|
527
|
+
`### 4. Basic AR Integration`,
|
|
528
|
+
``,
|
|
529
|
+
`\`\`\`swift`,
|
|
530
|
+
`import SwiftUI`,
|
|
531
|
+
`import SceneViewSwift`,
|
|
532
|
+
`import RealityKit`,
|
|
533
|
+
``,
|
|
534
|
+
`struct ARContentView: View {`,
|
|
535
|
+
` @State private var model: ModelNode?`,
|
|
536
|
+
``,
|
|
537
|
+
` var body: some View {`,
|
|
538
|
+
` ARSceneView(`,
|
|
539
|
+
` planeDetection: .horizontal,`,
|
|
540
|
+
` showCoachingOverlay: true,`,
|
|
541
|
+
` onTapOnPlane: { position, arView in`,
|
|
542
|
+
` guard let model else { return }`,
|
|
543
|
+
` let anchor = AnchorNode.world(position: position)`,
|
|
544
|
+
` let clone = model.entity.clone(recursive: true)`,
|
|
545
|
+
` clone.scale = .init(repeating: 0.3)`,
|
|
546
|
+
` anchor.add(clone)`,
|
|
547
|
+
` arView.scene.addAnchor(anchor.entity)`,
|
|
548
|
+
` }`,
|
|
549
|
+
` )`,
|
|
550
|
+
` .edgesIgnoringSafeArea(.all)`,
|
|
551
|
+
` .task {`,
|
|
552
|
+
` model = try? await ModelNode.load("models/robot.usdz")`,
|
|
553
|
+
` }`,
|
|
554
|
+
` }`,
|
|
555
|
+
`}`,
|
|
556
|
+
`\`\`\``,
|
|
557
|
+
``,
|
|
558
|
+
`### 5. AR Configuration Options`,
|
|
559
|
+
``,
|
|
560
|
+
`| Parameter | Options | Default |`,
|
|
561
|
+
`|-----------|---------|---------|`,
|
|
562
|
+
`| \`planeDetection\` | \`.none\`, \`.horizontal\`, \`.vertical\`, \`.both\` | \`.horizontal\` |`,
|
|
563
|
+
`| \`showPlaneOverlay\` | \`true\` / \`false\` | \`true\` |`,
|
|
564
|
+
`| \`showCoachingOverlay\` | \`true\` / \`false\` | \`true\` |`,
|
|
565
|
+
`| \`imageTrackingDatabase\` | \`Set<ARReferenceImage>\` | \`nil\` |`,
|
|
566
|
+
``,
|
|
567
|
+
`### 6. Image Tracking`,
|
|
568
|
+
``,
|
|
569
|
+
`\`\`\`swift`,
|
|
570
|
+
`let images = AugmentedImageNode.createImageDatabase([`,
|
|
571
|
+
` AugmentedImageNode.ReferenceImage(`,
|
|
572
|
+
` name: "poster",`,
|
|
573
|
+
` image: UIImage(named: "poster_ref")!,`,
|
|
574
|
+
` physicalWidth: 0.3 // meters`,
|
|
575
|
+
` )`,
|
|
576
|
+
`])`,
|
|
577
|
+
``,
|
|
578
|
+
`ARSceneView(`,
|
|
579
|
+
` imageTrackingDatabase: images,`,
|
|
580
|
+
` onImageDetected: { name, anchor, arView in`,
|
|
581
|
+
` let cube = GeometryNode.cube(size: 0.1, color: .blue)`,
|
|
582
|
+
` anchor.add(cube.entity)`,
|
|
583
|
+
` arView.scene.addAnchor(anchor.entity)`,
|
|
584
|
+
` }`,
|
|
585
|
+
`)`,
|
|
586
|
+
`\`\`\``,
|
|
587
|
+
].join("\n"),
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
return {
|
|
593
|
+
content: [{ type: "text", text: `Unknown type "${iosType}". Use "3d" or "ar".` }],
|
|
594
|
+
isError: true,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
266
597
|
default:
|
|
267
598
|
return {
|
|
268
599
|
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
|
|
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.0",
|
|
15
|
+
"User-Agent": "sceneview-mcp/3.3.0",
|
|
16
16
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
17
17
|
},
|
|
18
18
|
});
|
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.
|
|
12
|
-
| \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.
|
|
11
|
+
| \`io.github.sceneview:sceneview:2.x.x\` | \`io.github.sceneview:sceneview:3.3.0\` |
|
|
12
|
+
| \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.3.0\` |
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -174,7 +174,7 @@ LightNode(
|
|
|
174
174
|
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
175
175
|
Scene(
|
|
176
176
|
environment = rememberEnvironment(environmentLoader) {
|
|
177
|
-
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
177
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr") ?: createEnvironment(environmentLoader)
|
|
178
178
|
}
|
|
179
179
|
) { … }
|
|
180
180
|
\`\`\`
|
|
@@ -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
|
+
}
|