# Connect an agent

Connect OpenCode, Claude Code, Codex, or a bot on its own computer to BasaltDB over MCP.

Your agent talks to BasaltDB over MCP. Its MCP client starts `basalt mcp --agent NAME`, a small program that relays to the engine for that agent. It holds no credential. The engine checks that the program is run by the agent's OS user and refuses anyone else.

Before you start, run `basalt init --agent NAME` for the agent. See [Install](/start/install/), or the [Quickstart](/start/quickstart/) for the sample agent `demo_bot`. The examples below use `demo_bot`.

## What every client needs

Any MCP client takes a command and its arguments. Add one server per agent.

```json
{
  "mcpServers": {
    "basalt-demo_bot": {
      "command": "/usr/local/bin/basalt",
      "args": ["mcp", "--agent", "demo_bot"]
    }
  }
}
```

- Use the absolute path of `basalt` (`which basalt`) if the client does not inherit your `PATH`.
- If `init` used a non-default `--socket-dir`, add `"--socket-dir", "DIR"` to `args`.
- Do not put a database URL in the client config. The agent never holds one.

## OpenCode

Add the server to `opencode.json` in your project, or to `~/.config/opencode/opencode.json` to use it everywhere.

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "basalt-demo_bot": {
      "type": "local",
      "command": ["/usr/local/bin/basalt", "mcp", "--agent", "demo_bot"],
      "enabled": true
    }
  }
}
```

Start `opencode` and ask it which basalt tools it has. It should list `run_start`, `query` and `write`, among others.

## Claude Code

```sh
claude mcp add basalt-demo_bot -- "$(which basalt)" mcp --agent demo_bot
```

If the `claude` command was on your `PATH`, `basalt init` offered to run this and may have done it already. It adds the server for sessions started in the current directory. Add `--scope user` to use it from any directory.

Start `claude` and run `/mcp`. `basalt-demo_bot` should show as connected with its tools.

## Codex

```sh
codex mcp add basalt-demo_bot -- "$(which basalt)" mcp --agent demo_bot
```

Or add it to `~/.codex/config.toml` yourself:

```toml
[mcp_servers.basalt-demo_bot]
command = "/usr/local/bin/basalt"
args = ["mcp", "--agent", "demo_bot"]
```

Start `codex` and ask it which basalt tools it has.

## A bot on its own computer

Your bot runs on a machine you cannot reach, such as a server or a chat bot's host. The bot installs the engine there. You approve it from your own computer, where your database password stays. The bot never sees the admin connection string.

On the bot's machine, with `basalt` installed there (see [Install](/start/install/)), the bot runs `basalt init --remote`. It needs the connection string without a password. Supabase shows it with a `[YOUR-PASSWORD]` placeholder.

```sh
basalt init --remote --agent my_bot --operated-by=agent \
  --write public.leads --read public.lead_notes \
  --database-url "postgresql://postgres@HOST:5432/postgres"
```

It prints a setup code and a fingerprint, such as `3f9a 21c0 7d44 e1b2 90ac`. The code is valid for 24 hours and works once. The bot shows both in the chat.

On your own computer, with the admin connection string at the hidden prompt:

```sh
basalt init --setup-code SETUP_CODE
```

Check that the fingerprint it shows matches the one your bot gave you. If it does not, stop and ask your bot for a new code. Then read what the setup will do, answer `y`, and register a passkey when it asks. It ends with `Done. Tell my_bot to check its status.`

`basalt init --remote` does not install or start the engine. Your bot does that on its own machine, by running `basalt engine --config PATH`, or by installing it as a service. When the engine sees that your setup ran, it starts serving the agent.

Tell the bot. It calls its `status` tool and confirms it is ready.

Never paste your database password into the chat. The setup code holds no secret. For the full walkthrough and what each step checks, see [A bot on its own computer](/guides/bot-own-computer/).

## Check that it works

Run this on the machine where the agent runs. It sends one MCP `initialize` request through the relay.

```sh
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}' \
  | basalt mcp --agent demo_bot
```

A JSON response naming the server `basalt` means the relay reached the engine. If the connection closes at once, the engine refused the program: run the command as the agent's OS user, or check `osUser` in the engine config. `basalt status --agent demo_bot` prints the engine, the guard and the passkey, with the fix for each problem.

## What your agent can call

The client lists BasaltDB's tools: `run_start`, `describe`, `query`, `write`, `run_history`, `list_runs`, `list_pending`, `preview_revert`, `request_revert` and `status`, plus `revert_plan` and `apply_revert_batch` for large undos. A session usually starts a run with a reason, reads with `query` inside that run, and writes with `write` and a reason. See [MCP tools](/reference/mcp-tools/).
