Can MCP Servers Access My Database Safely
You Control the Access
An MCP server is not a direct pipeline from the AI model to your database. It is your code, written by you, deployed on your infrastructure, with your security rules. When the AI model calls a database tool, your server receives the request, validates it, constructs the query, executes it with the permissions you configured, and returns only the data you choose to expose. The model never sees your connection string, never touches your database driver, and never executes raw SQL unless you explicitly allow it.
The security of database access through MCP is the same as the security of database access through any API. If you build a REST API that queries your database, you apply input validation, parameterized queries, and access controls. MCP servers need the same protections, with the additional consideration that the caller (an AI model) can make many rapid, programmatic calls that a human user typically would not.
Security Best Practices
Use a read-only database user
Create a dedicated database user for your MCP server with SELECT-only permissions. This prevents the server from executing INSERT, UPDATE, DELETE, or DDL statements even if a bug or unexpected input somehow gets past your validation. The database enforces the read-only constraint as a last line of defense regardless of what the application code does.
-- PostgreSQL: create a read-only user for the MCP server
CREATE USER mcp_reader WITH PASSWORD 'secure-password';
GRANT CONNECT ON DATABASE mydb TO mcp_reader;
GRANT USAGE ON SCHEMA public TO mcp_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO mcp_reader;Validate and parameterize queries
Never pass user-provided (or model-provided) input directly into SQL strings. Use parameterized queries for all database operations. If your tool accepts a query string, validate that it is a SELECT statement before executing it. Better yet, do not accept raw SQL at all; design tools that accept structured parameters and construct queries internally.
# Safe: parameterized query
def search_customers(name: str, limit: int = 10):
cursor.execute(
"SELECT id, name, email FROM customers WHERE name ILIKE %s LIMIT %s",
(f"%{name}%", min(limit, 100))
)
return cursor.fetchall()
# Unsafe: string interpolation (never do this)
def bad_search(query: str):
cursor.execute(f"SELECT * FROM customers WHERE {query}") # SQL injectionRestrict table access
Grant the MCP database user access only to the tables that the AI tools need. If your MCP server provides a customer lookup tool, grant SELECT on the customers table and nothing else. Do not grant access to tables containing credentials, billing information, or internal administrative data unless those are explicitly needed by the tools.
Limit result sizes
Always apply a maximum limit to query results. An AI model might request "all records" without realizing the table has millions of rows. Enforce a maximum in your tool handler (for example, cap at 100 rows regardless of what the model requests) and return a count of total matching rows so the model knows there is more data available if needed.
Log everything
Log every query that your MCP server executes, including the tool name, the parameters, the query text, the number of rows returned, and the execution time. This audit trail is essential for debugging, compliance, and detecting unusual access patterns. If the AI model starts making unexpected queries, the logs tell you exactly what happened and when.
Design Patterns for Safe Database Tools
The safest approach is to design tools that accept structured parameters rather than raw queries. Instead of a tool that takes a SQL string, build tools for specific operations: "search customers by name," "get order details by ID," "list recent transactions." Each tool constructs its query internally using parameterized queries with the parameters the model provides.
This approach limits the attack surface because the model can only invoke predefined operations with validated parameters. It also produces better results because the tool descriptions can be specific ("Search customers by name or email address") rather than generic ("Run a SQL query"), which helps the model select the right tool and provide the right parameters.
Development vs Production
During development, it is common to use a more permissive database connection for convenience. For production, always apply the principle of least privilege: the MCP server should have the minimum database permissions required for its tools to function. Review the permissions periodically and revoke any access that is no longer needed by current tools.
Consider using a staging or read replica database for the MCP server rather than the primary production database. This eliminates any risk of impacting production performance and provides an additional safety layer against accidental writes.
Let Adaptive Recall handle memory storage for you. No database configuration needed, just connect and start storing memories.
Get Started Free