Get Key Light Position (Spherical Coordinates)
get_key_light_position_sphericalRetrieve the key light's current spherical coordinates relative to the camera. Query before making relative light adjustments to maintain accuracy.
Instructions
Get the current key light position in camera-centric spherical coordinates. Query this before relative position changes (e.g., "rotate light 10 degrees") to ensure accuracy. For absolute changes, you may use recently queried state from context if no manual interactions occurred.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- server.js:1114-1162 (registration)Registration of the 'get_key_light_position_spherical' tool via mcpServer.registerTool(). Includes schema definition (empty inputSchema) and the async handler that queries state and returns the key light position.
mcpServer.registerTool( 'get_key_light_position_spherical', { title: 'Get Key Light Position (Spherical Coordinates)', description: 'Get the current key light position in camera-centric spherical coordinates. ' + 'Query this before relative position changes (e.g., "rotate light 10 degrees") to ensure accuracy. ' + 'For absolute changes, you may use recently queried state from context if no manual interactions occurred.', inputSchema: {} }, async () => { const sessionId = getCurrentSessionId(); if (!sessionId) { return { content: [ { type: 'text', text: 'Error: No active session found.' } ], isError: true }; } try { const { state, metadata } = await getState(sessionId); const position = state.keyLight?.position || { azimuth: 0, elevation: 0, distance: 0 }; const positionText = `azimuth ${position.azimuth}°, elevation ${position.elevation}°, distance ${position.distance}`; return { content: [ { type: 'text', text: formatStateResponse(positionText, 'Key light position', sessionId, metadata) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error retrieving key light position: ${error.message}` } ], isError: true }; } } ); - server.js:1123-1161 (handler)The async handler function for get_key_light_position_spherical. It gets the current session ID, queries state from the browser via getState(), extracts keyLight.position (azimuth, elevation, distance), and returns the formatted response.
async () => { const sessionId = getCurrentSessionId(); if (!sessionId) { return { content: [ { type: 'text', text: 'Error: No active session found.' } ], isError: true }; } try { const { state, metadata } = await getState(sessionId); const position = state.keyLight?.position || { azimuth: 0, elevation: 0, distance: 0 }; const positionText = `azimuth ${position.azimuth}°, elevation ${position.elevation}°, distance ${position.distance}`; return { content: [ { type: 'text', text: formatStateResponse(positionText, 'Key light position', sessionId, metadata) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error retrieving key light position: ${error.message}` } ], isError: true }; } } - server.js:1121-1121 (schema)Input schema for get_key_light_position_spherical - an empty object ({}) indicating no parameters are required.
inputSchema: {} - server.js:329-338 (helper)queryFreshStateForManipulation helper - used to fetch fresh state from the browser before relative manipulations.
// Helper function to query fresh state before relative manipulations async function queryFreshStateForManipulation(sessionId) { try { const { state } = await getState(sessionId); return state; } catch (error) { console.warn(`Failed to query fresh state before manipulation: ${error.message}`); return null; } } - server.js:264-316 (helper)getState and queryStateFromBrowser helpers - used by the handler to query the current 3D scene state (including light positions) from the connected browser client.
// Query state from browser (with optional force refresh) async function queryStateFromBrowser(sessionId) { const requestId = generateRequestId(); // Send request to browser const sent = sendToSession(sessionId, { type: 'requestState', requestId: requestId, forceRefresh: false }); if (!sent) { throw new Error('Browser not connected'); } // Wait for response return await waitForStateResponse(requestId); } // Get state (always queries browser, cache only as fallback) async function getState(sessionId) { let state; let source; let wasCached = false; // Always query browser for current state try { state = await queryStateFromBrowser(sessionId); source = 'fresh'; } catch (error) { // If query fails, fall back to cache if available (browser may be disconnected) const cached = sessionStateCache.get(sessionId); if (cached) { console.warn(`Browser query failed for session ${sessionId}, returning cached state: ${error.message}`); state = cached.state; source = 'cache'; wasCached = true; } else { // No cache available, throw error throw new Error(`Unable to retrieve state: ${error.message}. Browser may be disconnected.`); } } // Return state with metadata return { state, metadata: { source, wasCached, timestamp: new Date().toISOString() } }; }