---
title: "MCP authentication"
description: "Make an agent key for Fluveo MCP, choose what it may do, and revoke it."
url: https://docs.fluveo.com/agents/mcp/authentication/
---

> Index of every page: https://docs.fluveo.com/llms.txt. Integrating Fluveo? Read https://docs.fluveo.com/agents/integrate.md first.

> Too long? This page with code in one language only: https://docs.fluveo.com/agents/mcp/authentication.curl.md (cURL), https://docs.fluveo.com/agents/mcp/authentication.node.md (Node.js), https://docs.fluveo.com/agents/mcp/authentication.python.md (Python), https://docs.fluveo.com/agents/mcp/authentication.php.md (PHP).

# MCP authentication

Make an agent key for Fluveo MCP, choose what it may do, and revoke it.

Fluveo MCP takes two kinds of credential. A client a person runs can sign in with OAuth: the person consents in the Dashboard, and the client holds a short-lived token with no key to copy. [MCP sign-in with OAuth](https://docs.fluveo.com/agents/mcp/oauth.md) covers that way. Any client can use an agent key, and this page covers keys. An agent key is a restricted test key (`rk_test_...`) that you mark for an AI agent when you create it in the Dashboard. The client sends it with every request as `Authorization: Bearer rk_test_...`. Give each agent its own key, with only the permissions it needs.

## What the server accepts

The server reads the form of the Bearer value first. A value shaped like an OAuth access token, three parts joined by dots, goes to the token checks of [MCP sign-in with OAuth](https://docs.fluveo.com/agents/mcp/oauth.md). The server refuses any other value that does not start with `rk_test_` before it checks the key anywhere. It then looks up a restricted test key among your store's keys.

| Key the client sends | Answer | `error.code` |
| --- | --- | --- |
| An agent key (`rk_test_...`, made for an AI agent) | Admitted |  |
| An OAuth access token from Fluveo's sign-in, while its connection is active | Admitted |  |
| An OAuth access token that expired, of an ended connection, or made for another server | 401 | `invalid_token` |
| No `Authorization` header, or a Bearer with no value | 401 | `api_key_required` |
| Two or more `Authorization` headers, whatever each holds | 401 | `authorization_repeated` |
| A secret key (`sk_test_...`, `sk_live_...`), a publishable key (`pk_test_...`, `pk_live_...`), a live restricted key (`rk_live_...`), or a scheme other than Bearer | 401 | `agent_key_required` |
| A restricted test key made without the agent mark ([details](https://docs.fluveo.com/agents/mcp/authentication.md#untagged)) | 401 | `agent_key_required` |
| An `rk_test_` key Fluveo does not know | 401 | `api_key_invalid` |
| A key that was expired in the Dashboard, or an old key past the end of a rotation | 401 | `api_key_expired` |

The Fluveo MCP server is not available in production yet.

## Create an agent key

### Step 1: Switch to test mode

Sign in to the [Dashboard](https://dash.fluveo.com). Check that the bottom of the sidebar shows **Test mode**. The form offers the agent mark only in test mode.

### Step 2: Open the API keys screen

Open **Settings** in the sidebar and go to the **API keys** section.

### Step 3: Start a restricted key

Under **Restricted keys**, click **Create restricted key**. In **Key name**, name the key after the agent that will use it, such as the client and the machine it runs on.

### Step 4: Mark the key for an AI agent

Check **This key is for an AI agent**. The hint under the box reads "Agent keys work in test mode only." You cannot add or remove the mark after the key exists.

### Step 5: Choose the permissions

Under **Permissions**, choose **None**, **Read** or **Write** for each resource. Give **Read** on each resource the agent may see, and **Write** only on a resource it may change. **Write** includes **Read**. Give **Read** on **Account** so the agent can call `get_account_info`. [Permissions](https://docs.fluveo.com/permissions.md) lists the paths each resource covers.

### Step 6: Copy the key once

Click **Create key**. The Dashboard shows the full key once, then only a masked hint. Copy it into the environment variable `FLUVEO_MCP_KEY` of the shell that starts your client, so no file holds the key.

*Terminal*

```bash
read -rs FLUVEO_MCP_KEY && export FLUVEO_MCP_KEY
```

The client configuration names the variable, never the key. [Connect a client](https://docs.fluveo.com/agents/mcp/connect.md) has the configuration for each client.

## Why not a secret key

- A secret key calls every endpoint your store may use. In the Dashboard, the **Standard keys** section that holds it says such a key "unlocks full API access". An agent key calls only what its permissions allow.
- A secret key carries no agent policy. Its calls do not wait for agent approval, but the API's other checks still apply.
- Fluveo MCP refuses it. A secret key gets 401 with `agent_key_required` before the server checks it anywhere.

## What the agent mark changes

The mark tells the API that an AI agent holds the key. The API applies the agent policy to every call made with that key, whether the call comes through Fluveo MCP or goes to the API directly. The key's permissions still apply first. Then each operation has one of three outcomes:

- **It runs.** An operation the policy allows runs as it would for any restricted key with the same permissions.
- **It waits for a person.** An operation that needs approval answers `approval_required` and changes nothing until a person approves it in the Dashboard. [Approvals](https://docs.fluveo.com/agents/mcp/approvals.md) shows the flow.
- **It is refused.** An operation the policy denies, or one it does not list, answers 403 even when the key holds the permission. [Tools](https://docs.fluveo.com/agents/mcp/tools.md#operations) says what an agent cannot run.

Where the mark shows, and how long it lasts:

- The key list shows an **AI agent** badge next to the key's type.
- **Edit key** shows **Agent key** with the note "Set when the key was created. It can't be changed." The form has no control that removes the mark.
- **Rotate key** gives the new key the same name, permissions, note and mark.

The Dashboard offers the mark only on a restricted key created in test mode.

## Permissions

The tools a client sees depend on the key's permissions. A tool that needs a permission appears in `tools/list` only when the key has it. `get_account_info`, and the resource `fluveo://account/summary`, need **Read** on **Account**.

`get_account_info` answers the key's permissions as an object. Each name is a resource from [Permissions](https://docs.fluveo.com/permissions.md), and each value is `read` or `write`. A resource with **Write** shows `write`, since **Write** includes **Read**.

*get_account_info answer (part)*

```json
{
  "permissions": { "account": "read", "customer": "read", "payment_intent": "write" }
}
```

The API checks the permission of every operation the agent runs. When the key lacks it, the tool answers an error that carries the API's 403. Its message names the permission that would allow the call, such as `rak_customer_read`. Add that permission with **Edit key**, and the agent mark stays as it is.

## A restricted key without the mark

Fluveo MCP refuses a restricted test key made without **This key is for an AI agent**. The request gets 401 with `agent_key_required`, and the message reads "This restricted key is not made for an AI agent. Make an agent key in the Dashboard under Settings > Developers > API keys with "This key is for an AI agent" checked, or sign in with OAuth. How to connect a client: https://docs.fluveo.com/agents/mcp". You cannot add the mark to an existing key, so [create an agent key](https://docs.fluveo.com/agents/mcp/authentication.md#agent-keys), put it in `FLUVEO_MCP_KEY`, and expire the old key if nothing else uses it.

## Rotate and revoke

Give each agent its own key. You can then end one agent's access without touching the others.

### See each agent key

Open [Settings > Developers > AI agents](https://dash.fluveo.com/settings?section=ai) in test mode. The **Connections** list shows each agent key of the store that still works, and no other key. After the keys come the apps connected with OAuth, which [MCP sign-in with OAuth](https://docs.fluveo.com/agents/mcp/oauth.md) describes. Each key's row shows:

- The key's name, or **Agent key** when it has none, with the **AI agent** badge. A key you rotated with a timed expiration also shows **Expires** and the time it stops.
- The key's hint. The full key never shows.
- When the key was made and when it was last used, or **never used**.
- How many resources it may read and how many it may write, such as 3 read · 1 write. Click it to list each resource and its access.

**Create an agent key** opens **API keys**. Owners, admins and developers of the store see the list. In live mode the list says **Agent keys are in test mode**.

### Revoke one agent key

1. In **Connections**, find the row of the agent's key by its name and hint.
2. Click **Revoke** on that row. The **Revoke agent key** panel names the key's hint.
3. Click **Revoke key**. The Dashboard shows "Agent key revoked. The agent can no longer call Fluveo with it." and the row leaves the list.

Only an owner or an admin can revoke. A developer sees **Revoke** turned off, with the reason "Only owners and admins can revoke agent keys." A revoked key cannot be restored. Your other keys keep working.

To stop every agent of the store at once instead, turn off **Allow AI agent access**, as [Security](https://docs.fluveo.com/agents/mcp/security.md) shows.

### From the API keys screen

The menu of each row in the key list under **Settings > Developers > API keys** has these actions:

- **Expire key** ends the key. In **Expire API key**, click **Expire key** again. The key cannot be restored. Your other keys keep working.
- **Rotate key** makes a new key with the same name, permissions, note and mark. In **Expiration**, choose when the old key stops: **Now**, or in 1 hour, 24 hours, 3 days or 7 days. To keep access during rotation, choose a timed expiration and put the new key in `FLUVEO_MCP_KEY` before the old one stops. **Now** revokes the old key during rotation, before the new key is shown.
- **Edit key** changes the key's name, note and permissions. It never changes the mark.

Fluveo MCP stops admitting a revoked or expired key within 3 seconds. From then on the key gets 401 with `api_key_expired`, and the message says the key "has expired or was revoked".

## Errors

The server answers these before any tool runs. Each body is `{"error": {"type", "code", "message"}}`.

| Status | `error.code` | When | What to do |
| --- | --- | --- | --- |
| 401 | `api_key_required`, `authorization_repeated`, `agent_key_required`, `api_key_invalid`, `api_key_expired` | The key is missing, sent in more than one header, of another kind, made without the agent mark, unknown or expired, as in [What the server accepts](https://docs.fluveo.com/agents/mcp/authentication.md#what-the-server-accepts). | Send an agent key. For `api_key_expired`, create a new one and put it in `FLUVEO_MCP_KEY`. |
| 401 | `invalid_token` | An OAuth access token expired, its connection ended, or it was made for another server. | Let the client refresh, or sign in again. [MCP sign-in with OAuth](https://docs.fluveo.com/agents/mcp/oauth.md) lists the token errors. |
| 503 | `service_unavailable` | The server could not check the key right now. The answer carries `Retry-After: 1`. | Send the request again after a second. Nothing ran. |
| 500 | `internal_error` | The server could not read the result of the key check. | Send the request again later. Nothing ran. |

> **For AI agents:**
>
> Read the agent key from the environment variable the client configuration names. Never ask the person to paste a key into the chat.
> On a 401, read `error.code` and tell the person which key to make. Never try a secret key instead.
> On `agent_key_required` for an `rk_test_` key, tell the person to make an agent key in the Dashboard with **This key is for an AI agent** checked.
> Retry a 503 after one second. Never retry a 401 with the same key.

## Next

- [Connect a client](https://docs.fluveo.com/agents/mcp/connect.md): The configuration for each AI client.
- [Approvals](https://docs.fluveo.com/agents/mcp/approvals.md): What a person approves in the Dashboard.
- [Security](https://docs.fluveo.com/agents/mcp/security.md): What the server withholds, masks and refuses.
- [MCP sign-in with OAuth](https://docs.fluveo.com/agents/mcp/oauth.md): Connect a client with no key, and revoke the connection.
