Skip to main content

Sql Mcp

API | MCP Server | A2A Agent

PyPI - Version MCP Server PyPI - Downloads GitHub Repo stars GitHub forks GitHub contributors PyPI - License GitHub GitHub last commit (by committer) GitHub pull requests GitHub closed pull requests GitHub issues GitHub top language GitHub language count GitHub repo size PyPI - Wheel PyPI - Implementation

Generic SQL database API + MCP Server + A2A Agent for the agent-utilities ecosystem — one connector for PostgreSQL, MySQL/MariaDB, Microsoft SQL Server, Oracle, and SQLite over SQLAlchemy 2.x Core.

Version: 0.5.0

Documentation — Installation, deployment, and usage across the API, CLI, and MCP interfaces are maintained in docs/.

Table of Contents

Overview

sql-mcp exposes read-only queries, gated DML/DDL, schema reflection, and connection administration as typed, deterministic MCP tools, and ships an optional Pydantic-AI agent server. It is read-only by default: every query passes a statement-type allowlist, every result is bounded by a row cap and a timeout, and all values travel as bound parameters — never interpolated into SQL strings.

What it provides

  • SqlApi (sql_mcp.api.api_client_sql) — a SQLAlchemy 2.x Core facade with named multi-connection support, lazy engine creation, the read-only statement gate, row-cap/timeout enforcement, and bounded result envelopes ({columns, rows, row_count, truncated}).
  • Four MCP tools (sql-mcp console script): sql_query (execute/explain), sql_execute (execute/script — gated by SQL_ALLOW_WRITES), sql_schema (schemas/tables/views/columns/indexes/foreign_keys/ddl/sample), and sql_admin (ping/version/active_connections/connections/dialects). See docs/usage.md for the full action surface.
  • A dialect registry (sql_mcp.dialects) — per-engine driver, URL scheme, pip extra, EXPLAIN prefix, and admin SQL. Core ships SQLite only; the other drivers install via extras.
  • An A2A agent server (sql-agent console script) — a Pydantic-AI graph agent wired to the MCP server via MCP_URL.

MCP tools

Tool Actions Description
sql_query execute, explain Run a read-only SELECT/CTE with bound parameters, or return the dialect's query plan
sql_execute execute, script One DML/DDL statement (or an all-or-nothing statement list) in a transaction — requires SQL_ALLOW_WRITES=True
sql_schema schemas, tables, views, columns, indexes, foreign_keys, ddl, sample Reflect schemas, tables, columns, indexes, FKs, CREATE DDL, and preview rows
sql_admin ping, version, active_connections, connections, dialects Connection health, server version, server sessions, registry info, driver availability

Every tool takes action, params_json, and an optional connection naming one of the configured connections. The whole set is toggled with SQLTOOL.

Dialects & extras

Dialect SQLAlchemy scheme Driver Install
SQLite sqlite+pysqlite stdlib pip install sql-mcp (core)
PostgreSQL postgresql+psycopg psycopg 3 pip install sql-mcp[postgres]
MySQL / MariaDB mysql+pymysql PyMySQL pip install sql-mcp[mysql]
SQL Server mssql+pyodbc pyodbc pip install sql-mcp[mssql]
Oracle oracle+oracledb python-oracledb pip install sql-mcp[oracle]

pip install sql-mcp[all] pulls every driver plus the MCP and agent extras.

Configuration (environment)

Var Default Meaning
SQL_CONNECTIONS (empty) JSON map of named connections: DSN strings or {dialect, host, port, username, password, database, options} objects
SQL_URL (empty) Single DSN registered as connection default
SQL_DIALECT / SQL_HOST / SQL_PORT / SQL_USERNAME / SQL_PASSWORD / SQL_DATABASE / SQL_OPTIONS (empty) Discrete fields for a single default connection
SQL_ALLOW_WRITES False Enable sql_execute (DML/DDL). Read-only by default
SQL_MAX_ROWS 500 Per-call row cap; tool requests are clamped to it
SQL_TIMEOUT_SECONDS 30 Per-statement timeout
SQLTOOL True Register the SQL tool set

With nothing configured the server registers a zero-infra in-memory SQLite connection named memory, so it works out of the box. Tools take an optional connection parameter naming one of the configured connections; it defaults to the sole/first one. Passwords are parsed into sqlalchemy.URL objects and only ever rendered redacted. Copy .env.example to .env and populate only what you use.

Installation

pip install sql-mcp            # core (SQLite, MCP server, API)
pip install sql-mcp[all]       # every driver + MCP + agent extras
pip install -e .               # from source

Or pull the container image:

docker pull knucklessg1/sql-mcp:latest

Usage

sql-mcp                        # stdio MCP server (default transport)
sql-mcp --transport streamable-http --host 0.0.0.0 --port 8000

Point it at a database:

export SQL_URL="postgresql+psycopg://svc:****@db.example.com:5432/app"
sql-mcp

Or several:

export SQL_CONNECTIONS='{
  "warehouse": "postgresql+psycopg://svc:****@dw.example.com:5432/dw",
  "erp": {"dialect": "mysql", "host": "erp.example.com", "username": "svc",
           "password": "****", "database": "erp"}
}'
sql-mcp

Run the agent server against a live MCP server:

sql-agent --mcp-url http://localhost:8000/mcp --host 0.0.0.0 --port 8080

MCP config

{
  "mcpServers": {
    "sql-mcp": {
      "command": "uv",
      "args": ["run", "sql-mcp"],
      "env": {
        "SQL_URL": "postgresql+psycopg://svc:****@db.example.com:5432/app",
        "SQL_ALLOW_WRITES": "False"
      }
    }
  }
}

Additional Deployment Options

sql-mcp can also run as a local container (Docker / Podman / uv) or be consumed from a remote deployment. The Deployment guide has full, copy-paste mcp_config.json for all four transports — stdio, streamable-http, local container / uv, and remote URL:

  • Local container / uv — launch the server from mcp_config.json via uvx, docker run, or podman run, or point at a local streamable-http container by url.
  • Remote URL — connect to a server deployed behind Caddy at http://sql-mcp.arpa/mcp using the "url" key.

Docker deployment

docker compose -f docker/mcp.compose.yml up -d      # MCP server only
docker compose -f docker/agent.compose.yml up -d    # MCP + A2A agent
curl -s http://localhost:8000/health                 # {"status":"OK"}

Both services read configuration from ../.env (copy .env.example); see docs/deployment.md.

Safety model

  • Read-only by defaultsql_execute refuses to run unless the server was started with SQL_ALLOW_WRITES=True; agents cannot flip the flag per call.
  • Statement allowlistsql_query accepts only SELECT/WITH/EXPLAIN/ SHOW/DESCRIBE/PRAGMA/VALUES; CTEs are inspected at paren depth zero so WITH ... INSERT cannot smuggle a write, SELECT INTO is rejected, and multi-statement payloads are refused.
  • Bounded results — per-call row caps clamp to SQL_MAX_ROWS; statements run under SQL_TIMEOUT_SECONDS on a worker thread.
  • Parameterized only — values bind via :name parameters; identifiers are quoted by SQLAlchemy reflection, never hand-interpolated.

Tests

python -m pytest          # full suite against in-memory SQLite (no live DBs)
pre-commit run --all-files

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sql_mcp-0.5.0.tar.gz (33.9 kB view details)

Uploaded Source

Built Distribution

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

sql_mcp-0.5.0-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

File details

Details for the file sql_mcp-0.5.0.tar.gz.

File metadata

  • Download URL: sql_mcp-0.5.0.tar.gz
  • Upload date:
  • Size: 33.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for sql_mcp-0.5.0.tar.gz
Algorithm Hash digest
SHA256 673ac7335039e03f8e192518b079b0ee9dda4b9fb04b48e6965b470d29f6f3de
MD5 052bbd68865e1867be10bfb9206a92f7
BLAKE2b-256 e5c9719571ea53c12eb1d475632d7a13ff20b7e2d0994833d5cd0e3429c45bc7

See more details on using hashes here.

File details

Details for the file sql_mcp-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: sql_mcp-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 26.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for sql_mcp-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b0eb787a75dbbcc84343a5b5686ed89fd7e75df6c828069a3347365027dd0345
MD5 40cabcc0a7738257eaf1b1780dd67d82
BLAKE2b-256 1e9f2ad21647ab510949fd27edd35514fd2acd953b19194c69f6f381648ba083

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 Sentry Error logging StatusPage Status page