Skip to main content

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"

PyPI version Python 3.9+ License: MIT Downloads


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:

  1. New database connectors โ€” MySQL, BigQuery, DuckDB (see sqlsense/connectors.py)
  2. Guardrail improvements โ€” edge cases, dialect-specific rules
  3. HTTP transport โ€” SSE server for remote deployments
  4. 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

sqlsense-0.1.4.tar.gz (30.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlsense-0.1.4-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

Details for the file sqlsense-0.1.4.tar.gz.

File metadata

  • Download URL: sqlsense-0.1.4.tar.gz
  • Upload date:
  • Size: 30.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for sqlsense-0.1.4.tar.gz
Algorithm Hash digest
SHA256 3f569f363e544126452c1555c3ece661fe723fe40be5b5d0b777a141e7bc2a6b
MD5 41a6c921537d9dc094ed6c2b846ab7dd
BLAKE2b-256 301eb919d3e4d1cd075613103902a359756f2af43e9c4073d401c1a84bbf9e25

See more details on using hashes here.

File details

Details for the file sqlsense-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: sqlsense-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 26.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for sqlsense-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ef312b91fa09f927a2be05b403c48ac4ebc3c7cc6867c26f78522b05f4716750
MD5 9c73b8e90da61b81df422d016c42cc5e
BLAKE2b-256 91c53fcca222913ccf5b781508a23704b468c26577f6762ee734723cb772540c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page