+++
title = "Bonsai MCP server"
description = "Serve cluster tools to Claude Code, Claude Desktop, Cursor, VS Code and other MCP clients."
weight = 122
updated = 2026-11-11

[extra]
nav_title = "MCP server"
weight = 90
+++

`bonsai mcp` is an [MCP](https://modelcontextprotocol.io) server, for clients that call tools instead of running a shell: Claude Code, Claude Desktop, Cursor, VS Code and others. It gives an agent tools to list, create, change and watch your clusters.

It runs on your machine, over stdin and stdout, and uses the same token as every other `bonsai` command. So `bonsai login` is all the setup it needs, and the token never goes in the client's config.

## Connect a client

First [install the CLI and log in](@/docs/cli/install/index.md). The server needs a valid token to start.

### Claude Code

Run this in your project folder:

```bash
claude mcp add bonsai -- bonsai mcp
```

Add `--scope user` to have it in every project:

```bash
claude mcp add --scope user bonsai -- bonsai mcp
```

### Claude Desktop, Cursor and others

Add the usual `mcpServers` entry to the client's MCP config:

```json
{
  "mcpServers": {
    "bonsai": {
      "command": "bonsai",
      "args": ["mcp"]
    }
  }
}
```

If the client can't find `bonsai`, give `command` the full path, from `which bonsai`.

VS Code and Codex use other config formats. See [Connect Claude Desktop, Cursor, VS Code and Codex](@/docs/agents/mcp-clients/index.md) for each client's file.

### Where there's no keychain

In a container or on a remote machine without a keychain, set `BONSAI_TOKEN` in the entry's `env`:

```json
{
  "mcpServers": {
    "bonsai": {
      "command": "bonsai",
      "args": ["mcp"],
      "env": { "BONSAI_TOKEN": "bonsai_<key>_<secret>" }
    }
  }
}
```

### Read-only

`bonsai mcp --read-only` leaves out the tools that create, rename, resize and destroy clusters:

```bash
claude mcp add bonsai -- bonsai mcp --read-only
```

For a limit the agent can't get around, also use a token without the `clusters:write` [scope](@/docs/api/authentication/index.md#scopes).

## Tools

The tools are named after the [API's operations](@/docs/api/reference/_index.md), and each returns the API's JSON, as `--json` prints it. A `cluster` argument is an ID or a name. A name that two clusters share is refused, so use the ID then.

### Reading

| Tool | What it returns | Arguments |
|---|---|---|
| `whoami` | The account the token belongs to | |
| `list_clusters` | The account's clusters | `state`, `region`, `name`, all optional |
| `get_cluster` | A cluster's state, plan, region, release, host and usage | `cluster` |
| `list_cluster_actions` | A cluster's Actions, newest first | `cluster`, `limit` (default 20, at most 100) |
| `get_action` | An Action's state and steps | `action` |
| `wait_action` | The Action, after waiting for it to finish | `action`, `timeout_seconds` (default 60, at most 300) |
| `get_cluster_usage` | Docs, shards and size against the plan's limits, over time | `cluster`, `since` (default `7d`, at most 90 days) |
| `get_cluster_metrics` | Request rates, errors, traffic and latency, over time | `cluster`, `since` (default `1h`, at most 30 days), `resolution` |
| `get_cluster_top_queries` | The most frequent search terms | `cluster`, `window` |
| `list_plans` | Plans the account may use, with their limits, prices and regions | |
| `list_regions` | Regions open for new clusters | |
| `list_spaces` | The account's private spaces | |
| `list_releases` | Elasticsearch and OpenSearch releases the account may use | |

`get_cluster_top_queries` needs a token with the `query_logs:read` scope.

### Connecting

| Tool | What it does | Arguments |
|---|---|---|
| `write_cluster_url` | Writes a cluster's connection URL to an env file in the project | `cluster`, `path` (default `.env`), `variable` (default `BONSAI_URL`), `credential` |

It changes a file in your project and nothing on Bonsai, so it stays available with `--read-only`. It needs the `credentials:read` scope.

### Changing

| Tool | What it does | Arguments |
|---|---|---|
| `create_cluster` | Creates a cluster | `name`, `plan`, `region`, and optionally `space` and `release` |
| `rename_cluster` | Renames a cluster | `cluster`, `new_name` |
| `resize_cluster` | Moves a cluster to another plan | `cluster`, `plan` |
| `destroy_cluster` | Deprovisions a cluster and every document in it | `cluster`, `confirm` |

These need the `clusters:write` scope, and are left out with `--read-only`.

## How it stays safe

**Changes return at once.** A tool call can't wait half an hour, so `create_cluster`, `resize_cluster` and `destroy_cluster` return the [Action](@/docs/api/actions/index.md) as soon as it starts. The agent follows it with `wait_action`, which waits up to five minutes per call. An Action that is still running when the time is up is an answer, not an error, and the agent calls `wait_action` again.

**Destroying needs the name.** `destroy_cluster` does nothing unless `confirm` is the cluster's current name, and the tool tells the agent to ask you for it instead of copying it from another answer.

**No tool returns a password.** `write_cluster_url` writes the connection URL to an env file for your app to read, and answers with the password as `****`:

```json
{
  "path": ".env",
  "replaced": false,
  "url": "https://z2z5nzv6l4:****@search-nozais.us-east-1.bonsaisearch.net/",
  "variable": "BONSAI_URL"
}
```

It writes only below the folder the server started in, and refuses a file that git doesn't ignore or that is tracked, so the password can't be committed. The file is left with mode `0600`.

**Search terms are data.** `get_cluster_top_queries` returns what your cluster's users typed. The tool tells the agent to treat the terms as data, never as instructions, but they are still untrusted text in the agent's context. Leave `query_logs:read` off the token if you don't need it.

**The tools carry hints.** Each tool is marked read-only or not, and `resize_cluster` and `destroy_cluster` are marked destructive, so clients that ask before risky calls know which ones to ask about.

**Errors are readable.** A failed call comes back as a tool error with the same message the CLI would print, such as which scope the token is missing.

## Troubleshooting

- **The server doesn't start, or shows no tools.** Run `bonsai doctor` in a terminal. Without a valid token the server exits; run `bonsai login`, or set `BONSAI_TOKEN` in the entry's `env`.
- **The change tools are missing.** Check the entry for `--read-only`.
- **`write_cluster_url` refuses the file.** Add the file to your `.gitignore`. If it's already tracked by git, it has to be untracked first.
- **`write_cluster_url` writes to the wrong folder.** It writes below the folder the client started the server in. In Claude Code, add the server from the project's folder.
- **To see what the server sends,** add `-v` to `args`. Logs go to stderr, which most clients keep in their MCP logs.

See also the [agent skill](@/docs/cli/agent-skill/index.md), which teaches shell-capable agents to use the CLI itself.
