Remote MCP server
The remote MCP server is Koo's hosted endpoint at https://mcp.koo.io/mcp. Any MCP host that speaks remote MCP over HTTP — Claude Code, Claude.ai, Cursor, ChatGPT — connects to it by URL, and you authorize it in the browser with Sign in with Koo. There is nothing to install: no package to add, no process for your host to launch, and no token to mint, paste, or store — the host gets an access token through OAuth and refreshes it on its own.
It exposes Koo to your agent as a set of koo_* tools — deploy a service, follow the deployment timeline, roll back, tail logs, read metrics, set variables, check status. Where there is no browser to authorize in — a CI runner, a remote shell — the same endpoint takes a kc_… API token as its bearer instead; see Headless / CI.
Connect
In Claude Code, one command adds it:
claude mcp add --transport http koo https://mcp.koo.io/mcpIn Claude.ai, Cursor, ChatGPT, or any other host with a remote-connector or custom-integration setting, add a connector and give it the same URL:
https://mcp.koo.io/mcpThe first tool call triggers the authorization flow. Your browser opens, you sign in to Koo, and you choose what the client may do — then the host stores the result and you are done.
What happens when you connect
- The host calls the endpoint with no credential and gets back a 401 that names Koo's authorization server.
- The host reads Koo's OAuth metadata and registers itself — no client id for you to create.
- Your browser opens on Sign in with Koo. If you are already signed in to the console, this is one click.
- You consent: pick one account, and pick Read or Write. The screen states exactly what the client will be able to do in that account before you approve.
- The host receives its tokens and the tools light up.
You approve again each time a client reconnects — a connection is always a deliberate act, never a silent renewal.
Tools
Every tool returns structured content and acts on the one account the connection is bound to — there is no account switch, and no account to pass. Reads are marked read-only; writes (koo_deploy, koo_rollback, koo_set_variables) carry a destructive hint, so your host can prompt before one is applied. The two creates are writes too, but marked non-destructive — they only add.
<!-- mcp-tools:begin -->
| Tool | Access | What it does |
|---|---|---|
koo_whoami | Read | The account and role the token is confined to (its blast radius). |
koo_list_projects | Read | The account's projects. |
koo_list_environments | Read | A project's environments. |
koo_list_services | Read | An environment's services, each with its health and URL. |
koo_get_service | Read | One service's full configuration and status. |
koo_service_status | Read | A compact health/applied/build rollup for a service, plus any failures. |
koo_list_deployments | Read | A service’s deployments, newest first — status + per-phase timestamps (the timeline). |
koo_get_build_logs | Read | The build output for one from-source deployment version. |
koo_get_logs | Read | Recent runtime logs, over the resolved (plan-clamped) window. |
koo_get_metrics | Read | A metric series (cpu/mem/req/latency) over the resolved (plan-clamped) window. |
koo_get_variables | Read | A service’s effective variables — source scope, sensitivity, kind, shadowing, and dangling refs. |
koo_deploy | Write | Ship a deployment — pin an image, or omit it to redeploy the configured source. |
koo_rollback | Write | Roll a service back to a prior deployment version. |
koo_set_variables | Write | Set or unset a service’s variables via a merge batch (literal name→value; the server merges). |
koo_create_project | Write | Create a project (with a default environment). |
koo_create_service | Write | Create an exposed web service from a prebuilt container image. |
| <!-- mcp-tools:end --> |
koo_get_logs and koo_get_metrics return the window actually queried after it is clamped to your plan's retention — the agent reports that resolved window and does not retry to widen it. Deploying from local source is not a tool: that goes through koo up in the CLI, and the agent then watches the result with these tools.
What the connection can do
A connection is deliberately narrower than your own account access:
- One account. The connection reaches exactly the account you chose at consent, and no other — even if you are a member of several.
- Read or Write, never more. Read can view everything in that account — projects, environments, services, deployments, and logs — but change nothing. Write adds deploying, rolling back, and editing configuration. Nothing beyond that is grantable.
- It can never manage members, billing, or plans, and it can never create API tokens. The first needs the owner role and the second needs admin — a connection can hold neither.
- Your live role is the ceiling. The connection's effective role is the lower of what you granted and what your membership currently allows. If your role in that account is later reduced to reader, the connection loses write access immediately — no reconnect required. If you are removed from the account, the connection stops working at once and the host is told to re-authorize.
Every action is attributed to you in the account's audit trail, together with the client that made it.
Guardrails
Koo maintains an agent skill — the Koo deploy flow written once and rendered for each host — that teaches an agent to work this way. The rules that matter hold whichever agent is driving, because the API is what enforces them:
- Authority from the API. Roles, plan limits, and retention windows are enforced server-side and come back as errors carrying a
codeand ahint. The agent acts on the hint — reconnect with a broader grant, upgrade the plan, stop retrying — and never invents a quota or a permission of its own. - Tools and the CLI only. The agent drives the
koo_*tools and thekooCLI; it has no reason to hand-build a request against the API, and the skill tells it not to. - Source builds via the CLI. The tools deploy prebuilt images. For a local-source build the agent has you run
koo upin your project directory, then watches the result with the tools. - Failures surfaced, never faked. A failed tool returns an error result carrying the Koo error code and a reference id. The agent reports it; it never claims a deploy that did not happen.
Headless / CI
OAuth needs a browser, and a CI runner does not have one. The same endpoint therefore also accepts a kc_… API token as its bearer, with no authorization flow at all — the token brings its own account and role, exactly as it does on the REST API.
In Claude Code, add the connection with a header:
claude mcp add --transport http koo https://mcp.koo.io/mcp \ --header "Authorization: Bearer ${KOO_TOKEN}"Your shell expands ${KOO_TOKEN} as that command runs, so the token comes from the environment rather than your shell history. Hosts differ on whether they expand ${VAR} themselves when reading a config file — one that does not will store the literal text you gave it. Check your host before you paste a real token anywhere.
Any host works the same way, on one condition: it must let you set a custom header on a remote MCP server. A host that accepts only a URL has nowhere to put the bearer, and OAuth in a browser is the only path there.
Token hygiene for an agent that runs unattended:
- Give it the smallest role that works — Write to deploy and manage, Read for an agent that only watches. Whichever you pick, a token can never manage members, plans, or billing.
- One token per system. A token per pipeline means any one can be revoked without disrupting the others, and the audit trail names which agent acted.
- Prune the stale ones. Each token records when it last authenticated, so a token no pipeline uses any more is visible in the console's Tokens page — revoke it there.
Revoke a connection
Open Connections in the console — it is in your avatar menu, and under User in the account sidebar. Each connection shows the client, the account, and the role you granted.
Revoking is immediate for anything new: the client's refresh token dies at once, so it cannot obtain fresh access. An access token it already holds keeps working until it expires, which is within one hour. If you need the connection cut off with no residue at all, remove the connection and adjust your membership — the live-role check applies on every single request.
A headless agent holds a kc_… token rather than a connection, so it is not listed there — revoke it from the account's Tokens page instead, where revocation takes effect at once.
Troubleshooting
- The host keeps asking you to authorize, or every call returns 401. The authorization is no longer valid — usually because your membership in the granted account changed, or you revoked the connection. Re-run the connection flow in your host and consent again.
- Tools return "forbidden" on deploys but reads work. The connection has Read access, or your own role in that account is now reader. Reconnect and choose Write, or ask an account owner to restore your role.
- The client cannot complete sign-in. Make sure you are signing in as a user who is a member of at least one Koo account; a brand-new user with no account has nothing to connect to. Finish setting up your account in the console first, then reconnect from the client.
- A headless agent gets 401 on every call. The header never reached the server, or the token is not a live
kc_…token. Confirm your host actually sends custom headers on remote servers, and that the variable was expanded rather than passed through as literal text. - You want to see what is connected. The Connections page lists every client you have authorized, with the account and role for each.