How-to

Deploy from CI or an unattended agent

API tokens for clients that can't open a browser — CI, cron, a background agent. How to mint one, use it and revoke it.

The normal way in is OAuth: a person signs in through the browser and their MCP client holds the session. That doesn't work for something with nobody sitting in front of it — a GitHub Actions job, a cron task, a background agent on a server. Those use a long-lived API token instead.

This page is for technical readers. If you're deploying by asking your agent, you don't need it.

Mint a token

Ask an already-connected agent:

create an agenthost API token called "ci"

Shown once

The secret appears in that result and never again — listing tokens returns metadata only. Put it straight into your secret store. If you lose it, mint a new one and revoke the old.

Use it

Send it as a bearer header on requests to the MCP endpoint:

POST https://agenthost.eu/mcp
Authorization: Bearer <token>

In an MCP client config, that's whatever your client calls a static header:

mcp.json
{
  "mcpServers": {
    "agenthost": {
      "url": "https://agenthost.eu/mcp",
      "headers": {
        "Authorization": "Bearer ${AGENTHOST_TOKEN}"
      }
    }
  }
}

A token acts as the user who minted it, on the organization it was minted in, with that person's role. It never expires — revoking is the only way to retire one.

A CI deploy, end to end

Mint the token once, by hand

From your own connected agent. Store it as a secret in your CI provider (AGENTHOST_TOKEN).

Point an agent at agenthost in the job

Any MCP client works. Give it the token as the bearer header above.

Deploy the existing app

Your app already exists, so the call is deploy_app with the service id and your project files — not create_app, which would make a second app on a different address. Keep the service id in your repository or CI config.

Verify, and fail the job if it didn't come up

Poll get_app until the status settles, then make a real request to the app's URL and assert on the response. A queued build that later crashes will otherwise pass silently.

Managing tokens

WhatAsk
See what exists"list my agenthost tokens" — label, prefix, active or revoked, and id
Revoke one"revoke the token called ci"

Revoking is immediate and permanent. Rotate by minting the replacement, deploying it, then revoking the old one.

Keeping it tight

  • One token per job, labelled after the job. A shared token can't be revoked without breaking everything.
  • A token has the same power as the person who made it — including deleting apps and projects. There is no scoped or read-only token.
  • Never put a token in a repository, and never paste one into a chat. Your agent doesn't need to see it; the client does.

Under the hood

Only a hash of each token is stored (SHA-256 with a server-side pepper), so nobody — including us — can read one back. The same is true of OAuth tokens and sign-in codes. Access tokens from the OAuth flow live an hour and refresh silently; refresh tokens rotate on every use, and revoking either half drops the whole grant.

Tools: create_token, list_tokens, revoke_token. Full auth model: Signing in.