MCP Server

oxidb-mcp speaks the Model Context Protocol — the standard Claude Code, Claude Desktop, Cursor and other agentic editors use to reach external tools. Point a host at it and an AI assistant can orient itself in an OxiDB instance and query it directly: documents, SQL, time-series and full-text search, with nothing copy-pasted into a prompt.

Set it up

The server is a standalone binary that the AI host launches for you. With Claude Code:

claude mcp add oxidb \
  -e OXIDB_ADDR=127.0.0.1:4444 \
  -e OXIDB_USER=assistant -e OXIDB_PASSWORD=… \
  -- oxidb-mcp

Any other MCP host takes the same thing as JSON — Claude Desktop, Cursor, Windsurf, Zed:

{
  "mcpServers": {
    "oxidb": {
      "command": "oxidb-mcp",
      "env": {
        "OXIDB_ADDR": "127.0.0.1:4444",
        "OXIDB_USER": "assistant",
        "OXIDB_PASSWORD": "…"
      }
    }
  }
}

Configuration

VariableDefaultWhat it does
OXIDB_ADDR127.0.0.1:4444The OxiDB server to connect to
OXIDB_USER / OXIDB_PASSWORDSCRAM credentials. Omit both only against a server with auth disabled
OXIDB_MCP_DBPin every call to one database. A request naming a different one is refused
OXIDB_MCP_WRITES0Register the write tools. Off means they are not offered at all

What the assistant can do

AreaTools
Orientationlist_databases, list_collections, list_tables, describe_table, list_indexes
Documentsfind, count, aggregate
SQLsql_query — parameterized, single statement, read-only
Time-seriestsdb_query — tag filters, time ranges, downsampling, group-by
Searchtext_search — BM25, with optional highlights
Diagnosticsexplain
Writes opt-ininsert, update, delete, sql_execute

explain is a tool of its own on purpose. It returns the plan — strategy, index used, documents examined versus returned — plus real timing, so an assistant can work out why a query is slow and propose the index that fixes it, instead of guessing.

Security: read-only by default

There are two gates, and the one that matters is the server's.

  • The write tools are not registered unless OXIDB_MCP_WRITES=1. A model cannot call a tool it was never offered — asking for one is a protocol error, and nothing reaches the database.
  • Give the assistant a Read-role account. Then writes are refused by OxiDB's own RBAC, whatever the tool layer asks for. This is the gate to rely on: it holds even if the MCP process is misconfigured or compromised.
// Create a read-only account for the assistant (admin connection)
{ "cmd": "create_user", "username": "assistant",
  "password": "…", "role": "read" }

This matters more than it first looks. Everything a model reads out of a database enters its context, and a hostile document that talks a model into writing is a known attack shape. Read-only by default doesn't make that impossible — it means there is nothing to write with until an operator widens it, deliberately, twice.

Results are budgeted for a context window

A read returns 50 rows by default and 500 at most. When a result is trimmed it says so and reports the true total from an index-only count, so an assistant knows to narrow the query rather than believe it has seen everything. A silent cap would read as “that was all of it” — a different, and wrong, answer.

Hosted: one endpoint per project

The setup above spawns oxidb-mcp on the machine running the host. For a hosted project there is a second mode: run it once as a server, and an assistant reaches a project over plain HTTP with nothing installed.

OXIDB_MCP_HTTP_PORT=8090 \
OXIDB_MCP_UPSTREAM=http://127.0.0.1:8080 \
  oxidb-mcp

# the endpoint, carrying the project's own key
curl -X POST https://your-host/mcp/<project-ref> \
  -H "Authorization: Bearer $ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The key is forwarded, not interpreted. The request is served by passing your project key to the REST surface, which verifies it against that project’s own secret and applies the project’s security rules, role and rate limit — the same gate every other request to the project passes. The MCP layer decides nothing about access; if a rule refuses a collection to your anon key, the tool call is refused with it.

Each request is independent: the project comes from the path and the key from the header, and nothing is cached between requests. One process can serve many projects with no shared state. Set OXIDB_MCP_DB to fix it to a single project, and a ref in the path is then ignored rather than honoured. GET /mcp/health answers without a key.

Two differences from the local mode: explain is not available (it is a wire-protocol diagnostic with no HTTP equivalent), and the time-series tool goes through the PostgREST time-series route, so its rows come back flattened.

How it fits

oxidb-mcp is a client, not a listener: it talks to any OxiDB server over the native protocol, changes nothing on the server side, and works against deployments you already have running. It is a separate process the AI host starts and stops, so an instance with no assistant attached pays nothing for it.

The design decisions — and what was deliberately left out — are recorded in ADR-0024 in the repository. Not in this version: MCP resources and prompts (tools only), realtime subscriptions, and the remote HTTP transport; each is refused by name rather than silently ignored.

Download: oxidb-mcp ships for all five platforms on the downloads page, or build it with cargo build --release -p oxidb-mcp.
Report Issue