← All releases
v3.1.0

xprem: observability, device identity and an MCP server

  • Server
  • Dashboard
  • eoas CLI
  • Observe
  • MCP
  • Enterprise
  • Helm & Docker

Expo Open OTA is now xprem. Same project, same maintainers, same licenses, renamed to respect Expo's trademark. xprem is not affiliated with, sponsored or endorsed by Expo.

The rename

Everything is republished under the new name and every old name keeps working:

NewOld, still published
Repositorymercuretechnologies/xpremredirects
Docker imageghcr.io/mercuretechnologies/xpremghcr.io/mercuretechnologies/expo-open-ota, ghcr.io/axelmarciano/expo-open-ota
Helm chartoci://ghcr.io/mercuretechnologies/charts/xpremoci://ghcr.io/mercuretechnologies/charts/expo-open-ota
Docsmercure-technologies.gitbook.io/xprem
CLInpx eoas, unchanged

No environment variable, API route or bucket layout changes. Bump the tag, switch image and chart names when you want.

Observability with expo-observe

The server is a backend for Expo's expo-observe SDK: point extra.eas.observe.endpointUrl at it and keep the stock SDK. Native and JS crashes, cold launch, bundle load, time to first render, time to interactive, sessions, and your own events and logs are stored with the update, branch and channel that produced them.

The data lands in your ClickHouse. The dashboard gets an Observe section: an overview with a live device map, per-metric percentiles with breakdowns by device model, OS, region, app version and screen (read from expo-router or react-navigation), an event explorer and a log stream. Grafana, PostHog or Datadog can read the same tables.

Device identity

Every device that checks in is registered per app: first and last seen, model, OS, current update, branch, runtime version and location. The Devices view lists and searches them, with a live online count.

Custom device attributes (Enterprise): declare an allowlist of typed keys, then send $set, $set_once and $unset operations from the app through the expo-observe pipeline. Each key becomes a filter and a breakdown dimension across metrics, events, logs and update health.

MCP server

The server exposes /mcp. Agents sign in with OAuth 2.1 as dashboard users: dynamic client registration, PKCE, refresh tokens with revocation, no API keys. Every call runs with that user's per-app permissions.

16 tools ship under MIT and cover the dashboard operations: list apps, branches, channels and updates, inspect rollouts, create and delete branches and channels, roll back, republish. 10 more come with the Enterprise edition and read the observability dataset: update health, metric breakdowns, events, logs, audit logs and device search.

Publish groups

One eoas publish produces an iOS update and an Android update. They are now linked by a publish group. The dashboard shows them as one row with health aggregated over both platforms, and republish and rollback act on the whole group. Older CLIs keep publishing ungrouped rows.

Republish and roll back from the dashboard

Revert a branch to its previous update, or put any past update or publish group back live, from the Updates feed.

GeoIP

Two options: trust the location headers your CDN already sets (Cloudflare, CloudFront, Vercel, or custom X-Geo-* headers), or give the server MaxMind GeoLite2 credentials and it downloads and refreshes the database itself. Location feeds the device map and adds region as a breakdown dimension. Configure neither and the rest works as before.

Server configuration wizard

npx eoas server:init walks through storage, delivery, database, cache, key store, GeoIP and replicas, then writes a .env for Docker or a values.yaml plus a gitignored secrets file for Helm. It reuses an existing master key on re-run. npx eoas server:validate checks a config before deploy.

Hot path

Manifest signatures are cached, keyed by content hash. App config and channel mappings get short-TTL caches. A new S3 presigned URL delivery mode serves assets from a private bucket with no CDN and no traffic through the server.

A reproducible k6 load test ships with the repo. One 1-vCPU instance served real expo-updates polls from 100,000 devices with code signing and telemetry on, at 938 req/s at the peak of a full-fleet rollout, with zero errors. Method and raw data in test/load/results.

Security

  • Sign-in, token issuance and uploads are rate limited.
  • Dashboard sessions can be revoked server-side. Refresh tokens rotate with session-version invalidation.
  • API tokens carry specific roles instead of blanket access.
  • Upload requests are validated before touching storage.
  • GitHub workflows run read-only by default.

Also

  • DISABLE_DEVICE_TELEMETRY=true switches off the device registry and telemetry ingest.
  • eoas asks before overwriting an existing config.
  • Dashboard: debounced filters, loading skeletons, richer update details.
  • pgx 5.9.2.

Release on GitHub