When a user starts your app, you get a MentraSession. This is your connection to that user - everything you do with their glasses goes through it.
import { MiniAppServer, type MentraSession } from "@mentra/sdk";

const app = new MiniAppServer({ ... });

app.onSession((session: MentraSession) => {
  // session.userId        - who this user is
  // session.sessionId     - unique ID for this session
  // session.logger        - pino logger scoped to this user

  session.transcription.on((data) => {
    session.display.showTextWall(data.text);
  });
});

Managers

Every capability on the glasses is accessed through a manager on the session object. Type session. in your editor and autocomplete will show you everything available.

Input

ManagerAccessWhat it does
Transcriptionsession.transcriptionReal-time speech-to-text. Subscribe to all languages or filter by language. Configure diarization and language hints.
Translationsession.translationReal-time translation. Subscribe to all translations or filter by target language.
Micsession.micRaw audio chunks from the microphone and voice activity detection. Independent from transcription - subscribing to one does not give you the other.
Camerasession.cameraTake photos, start/stop video streams. Supports both display glasses (no camera) and camera glasses (Mentra Live).
Locationsession.locationGPS coordinates. Get the latest location or subscribe to updates.

Output

ManagerAccessWhat it does
Displaysession.displayShow text, text walls, double text walls, reference cards, and bitmaps on the glasses HUD.
Speakersession.speakerPlay audio files, text-to-speech, and stream audio in real time.
LEDsession.ledControl the LED light on supported glasses.
Dashboardsession.dashboardWrite to the system dashboard view (the screen users see when they look up).

Device & State

ManagerAccessWhat it does
Devicesession.deviceHardware state (battery, model, connection), button/touch events, WiFi, and device capabilities. All state values are reactive Observables.
Phonesession.phonePhone notifications, calendar events, and phone battery. Sub-scoped: session.phone.notifications and session.phone.calendar.
Permissionssession.permissionsCheck what your app is allowed to do. Query individual permissions or get all of them. Subscribe to changes.

Utilities

ManagerAccessWhat it does
Storagesession.storagePersistent key-value storage for your app. Data survives across sessions.
Timesession.timeTimezone-aware time utilities. Get the current time in the user’s timezone, format dates, access the timezone string.

Lifecycle

A session goes through these states:
  1. Connected - onSession fires. The user opened your app.
  2. Running - Your code is active. Subscriptions are delivering data.
  3. Transport down - The WebSocket connection dropped briefly (network blip, cloud deploy). Your session stays alive. Subscriptions are preserved.
  4. Reconnected - The connection was restored. session.onReconnected() fires. No action needed - everything resumes automatically.
  5. Stopped - The session ended (user closed the app, or the grace period expired). session.onStopped() fires.
app.onSession((session) => {
  // 1. Connected - set up your app
  session.transcription.on((data) => {
    session.display.showTextWall(data.text);
  });

  // 4. Reconnected - connection restored after a blip
  session.onReconnected(() => {
    session.logger.info("Reconnected - subscriptions still active");
  });

  // 5. Stopped - clean up
  session.onStopped((reason) => {
    session.logger.info("Session ended:", reason);
  });
});
The key thing: a transport blip does not kill your session. In v3, the SDK holds the session alive during brief disconnections. Your subscriptions, your state, your handlers - all preserved. The user doesn’t notice unless the disconnection lasts longer than the grace period.

Subscriptions

When you register a handler on a manager, the SDK automatically subscribes to the right data stream. When you remove the handler, it unsubscribes. You never manage subscriptions manually.
// Registering a handler subscribes automatically
const cleanup = session.transcription.on((data) => {
  session.display.showTextWall(data.text);
});

// Calling cleanup() unsubscribes
cleanup();
Every .on(), .forLanguage(), .to(), .onUpdate(), .onChange(), .onChunk(), etc. returns a cleanup function. Call it when you’re done.

Properties

PropertyTypeDescription
session.userIdstringThe user’s ID
session.sessionIdstringUnique ID for this session instance
session.loggerLoggerPino logger scoped to this user. Use session.logger.info(...) for per-user logging.
session.settingsDataAppSettingsCurrent app settings from the user
session.mentraosSettingsRecord<string, any>MentraOS system settings
session.appConfigAppConfig | nullYour app’s configuration from the developer console
session.capabilitiesCapabilities | nullWhat the connected glasses can do (display, camera, microphone, etc.)

Multiple Users

Your app serves many users at once. Each user gets their own MentraSession with isolated state:
const users = new Map<string, { name: string }>();

app.onSession((session) => {
  const userId = session.userId;
  users.set(userId, { name: userId });

  session.display.showTextWall(`Welcome! You are user #${users.size}`);

  session.onStopped(() => {
    users.delete(userId);
  });
});
Each session has its own subscriptions, its own managers, its own state. Nothing leaks between users.

Next Steps

Transcription

Capture and process speech in real time

Display

Show text and graphics on the glasses

Camera

Take photos and stream video

Device

Hardware state, capabilities, and events