db-compare MCP
Read-only MCP server for comparing SQL Server / Azure SQL schema between named environments (e.g. dev vs prod).
This server never writes to the database. All operations are SELECT queries against catalog views (sys.*). No DDL, DML, or EXEC is performed.
What it compares
- Tables (columns, PKs, FKs, indexes, check constraints)
- Stored procedures, views, functions, triggers (line-by-line definition diff)
- Object inventory (objects only in A, only in B, or changed)
Prerequisites
- Python 3.10+ and uv
- Read-only database credentials for each environment (
db_datareader+VIEW DEFINITION) - One of these drivers:
- ODBC (default): ODBC Driver 18 for SQL Server (
Get-OdbcDriver | Where-Object Name -like '*SQL Server*') - JDBC (optional): Java 11+ and Microsoft JDBC Driver for SQL Server JAR
- ODBC (default): ODBC Driver 18 for SQL Server (
Setup
cd c:\Users\yadukrishnan\Develop\DBCompare
uv sync
# JDBC only:
uv sync --extra jdbc
ODBC configuration (default)
SQLDIFF_DRIVER=odbc
SQLDIFF_CONN_<NAME>=<odbc connection string>
Example:
SQLDIFF_CONN_DEV=Driver={ODBC Driver 18 for SQL Server};Server=tcp:myserver-dev.database.windows.net,1433;Database=mydb;Uid=readonly;Pwd=...;Encrypt=yes;TrustServerCertificate=no;ApplicationIntent=ReadOnly;
JDBC configuration
SQLDIFF_DRIVER=jdbc
SQLDIFF_JDBC_JAR=C:/path/to/mssql-jdbc-12.8.1.jre11.jar
SQLDIFF_CONN_<NAME>=jdbc:sqlserver://host:1433;databaseName=mydb;encrypt=true;trustServerCertificate=false;
SQLDIFF_JDBC_USER_<NAME>=readonly
SQLDIFF_JDBC_PASSWORD_<NAME>=...
Notes:
- A connection string starting with
jdbc:sqlserver:automatically uses JDBC even ifSQLDIFF_DRIVER=odbc. - Per-environment override:
SQLDIFF_DRIVER_DEV=jdbc,SQLDIFF_DRIVER_PROD=odbc. - Credentials can be embedded in the JDBC URL (
user=...;password=...) instead of separate env vars. - The server automatically appends read-only intent (
ApplicationIntent=ReadOnly/applicationIntent=ReadOnly) if not present.
Run standalone
uv run server.py
# or
uv run db-compare
Cursor MCP integration
Edit .cursor/mcp.json with your connection strings (or use Cursor secrets). Restart Cursor, then verify tools appear in the MCP panel.
Example mcp.json:
{
"mcpServers": {
"db-compare": {
"command": "uv",
"args": ["run", "server.py"],
"cwd": "/path/to/DBCompare",
"env": {
"SQLDIFF_CONN_DEV": "...",
"SQLDIFF_CONN_PROD": "..."
}
}
}
}
Example chat prompts:
- "Use db-compare to list configured environments"
- "Diff schema inventory between dev and prod"
- "Show full drift report between dev and prod for schema dbo"
- "Diff table structure for dbo.Orders between dev and prod"
MCP tools
| Tool | Description |
|---|---|
list_environments |
Show configured environment names |
test_connection |
Verify read-only connectivity |
list_schemas |
List user schemas in one environment |
list_objects |
List tables/views/procs/functions/triggers |
diff_schema_inventory |
High-level inventory diff |
diff_object_definition |
Line diff for a proc/view/function/trigger |
diff_table_structure |
Structural diff for a table |
full_drift_report |
Inventory + deep compare of all common objects |
Testing
# Unit tests (no database required)
uv sync --extra dev
uv run pytest tests/test_differ.py tests/test_readonly.py -v
# Integration tests (requires .env.test with SQLDIFF_CONN_DEV and SQLDIFF_CONN_PROD)
uv run pytest tests/ -m integration -v
Copy .env.test.example to .env.test and fill in credentials. Integration tests are read-only — they never modify the database.
Known limitations
- Encrypted modules cannot be diffed (reported explicitly)
- Computed columns and filtered index WHERE clauses are not captured
- Synonyms, sequences, and user-defined types are not yet included
Security
- Use read-only database users, not admin accounts
- Never commit connection strings — use
.env.test(gitignored) or Cursor env secrets - All SQL passes through a SELECT-only guard in
db.py
Install (for users)
After publishing to PyPI:
uvx db-compare-mcp
Or add to Cursor mcp.json:
{
"mcpServers": {
"db-compare": {
"command": "uvx",
"args": ["db-compare-mcp"],
"env": {
"SQLDIFF_CONN_DEV": "...",
"SQLDIFF_CONN_PROD": "..."
}
}
}
}
See PUBLISHING.md for maintainer release steps.
Publishing
| Item | Value |
|---|---|
| GitHub | https://github.com/yadu-tv/db-compare |
| PyPI package | db-compare-mcp |
| MCP registry name | io.github.yadu-tv/db-compare |
| CLI entry point | db-compare |
Metadata
Release files for db-compare-mcp 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| db_compare_mcp-0.1.1.tar.gz | 16.7 kB | Without provenance | Details for db_compare_mcp-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| db_compare_mcp-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for db_compare_mcp-0.1.1-py3-none-any.whl |
Total release size: 31.9 kB
Release files / db_compare_mcp-0.1.1.tar.gz
| Download URL | db_compare_mcp-0.1.1.tar.gz |
|---|---|
| Size | 16.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d423164df7fe649747c8f395a8c44d9f3dd099f7d7da53b9cdca3dbde870e3cd
|
|
BLAKE2b-256 checksum How to use checksums |
42155c653b5d1bd3d68a30554f5b8f84cb84e5f641360986dcd3f50bdbea3e2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / db_compare_mcp-0.1.1-py3-none-any.whl
| Download URL | db_compare_mcp-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc74ba65a5bf7cbe2f04e632d6ec4516e658ee663a17d3d61b9ee10f648f0413
|
|
BLAKE2b-256 checksum How to use checksums |
5062350d82987c80c7e50f8d79d3f3a4f2da3771459e3fd1803ede01a42d5032
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for db-compare-mcp 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.