> ## Documentation Index
> Fetch the complete documentation index at: https://agent.minimax.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# miniapp.json fields

> Every field of the Mini App declaration. Unknown fields are rejected.

## Top-level fields

| Field | Type | Description |
| - | - | - |
| `schemaVersion` | `1` | Always 1 |
| `artifacts.client` | `string[]` | Required. Page payload roots, non-empty and unique, under `miniapp/` |
| `artifacts.node` | `string[]` | Required. Node payload roots; may overlap `client` |
| `runtime.kind` | `"process"` | Always `process` |
| `runtime.entry` | `string` | Node entry, `.js` / `.mjs` / `.cjs`, inside the Node payload |
| `runtime.lifecycle` | `"on-demand"` | May be omitted. Only on-demand is supported; the legacy `background` value is treated as `on-demand` |
| `surface.path` | `string` | Page entry route starting with `/`, without origin, query, fragment, or backslashes |
| `surface.window` | `object` | Optional. Properties for the pop-out window; see [below](https://agent.minimax.io/docs/miniapp/reference/manifest.md#window) |
| `mcpEndpoints` | `{ server, path }[]` | Managed MCP. `server` must be an MCP server declared in `plugin.json`; use an empty array if you have none |
| `hostConnectorAccess.providers` | `string[]` | Allowed Connector providers: lowercase letters, digits, `_`, `-`, no duplicates |
| `agentAccess` | `string[]` | Optional. `session.run` runs the Mini App's own Agent sessions; `session.read` lists, reads, and observes user sessions. The two grants are independent; absent or empty means denied |
| `agentConcurrency` | `integer` | Optional, 1–32, default 4. How many Agent turns run at once; no effect without `session.run` |
| `toolAccess` | `["call"]` | Optional. Gives Node code `context.tool` for the host's mounted MCP tools and Connectors; every call still follows the user's tool permission rules |
| `deviceAccess` | `string[]` | Optional. Device permissions the page may request. See [Device permissions](https://agent.minimax.io/docs/miniapp/reference/manifest.md#devices) |
| `engines.mcode` | `string` | Optional. Minimum MiniMax Code version; only `>=MAJOR.MINOR.PATCH` is accepted. See [Version requirement](https://agent.minimax.io/docs/miniapp/reference/manifest.md#compat) |

## Capability declarations and switches

Declare only the capabilities the app uses. This is a fragment of `miniapp/miniapp.json`, not a complete file:

```json theme={null}
{
  "agentAccess": ["session.run", "session.read"],
  "toolAccess": ["call"],
  "deviceAccess": ["microphone"]
}
```

Users can turn off individual Connector providers, Agent sessions, session reads, tool calls, and microphone, camera, and system notification access in the plugin detail page's permission panel. Declarations bound the capabilities the app may request; switches determine whether a call is allowed. A switch takes effect without restarting the Mini App, and the code must handle refused calls. See the [Security model](https://agent.minimax.io/docs/miniapp/host/security.md#permissions) for the limits.

## Device permissions

v3.1.6 supports `microphone`; `camera` and `notifications` are officially supported from v3.1.9.

| `deviceAccess` item | Allowed page operation |
| - | - |
| `microphone` | Record with `getUserMedia({ audio: true })` and transcribe through the host's `speech.transcribe` |
| `camera` | Get a camera stream with `getUserMedia({ video: true })` |
| `notifications` | Send system notifications with `new Notification(...)` |

The corresponding permission switch must also be on. A combined audio/video request requires both `microphone` and `camera` to be declared and enabled. Other unavailable page permissions, including location, clipboard read, and screen capture, remain denied. See [Page device APIs](https://agent.minimax.io/docs/miniapp/authors/client-api.md#devices) for usage.

When using the camera or system notifications, declare the minimum host version in `miniapp/miniapp.json`:

```json theme={null}
{
  "engines": { "mcode": ">=3.1.9" },
  "deviceAccess": ["camera", "notifications"]
}
```

Older hosts may reject these device items; `capabilities.has()` cannot bypass manifest validation. Camera and notifications have no separate capability names, and an interface probe does not replace declarations or user permission switches. See [Version requirement](#compat) for how the lower bound is handled.

## Version requirement

Put `engines` in `miniapp/miniapp.json` alongside `agentAccess`, rather than in `plugin.json`:

```json theme={null}
{
  "engines": { "mcode": ">=3.1.5" }
}
```

Only `>=` followed by three numeric segments is supported, without `^`, `~`, or multiple ranges. Confirm the target version before setting a lower bound so that otherwise usable hosts are not excluded.

A host that recognizes `engines` but is below the bound refuses workspace publishing. For an installed package, it withholds the Mini App and its managed MCP endpoints while keeping the package's Skills and ordinary MCP available. Earlier hosts may not recognize `engines` or other new fields and reject the manifest outright; a version bound cannot make unknown fields degrade gracefully.

On the page, use `window.mcode?.miniapp?.capabilities?.has(name)`; in Node, use `context.capabilities?.has(name)` to detect host implementation support for an interface such as `agent.observe` or `tool`. Older hosts may omit `capabilities`, so check for its presence first. A `true` result does not mean the plugin declared or was granted the capability. See [Capability reference](https://agent.minimax.io/docs/miniapp/reference/client-api.md#capabilities) for names and the interface available on each side.

## surface.window

Properties applied when the page pops out: a whitelisted subset of Electron window options. Every field is optional.

| Field | Default | Description |
| - | - | - |
| `width` / `height` | The page's size in the file panel before it popped out | Integers, 200–10000 |
| `minWidth` / `minHeight` | 480 / 360 | When both are given, can't exceed `width` / `height` |
| `resizable` | `true` | When `false`, the size can't change at runtime either |
| `frame` | `true` | When `false`, provide your own drag region |
| `transparent` | `false` | When `true`, `frame: false` must also be declared |
| `alwaysOnTop` | `false` | Upper bound for turning on always-on-top at runtime |
| `skipTaskbar` | `false` | Keeps the window out of the taskbar |
| `clickThrough` | `false` | Mouse events pass through to windows below while the page still gets move events; also the upper bound at runtime |

You can't declare the window's relationship to the main window (it is always an independent top-level window whose visibility doesn't follow the main window: hiding, minimizing, or closing the main window to the tray leaves it as is), its title (always `displayName`), its screen position, or open and close behavior. The page can enter a separate window through the file panel's pop-out action or by calling [`window.update({ mode: 'window' })`](https://agent.minimax.io/docs/miniapp/reference/client-api#window-update) during a user gesture. Closing the window returns the page to the file panel.
