Connecting an AI assistant to your database with MCP — without letting it do damage

By Arshad Ansari

You want to ask Claude questions about your data without typing SQL. "How many customers signed up last week?" or "What tables relate to orders?" This is exactly what the Model Context Protocol (MCP) is built for.

MCP is a standard way to give an AI assistant tools and data sources. An MCP "server" is a small program that exposes a database as a tool the assistant can call. Claude can then ask questions, explore schemas, and run safe queries. No custom agent code. No bespoke tool layer. Just a standard server with the right permissions.

What MCP is, plainly

MCP works like this: you run a server that wraps your database and tells Claude what it can do ("I have a query tool, a list_tables tool," etc). Claude can then use those tools inside any conversation. When you ask "show me the five largest tables," Claude calls the list_tables tool and gets back structured data. For you, it looks like a chat. For your database, it's a tool invocation.

The protocol itself is just JSON over stdin/stdout. Your assistant makes a request, the server processes it, returns a response. Simple and boring, which is exactly right.

Wiring it up

You add the MCP server to Claude Desktop's config file at ~/.config/Claude/claude_desktop_config.json (or use Claude Code's .mcp.json for project-level servers). Here's what real configs look like.

DuckDB

If you're exploring a local DuckDB file:

npx -y @smithery/cli install mcp-server-duckdb --client claude

Then add to claude_desktop_config.json:

{
  "mcpServers": {
    "duckdb": {
      "command": "uvx",
      "args": [
        "mcp-server-duckdb",
        "--db-path",
        "~/my-analysis/data.db",
        "--readonly"
      ]
    }
  }
}

The --readonly flag prevents writes. Use your actual database path.

Postgres

For a Postgres database, install the server:

pipx install postgres-mcp

Then add to claude_desktop_config.json:

{
  "mcpServers": {
    "postgres": {
      "command": "uvx",
      "args": [
        "postgres-mcp",
        "--access-mode=restricted"
      ],
      "env": {
        "DATABASE_URI": "postgresql://readonly_user:password@localhost:5432/mydb"
      }
    }
  }
}

The --access-mode=restricted flag enables read-only mode. The DATABASE_URI points to your database using a read-only user (more on that next).

The guardrails that actually matter

The server config alone is not enough. You also need database-level permissions. An agent with write access to a production database will drop a table on a misread instruction. Count on it.

Create a read-only Postgres role

Connect to Postgres as a superuser and create a dedicated role:

CREATE ROLE readonly_user LOGIN PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE mydb TO readonly_user;
GRANT USAGE ON SCHEMA public TO readonly_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_user;

This role can only SELECT. It cannot drop tables, truncate, insert, update, or change the schema. Even if the agent tries a destructive query, the database rejects it.

Use this role in the DATABASE_URI above. Now the MCP server can only read.

For DuckDB

DuckDB read-only mode disables file modifications. Use an existing database file (not one the server creates), add the --readonly flag, and you're locked down.

What it's actually good for

MCP with read-only database access is excellent for ad hoc exploration: quick questions, schema discovery, fact-checking a hypothesis. "What's the row count of the customers table?" "Which columns are NULL?" "Show me the schema for the orders table and what it relates to." These queries are fast, safe, and you get natural-language results.

It's also helpful for iterative analysis. You ask a question, Claude runs a query, you see the result, and you refine the next question without writing SQL.

What it is not for: production migrations, scheduled jobs, writes of any kind, or anything unattended. Do not point Claude at production schemas with write credentials, and do not run this as part of an automated pipeline. It explores; it does not replace a reviewed ETL or a DBA-approved schema change.

Honest boundaries

This setup reduces risk, but it does not eliminate it. The assistant will run inefficient queries that lock resources or scan entire tables. Token cost scales with schema size; a thousand-table database is expensive to analyze. The assistant makes mistakes: it might misunderstand a query result or suggest a query that does not answer your question. Its output is not deterministic; you cannot rely on consistent, reproducible results for any critical decision.

The combination of read-only access and a standard MCP server gets you about 90% of the value with minimal operational risk. If you need more (write access, scheduled inference, integrations with other tools), build more. But start here.

Next steps

Set up an MCP server against a read-only role in a non-production database or a local DuckDB file. Spend a week asking it questions. You will find it useful for exploration and useless for the things you thought it would be good for. Use it accordingly.

If you're building a data platform or pipeline and want to talk through where MCP or other assistive tools fit, reach out.

Building something data-heavy? Let's talk.