MCP serverTools

Simulation tools

The Extentos MCP server's simulation tools — createSimulatorSession (provision a browser-mode session at extentos.com/s with auto-bind to the running app; first call requires a free email-only account), ensureSimulatorBrowser (open + confirm a connected sim browser tab — the precondition for camera/inject flows), completeAuthLink (poll the device-code flow when account-linking is required), getEventLog (structured 6-chip event trace from a session), getSimulatorStatus (live session state). The browser-driven dev loop.

Five tools orchestrate the browser-simulator dev loop. The simulator hosts your customer-built app running against a Meta-DAT-shaped transport stub — glasses.audio.transcriptions(), glasses.camera.capturePhoto(), glasses.audio.speak() and every other capability primitive flow through it exactly as on real hardware.

createSimulatorSession

Get-or-create a browser-based simulator session for the current project. Persistent-simulations model: each (account, project, platform) has at most one saved sim. Calling this returns that sim's existing URL (status: "resumed") instead of minting a new one.

Parameters: glasses: "meta_rayban" (required), platform: "android" | "ios", projectPath, recordBinary, autoOpenBrowser, autoLink (default true; auto-poll the device-code flow if auth_required returns), autoLinkSeconds (default 30), resetFresh (default false; force-archive existing and mint fresh).

Response: { status, sessionId, sessionUrl, transportEndpoint, expiresAt, autoBind: "attached" | "no_device", capabilities, developerInstructions, summary }. Auto-bind tries to attach the running app via the local MCP bridge; falls back to a URL-bake snippet (Android buildConfigField patch / iOS extentos.session.plist write) when the bridge can't reach.

Iteration model — do NOT call this per change: app-code edits rebuild + reinstall and reattach automatically. The simulator URL is stable. Calling this again on the same project just returns the same sim — cheap, idempotent.

ensureSimulatorBrowser

Guarantee a connected simulator browser tab — open one if needed and confirm its WebSocket actually attached before returning. The browser tab is the hardware surrogate's viewport: camera and inject flows (setSimVideo, and any capture_photo / describe_scene the assistant runtime drives) return browser_role_not_attached without it. Idempotent — a no-op if a browser is already connected, so it's safe to call before every camera flow.

When to call: right after createSimulatorSession before a camera-driven flow; after a backend deploy (which severs every sim WebSocket — the tab does not auto-reconnect); whenever the tab was closed; or any time the browser role shows as detached.

Parameters: sessionId (required), timeoutMs (default 20000, clamped [5000, 60000]), autoOpen (default true).

Response: { alreadyOpen, opened, browserConnected, browserClientId, appConnected, sessionUrl, waitedMs, summary }. On an auto-open that doesn't attach in time, errors with browser_not_connected (carrying sessionUrl).

It reads the authoritative in-memory hub liveness — the same signal setSimVideo/inject enforce, so it can't disagree with them (unlike getSimulatorStatus.connectedRoles, which is persisted state that can lag a dead socket by ~25–50s). When a tab is needed it opens the session URL in your default browser cross-platform, from the MCP server itself (no shell command for you to run), then polls until the WebSocket attaches. Headless / remote agents: pass autoOpen: false to get the sessionUrl back with no spawn and no wait — surface it to the developer to open on a machine with a display, then re-run with autoOpen: true to confirm.

Poll the backend until the developer finishes signup at the verification URL, then persist the bearer token to ~/.extentos/auth.json. Use only when createSimulatorSession returns status: "auth_required" AND you opted out of autoLink (or the inline poll timed out).

Parameters: deviceCode (from the prior createSimulatorSession response), maxWaitSeconds, pollIntervalSeconds.

getEventLog

Fetch structured event trace inside a simulator session. The primary debugging tool — answers "why didn't my handler see what I expected?"

Parameters: sessionId (required), filter (all / errors / voice / camera / ai / lifecycle / custom), limit, since, responseFormat (concise / detailed), redactBinary (default true — large data: URIs and >2KB strings collapse to a [redacted: N chars] marker so a single capture_photo response doesn't blow the agent's context).

Response: { events: EventRecord[], sessionStatus, totalEvents, hasMore, summary }. Each event carries layer + severity + type + message + optional details.

Post-2026-05 redesign uses a 6-chip taxonomy. One label per event: severity≥warn absorbs into errors regardless of modality (so camera_error lives in errors, not camera); then prefix-match into voice / camera / ai / lifecycle; then custom for app-emitted opens. Pre-pivot filter values (triggers / blocks / callbacks / spec) AND the intermediate 7-layer values (transport / audio / speak / toggles / streams / system) are retired. See searchDocs("event_log_schema") for the complete rules + event-type catalog per chip.

getSimulatorStatus

Read a live simulator session's current state — phase (active / paused / closed), hardware-ready, attached roles (app + browser), active capability streams (which subscriptions are open right now), current toggle values.

Parameters: sessionId (required).

Response: { sessionId, sessionState, hardwareReady, connectionState, connectedRoles, activeStreams[], expiresAt, recording, summary }.

Use during testing to confirm a stream is open, a toggle is set, the session is healthy, or the app role has actually attached. Distinct from getEventLog (event trace) — this is the snapshot view.