MCP stdio server for Greenplum 6.x query plan evaluation: - explain_sql / explain_dbt_model tools - read-only session enforcement + statement_timeout - dbt compile integration - all settings via env vars (no hardcoded defaults)
gp-mcp
MCP-сервер для оценки плана запросов dbt-моделей в Greenplum 6.x.
Запускается локально по stdio рядом с AI-агентом, который рефакторит легаси PL/SQL
в dbt-модели. Сервер:
- компилирует выбранную dbt-модель (
dbt compile --select <model>); - подключается к Greenplum под read-only пользователем
(
SET default_transaction_read_only = on,statement_timeout); - выполняет
EXPLAIN (ANALYZE, VERBOSE, FORMAT JSON); - возвращает JSON-план + краткую сводку с GP-метриками (motion-узлы, самый медленный узел, ошибка оценки строк).
Tools
| Tool | Параметры | Что делает |
|---|---|---|
explain_sql |
sql: str, statement_timeout_ms?: int |
EXPLAIN ANALYZE для произвольного SQL |
explain_dbt_model |
model_name: str, statement_timeout_ms?: int |
dbt compile + EXPLAIN ANALYZE для модели |
Возвращаемый JSON:
{
"summary": {
"total_cost": 12345.6,
"plan_rows": 100000,
"actual_rows": 98412,
"execution_time_ms": 842.3,
"planning_time_ms": 12.1,
"slowest_node": { "node_type": "Seq Scan", "actual_total_time_ms": 700.2, "...": "..." },
"motion_nodes": [{ "node_type": "Redistribute Motion", "...": "..." }],
"rows_misestimation_factor": 1.02
},
"plan": [ /* raw EXPLAIN JSON */ ],
"statement_timeout_ms": 300000,
"compiled_sql": "select ...",
"model_name": "fct_orders"
}
Установка
cd /Users/admin/Projects/vpn
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Конфигурация
Все настройки — через переменные окружения. Скопируй .env.example в .env
и заполни.
| Переменная | Обязательная | Назначение |
|---|---|---|
GP_HOST |
+ | Хост Greenplum master |
GP_PORT |
+ | Порт |
GP_USER |
+ | Read-only пользователь (см. ниже) |
GP_PASSWORD |
+ | Пароль |
GP_DATABASE |
+ | Имя БД |
GP_SCHEMA |
search_path, можно через запятую |
|
DBT_PROJECT_DIR |
+ | Каталог dbt-проекта (содержит dbt_project.yml) |
DBT_PROFILES_DIR |
+ | Каталог с profiles.yml |
DBT_TARGET |
+ | Имя target из profiles.yml (напр. dev) |
DBT_EXECUTABLE |
Путь к dbt, по умолчанию dbt из PATH |
|
STATEMENT_TIMEOUT_MS |
+ | Дефолтный statement_timeout для EXPLAIN ANALYZE |
MAX_STATEMENT_TIMEOUT_MS |
+ | Верхняя граница, агент не сможет превысить |
LOG_LEVEL |
DEBUG/INFO/WARNING/ERROR, дефолт INFO |
Если обязательная переменная не задана — сервер не стартует и пишет в stderr имя недостающей переменной.
Read-only роль в Greenplum
Сервер требует, чтобы доступ был ограничен на уровне БД. Минимум:
CREATE ROLE dbt_explain LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE <db> TO dbt_explain;
GRANT USAGE ON SCHEMA <schema> TO dbt_explain;
GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO dbt_explain;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT SELECT ON TABLES TO dbt_explain;
Сервер дополнительно ставит сессионный default_transaction_read_only = on,
но GRANT-ы — единственная надёжная защита.
Запуск
Локально (для отладки):
python -m gp_mcp.server
Сервер ничего не печатает в stdout (это канал MCP) — все логи идут в stderr.
Подключение к клиенту
Сервер общается по stdio, поэтому клиент должен сам его запускать.
Конфиг — стандартный MCP JSON: одинаковая форма для Claude Code и Cursor,
различаются только пути к файлам настроек.
Общий блок, который пригодится ниже:
{
"command": "/Users/admin/Projects/vpn/.venv/bin/python",
"args": ["-m", "gp_mcp.server"],
"cwd": "/Users/admin/Projects/vpn/src",
"env": {
"GP_HOST": "gp-master.internal",
"GP_PORT": "5432",
"GP_USER": "dbt_explain",
"GP_PASSWORD": "REPLACE_ME",
"GP_DATABASE": "analytics",
"GP_SCHEMA": "analytics,public",
"DBT_PROJECT_DIR": "/Users/admin/Projects/dbt-analytics",
"DBT_PROFILES_DIR": "/Users/admin/.dbt",
"DBT_TARGET": "dev",
"STATEMENT_TIMEOUT_MS": "300000",
"MAX_STATEMENT_TIMEOUT_MS": "900000",
"LOG_LEVEL": "INFO"
}
}
Важно:
command— абсолютный путь к Python из venv проекта. Клиенты MCP обычно стартуют без активированного окружения, поэтому полагаться наpythonиз PATH нельзя.cwdуказан наsrc/, чтобы Python нашёл пакетgp_mcpбез установки (pip install -e .не делаем).- Секреты держим в
envсоответствующего конфига клиента, не в коде и не в репозитории.
Claude Code
Есть три способа добавить сервер — выбери один.
1. Через CLI (быстрее всего)
claude mcp add gp-mcp \
--scope user \
--env GP_HOST=gp-master.internal \
--env GP_PORT=5432 \
--env GP_USER=dbt_explain \
--env GP_PASSWORD=REPLACE_ME \
--env GP_DATABASE=analytics \
--env DBT_PROJECT_DIR=/Users/admin/Projects/dbt-analytics \
--env DBT_PROFILES_DIR=/Users/admin/.dbt \
--env DBT_TARGET=dev \
--env STATEMENT_TIMEOUT_MS=300000 \
--env MAX_STATEMENT_TIMEOUT_MS=900000 \
-- /Users/admin/Projects/vpn/.venv/bin/python -m gp_mcp.server
Флаг --scope:
user— для всех проектов (пишется в~/.claude.json);project— общий для команды, кладётся в.mcp.jsonв корне проекта, его можно коммитить в git (секреты тогда задают через${VAR}-подстановку из окружения, а не хардкодом);local— только в текущем проекте, только у тебя.
2. Вручную, user-scope: ~/.claude.json
{
"mcpServers": {
"gp-mcp": { /* см. общий блок выше */ }
}
}
3. Вручную, project-scope: .mcp.json в корне dbt-репозитория
{
"mcpServers": {
"gp-mcp": {
"command": "/Users/admin/Projects/vpn/.venv/bin/python",
"args": ["-m", "gp_mcp.server"],
"cwd": "/Users/admin/Projects/vpn/src",
"env": {
"GP_HOST": "${GP_HOST}",
"GP_PORT": "${GP_PORT}",
"GP_USER": "${GP_USER}",
"GP_PASSWORD": "${GP_PASSWORD}",
"GP_DATABASE": "${GP_DATABASE}",
"DBT_PROJECT_DIR": "${DBT_PROJECT_DIR}",
"DBT_PROFILES_DIR": "${DBT_PROFILES_DIR}",
"DBT_TARGET": "${DBT_TARGET}",
"STATEMENT_TIMEOUT_MS": "300000",
"MAX_STATEMENT_TIMEOUT_MS": "900000"
}
}
}
}
Проверка:
claude mcp list # gp-mcp должен быть в списке
claude mcp get gp-mcp # детали конфига
В сессии /mcp покажет статус подключения и список tool'ов. Если статус
failed, посмотри ~/Library/Logs/Claude/ — сервер пишет ошибки запуска
(включая отсутствующие env-переменные) в stderr.
Cursor IDE
Cursor использует тот же MCP-формат, но свой файл настроек.
1. Через UI
Settings → Cursor Settings → MCP & Integrations → New MCP Server →
откроется mcp.json для редактирования.
2. Вручную, глобально: ~/.cursor/mcp.json
Доступно во всех проектах.
{
"mcpServers": {
"gp-mcp": {
"command": "/Users/admin/Projects/vpn/.venv/bin/python",
"args": ["-m", "gp_mcp.server"],
"cwd": "/Users/admin/Projects/vpn/src",
"env": {
"GP_HOST": "gp-master.internal",
"GP_PORT": "5432",
"GP_USER": "dbt_explain",
"GP_PASSWORD": "REPLACE_ME",
"GP_DATABASE": "analytics",
"DBT_PROJECT_DIR": "/Users/admin/Projects/dbt-analytics",
"DBT_PROFILES_DIR": "/Users/admin/.dbt",
"DBT_TARGET": "dev",
"STATEMENT_TIMEOUT_MS": "300000",
"MAX_STATEMENT_TIMEOUT_MS": "900000"
}
}
}
}
3. Вручную, для проекта: .cursor/mcp.json в корне dbt-репозитория
Видно только в этом проекте. Удобно, когда у разных dbt-проектов разные
DBT_PROJECT_DIR/DBT_TARGET.
Проверка:
Settings → MCP & Integrations — справа от gp-mcp должен загореться
зелёный индикатор и появиться список tool'ов (explain_sql,
explain_dbt_model). В чате tools будут доступны Agent-режиму.
Если индикатор красный — раскрой сервер в этом же окне, там показывается
stderr запуска (включая Configuration error: Required environment variable '...' is not set).
Общие проблемы при подключении
| Симптом | Причина |
|---|---|
Configuration error: Required environment variable 'X' is not set |
Переменная X не задана в env конфига клиента |
ModuleNotFoundError: No module named 'gp_mcp' |
Неверный cwd — должен указывать на src/, или Python не из venv |
ModuleNotFoundError: No module named 'mcp' |
command указывает не на Python из venv, где установлены зависимости |
| Сервер стартует, но tools не появляются | Клиент не перезапущен / нет permissions в Cursor для MCP |
dbt: command not found при вызове explain_dbt_model |
Поставь DBT_EXECUTABLE=/абсолютный/путь/к/dbt в env |
Структура
vpn/
├── .env.example
├── .gitignore
├── requirements.txt
├── README.md
└── src/
└── gp_mcp/
├── __init__.py
├── config.py # загрузка и валидация env
├── db.py # psycopg2 + read-only + timeout
├── dbt_runner.py # subprocess dbt compile + чтение compiled SQL
├── explain.py # EXPLAIN ANALYZE + summary
└── server.py # FastMCP, регистрация tools, stdio