MCP server

tobira mcp turns tobira into a Model Context Protocol server, so an MCP client such as Claude Code, Claude Desktop, Cursor or VS Code can look at your databases and run read-only queries on them. It uses the same tools as the AI assistant, and every call is recorded in the history.

Nothing is exposed by default. A client can see a connection only if you name it, with --expose or in the mcp: section of the config file. Any other name is answered exactly as if it did not exist.

An MCP client is an agent: it decides on its own what to ask, and what it reads goes to the model behind it. Expose only the connections it should see, and prefer connections that are read_only: true.

Quick start

tobira connections add --name local-pg --driver postgres --dsn 'postgres://app@localhost/app' --read-only
claude mcp add tobira -- tobira mcp --expose local-pg

Then ask Claude Code something about the database. To check the server by hand, run tobira mcp --expose local-pg and type nothing: it prints what it serves on stderr, waits for a client on stdin and exits when stdin closes. Nothing else is printed: stdout is the protocol stream, and the --debug log goes to a file.

In this section

PageCovers
Client setupClaude Code, Claude Desktop, Cursor and VS Code
Tools and resourcesThe tools, the schema resources, send_rows, writes and the call history
HTTP modeServing over Streamable HTTP with a bearer token
tobira mcpEvery flag and exit code

Configuration

Each flag replaces its mcp: config value.

mcp:
  expose: [local-pg, cache]   # connections an MCP client may use; empty exposes nothing
  allow_writes: [cache]       # a subset of expose; the rest stay read-only
  max_rows: 200               # 1 to 1000
  send_rows: always           # always or never
  token: env:TOBIRA_MCP_TOKEN # HTTP only: a secret reference
Config keyFlagDefault
expose--expose a,bnone, so tobira mcp exits 1 until you set one
allow_writes--allow-writes anone: every exposed connection is read-only
max_rows--max-rows n200 (1 to 1000)
send_rows--send-rows always|neveralways
tokennonea random token per start (HTTP only)
  • A name in expose or allow_writes that is not a connection, and an allow_writes entry that is not exposed, are reported as warnings when the file loads. tobira mcp then refuses to start until they are fixed, and the error names the entry’s position in the file.
  • A repeated entry is warned about and ignored: it never stops the server.
  • mcp.token must be a secret reference (env:, file://, dotenv:// or keyring:); a literal token is a load error.

Security

  • The exposed set is the policy. Everything the tools can reach on those connections can reach the client’s model.
  • Prefer read_only: true connections and a database user that can only read. The read-only guard refuses anything it cannot recognise as a read, but a database role is the boundary that does not depend on tobira.
  • Tool results are data from your database. A row can contain text that tries to instruct the model. The only defence that does not depend on the model is what the connection is allowed to do.
  • Schemas are served without DDL, and error text is redacted against the connection’s secrets.
  • execute exists only for connections in allow_writes, and there is no per-call confirmation.

See Security for the full picture.