Safe, audited SQL for AI agents via MCP
Project description
๐ก๏ธ SQLSense
Safe, audited SQL for AI agents via MCP.
AI agents are talking to your database. SQLSense makes sure they don't destroy it.
pip install sqlsense
sqlsense serve --dsn "postgresql://user:pass@localhost/mydb"
The problem
You're giving an AI agent access to your database. It generates SQL, executes it. What could go wrong?
-- Agent confidently generates this
DELETE FROM users;
-- Or this
SELECT password, ssn, credit_card FROM customers;
-- Or this
DROP TABLE orders;
No existing MCP database tool blocks these. SQLSense does.
What SQLSense does
SQLSense is an MCP server that wraps your database connection with:
- ๐ซ Guardrails โ blocks dangerous queries before they reach your database
- ๐ Readonly mode โ SELECT-only by default, writes opt-in
- ๐ Audit log โ every query an agent runs, logged to JSONL
- ๐ข Auto-LIMIT โ automatically caps SELECT queries to prevent full-table scans
- ๐ Column blocking โ blocklist sensitive columns (
password,ssn,api_key...) - ๐ Injection guard โ multi-statement queries blocked at parse time
- ๐๏ธ Multi-database โ SQLite, PostgreSQL, SQL Server, Snowflake
Quickstart
Install
pip install sqlsense
# With your database driver
pip install "sqlsense[postgres]" # PostgreSQL
pip install "sqlsense[sqlserver]" # SQL Server
pip install "sqlsense[snowflake]" # Snowflake
pip install "sqlsense[all]" # Everything
SQL Server โ extra step required
pyodbc (installed by sqlsense[sqlserver]) needs the Microsoft ODBC Driver 17 installed at the OS level. pip cannot do this part.
macOS:
brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
brew update
HOMEBREW_ACCEPT_EULA=Y brew install msodbcsql17
Ubuntu / Debian:
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list \
| sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17
Windows: Download from Microsoft's ODBC Driver page and run the installer.
Start the MCP server
# PostgreSQL (readonly by default)
sqlsense serve --dsn "postgresql://user:pass@localhost/mydb"
# SQL Server (common in enterprise/fintech)
sqlsense serve --dsn "mssql://user:pass@server:1433/mydb"
# Snowflake
sqlsense serve --dsn "snowflake://user:pass@account/warehouse/database"
# SQLite (great for local dev)
sqlsense serve --dsn "sqlite:///./myapp.db"
Connect to Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"sqlsense": {
"command": "sqlsense",
"args": ["serve", "--dsn", "postgresql://user:pass@localhost/mydb"]
}
}
}
Claude now has safe, audited database access. Ask it:
"Show me the top 10 customers by order value this month"
SQLSense intercepts every query, checks it against guardrails, logs it, and either executes it safely or blocks it with a clear reason.
Connect to Claude Code
# In your project
claude mcp add sqlsense -- sqlsense serve --dsn "postgresql://..."
Credentials โ never hardcode them
Never put database credentials directly in your MCP config or shell history. Use one of these patterns instead.
Option 1 โ Wrapper script (recommended)
Create a script that pulls credentials from your secret store at runtime:
# ~/scripts/sqlsense-mydb.sh
#!/bin/bash
sqlsense serve \
--dsn "postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:5432/${DB_NAME}" \
--max-rows 1000 \
--audit-log ~/.sqlsense/audit.jsonl
chmod +x ~/scripts/sqlsense-mydb.sh
Then your Claude Desktop config stays clean โ no credentials anywhere:
{
"mcpServers": {
"mydb": {
"command": "/Users/you/scripts/sqlsense-mydb.sh"
}
}
}
Option 2 โ macOS Keychain
# Store once
security add-generic-password -a sqlsense -s db-password -w "your_password"
# Retrieve in your wrapper script
DB_PASS=$(security find-generic-password -a sqlsense -s db-password -w)
Option 3 โ Environment variables via env block
Claude Desktop supports an env block in the config โ credentials stay out of args:
{
"mcpServers": {
"mydb": {
"command": "sqlsense",
"args": ["serve", "--dsn", "postgresql://$(DB_USER):$(DB_PASS)@$(DB_HOST)/$(DB_NAME)"],
"env": {
"DB_USER": "myuser",
"DB_PASS": "mypassword",
"DB_HOST": "localhost",
"DB_NAME": "mydb"
}
}
}
}
Option 4 โ .env file with a loader
# .env (never commit this)
DB_USER=myuser
DB_PASS=mypassword
DB_HOST=localhost
DB_NAME=mydb
# wrapper script
#!/bin/bash
set -a && source ~/.sqlsense/.env && set +a
sqlsense serve --dsn "postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_NAME}"
Guardrails in action
# Test any query before running it
$ sqlsense check "DELETE FROM users"
๐ซ BLOCKED (risk: HIGH)
Reason: DELETE is blocked. Set allow_delete=True to enable.
$ sqlsense check "SELECT * FROM orders"
โ
ALLOWED (risk: MEDIUM)
Warnings:
โข SELECT * detected โ prefer explicit column names.
โข No WHERE clause โ query may scan the full table.
โข LIMIT 1000 automatically added to protect against full-table scans.
$ sqlsense check "SELECT id FROM users WHERE id = 1"
โ
ALLOWED (risk: LOW)
Hash: a3f9c2d1b8e4
Configuration
All guardrails are configurable. Defaults are deliberately conservative.
# Allow writes (careful!)
sqlsense serve --dsn "..." --allow-writes
# Increase row limit
sqlsense serve --dsn "..." --max-rows 5000
# Block specific tables
sqlsense serve --dsn "..." \
--block-table audit_log \
--block-table internal_config
# Disable auto-LIMIT (not recommended)
sqlsense serve --dsn "..." --no-auto-limit
Or configure programmatically:
from sqlsense import SQLSenseMCPServer
from sqlsense.guardrails import GuardrailConfig
config = GuardrailConfig(
max_rows=2000,
readonly_mode=True, # default: True
auto_add_limit=True, # default: True
blocked_tables=["secrets"],
blocked_columns=["password", "token", "ssn", "credit_card"],
require_where_on_writes=True, # default: True
)
server = SQLSenseMCPServer(dsn="postgresql://...", config=config)
server.run()
Audit log
Every query an agent runs is written to a JSONL file:
# View recent queries
sqlsense audit --tail 20
# Output
TIME ALLOWED RISK ROWS MS SQL
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2025-02-26T14:22:01Z โ
low 42 12.3 SELECT id, name FROM customers WHE...
2025-02-26T14:22:15Z ๐ซ high โ โ DELETE FROM users
2025-02-26T14:22:31Z โ
medium 1000 891.2 SELECT * FROM orders
# JSON output for piping to your observability stack
sqlsense audit --tail 100 --json | jq '.[] | select(.allowed == false)'
Each entry is a self-contained JSON object โ trivially parseable by Splunk, Datadog, CloudWatch, or grep.
MCP Tools
SQLSense exposes 4 tools to the AI agent:
| Tool | Description |
|---|---|
sql_query |
Execute SQL (with guardrails + auto-LIMIT) |
get_schema |
Get table/column definitions for context |
explain_query |
Check what a query will do before running |
get_audit_log |
Retrieve recent query history |
The agent calls get_schema first to understand the database, then explain_query to validate before executing โ SQLSense nudges agents toward safer patterns.
Supported databases
| Database | Status | Install |
|---|---|---|
| SQLite | โ Built-in | pip install sqlsense |
| PostgreSQL | โ Stable | pip install "sqlsense[postgres]" |
| SQL Server | โ Stable | pip install "sqlsense[sqlserver]" |
| Snowflake | โ Stable | pip install "sqlsense[snowflake]" |
| MySQL | ๐ง Planned | โ |
| BigQuery | ๐ง Planned | โ |
| DuckDB | ๐ง Planned | โ |
Use with other AI frameworks
SQLSense is an MCP server, so it works with anything that speaks MCP:
- โ Claude Desktop
- โ Claude Code
- โ Any MCP-compatible agent framework
- โ Custom agents (via stdio JSON-RPC)
Python API
Use SQLSense as a library if you don't need the MCP layer:
from sqlsense.guardrails import GuardrailsEngine, GuardrailConfig
from sqlsense.connectors import create_connector
from sqlsense.audit import AuditLogger
# Guardrails only
engine = GuardrailsEngine(GuardrailConfig())
result = engine.check("SELECT * FROM users")
if not result.allowed:
raise PermissionError(result.reason)
# Full stack
db = create_connector("postgresql://user:pass@localhost/mydb")
logger = AuditLogger("./audit.jsonl")
guard = engine.check(sql)
if guard.allowed:
safe_sql = guard.rewritten_sql or sql
query_result = db.execute(safe_sql)
logger.record(sql, guard, rows_returned=query_result.row_count)
Roadmap
- HTTP/SSE transport (in addition to stdio)
- MySQL connector
- BigQuery connector
- DuckDB connector
- Web dashboard for audit log
- Query cost estimation (EXPLAIN integration)
- Rate limiting per agent/session
- Row-level security policies
- Slack/webhook alerts on blocked queries
- Docker image
Contributing
Contributions very welcome. The most useful things right now:
- New database connectors โ MySQL, BigQuery, DuckDB (see
sqlsense/connectors.py) - Guardrail improvements โ edge cases, dialect-specific rules
- HTTP transport โ SSE server for remote deployments
- Tests โ more edge cases in
tests/test_sqlsense.py
git clone https://github.com/raj8github/sqlsense
cd sqlsense
pip install -e ".[dev]"
pytest tests/ -v
See CONTRIBUTING.md for details.
Why this exists
AI agents with database access are powerful. They're also one bad prompt away from DELETE FROM production_users without a WHERE clause.
The current ecosystem of MCP database tools (sqlite-mcp, postgres-mcp, etc.) gives agents raw access with no guardrails, no audit trail, and no circuit breakers. SQLSense fills that gap โ built with patterns from production fintech environments where database safety isn't optional.
License
MIT โ see LICENSE
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sqlsense-0.1.3.tar.gz.
File metadata
- Download URL: sqlsense-0.1.3.tar.gz
- Upload date:
- Size: 26.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0acdda5cc9e01b0d73b4a924ec215ec77a69e4602a6281310abec95c092d456
|
|
| MD5 |
e0ea66f9f4a3b4ed17ae3853ffdc37d5
|
|
| BLAKE2b-256 |
bcd8d43211df8c8920157640e9207212292449f1edf3e96525ca0076015a1bc8
|
File details
Details for the file sqlsense-0.1.3-py3-none-any.whl.
File metadata
- Download URL: sqlsense-0.1.3-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4bc304cc4208d4f9f845493f61834eb6895ab715ddd1f7a76426eff45029676
|
|
| MD5 |
643358d7a74a4e057feba7eae1d117c1
|
|
| BLAKE2b-256 |
aa82e35b120b60ee64972c330ad80b4cddb9b1c21ef39ed176b4c1945a69e18e
|