sceneview-mcp 3.6.2 → 3.6.5

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.
@@ -0,0 +1,120 @@
1
+ // ─── Anonymous opt-out telemetry for sceneview-mcp ───────────────────────────
2
+ //
3
+ // Fire-and-forget, non-blocking, no personal data. Ever.
4
+ //
5
+ // What gets sent:
6
+ // - timestamp (UTC ISO string)
7
+ // - event: "init" | "tool"
8
+ // - client: MCP client name (e.g. "claude-desktop", "cursor")
9
+ // - clientVersion: MCP client version string reported during handshake
10
+ // - mcpVersion: this package's version
11
+ // - tier: "free" | "pro"
12
+ // - tool?: tool name (only for "tool" events)
13
+ //
14
+ // What NEVER gets sent:
15
+ // - IP address (the endpoint strips it server-side; we never send headers)
16
+ // - hostname, OS user, machine id
17
+ // - prompt content, tool arguments, tool results
18
+ // - API keys, billing info
19
+ //
20
+ // Opt out with `SCENEVIEW_TELEMETRY=0` or by running in CI (`CI=true`).
21
+ // TODO: Provision a Cloudflare Worker at this address that ingests events
22
+ // into a lightweight store (Workers Analytics Engine or R2 + daily rollup).
23
+ // Until the Worker is deployed, requests to this endpoint will fail silently,
24
+ // which is fine — fetch errors are swallowed by design.
25
+ const TELEMETRY_ENDPOINT = "https://telemetry.sceneview.io/v1/events";
26
+ // Hard cap so we never hang the process on a slow endpoint.
27
+ const TELEMETRY_TIMEOUT_MS = 2000;
28
+ let clientContext;
29
+ // Read lazily so tests that mutate env vars between runs see the latest value.
30
+ function isEnabled() {
31
+ if (process.env.SCENEVIEW_TELEMETRY === "0")
32
+ return false;
33
+ if (process.env.CI === "true")
34
+ return false;
35
+ return true;
36
+ }
37
+ // Read the package version lazily so tests don't need to mock fs.
38
+ // Falls back to "unknown" so payloads stay well-formed even if
39
+ // something goes wrong.
40
+ function getMcpVersion() {
41
+ return process.env.SCENEVIEW_MCP_VERSION ?? "3.6.4";
42
+ }
43
+ /** Exposed for tests — resets the cached client context. */
44
+ export function __resetClientContext() {
45
+ clientContext = undefined;
46
+ }
47
+ // Fire-and-forget POST with a timeout. Never throws, never awaits the caller.
48
+ function send(payload) {
49
+ if (!isEnabled())
50
+ return;
51
+ // Build a bounded promise so we never hang on a slow endpoint. We
52
+ // intentionally do NOT await this from the caller — telemetry must
53
+ // never block the handshake or a tool call. Wrap everything in a
54
+ // try/catch because a buggy fetch polyfill (or a test mock) could
55
+ // throw synchronously before we get a chance to attach .catch.
56
+ try {
57
+ const controller = new AbortController();
58
+ const timeoutId = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
59
+ fetch(TELEMETRY_ENDPOINT, {
60
+ method: "POST",
61
+ headers: { "content-type": "application/json" },
62
+ body: JSON.stringify(payload),
63
+ signal: controller.signal,
64
+ })
65
+ .catch(() => {
66
+ // Swallow all failures — network errors, DNS, timeouts, non-2xx.
67
+ // Telemetry is best-effort.
68
+ })
69
+ .finally(() => {
70
+ clearTimeout(timeoutId);
71
+ });
72
+ }
73
+ catch {
74
+ // Swallow synchronous throws too.
75
+ }
76
+ }
77
+ /**
78
+ * Record an MCP client handshake. Called from the server's `oninitialized`
79
+ * callback once the client has advertised its name/version. Safe to call
80
+ * with `undefined` if the client didn't report info — the event is dropped.
81
+ */
82
+ export function recordClientInit(clientInfo) {
83
+ if (!clientInfo)
84
+ return;
85
+ clientContext = {
86
+ client: clientInfo.name,
87
+ clientVersion: clientInfo.version,
88
+ };
89
+ if (!isEnabled())
90
+ return;
91
+ send({
92
+ timestamp: new Date().toISOString(),
93
+ event: "init",
94
+ client: clientContext.client,
95
+ clientVersion: clientContext.clientVersion,
96
+ mcpVersion: getMcpVersion(),
97
+ tier: "free",
98
+ });
99
+ }
100
+ /**
101
+ * Record a tool invocation. Called from the `CallToolRequestSchema` handler
102
+ * after the tier check has passed. `tier` is the tier the tool resolved to,
103
+ * not the user's subscription status.
104
+ */
105
+ export function recordToolCall(toolName, tier) {
106
+ if (!isEnabled())
107
+ return;
108
+ // If the client never completed initialization (which shouldn't happen in
109
+ // practice), fall back to "unknown" so we can still see the tool mix.
110
+ const ctx = clientContext ?? { client: "unknown", clientVersion: "unknown" };
111
+ send({
112
+ timestamp: new Date().toISOString(),
113
+ event: "tool",
114
+ client: ctx.client,
115
+ clientVersion: ctx.clientVersion,
116
+ mcpVersion: getMcpVersion(),
117
+ tier,
118
+ tool: toolName,
119
+ });
120
+ }
package/dist/tiers.js ADDED
@@ -0,0 +1,100 @@
1
+ // ─── Tool tier system ─────────────────────────────────────────────────────────
2
+ //
3
+ // Defines free vs pro tool access for SceneView MCP.
4
+ // ─── Free tools (17) ─────────────────────────────────────────────────────────
5
+ const FREE_TOOLS = [
6
+ "list_samples",
7
+ "get_sample",
8
+ "get_setup",
9
+ "get_node_reference",
10
+ "list_platforms",
11
+ "validate_code",
12
+ "get_troubleshooting",
13
+ "debug_issue",
14
+ "get_best_practices",
15
+ "get_animation_guide",
16
+ "get_gesture_guide",
17
+ "get_performance_tips",
18
+ "get_material_guide",
19
+ "get_collision_guide",
20
+ "get_platform_roadmap",
21
+ "search_models",
22
+ "analyze_project",
23
+ ];
24
+ // ─── Pro tools ────────────────────────────────────────────────────────────────
25
+ const PRO_TOOLS = [
26
+ // Core pro tools
27
+ "get_ios_setup",
28
+ "get_web_setup",
29
+ "get_ar_setup",
30
+ "get_platform_setup",
31
+ "migrate_code",
32
+ "get_migration_guide",
33
+ "render_3d_preview",
34
+ "create_3d_artifact",
35
+ "generate_scene",
36
+ "get_model_optimization_guide",
37
+ "get_web_rendering_guide",
38
+ // Automotive package
39
+ "get_car_configurator",
40
+ "get_dashboard_3d",
41
+ "get_parts_catalog",
42
+ "get_hud_overlay",
43
+ "get_ar_showroom",
44
+ "list_car_models",
45
+ // Gaming package
46
+ "get_physics_game",
47
+ "get_particle_effects",
48
+ "get_level_editor",
49
+ "get_inventory_3d",
50
+ "get_character_viewer",
51
+ "list_game_models",
52
+ // Healthcare package
53
+ "get_surgical_planning",
54
+ "get_dental_viewer",
55
+ "get_medical_imaging",
56
+ "get_anatomy_viewer",
57
+ "get_molecule_viewer",
58
+ "list_medical_models",
59
+ // Interior package
60
+ "get_room_planner",
61
+ "get_lighting_design",
62
+ "get_room_tour",
63
+ "get_material_switcher",
64
+ "get_furniture_placement",
65
+ "list_furniture_models",
66
+ ];
67
+ // ─── Tier map ─────────────────────────────────────────────────────────────────
68
+ export const TOOL_TIERS = Object.fromEntries([
69
+ ...FREE_TOOLS.map((name) => [name, "free"]),
70
+ ...PRO_TOOLS.map((name) => [name, "pro"]),
71
+ ]);
72
+ // ─── Helper functions ─────────────────────────────────────────────────────────
73
+ /** Returns true if the tool requires a Pro subscription. Unknown tools default to pro. */
74
+ export function isProTool(toolName) {
75
+ return getToolTier(toolName) === "pro";
76
+ }
77
+ /** Returns the tier for a tool. Defaults to "pro" for unknown tools. */
78
+ export function getToolTier(toolName) {
79
+ return TOOL_TIERS[toolName] ?? "pro";
80
+ }
81
+ /** Returns all pro tool names. */
82
+ export function getProToolNames() {
83
+ return [...PRO_TOOLS];
84
+ }
85
+ /** Returns all free tool names. */
86
+ export function getFreeToolNames() {
87
+ return [...FREE_TOOLS];
88
+ }
89
+ // ─── Upgrade message ──────────────────────────────────────────────────────────
90
+ export const PRO_UPGRADE_MESSAGE = `## \u{1F512} Pro Feature
91
+
92
+ This tool requires a SceneView MCP Pro subscription.
93
+
94
+ **Upgrade for \u20AC19/month** to unlock:
95
+ - 35+ premium tools (AR, multi-platform, scene generation, artifacts)
96
+ - Specialized packages (Automotive, Gaming, Healthcare, Interior)
97
+ - Email support
98
+
99
+ \u2192 Subscribe at https://sceneview-mcp.mcp-tools-lab.workers.dev/pricing
100
+ \u2192 Then set your API key: \`SCENEVIEW_API_KEY=your_key\``;