How to Connect PostgreSQL and SQLite Databases to LLMs via MCP Safely
A comprehensive engineering tutorial on building secure, read-only database MCP servers. Enable AI agents to query relational databases with parameterized safety, zero data leaks, and ultra-fast vector search.

The DROP TABLE Incident: The Perils of Unrestricted Database Access
In the early days of experimentation with autonomous AI assistants, an engineer at a peer startup gave an LLM direct terminal access to their development database to 'clean up orphaned test records'. The model generated a script that accidentally cascaded foreign key deletions, dropped three core billing tables, and locked the entire team out of the staging environment for six hours.
This cautionary tale illustrates a fundamental law of AI systems architecture: Large Language Models must never be given unrestricted, raw database write permissions. When an AI agent has direct access to database credentials, a single hallucinated SQL query or prompt injection exploit can cause catastrophic data loss.
However, cutting AI off from database intelligence is equally debilitating. To build intelligent software, agents need to inspect table schemas, analyze query performance metrics, and query test records. In this tutorial, we will build a production-grade, secure Database MCP server that grants AI agents rich query capabilities while enforcing mathematical safety boundaries.
Architectural Security Blueprint: Read-Only Replicas and Schema Guards

To safely connect relational databases like PostgreSQL and SQLite to AI hosts (such as Claude Code, Cursor, or Ruflo swarms), we implement a multi-layered security architecture:
1. Read-Only Replica Isolation: The MCP server never connects to your primary database master. It connects exclusively to a dedicated, read-only replica provisioned with an unprivileged database user (`SELECT`-only permissions).
2. Query Parameterization and AST Validation: Instead of allowing the LLM to execute arbitrary raw SQL strings, the MCP server parses incoming queries through an SQL Abstract Syntax Tree (AST) parser (such as `pgsql-parser` or `sql-parser-cst`). Any query containing `DROP`, `DELETE`, `UPDATE`, `ALTER`, or `TRUNCATE` keywords is instantly rejected before reaching the database connection pool.
3. Row Limit and Query Timeout Safeguards: All outgoing queries are automatically wrapped with strict `LIMIT 100` clauses and 3-second statement timeouts to prevent rogue queries from consuming excessive database memory or locking CPU threads.
Step-by-Step Code: Building the PostgreSQL MCP Server in TypeScript
Let's construct our secure database server. Initialize a new TypeScript project: 'mkdir pg-mcp-server && cd pg-mcp-server && npm init -y'. Install the required dependencies: 'npm install @modelcontextprotocol/sdk pg zod'.
In `src/index.ts`, establish a connection pool using the `pg` library configured with your read-only database connection string. Create an MCP server instance using `StdioServerTransport`.
Define two essential tools using Zod schemas:
- `inspect_schema`: Accepts an optional table name and queries `information_schema.columns` to return table structures, primary keys, and foreign key relationships formatted as clean Markdown tables.
- `execute_safe_query`: Accepts a SQL query string, validates that it starts strictly with `SELECT`, executes the query via the read-only connection pool, and returns the tabular result set.
By exposing these two tools, your AI assistant can understand your entire database architecture and query records without ever exposing dangerous mutation endpoints.
Schema Introspection Without Context Window Bloat
A common mistake when connecting databases to AI is dumping the entire 200-table database schema into the system prompt on every turn. In an enterprise application, a raw database schema can easily exceed 40,000 tokens, wasting money and degrading model attention.
Our MCP server solves this by implementing dynamic, on-demand schema introspection. The server only returns high-level table names during initialization. When the agent is tasked with writing a query about user subscriptions, it dynamically calls `inspect_schema({ table: 'subscriptions' })`.
The agent receives only the exact 15 lines of column definitions it needs, keeping its working context window lean, ultra-fast, and focused.
Live Integration: Querying Live Data Inside Claude Code
Let's connect your database server to Claude Code. In your terminal, register the server: 'claude mcp add postgres -- npx tsx /path/to/pg-mcp-server/src/index.ts'.
Launch Claude Code and test natural language data exploration: 'claude> Query our PostgreSQL database to find the top 5 organizations with the highest API error rates over the last 24 hours'.
Claude will call `inspect_schema` to identify the `api_logs` and `organizations` tables, generate an optimized SQL `JOIN` query with aggregation, execute it via `execute_safe_query`, and present a clean markdown summary table directly in your terminal.
The entire operation takes less than 3 seconds, requiring zero manual database GUI navigation on your part.
Conclusion & Key Takeaways: Unlocking Database Intelligence Safely
Connecting your relational databases to AI agents via the Model Context Protocol unlocks immense productivity for software engineering teams. Developers can debug data inconsistencies, optimize slow queries, and generate complex migrations in seconds without leaving their coding environments.
Summary of Essential Best Practices:
- Always connect to read-only database replicas with strict `SELECT`-only user permissions.
- Enforce server-side SQL AST parsing to block destructive mutation commands at the transport layer.
- Implement on-demand schema introspection to prevent massive token context bloat.
- Enforce mandatory statement timeouts and row limit constraints on all query executions.
By implementing these security principles, you empower your AI assistants with rich real-time context while maintaining 100% operational safety and compliance.
Frequently asked questions
Yes! You can replace the `pg` client with `better-sqlite3` to query local SQLite databases (including Ruflo's memory databases) using the exact same MCP pattern.
The server's AST validation parser will intercept the command, reject execution, and return an error message to the AI explaining that mutations are strictly forbidden.
You can configure a column blacklist in the server (e.g. `['password_hash', 'api_secret', 'ssn']`). The server will automatically redact these fields from all query results.
Yes. Using the standard `pg.Pool` driver, the server manages concurrent agent queries efficiently across a shared pool of database connections.
Yes! A single MCP server can expose tools connecting to multiple databases, message queues, and cache stores simultaneously.
If you connect the MCP server locally over stdio transport, all database queries and result parsing happen strictly locally on your machine.