Skip to main content
Glama
README.md
# mqdh-mcp

**Unofficial MCP server for Meta Quest developers.** Lets an AI assistant list your developer organizations, apps and release channels, and upload builds (APK/OBB) to a channel such as ALPHA, BETA, RC or LIVE — the same way Meta Quest Developer Hub (MQDH) does.

> Not affiliated with or endorsed by Meta. Uploads use Meta's official `ovr-platform-util`. Org/app/channel lookups use undocumented `graph.oculus.com` operations that may change without notice.

## TL;DR for AI assistants

1. `auth_status` — confirm a Meta login is available.
2. `list_orgs` → `select_org { org }` — pick the developer organization (saved for later calls).
3. `list_apps` → find the app; `list_channels { app }` — see channels and latest builds.
4. `upload_build { app, channel, apk, dry_run: true }` — preview, then run without `dry_run`.
5. `upload_status { job_id }` — poll until `status` is `succeeded` or `failed`.

Rules: uploads are **drafts** unless `publish: true`. Publishing to **LIVE** (or copying a build into LIVE) needs `confirm_live: true` — only set it when the user explicitly asks to ship to the public store. `app` and `org` accept an id or a partial name.

## Tools

| Tool | Purpose | Key arguments |
|---|---|---|
| `auth_status` | Show login state, token source, selected org | — |
| `list_orgs` | List organizations you belong to | — |
| `select_org` | Set the default organization | `org` |
| `list_apps` | List apps in an org | `org?` |
| `list_channels` | Channels + latest builds for an app (`is_live` marks the store channel) | `app`, `org?` |
| `upload_build` | Upload a build in the background; returns `job_id` | `app`, `channel`, `apk`, `obb?`, `notes?`, `publish?`, `confirm_live?`, `dry_run?`, `extra_args?`, `org?` |
| `upload_status` | Progress/output of an upload (or list all) | `job_id?`, `tail?` |
| `copy_build` | Copy an existing build into another channel | `app`, `binary_id`, `to_channel`, `confirm_live?`, `org?` |
| `list_test_users` | Test users for an org | `org?` |
| `graphql` | Raw graph.oculus.com query (advanced) | `query`, `variables?` |
| `metavr` | Run any bundled `metavr` CLI command (devices, logcat, perf…) | `args[]` |

`channel` accepts `ALPHA`, `BETA`, `RC`, `LIVE` (aliases `store`, `production`), a custom channel name, or a channel id.

## Example

```text
User: Upload C:\builds\game.apk to the BETA channel of "Space Game" with notes "fixes crash".

→ list_orgs / select_org { "org": "My Studio" }
→ upload_build { "app": "Space Game", "channel": "BETA", "apk": "C:\\builds\\game.apk", "notes": "fixes crash", "dry_run": true }
→ upload_build { "app": "Space Game", "channel": "BETA", "apk": "C:\\builds\\game.apk", "notes": "fixes crash" }
← { "job_id": "a1b2c3d4", "channel": "BETA", "mode": "draft", "status": "uploading" }
→ upload_status { "job_id": "a1b2c3d4" }
```

## Install

Requirements: Node.js 20+, and [Meta Quest Developer Hub](https://developers.meta.com/horizon/documentation/unity/ts-mqdh/) installed and logged in (open it once so it downloads `ovr-platform-util`).

```bash
git clone https://github.com/thankyoucoinbase/mqdh-mcp.git
cd mqdh-mcp
npm install
```

**Claude Code**

```bash
claude mcp add mqdh -- node /absolute/path/to/mqdh-mcp/Source/server.js
```

**Claude Desktop / other MCP clients**

```json
{
  "mcpServers": {
    "mqdh": { "command": "node", "args": ["/absolute/path/to/mqdh-mcp/Source/server.js"] }
  }
}
```

## Authentication

No separate login: the server reuses your existing MQDH session. Token sources, in order:

1. `MQDH_TOKEN` environment variable
2. MQDH's `odh/mcp-config.json` in your app-data folder
3. Windows Credential Manager entry `Meta Quest Developer Hub/default`
4. `metavr auth profile-token`

If none work, log in to MQDH or run `metavr auth login`.

## Configuration

All optional; defaults follow the standard MQDH install.

| Variable | Default |
|---|---|
| `MQDH_DIR` | `%ProgramFiles%\Meta Quest Developer Hub` (Windows), `/Applications/Meta Quest Developer Hub.app` (macOS) |
| `MQDH_USER_DATA` | `%APPDATA%\odh` (Windows), `~/Library/Application Support/odh` (macOS) |
| `METAVR_PATH` | `metavr` inside MQDH's `resources/bin` |
| `OVR_PLATFORM_UTIL` | `ovr-platform-util` inside `MQDH_USER_DATA` |
| `MQDH_TOKEN` | — |
| `MQDH_MCP_STATE` | `~/.mqdh-mcp.json` (stores the selected org) |

Tested on Windows. macOS paths follow MQDH's layout but are untested.

## Security

- Tools never return the access token; it is redacted from upload output.
- `ovr-platform-util` receives the token as a command-line argument (as MQDH does), so it is visible to other local processes while an upload runs.
- The `graphql` tool can run mutations as you. Remove it from your client's allowed tools if you don't need it.

## How it works

| Operation | Mechanism |
|---|---|
| Orgs, apps, channels, test users, copy build | `POST https://graph.oculus.com/graphql` with form fields `access_token`, `doc_id`, `operation_name`, `variables` (persisted operations from MQDH 6.5.2, listed in [`Source/graph.js`](Source/graph.js)) |
| Upload | `ovr-platform-util upload-quest-build --app_id … --token … --channel … --apk … [--obb] [--notes] --disable-progress-bar [--draft]` (PC apps: `upload-rift-build --build-dir`). LIVE is passed as `store`. |

## Development

```bash
npm test            # offline tests, no login needed
npm run test:live   # read-only tests against your account; never uploads
```

Project layout and conventions for contributors (human or AI): [`AGENTS.md`](AGENTS.md).

## License

[MIT](LICENSE)

TDQS

A3.5/5.0

Scored across 11 tools

Disambiguation4/5

Core tools target distinct resources and actions (list_orgs vs select_org, upload_build vs upload_status vs copy_build), and the descriptions clearly separate read paths from write paths. The only soft spot is the pair of catch-all escape hatches (graphql, metavr), which can in principle do anything an agent might otherwise pick a dedicated tool for, though they are explicitly flagged as advanced/raw.

Naming Consistency4/5

The majority of tools follow a clean verb_noun pattern (list_orgs, select_org, list_apps, list_channels, upload_build, upload_status, copy_build). Deviations are minor: auth_status is noun-first and graphql/metavr are bare product names, but all remain immediately readable.

Tool Count5/5

Eleven tools is well within the sweet spot and each one maps to a distinct step in the org -> app -> channel -> build workflow. Nothing feels padded; even the two broad tools exist to cover long-tail needs without bloating the surface.

Completeness4/5

The surface covers auth, org/app/channel discovery, build upload with draft/publish semantics and async polling, and channel-to-channel copying. Gaps exist around build lifecycle management (deleting builds, editing release notes, app creation, broader user management), but graphql and metavr provide viable workarounds.

Maintenance

ActivityMaintained
ResponsivenessNo issues