Skip to main content

Generic SQL database (Postgres, MySQL/MariaDB, MSSQL, Oracle, SQLite) API + MCP Server + A2A Server for Agentic AI!

Project description

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.1.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"
      }
    }
  }
}

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

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

sql_mcp-0.1.0.tar.gz (33.2 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.1.0-py3-none-any.whl (25.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: sql_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 33.2 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.1.0.tar.gz
Algorithm Hash digest
SHA256 e3599d125d20a9f81a24cc6092a8772600245a69b00872b7db3dd8b5667e0bee
MD5 bc9e00d9945737403d23e2edfa063178
BLAKE2b-256 bdb797f065bb53e9ffa4db5b36c3ba72e554c63ba0da8a674f95d7972d9226ac

See more details on using hashes here.

File details

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

File metadata

  • Download URL: sql_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.8 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ee703f3d4d9d02db6d3cfc8914269094bb809b2e6fc1e130ab6bb7789479754e
MD5 fcbd3e2be9efd0560be2d58a41b5d059
BLAKE2b-256 4b41131ebdeda0e54e81fbd61d8610a206e932efb5337b8d9fc7adb95666ffd2

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