# romcp analytics preview

Use `roblox_read_analytics`, `POST /v1/cloud/analytics/read`, or `client.analytics.read(input)`. Configure the server's Open Cloud key with `universe.analytics:read` for the explicit universe. No Studio connection is required.

```ts
const pendingOrResult = await client.analytics.read({
  universeId: 123,
  query: {
    metric: 'DailyActiveUsers',
    granularity: 'OneDay',
    startTime: '2026-01-01T00:00:00Z',
    endTime: '2026-02-01T00:00:00Z',
  },
});
// On a later check, reuse the operation ID instead of resubmitting the query:
if (!pendingOrResult.operation.done) {
  const status = await client.analytics.read({
    universeId: 123,
    operationId: pendingOrResult.operationId,
  });
  console.log(status);
}
```

Each call makes one request. There is no automatic retry or polling loop. A timeout after submission may leave an operation running. Keep pending IDs in caller state. Completed operations can contain an error; inspect `operation.error` before using `operation.response`.

Point statuses and `stringValues` are preserved. Empty series remain empty, not fabricated zeroes. Query dates use an exclusive end time. Roblox validates metric-specific dimensions, granularities, and retention. Consult the [official analytics guide](https://create.roblox.com/docs/cloud/guides/analytics) for supported metrics and combinations.

romcp bounds requests to 20 seconds, streamed responses to 2 MiB, and results to 512 KiB, 100 series, and 5,000 points per series. Exceeding limits fails explicitly; narrow the query. Raw upstream error messages are sanitized. Polling paths must match the requested universe and operation. Credentials are never sent to arbitrary response URLs.

Dimension discovery uses `roblox_discover_analytics_dimensions`, `POST /v1/cloud/analytics/dimensions`, or `client.analytics.dimensions(input)`. Pass a query containing `metric`, `dimensions`, `startTime`, and `endTime`. Optional filters use the same shape as metric queries. A `limit` requires omitted or `None` granularity. Resume pending discoveries through the dimensions method using their operation ID; metric and dimension operation IDs have distinct polling routes.

```ts
const countries = await client.analytics.dimensions({
  universeId: 123,
  query: {
    metric: 'DailyActiveUsers',
    dimensions: ['Country'],
    startTime: '2026-01-01T00:00:00Z',
    endTime: '2026-02-01T00:00:00Z',
    limit: 10,
  },
});
```

Use returned `value` strings as filter IDs. `displayValue` is an optional label, not an ID. A discovery result is bounded to eight dimensions and 5,000 values per dimension, plus the shared byte limits. Empty results do not imply that a dimension is unsupported.

Local tests cover the shared service, MCP catalog, and SDK/HTTP path with synthetic Roblox responses. Live queries, dashboard UI, and native funnel analysis remain unfinished.
