testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited testing (Rules) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A lightweight, extensible, cross-database MCP server (Model Context Protocol server) written in Python, designed to help AI coding assistants (e.g., Cursor, Claude Code, and other MCP-compatible clients) introspect, analyze, and verify SQL-based database systems.
psycopg2-binary)The quickest way to get running is with uvx (the tool runner from uv). No cloning or virtual environments needed.
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | shAdd the server entry to your MCP client config. Both Cursor and Claude Code use the same mcpServers format, just in different files:
| Client | Project-level config | User-level (global) config |
|---|---|---|
| Cursor | .cursor/mcp.json | ~/.cursor/mcp.json |
| Claude Code | .mcp.json | ~/.claude.json |
Add this to the appropriate config file:
{
"mcpServers": {
"db-inspector-mcp": {
"command": "uvx",
"args": ["db-inspector-mcp@latest"]
}
}
}The @latest suffix ensures uvx always pulls the latest version from PyPI instead of using a cached copy.
Alternative for Claude Code -- you can use the CLI instead of editing JSON:
claude mcp add db-inspector-mcp -- uvx db-inspector-mcp@latestShortcut -- the built-in init command registers the server globally and creates a .env template in one step:
uvx db-inspector-mcp initCreate a .env file in your project root (or edit the one created by init):
# SQL Server
DB_MCP_DATABASE=sqlserver
DB_MCP_CONNECTION_STRING=Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=mydb;UID=user;PWD=password
# PostgreSQL
DB_MCP_DATABASE=postgres
DB_MCP_CONNECTION_STRING=dbname=mydb user=postgres password=secret host=localhost port=5432
# Microsoft Access (ODBC -- works without Access installed)
DB_MCP_DATABASE=access_odbc
DB_MCP_CONNECTION_STRING=Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\path\to\database.accdb;
# Microsoft Access (COM -- query-by-name, requires Access installed)
DB_MCP_DATABASE=access_com
DB_MCP_CONNECTION_STRING=Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\path\to\database.accdb;See Configuration for full details on connection strings, multi-database setups, and all environment variables.
Close and reopen Cursor or Claude Code. The MCP server will be detected and loaded automatically.
Ask the AI assistant to use the database tools:
"What tables are in the database? Use db_list_tables"
"How many rows are in the users table? Use db_count_query_results"
"Verify the database is read-only using db_check_readonly_status"
All configuration is done through environment variables, typically in a .env file in your project root. The server loads .env automatically at startup.
| Variable | Description | Default | Required |
|---|---|---|---|
DB_MCP_DATABASE | Database type: sqlserver, postgres, access_odbc, or access_com | - | Yes* |
DB_MCP_CONNECTION_STRING | Database connection string | - | Yes* |
DB_MCP_<name>_DATABASE | Database type for named database (multi-database) | - | Yes* |
DB_MCP_<name>_CONNECTION_STRING | Connection string for named database (multi-database) | - | Yes* |
DB_MCP_PROJECT_DIR | Project directory for .env file lookup (see User-Level Configuration) | auto-detected | No |
DB_MCP_QUERY_TIMEOUT_SECONDS | Query timeout in seconds | 30 | No |
DB_MCP_ALLOW_DATA_ACCESS | Global flag to enable data access tools | false | No |
DB_MCP_VERIFY_READONLY | Verify read-only at startup; fail if not confirmed | true | No |
*Either single-database (DB_MCP_DATABASE + DB_MCP_CONNECTION_STRING) or multi-database (DB_MCP_<name>_DATABASE + DB_MCP_<name>_CONNECTION_STRING) configuration is required.
#### SQL Server
DB_MCP_DATABASE=sqlserver
# ODBC connection string
DB_MCP_CONNECTION_STRING=Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=mydb;UID=user;PWD=password
# Or using DSN
DB_MCP_CONNECTION_STRING=DSN=MySQLServerDSN#### PostgreSQL
DB_MCP_DATABASE=postgres
DB_MCP_CONNECTION_STRING=dbname=mydb user=postgres password=secret host=localhost port=5432#### Microsoft Access
Two backends are available:
DB_MCP_DATABASE=access_odbc # or access_com
DB_MCP_CONNECTION_STRING=Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\path\to\database.accdb;Both backends support .accdb, .accda, and .mdb file formats. The driver name in the connection string is the same regardless of file extension.
Relative paths are resolved against the directory containing the .env file, making configurations portable:
DB_MCP_CONNECTION_STRING=Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=.\database.accdb;
# Or just the filename
DB_MCP_CONNECTION_STRING=database.accdbUse access_odbc for standard SQL operations. Use access_com when you need to retrieve Access queries by name (see db_get_access_query_definition).
Connect to multiple databases simultaneously for migration validation, testing, or comparison scenarios. Use the pattern DB_MCP_<name>_DATABASE and DB_MCP_<name>_CONNECTION_STRING:
# Migration scenario: Access to SQL Server
DB_MCP_LEGACY_DATABASE=access_com
DB_MCP_LEGACY_CONNECTION_STRING=Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\path\to\legacy.accdb;
DB_MCP_NEW_DATABASE=sqlserver
DB_MCP_NEW_CONNECTION_STRING=Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=mydb;UID=user;PWD=passwordName databases to match your use case: legacy/new, prod/dev, v1/v2, etc. The first database configured (or one named "default") becomes the default.
When multiple databases are configured, all tools accept an optional database parameter:
db_count_query_results("SELECT * FROM customers", database="legacy")
db_compare_queries(
"SELECT * FROM customers WHERE active = 1",
"SELECT * FROM customers WHERE status = 'active'",
database1="legacy",
database2="new"
)Call db_list_databases() first to discover available database names.
Project-level -- add .cursor/mcp.json to your project root (can be version-controlled for team sharing):
{
"mcpServers": {
"db-inspector-mcp": {
"command": "uvx",
"args": ["db-inspector-mcp@latest"]
}
}
}User-level -- add to ~/.cursor/mcp.json to make the server available in all projects. The server automatically finds each project's .env file via workspace detection (see User-Level Configuration below).
Project-level -- add .mcp.json to your project root:
{
"mcpServers": {
"db-inspector-mcp": {
"command": "uvx",
"args": ["db-inspector-mcp@latest"]
}
}
}User-level -- add to ~/.claude.json to make the server available in all projects.
CLI alternative -- register without editing JSON:
claude mcp add db-inspector-mcp -- uvx db-inspector-mcp@latestAny MCP-compatible client can use this server. The configuration format is the same mcpServers object shown above -- consult your client's documentation for where to place it.
When configured at the user level (global config), you don't need a per-project MCP config file. The server finds each project's .env file automatically:
.env, .cursor/mcp.json, or pyproject.toml.env was found at startup, asks the client for its workspace roots via the MCP protocolThis works even when the working directory is not the project root (the typical case for user-level configs).
Fallback: If automatic detection doesn't work, set DB_MCP_PROJECT_DIR explicitly in your MCP config:
{
"mcpServers": {
"db-inspector-mcp": {
"command": "uvx",
"args": ["db-inspector-mcp@latest"],
"env": {
"DB_MCP_PROJECT_DIR": "C:\\Users\\me\\projects\\my-project"
}
}
}
}For contributing or running from source, see CONTRIBUTING.md. The short version:
git clone https://github.com/joyfullservice/db-inspector-mcp.git
cd db-inspector-mcp
uv sync --frozen --extra devThis project uses uv with a committed uv.lock; uv sync creates a managed .venv and installs the project in editable mode. See CONTRIBUTING.md for the full workflow.
For development installs, use uv run python -m db_inspector_mcp.main as the command in your MCP config:
{
"mcpServers": {
"db-inspector-mcp": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/db-inspector-mcp", "python", "-m", "db_inspector_mcp.main"]
}
}
}Replace /absolute/path/to/db-inspector-mcp with your local clone path. uv run ensures the locked .venv is used regardless of the client's working directory.
If the MCP server doesn't load:
Ctrl+Shift+P / Cmd+Shift+P) and look for MCP-related output. In Claude Code, check the terminal output.uvx db-inspector-mcp --help in your terminal. DB_MCP_DATABASE=sqlserver DB_MCP_CONNECTION_STRING="your-connection-string" uvx db-inspector-mcp#### db_list_databases()
List all configured database backends.
db_list_databases()
# Returns: {"databases": [{"name": "source", "is_default": True}, {"name": "dest", "is_default": False}], "default": "source"}#### db_count_query_results(query, database=None)
Count rows a SELECT query returns by wrapping it in SELECT COUNT(*) FROM (your_query).
db_count_query_results("SELECT * FROM users WHERE active = 1")
# Returns: {"count": 1234}#### db_get_query_columns(query, database=None)
Analyze column schema of a query's results (fetches 0 rows, inspects metadata only).
db_get_query_columns("SELECT * FROM users")
# Returns: {"columns": [{"name": "id", "type": "int", "nullable": false, ...}, ...]}#### db_sum_query_column(query, column, database=None)
Sum a specific column from a query's results.
db_sum_query_column("SELECT amount FROM transactions", "amount")
# Returns: {"sum": 12345.67}#### db_measure_query(sql, max_rows=1000, database=None)
Return execution time, row count, and whether the row cap was hit.
db_measure_query("SELECT * FROM large_table", max_rows=1000)
# Returns: {"execution_time_ms": 123.45, "row_count": 1000, "hit_limit": true}#### db_preview(sql, max_rows=100, database=None)
Sample N rows from a query result. Requires DB_MCP_ALLOW_DATA_ACCESS=true.
db_preview("SELECT * FROM users ORDER BY created_at DESC", max_rows=10)
# Returns: {"rows": [{"id": 1, "name": "Alice", ...}, ...]}#### db_explain(sql, database=None)
Return database-native execution plan.
db_explain("SELECT * FROM users JOIN orders ON users.id = orders.user_id")
# Returns: {"plan": "<execution plan XML/JSON>"}#### db_compare_queries(sql1, sql2, compare_samples=False, database1=None, database2=None)
Compare two queries side-by-side, optionally from different databases. Useful for migration validation.
If compare_samples=True, requires data access permission.
db_compare_queries(
"SELECT * FROM customers WHERE active = 1",
"SELECT * FROM customers WHERE status = 'active'",
database1="legacy",
database2="new",
compare_samples=True
)
# Returns: {"row_count_diff": 0, "columns_missing_in_2": [], "type_mismatches": [], ...}#### db_list_tables(database=None)
List all tables in the database with metadata.
db_list_tables()
# Returns: {"tables": [{"name": "users", "schema": "dbo", "row_count": 1234}, ...]}#### db_list_views(database=None)
List all views with their SQL definitions.
db_list_views()
# Returns: {"views": [{"name": "active_users", "schema": "dbo", "definition": "SELECT ..."}, ...]}Note for Access COM backend: Returns query names without SQL (extraction is expensive). Use db_get_access_query_definition() to get SQL for specific queries.
#### db_get_access_query_definition(name, database=None)
Get Access query SQL definition by name. Requires the access_com backend.
db_get_access_query_definition("ActiveCustomers", database="legacy")
# Returns: {"name": "ActiveCustomers", "sql": "SELECT * FROM Customers WHERE Active = True", "type": "Select"}#### db_check_readonly_status(database=None)
Verify that the database connection is read-only.
db_check_readonly_status()
# Returns: {"readonly": true, "details": "Read-only verification passed"}All SQL queries are validated to reject write operations (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.).
Some tools require explicit authorization:
DB_MCP_ALLOW_DATA_ACCESS=trueMetadata tools (row counts, column schemas, execution plans) are always available.
By default, db-inspector-mcp exposes only schema metadata and aggregates — table names, column types, row counts, and execution plans. No actual row data leaves your database.
When you enable data access (DB_MCP_ALLOW_DATA_ACCESS=true), tools like db_preview return actual row values from your database. This data is sent to your AI provider as part of the conversation context. Depending on your provider and configuration, this data may be:
Before enabling data access on databases that contain personally identifiable information (PII), protected health information (PHI), financial records, or other regulated data, verify your AI provider's data retention and model training policies. Most providers offer settings to opt out of training — ensure these are configured appropriately for your environment.
For granular control, use per-connection overrides to enable data access selectively — for example, allowing it on development databases while keeping it off for production:
DB_MCP_DEV_ALLOW_DATA_ACCESS=true
DB_MCP_PROD_ALLOW_DATA_ACCESS=falseAt startup (if DB_MCP_VERIFY_READONLY=true, the default), the server verifies each SQL Server/PostgreSQL backend is read-only by checking role membership or privileges. Access backends are exempt (no role-based permission model). If write permissions are detected or verification is inconclusive (timeout/error), startup fails. Set DB_MCP_VERIFY_READONLY=false to skip verification.
db-inspector-mcpStarts the MCP server (stdio transport). This is how MCP clients launch it.
db-inspector-mcp initInitialize db-inspector-mcp in a project directory:
.env file:--force to replace an existing .env with the full template~/.cursor/mcp.json and ~/.claude.json for automatic discoverydb-inspector-mcp init # current directory
db-inspector-mcp init --force # overwrite existing .env
db-inspector-mcp init --dir /path/to/projectdb-inspector-mcp --versionShow the installed version number.
db-inspector-mcp --helpShow available commands.
For development setup, testing, project structure, and contribution guidelines, see CONTRIBUTING.md.
For architectural decisions and design rationale, see DECISIONS.md.
MIT License - see LICENSE file for details.
Contributions are welcome! Please open an issue or submit a pull request. See CONTRIBUTING.md for development setup, testing, and adding new backends.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.