Skip to main content
Glama
Kenza-21

SQL MCP Server

by Kenza-21

SQL MCP Server

Сервер на основе Model Context Protocol, который предоставляет LLM-агентам (Claude Desktop, Claude Code или любому MCP-клиенту) доступ к базе данных Postgres через шесть инструментов только для чтения. Подключите к нему агента и задавайте вопросы вроде «какие клиенты сделали более пяти заказов в прошлом месяце?» — агент сам изучит схему и выполнит запросы к данным с помощью инструментов ниже.

Инструменты

Инструмент

Описание

list_tables()

Обзор всех таблиц: имя, описание, размер, количество столбцов

describe_table(table)

Столбцы, типы и связи внешних ключей для одной таблицы

search_schema(keyword)

Поиск таблиц/столбцов, имя которых соответствует ключевому слову

sample_rows(table, limit)

Просмотр реальных строк (по умолчанию 5)

count_rows(table)

Количество строк в таблице

execute_select(sql)

Выполнение произвольного запроса SELECT / WITH ... SELECT только для чтения

Related MCP server: mcp-data-gateway

Почему это не «просто обёртка вокруг psycopg2»

Демо Text-to-SQL — обычное дело; по-настоящему сложная часть — и именно на ней сосредоточены усилия этого проекта — сделать execute_select безопасным для передачи LLM, которая будет генерировать произвольный SQL:

  1. Роль Postgres только для чтения. Сервер подключается как mcp_readonly — роль с привилегиями только на SELECT (см. scripts/init_schema.sql). Даже ошибка в описанных ниже проверках на уровне приложения не может привести к записи.

  2. Принудительный режим только для чтения на уровне сессии. Каждое соединение выполняет SET TRANSACTION READ ONLY (db.py).

  3. Проверка выражений (security.py): допускается только одно выражение SELECT/WITH — без нескольких инструкций подряд (; DROP TABLE ...), без SQL-комментариев (блокируется протаскивание инструкций через комментарии), а список запрещённых ключевых слов покрывает INSERT/UPDATE/DELETE/DDL/GRANT/и т.д., включая SELECT ... INTO (который молча создаёт таблицу).

  4. Проверка идентификаторов. describe_table, sample_rows и count_rows принимают имя таблицы как параметр. Поскольку SQL-идентификаторы нельзя параметризовать плейсхолдерами, имена таблиц проверяются по строгому регулярному выражению и по актуальному списку разрешённых имён, полученному из information_schema, — а не просто экранированием строк.

  5. Ограничение ресурсов. statement_timeout в Postgres предотвращает вышедшие из-под контроля запросы, а на стороне сервера для каждого результата запроса применяется ограничение на количество строк, даже если в запросе LLM не указан LIMIT.

Быстрый старт

git clone <this-repo>
cd sql-mcp-server
pip install -r requirements.txt

# 1. Start Postgres with the sample schema
docker compose up -d

# 2. Generate sample e-commerce data (uses the postgres superuser, not mcp_readonly)
PGUSER=postgres PGPASSWORD=postgres python scripts/generate_sample_data.py

# 3. Configure the server to use the read-only role
cp .env.example .env
# edit .env if you changed the default mcp_readonly password

# 4. Run the tests
pytest

# 5. Run the server (stdio transport, for use with an MCP client)
python -m sql_mcp_server.server

Подключение к Claude Desktop

Добавьте в конфигурацию MCP Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "sql-explorer": {
      "command": "python",
      "args": ["-m", "sql_mcp_server.server"],
      "cwd": "/absolute/path/to/sql-mcp-server",
      "env": {
        "PGHOST": "localhost",
        "PGPORT": "5432",
        "PGDATABASE": "sales",
        "PGUSER": "mcp_readonly",
        "PGPASSWORD": "change_me"
      }
    }
  }
}

Перезапустите Claude Desktop и задайте, например, такой вопрос: «Какие таблицы доступны и какая категория товаров приносит наибольшую выручку?»

Пример схемы

orders → order_items → products → categories, плюс customers. Выручка заказа = sum(order_items.quantity * order_items.unit_price). Генератор наполняет базу ~600 клиентами, ~3,500 заказами и несколькими намеренными странностями в данных (отсутствующие email, пара выделяющихся оптовых заказов), чтобы запросы выглядели так, будто работают с реальными данными.

Тестирование

tests/test_security.py и tests/test_tools.py запускаются без базы данных: они проверяют слой валидации напрямую, а функции инструментов — с замоканным слоем БД. Именно это и запускает CI. Сам db.py (слой psycopg2) проверяется на практике запуском сервера с Docker-инстансом Postgres; см. «Быстрый старт» выше.

Структура проекта

sql_mcp_server/
  config.py    Environment-based settings
  security.py  SQL/identifier validation (the core safety logic)
  db.py        psycopg2 access layer
  server.py    MCP tool definitions
scripts/
  init_schema.sql            Schema + read-only role setup
  generate_sample_data.py    Faker-based sample data
tests/
  test_security.py  Validation logic (18+ cases: injection, stacked
                     statements, comment smuggling, DDL/DML blocking, etc.)
  test_tools.py     Tool functions with mocked DB

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with PostgreSQL databases through MCP, allowing users to explore database structures, inspect table schemas, and execute read-only SQL queries.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to query a PostgreSQL database through a small set of controlled, read-only tools for schema inspection, row lookup, and aggregate statistics.
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A read-only natural-language database agent that exposes PostgreSQL schema-discovery and SELECT tools via MCP, enabling users to query databases in plain English.
    MIT