Appearance
The MCP connector
Pantacor Hub serves a Model Context Protocol endpoint, so an AI assistant can look after your fleet the way the web app does: list devices, read their status and logs, change their configuration, and build and deploy new revisions. Nothing about the platform changes — the connector appends steps to the same trail the UI and pvr do, and the device picks them up exactly as described in Deploying updates.
The endpoint is:
https://api.pantahub.com/mcpOn a self-hosted Hub it is <your API>/mcp, and it has to be enabled there first — see the mcp service.
Before you begin
- A Hub account with at least one claimed device.
- An MCP client that supports remote servers over HTTP with OAuth, such as claude.ai, Claude Code, OpenCode or the MCP Inspector.
Connecting a client
A client needs nothing but the URL. It discovers the authorization server from the endpoint, sends you to Hub to sign in, and receives a token that works only against this endpoint.
- Add a custom connector in your client and give it the endpoint URL.
- The client opens Pantacor Hub in your browser. Sign in as usual.
- Hub shows which client is asking and what access it wants. Approving it completes the connection.
Where each client keeps that:
| Client | How it is added |
|---|---|
| claude.ai | Settings → Connectors → Add custom connector, with the endpoint URL |
| Claude Code | claude mcp add --transport http pantahub https://api.pantahub.com/mcp, then /mcp to sign in |
| OpenCode | a remote server in ~/.config/opencode/config.json, then opencode mcp auth pantahub |
| MCP Inspector | npx @modelcontextprotocol/inspector, then choose the streamable HTTP transport and enter the endpoint URL |
Requests from claude.ai come from Anthropic's cloud, so a self-hosted Hub has to be reachable from the internet over HTTPS for that client; the desktop and CLI clients connect from your own machine.
What you approve
A first connection asks for read access only: devices.readonly and trails.readonly. The first time a tool needs more than that — changing configuration, posting a revision, editing a registered application — the endpoint refuses the call and the client asks you to approve that one extra scope.
| Scope | What it unlocks |
|---|---|
devices.readonly | Devices, their metadata, join tokens, log reading, export downloads |
trails.readonly | Revisions, their state and parts, device status, received exports |
devices.write | Changing a device's user-meta |
devices.change | Renaming a join token and changing what devices enrol with |
trails.write | Planning and committing revisions, and taking exports in |
apps.readonly | Reading your registered OAuth applications |
apps.write | Changing their name and callback URLs |
Each approval is a connection on your account, and every token issued under it names that connection. Ending the connection stops the endpoint from accepting its tokens within seconds, whether or not they have expired; resetting your password ends every connection at once.
What the connector can do
Twenty tools, all of them limited to the devices of the account that approved the connection. Somebody else's device is indistinguishable from one that does not exist. Read-only tools are annotated as such and run without a prompt; the ones that change something are annotated destructive, and the client asks before every single call.
| Tools | What they cover |
|---|---|
list_devices, get_device | The devices you own, with user-meta (set by you) and device-meta (reported by the device) |
get_device_status | Whether a device runs its newest revision, how far it got, and when it was last seen |
list_revisions, get_revision | The trail, and one revision with its status, progress and files |
get_revision_parts | A revision split into apps, BSP, configuration overlays, documents and signatures |
get_device_logs | What a device logged, filtered by revision, level, source or time |
update_user_meta | Adding, overwriting and deleting keys of a device's configuration |
list_device_tokens, get_device_token, update_device_token | Auto-join tokens and the configuration devices enrolled with them start out with |
list_apps, get_app, update_app | Your registered OAuth applications: name and callback URLs |
plan_revision, commit_revision | Preparing a new revision, then sending it to the device |
get_export_link, get_export_upload_link, import_export_from_url, get_export_upload | Moving pvr exports out of and into your account |
How a new revision reaches a device
A revision is built in two steps, so that what you approve is exactly what the device is sent.
- Plan.
plan_revisionstarts from the device's newest revision and applies the requested operations: remove an app (which takes its_config/<app>overlay and its signature with it), copy parts from another device or from an older revision, roll back a whole state or some of its parts, replace an inline JSON document such as<app>/run.json, delete a file, or merge in apvrexport. It sends nothing. The answer is the new revision number, every file added, removed and changed, the parts touched, and any warnings. A plan is limited to 20 operations and expires after an hour. - Review. The plan is a diff of the state the device would be asked to run. Binaries are never edited, only copied with the part they belong to, so what changes is always something you can read.
- Commit.
commit_revisionposts exactly the planned state as the next revision on the trail, through the same path as any other update. A plan can be committed once. If the device received another revision in the meantime the commit fails and nothing is posted — plan again from the new head.
From there it is a normal update: the device downloads and installs the revision when it is online, and get_device_status and get_device_logs report how that went. Revisions posted this way are marked with the source mcp, the plan they came from and the client that committed them, and carry the commit message in the trail's history.
Signatures
Signatures are produced with pvr or in CI, never by the Hub — the signing keys never reach it — and it is the device that verifies them.
What a plan does is point out where a device that verifies signatures would refuse the result: a signature left untouched while files it protects changed, a signature that cannot be read, and parts that nothing signs any more on a device whose state was signed. The answer is to re-sign the part with pvr and bring the result in as an export, rather than commit a revision the device will reject. Parts signed without their configuration (pvr sig add --noconfig) can have their configuration edited without breaking anything.
Exports
Exports are the same .tar.gz archives pvr export writes and the Manage tab takes, described in Exporting a part for the Manage tab.
get_export_linkreturns a download link for a revision, or for some of its parts. It works without signing in and expires after ten minutes, so treat it as a credential while it lasts.get_export_upload_linkreturns a single-use upload link, valid for thirty minutes, for a new build:curl -T export.tar.gz '<upload_url>'.import_export_from_urlhas the Hub fetch an export over HTTPS itself, from a host the Hub allows — a CI artifact, for example.get_export_uploadreports whether an upload or import arrived, what parts and signatures it holds, how many objects were new to the account, and any object its state names that is missing.plan_revisionthen merges it in with theimport_exportoperation, the same merge the Manage tab performs.
A received export is kept for an hour, which is how long you have to plan a revision from it.
What it cannot do
- It never returns a secret: not client secrets, not join-token secrets, not device secrets.
- It cannot create or delete join tokens, applications or devices. Those are created in the web app, where the secret is shown to you once.
- It cannot change device-meta, which only the device itself reports.
- It cannot sign a revision, or verify a signature on the Hub's behalf.
- It cannot reach anything outside the account that approved the connection, and its token is refused by the rest of the API and by MQTT.
Troubleshooting
| What you see | What it means |
|---|---|
| The client asks you to sign in again | The connection lapsed or was ended; reconnect the connector |
| A call is refused for a missing scope | That access was never approved; the client asks for it, and the call works after you approve |
commit_revision fails because the device moved on | Another revision was appended after the plan was made; plan again |
| A plan id is no longer known | Plans last an hour and are good for one commit; plan again |
| A plan warns about a signature | A device that verifies signatures would refuse the result; re-sign the part with pvr |
| A revision is committed but the device stays behind | The device is offline or the step failed; check its status, then its logs, as in Deploying updates |
| An upload or download link stopped working | Upload links last thirty minutes and one use, download links ten minutes; ask for a new one |
Privacy and support
The connector reaches only your own account, through a token you approved and can revoke. The Hub receives the tool calls your client makes and their arguments — never your conversation — and answers them from the same data the web app shows you. The Hub's privacy policy covers what it keeps; for anything else, write to support@pantacor.com.
For what the endpoint looks like from the protocol side — transport, discovery documents, the scope each tool needs, and how to enable it on your own Hub — see the mcp service.