← Back to list

My Two Database MCP Projects: From One Engine to Eight

Not a medium member? Read here!

Lorenzo Uriel · 2026-06-25 23:01 · 0 claps · 4.5 min read paywalled
#mcp-server #sql-mcp #claude #claude-code #mcps
Open on Medium ↗
Wiki topics: LLM · Large Language Models AGT · AI Agents

My Two Database MCP Projects: From One Engine to Eight

Source: Author

Source: Author

Not a medium member? Read here!

I started a specific MCP project last year: the MSSQL MCP. The goal was to learn more about the creation and whole structure of an MCP.

This week I launched my second MCP project, that time was something more ambitious: One MCP to Rule Them All.

This MCP connect with more than 8 engines including SQL Server, MongoDB, Microsoft Fabric, and Databricks.

What is crazy about all that? It’s that it works… rs

I have a specific article explaining about sql-mcp. I will use this one to talk about both, why I created and what I learned in the process.

What is MCP?

The Model Context Protocol (MCP) is an open standard that lets AI apps talk to external tools and data through one uniform interface. The usual analogy is a USB-C port for AI.

A server exposes tools, meaning functions the model can call. Mine expose database tools: run a query, list schemas, describe tables, check connectivity.

Project 1: mssql-mcp-python, the focused approach

Source: Author

Source: Author

Repository: github.com/lorenzouriel/mssql-mcp-python

This was the first one. I live and breath SQL Server, and I wanted a clean MCP server built specifically for it.

What it does

It connects Claude (or any MCP client) to a single SQL Server instance through seven tools:

  • execute_sqlRun SELECT queries (or writes if explicitly enabled)
  • list_schemasList all database schemas
  • list_tablesList tables with optional schema filter
  • schema_discoveryFull column-level metadata: types, nullability, defaults
  • get_database_infoServer and database metadata
  • get_policy_infoActive security policy settings
  • check_db_connectionHealth check

Claude chains them naturally: list the schemas, inspect a table’s structure, then write a query against the real columns instead of hallucinating names.

Why it exists

When I started, there wasn’t a solid MCP server for it, and I wanted to learn more. That’s it.

Tech stack

  • Python 3.10+ with FastMCP
  • pyodbc for connectivity (ODBC Driver 17)
  • Pydantic for config and validation
  • Prometheus metrics, structured JSON logging, optional Sentry
  • Docker image with the ODBC driver baked in
  • HTTP and stdio transports

Security model

This is the part I cared most about.

  • Read-only by default. Writes need both ENABLE_WRITES=true and an ADMIN_CONFIRM token. You opt into danger. You don't opt out of safety.
  • SQL injection prevention: multi-statement blocking, banned-keyword detection (DROP, ALTER, EXEC, xp*, sp*, KILL, SHUTDOWN, OPENROWSET, BULK INSERT), query-length limits.
  • Resource limits: 30-second query timeout, 50,000-row cap, connection pooling.
  • Audit trail: every query, allowed or denied, logged with a SHA-256 hash and the reason for any rejection.
  • Sensitive-data redaction: passwords and connection strings are stripped from logs.

Getting started

pip install -r requirements.txt

# Set your connection string
export MSSQL_CONNECTION_STRING="Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=mydb;UID=sa;PWD=secret"

# Run with stdio (for Claude Desktop)
python -m mssql_mcp.cli

# Or with HTTP (for development/testing)
python -m mssql_mcp.cli --transport http --bind 0.0.0.0:8080

Wire it into Claude Desktop:

{
  "mcpServers": {
    "mssql": {
      "command": "python",
      "args": ["-m", "mssql_mcp.cli"],
      "env": {
        "MSSQL_CONNECTION_STRING": "Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=mydb;UID=sa;PWD=secret"
      }
    }
  }
}

Restart Claude Desktop and ask: “What schemas exist in this database?”

When to use it

Use it when SQL Server is all you need.

One connection string and you’re done, and you get SQL Server-specific touches like reading table descriptions from sys.extended_properties.

Project 2: sql-mcp, the universal approach

Source: Author

Source: Author

Repository: github.com/lorenzouriel/sql-mcp

The obvious and ambitious problem: my data doesn’t live in one place. PostgreSQL warehouses, MongoDB stores, Databricks lakehouses, Fabric workspaces.

A separate MCP server per engine was never going to scale.

So sql-mcp: one server, eight engines, up to twenty live connections, one interface.

What it does

sql-mcp gives Claude structured access to:

  • Microsoft SQL Server
  • PostgreSQL
  • MySQL
  • MariaDB
  • SQLite
  • MongoDB
  • Databricks
  • Fabric

It exposes nine tools, the same seven from project 1 plus two:

  • list_connectionsLists all registered connections. Claude calls this first when multiple databases exist
  • execute_native_queryRuns native non-SQL queries (MongoDB MQL filters and aggregation pipelines)

The killer feature: multi-database conversations

Drop a connections.json describing every database you care about:

{
  "connections": [
    {
      "id": "prod_mssql",
      "engine": "mssql",
      "dsn": "Driver={ODBC Driver 17 for SQL Server};Server=prod-sql.internal;Database=orders;UID=ro_user;PWD=secret",
      "read_only": true,
      "description": "Production MSSQL — orders database",
      "query_timeout": 30,
      "max_rows": 10000
    },
    {
      "id": "analytics_pg",
      "engine": "postgres",
      "dsn": "postgresql://analyst:secret@analytics.internal:5432/dw",
      "read_only": true,
      "description": "Analytics Postgres data warehouse"
    },
    {
      "id": "app_mongodb",
      "engine": "mongodb",
      "dsn": "mongodb://user:pass@mongo.internal:27017/appdb?authSource=admin",
      "read_only": true,
      "description": "Application MongoDB — document store"
    }
  ]
}

Run:

sql-mcp --config connections.json

Now you can ask: “How many orders did we process in production yesterday, and how does that compare to what’s loaded in analytics?”

Claude calls list_connections, works out which connection owns orders and which owns analytics, queries each, and stitches the answer together.

Every connection carries its own security envelope: its own read-only flag, timeout, and row cap.

Security

Every query runs through a multi-layer pipeline:

  1. Length check: reject anything over 50,000 characters.
  2. Normalization: uppercase, strip comments.
  3. Multi-statement blocking: reject semicolon- or GO-chained queries.
  4. Write protection: reject INSERT/UPDATE/DELETE/DROP/ALTER/TRUNCATE/CREATE in read-only mode.
  5. Engine-specific banned patterns
  6. Audit logging: SHA-256 hash of every query with tool name, mode, and rejection reason.

Getting started

# Install for the engines you need
pip install "sql-mcp[postgres]"
pip install "sql-mcp[mssql]"
pip install "sql-mcp[mongodb]"

# Or everything
pip install "sql-mcp[all]"

# SQLite needs no extra — it ships with Python
pip install sql-mcp

# Run against a single database
sql-mcp --engine postgres --dsn "postgresql://user:pass@localhost:5432/mydb"

# Run against multiple databases
sql-mcp --config connections.json

Claude Desktop config:

{
  "mcpServers": {
    "sql-mcp": {
      "command": "sql-mcp",
      "args": ["--transport", "stdio", "--config", "C:/path/to/connections.json"]
    }
  }
}

When to use it

Use it when you work across multiple engines, want multi-database conversations, or just don’t want five different tools open.

Try Yourself

Both are open source under MIT:

Issues, ideas, and PRs welcome on both.

If your data lives in one place, start with mssql-mcp-python. If it’s everywhere, start with sql-mcp. Either way, the copy-paste loop ends here.

Enjoying the content?

Support me saying thanks by buying me a coffee!


메타데이터
post_id
ef501c97a5d1
slug
my-two-database-mcp-projects-from-one-engine-to-eight-ef501c97a5d1
url
https://medium.com/@lorenzouriel/my-two-database-mcp-projects-from-one-engine-to-eight-ef501c97a5d1
canonical_url
https://medium.com/@lorenzouriel/my-two-database-mcp-projects-from-one-engine-to-eight-ef501c97a5d1
author_url
https://medium.com/@lorenzouriel
status
ok
fetched_at
2026-06-26 12:24:55