Repository navigation
Releases: dbelokursky/pg-explorer-mcp
Releases · dbelokursky/pg-explorer-mcp
Release list
pg-explorer-mcp 0.8.0
- Инструмент
schema_diagramво всех профилях рисует модель данных: ответ — текст диаграммы Mermaid
(erDiagram), который агент показывает в блоке ```mermaid, и пользователь видит картинку там, где читает:
в GitHub, Obsidian, VS Code или в чате агента. Схема целиком — таблицы с первичными, уникальными и внешними ключами и
связи между ними, в том числе к таблицам других схем, на которые схема ссылается; или одна таблица с соседями
по внешним ключам в обе стороны (table, `depth` до 3). По умолчанию только ключевые колонки, `columns: all` —
все колонки с комментариями, `none` — только таблицы и связи. Кардинальность берётся из каталога: `}o--||` у
ключа из колонок NOT NULL, `}o--o|` у необязательного, `|o--||` у ключа на уникальных колонках. Диаграмма
укладывается в бюджет ответа целиком: когда не влезает, опускаются колонки, потом ключи, а о слишком большой
схеме сервер говорит, как нарисовать часть; обрезанный текст диаграммы не рендерился бы. На стендах те же
`stand`, `schema` и `database`, а строка `стенд / база / схема` идёт комментарием Mermaid, чтобы ответ
рендерился как есть. Команда `/pg:diagram` просит агента показать диаграмму и сохранить её в файл рядом с
проектом. Список инструментов стал длиннее примерно на тысячу символов (ADR 0008). - Стенд, где одна учётка читает много схем, работает целиком. Реестр считал схему именем учётки: импорт из DBeaver
записывал подключение ИФТ-Caldera как[ift-caldera.caldera_ift1.cldr_testers_user], и сервер видел на стенде
одну схемуcldr_testers_user, которой в базе нет: любая настоящая из 61 схемы отвергалась ещё до подключения,
list_tablesотвечал «нет таблиц в cldr_testers_user», а имена без схемы давали 42P01. Теперь база, у всех
секций которой одна учётка, читается целиком через неё:schemaпринимает любую схему,list_schemasи
list_tablesбез схемы показывают то, что учётка читает по правам, аdescribe_tableнаходит таблицу в любой
из этих схем. База с учёткой на схему работает как раньше, только по схемам реестра; если на стенде несколько
баз, читаемых целиком, ошибка проситdatabase. Секции на каждую настоящую схему сuser=больше не нужны. - Стенд за пулером соединений в transaction-режиме (pgbouncer, Odyssey) работает целиком. Раньше там отвечали
толькоrun_selectиexplain_query, аstatus,list_tables,describe_table,search_schema,
sample_rowsиcompare_schemaпадали сprepared statement "pg8000_statement_0" does not exist
(SQLSTATE 26000): запросы к каталогу шли именованным prepared statement в трёх сообщениях без транзакции, и
пулер отдавал их разным серверным сессиям или сбрасывал сессию между ними. К тому жеstatement_timeoutи
search_path, заданные при подключении, после такого сброса исчезали: таймаут не действовал, а имена без
схемы не находились. Теперь каждый вызов — одна транзакцияREAD ONLY, которая в той же посылке задаёт
SET LOCAL statement_timeoutиSET LOCAL search_path, а запрос идёт безымянным statement. Интеграционный
тест гоняет инструменты через настоящий pgbouncer сDISCARD ALLпосле каждой транзакции. - Импорт из DBeaver берёт базу и хосты сначала из URL и только потом из полей: у подключения «по URL» поля держат
значения по умолчанию, базуpostgresсреди них. Подключение, в котором шаблон стенда ничего не нашёл ни в папке,
ни в имени, ни в хосте, получает стендом своё имя (IFT-Caldera→ift-caldera,DEV-indiamall→
dev-indiamall), и предпросмотр это отмечает; раньше такие подключения пропускались. Шаблон по умолчанию
принимает разделитель между буквами и числом,(dev|ift)[-_ ]?\d+, а найденный стенд его теряет:DEV-27
становитсяdev27и складывается в диапазон с соседями. - Стенд может жить на нескольких хостах. В реестре
host=h1,h2с однимportилиport=6544,6545— по порту на
хост, как в libpq: сервер пробует хосты по порядку и берёт первый, который пустил, а если не пустил ни один —
называет каждый. Так же читаютсяPGHOSTиPGPORTзаписи на одну базу. Импорт из DBeaver сохраняет оба хоста
подключения, как их пишет DBeaver (h1:6544,h2с портом 6544 или URLjdbc:postgresql://h1:6544,h2:6544/db),
и кладёт в файл паролей строку на каждый хост; раньше такое подключение попадало в реестр с хостомh1:6544,h2,
которого нет в DNS. Выгрузка отдаёт все хосты psql, DBeaver и DataGrip; pgAdmin и расширению PostgreSQL для
VS Code — когда порт у хостов один, иначе первый хост; SQLTools получает первый хост. - Проверка SQL отвергает идентификаторы в записи
U&"...". PostgreSQL раскрывает в них escape-последовательности,
а проверка читала имя как написано:SELECT U&"pg\005fsleep"(0)проходил её и выполнялся, и так же прошла бы
pg_terminate_backend, которой любая роль обрывает сессии своей же роли, а у группы роль одна. Отказ говорит
написать имя как есть; модели такая запись не нужна. - Стенды опрашиваются одновременно.
run_select,search_schemaиcompare_schemaсоstandsспрашивают
все стенды вызова сразу, по потоку на стенд, и вызов длится столько, сколько самый медленный стенд, а не
все вместе; предел — 100 стендов за вызов вместо 10. Раньше стенды шли по очереди, и перед каждым
следующим сервер резервировал 15 секунд из 25: даже когда каждый стенд отвечал за 3 секунды, вызов успевал
около четырёх, а «на каком стенде заказ» по 53 стендам требовало 13 вызовов. Стенд, который за 25 секунд не
ответил, называется в конце ответа. Стенды, ответившие без строк или без совпадений, сворачиваются в одну
строку (no rows on dev1–dev6, dev8–dev50), чтобы стенд с находкой был виден сразу. - Вшитые пакеты видны GitHub:
src/pg_explorer_mcp/_vendor/requirements.txtперечисляет их точные версии, граф
зависимостей читает его как манифест pip, и об уязвимости в pg8000 или его зависимостях придёт Dependabot
alert — раньше GitHub не знал, что они в репозитории есть.scripts/check_vendor.pyсверяет манифест с
*.dist-info: пакет без строки, строка без пакета и другая версия — ошибка. - Новое имя — pg-explorer-mcp: репозиторий
dbelokursky/pg-explorer-mcp, архивpg-explorer-mcp-X.Y.Z.zipс
папкойpg-explorer-mcp/, пакетpg_explorer_mcp(python -m pg_explorer_mcp), командаpg-explorer-mcp,
расширениеpg-explorer-mcp, переменныеPG_EXPLORER_MCP_*,application_name = 'pg-explorer-mcp'. Под
именемpg-mcpна PyPI живёт другой проект с тем же пакетомpg_mcpи той же командойpg-mcp: pip принимал
бы один за другой —pip install -U pg-mcpзаменил бы копию из git чужим пакетом, — а каталоги MCP путали бы
их (ADR 0007). - Установленное раньше продолжает работать. Записи агентов со старыми
PG_MCP_*читаются как прежде: новое имя
важнее старого, а повторныйinstall.pyпишет только новые. Реестр стендов из~/.pg-mcp/читается, пока в
новой папке нет своего. Разделыpg_service.confпод строкой# pg-mcp exportвыгрузка узнаёт и переписывает
под новой. Подключения в DBeaver и VS Code обновляются те же: у них прежние id. - Что сделать при переходе. Клону —
git pullи перезапуск агента. Распакованному архиву — распаковать новый и
один раз запуститьinstall.pyиз папкиpg-explorer-mcp/, затем заново подключить расширение. Если GigaCode
отвечает, что расширение уже установлено, удалите~/.gigacode/extensions/pg-mcp(для Qwen Code —
~/.qwen/extensions/pg-mcp): клиент сам её не удаляет, аinstall.pyназывает её, если находит. Расширение,
которое выключали, после перехода снова включено. DBA, которые отбирают подключения сервера по
application_name = 'pg-mcp', должны сменить фильтр.
pg-mcp 0.7.0
- Угаданная схема больше не тупик. Если в названной схеме нет ни одной таблицы (обычно это угаданная моделью
public),list_tablesиsearch_schemaотвечают таблицами всех схем, а первая строка говорит, что в той
схеме таблиц нет;describe_tableиsample_rowsнаходят таблицу по имени, в том числе по полному, как
shop.orders. В прогоне с моделью она получила наlist_tablesсоschema: publicошибку со списком схем
и вместо нового вызова спросила пользователя. - Схема, где таблицы есть, но роль их не читает, как
hrв демо-базе, по-прежнему получает отказ, и теперь он
прямо говорит, что роль не может читать ни одну её таблицу: прежнее «нет таблиц, доступных для чтения»
модель пересказывала как «в схеме hr таблиц нет». Про системные схемы ответ говорит, чтоlist_tablesи
search_schemaих не показывают.list_tablesпринимает схему в кавычках и с пробелами, как остальные
инструменты. - Ещё три находки прогона с моделью.
compare_schemaпишет имена со схемой, какlist_tables
(shop.returns | table): таблицу, которая есть только на одном стенде, модель ни разу не упомянула — похоже,
строкуreturns | tableона читала как слова. Ошибка стенда о пропущенной или неизвестной схеме сразу
называет его схемы, а не только отсылает кlist_schemas; если схем больше пятнадцати — первые пятнадцать и
сколько всего. Ошибка 42703 о колонке уrun_selectиexplain_queryперечисляет колонки таблиц запроса,
которые роль читает: таблицуto_regclassнаходит так же, как её нашёл запрос. statusсразу после имени сервера говорит, что сервер только читает и что просьбу изменить данные надо отклонить, а
не просить её подтвердить. В прогоне с моделью она видела «read only = on» и всё равно предлагала удалить
заказы; ответstatus, в отличие от описаний инструментов, не ограничен по размеру.- Описание команды
/pg:setupбольше не обещает проверить подключение: это делает инструментstatus, а
команда — для установки и починки, когда инструментов нет илиstatusговорит, что база недоступна. На
«Check the database connection» модель выбрала/pg:setup— описание почти дословно повторяло вопрос —
и, не сумев запустить команду без подтверждения, так и не вызвалаstatus. - Описания инструментов без лишних полей:
destructiveHintиidempotentHintприreadOnlyHintничего не
значат, а название осталось только вannotations, где его находят клиенты любых версий протокола. Список
инструментов для стендов стал короче на 700 символов — запас для будущих правок описаний. - На стендах модель знает стенды до первого вызова. Описание аргумента
standназывает стенды реестра
(dev1–dev50, ift1–ift3; если записей больше двенадцати — первые и сколько всего), а не пример"dev7".
Список берётся при запуске сервера, аstatusи ошибки называют стенды такими, какие они сейчас. Если
run_selectна одном стенде не вернул строк, ответ называет другие стенды с той же схемой и напоминает про
stands. В прогоне с моделью на вопрос, на каком стенде заказ, она смотрела только dev7 из примера,
ничего не находила и называла стенды, которых нет; по-английски сценарий проходил в 5 случаях из 9. run_selectиsearch_schemaпонимают шаблон или список и вstand("*","dev7,dev12") — как
stands: так модель спрашивала все стенды сразу и получала «No stand '*'». Имя стенда не может содержать
*,?,[или запятую, поэтому путаницы нет.- Ошибка о неизвестном стенде у
run_selectиsearch_schemaговорит, как посмотреть на всех стендах:
stands: "*", а если стендов больше десяти — список или шаблон, не больше десяти за вызов. Узнав только,
что стендаpg(имени сервера) нет, модель спрашивала пользователя, какой стенд взять. - На стенде
run_select,explain_queryиcompare_schemaбез схемы (модель присылаетschema: "")
отвечают ошибкой стенда со списком его схем, а не одним «Missing argument(s): schema.»: после неё модель
тратила вызов наlist_schemas. - В журнале запросов у каждой строки есть версия Python (
python), аscripts/querylog_report.py
показывает, сколько пользователей на какой версии: так видно, во что обойдётся подъём минимальной. scripts/agent_eval.pyпроверяет и стенды: демо-база становится стендом dev7, а её изменённая копия на
время прогона — стендом dev12, и модель отвечает черезpg-stands, какие стенды есть, чем отличается схема,
где лежит заказ и сколько заказов на dev12 (--mode single|stands|both).--repeat Nзадаёт каждый вопрос
несколько раз и печатает долю успехов и ответы с ошибкой, которые повторялись.- В
scripts/agent_eval.pyзаказ, который есть только на копии dev12, теперь 9001, а не 501: в копии 501
заказ, и модель принимала «~501 rows» в списке таблиц за этот заказ, не проверив его запросом. - CI проверяет выгрузку настоящими программами: psql подключается по секции, которую пишет
install.py export pg-service, а pgAdmin 9.18 загружает файл серверов и отдаёт его обратно без расхождений. Полный набор CI с
macOS идёт и ночью наdevelop: слияние, которое сделало автослияние, push-прогона не запускает. PR вmain
тоже вливаются автослиянием: уmainтеперь те же обязательные проверки, что уdevelop.
pg-mcp 0.6.0
- Запись сервера для других клиентов MCP:
install.py --clientпишет её в файл и в формате VS Code
(GitHub Copilot), Cursor, Windsurf, Cline, Roo Code, Continue, LM Studio, Claude Desktop и Junie, а для
JetBrains AI Assistant печатает, что вставить в настройки;--printтолько показывает запись и куда её
положить. Файл с комментариями не переписывается — печатается, что добавить. В терминалеinstall.py
находит другие установленные клиенты и предлагает зарегистрировать сервер и там. - Выгрузка подключений к стендам в инструменты БД:
install.py exportдля DBeaver, DataGrip и других
IDE JetBrains, pgAdmin 4, psql и pgcli (pg_service.conf), расширений VS Code PostgreSQL (Microsoft)
и SQLTools — предпросмотр по умолчанию, запись с--write,--standsвыбирает стенды. DBeaver
получает свой файлdata-sources-pg-mcp.jsonс папкой на стенд, DataGrip — проект
~/.pg-mcp/datagrip(или--project), pgAdmin —servers.jsonдля импорта, psql — секции со схемой
первой в search_path, расширения VS Code — подключения в настройках пользователя (--editorдля
Cursor и Windsurf). Пароли не копируются: подключения входят по файлу паролей, только расширение
Microsoft его не читает и спрашивает пароль один раз. Выгрузка заменяет только свои подключения,
оставляет датированные копии и права файлов (файл-ссылка остаётся ссылкой), пропускает то, что уже
есть в DBeaver, и переноситsslmodeиsslrootcert. В~/.pg_service.confвыгруженные секции стоят
под строкой# pg-mcp export: следующая выгрузка переписывает только их, сервер и импорт не считают
их стендами, а одноимённые секции пользователя не трогаются. Файл настроек с комментариями не
переписывается — печатается, что добавить.
В терминалеinstall.pyпосле импорта и регистрации находит эти инструменты и предлагает выгрузку. - Модели реже ошибаются с первого вызова — по находкам прогона
scripts/agent_eval.py. Пустая строка в
необязательном аргументе считается пропущенным аргументом. Из описаний и ошибок убран пример"public",
который модель подставляла буквально. Ошибка PostgreSQL о ненайденной таблице (42P01) уrun_selectи
explain_queryназывает схемы, где таблица с таким именем есть; на стенде — схемы реестра, с которыми
повторить вызов.search_schemaв схеме без доступных таблиц — модель по привычке берётpublic—
называет схемы с таблицами, какlist_tables. Описанияstatusиrun_select, инструкции сервера и
отказ проверки SQL прямо говорят, что сервер только читает и просьбы изменить данные надо отклонять, а не
просить их подтвердить. scripts/querylog_report.py— сводка по журналу запросов для администратора группы: один или несколько
файлов (ротированные.1и.gzтоже), окно--since/--untilв UTC; вызовы по инструментам с долей
ошибок, отказов проверки SQL, недоступной базы и сбоев сервера, по пользователям ОС (вызовы, запросы, строки)
и по стендам (вызов на несколько стендов засчитывается каждому), медиана и 95-й процентильduration_ms,
десять самых долгих вызовов и все отклонённые проверкой SQL запросы;--format jsonи--format csvв
разрезе--by. Аргументы обрезаются до 80 символов, значения ключей, похожих на пароль, скрыты; битые
строки пропускаются и считаются.scripts/agent_eval.py— ручная проверка с настоящей моделью перед выпуском (в CI модели нет): в одноразовой
домашней папке регистрирует сервер в Qwen Code на демо-базе, задаёт типовые вопросы по-русски и по-английски
модели из Ollama (или другого OpenAI-совместимого эндпоинта) и по журналу запросов сверяет, какие
инструменты она вызвала и что ответила; просьба удалить должна кончиться отказом сервера или модели, заказы
после неё пересчитываются. Итог — таблица и счёт. Раздел в CONTRIBUTING.md; разбор журнала и сверка со
сценариями покрыты тестами без модели.- PR в
developвливаются сами, когда зелёные все обязательные проверки: workflow
.github/workflows/automerge.ymlвключает на них автослияние GitHub. Черновики, PR из форков и PR
вmainвливаются вручную.
pg-mcp 0.5.0
- Импорт подключений к стендам:
install.py import dbeaverиinstall.py import pg-service <файл>—
предпросмотр по умолчанию, запись с--write: реестр~/.pg-mcp/stands.conf(дополняется, с--prune
заменяется), пароли в файл паролей (только добавляются и обновляются), датированные копии обоих, запись
pg-standsрядом сpg; при сбое ничего не меняется. Стенд распознаётся по папке DBeaver, имени
подключения и хосту (--stand-pattern), схема — учётка подключения. Сохранённые пароли DBeaver
расшифровываются своим AES-128-CBC (src/pg_mcp/aes.py), без зависимостей. В терминалеinstall.py
предлагает предпросмотр, найдя DBeaver; агенту — команда/pg:import. - Сервер перечитывает реестр стендов, когда его файлы изменились: импорт виден без перезапуска агента.
Если после изменения стендов прочитать не удалось, остаются прежние, аstatusпредупреждает. - Реестр стендов со строкой
password=, который могут читать другие пользователи, даёт предупреждение
вstatusс подсказкойchmod 600. compare_schemaсравнивает один стенд с несколькими:standsвместоstand_b(список или шаблон, не
больше 10). Эталон читается один раз, стенды — по очереди в бюджете вызова; до трёх стендов получают
полные различия, больше — строку с числами; в конце итог «как эталон / отличаются / не проверены».
Недоступный стенд или стенд без учётки схемы не мешает остальным; журнал запросов пишет итог по стендам.- Демо-база из README в репозитории:
docs/demo.sqlстроит магазин с детерминированными данными
(50 покупателей, 20 товаров, 500 заказов — 174 shipped, 162 paid, 90 cancelled, 74 new — и 2200
позиций) и схемуhr, закрытую для агента;scripts/demo.pyсоздаёт базу и роль агента и удаляет их
с--drop. Тест сверяет ответы инструментов с примерами README на PostgreSQL 13–18 и Windows. - Репозиторий стал публичным: лицензия MIT (
LICENSE), лицензии вендорных пакетов в
THIRD_PARTY_NOTICES.md, оба файла входят в архив релиза;SECURITY.mdо том, как сообщать об
уязвимостях и где проходит граница безопасности; у архива релиза аттестация происхождения
(gh attestation verify); CodeQL по push и раз в неделю; веткиmainиdevelopзащищены от
удаления и force-push.
pg-mcp 0.4.0
- Вызов на несколько стендов начинает следующий стенд, только если до 25 секунд хватит и на подключение,
и на запрос до его таймаута; раньше в запас входило только подключение, и последний стенд мог вывести
вызов за 30 секунд, которые ждёт клиент. - Описания инструментов короче: в режиме стендов
tools/listужался с 9,5 до 7 тысяч символов, для одной базы —
с 5 до 4,3 тысячи. Правила проstand,schemaиdatabaseсказаны один раз в инструкциях сервера, а не в
каждом инструменте; тест не даёт объёму расти обратно. - CI на PR стал вдвое дешевле: без macOS и с PostgreSQL 13, 16 и 18 вместо шести версий; полный набор
идёт на push вdevelopиmain. Сборка архива релиза на PR — только когда менялись её исходники. - Инструмент
compare_schemaв режиме стендов, во всех профилях: сравнивает структуру одной схемы на двух
стендах — таблицы и представления, колонки (тип,NOT NULL, значение по умолчанию), ограничения и
индексы — и показывает, что есть только на одном стенде и что отличается; данные не читаются. Структура
берётся из каталога под учёткой схемы на каждом стенде, три запроса на стенд. Схема, которой нет в базе
одного из стендов, — отдельная ошибка, а не «только на A: всё». - Один запрос на нескольких стендах за один вызов: в режиме стендов
run_selectиsearch_schemaпринимают
вместоstandаргументstands— имена через запятую или шаблон (dev1,dev2,dev*), не больше 10
стендов. Стенды опрашиваются по очереди, в ответе на каждый своя секция под строкойстенд / база / схема;
недоступный стенд, стенд без учётки схемы или ошибка запроса — одна строка под его заголовком, остальные
стенды отвечают. Строкиrun_selectи совпаденияsearch_schemaделятся между стендами, не меньше 10 на
стенд; вызов укладывается в 25 секунд, остальные стенды перечисляются как не проверенные. Журнал запросов
пишет на такой вызов одну запись с итогом по каждому стенду (stands). - Тесты на то, что раньше проверялось только без базы: TLS во всех режимах
PGSSLMODEчерез
TLS-прослойку перед настоящим PostgreSQL (сертификат делаетopenssl), включая отказ от чужого
сертификата и несовпадение имени хоста; срабатываниеstatement_timeoutна долгом запросе и то, что
сокет его дожидается; подключение через Unix-сокет. - Сервер, который принял подключение и закрыл его при входе без сообщения, объясняется отдельно:
обычно это пароль илиpg_hba.conf. Так на Windows выглядит отвергнутый пароль, когда сброс
соединения стирает сообщение сервера; раньше это была безликая «network error». - Много стендов в одной записи (ADR 0006). С
PG_MCP_STANDSсервер читает реестр в формате
pg_service.conf(~/.pg-mcp/stands.confи~/.pg_service.conf, секциистенд.база.схема), и каждый
инструмент принимаетstand, а для чтения данных —schema: сервер подключается под учёткой этой схемы.
Новый инструментlist_schemas; структура по всему стенду берётся из каталога, только по схемам реестра;
каждый ответ начинается со строкистенд / база / схема, журнал запросов пишет стенд и схему.
Подключения открываются по требованию, открытыми держится не больше 8 (PG_MCP_MAX_CONNECTIONS).
БезPG_MCP_STANDSили без стендов в реестре всё работает как раньше. Запись регистрирует
PG_MCP_STANDS='*' install.py --name stands; проверке установки достаточно найденных стендов. - Быстрый отказ недоступного стенда. Хост, который не ответил (нет маршрута, таймаут, отказ порта), в
пределах вызова больше не пробуется ни под одной учёткой, а вторая учётка базы пробуется, только когда
сервер ответил и отверг первую: стенд за упавшим VPN стоит один таймаут, а не один на каждую учётку
и базу, и вызов укладывается в 30 секунд ожидания клиента. «Нет маршрута до хоста» объясняется
отдельно — подключите VPN. Хост, который принимает соединение и молчит, раньше ронял вызов ошибкой
сервера, теперь даёт ту же подсказку про таймаут. - Таймаут сети разделён: подключение ждёт
PG_MCP_SOCKET_TIMEOUT_S(30 секунд, для стендов 10), а
открытый сокет — не меньше таймаута запроса плюс 5 секунд: долгий запрос кончается ошибкой PostgreSQL,
а не обрывом соединения и повторным запуском. - Сервер, который принял подключение и закрыл его при входе без сообщения, объясняется отдельно:
обычно это пароль илиpg_hba.conf. Так на Windows выглядит отвергнутый пароль, когда сброс
соединения стирает сообщение сервера; раньше это была безликая «network error». - Один запрос на нескольких стендах за один вызов: в режиме стендов
run_selectиsearch_schemaпринимают
вместоstandаргументstands— имена через запятую или шаблон (dev1,dev2,dev*), не больше 10
стендов. Стенды опрашиваются по очереди, в ответе на каждый своя секция под строкойстенд / база / схема;
недоступный стенд, стенд без учётки схемы или ошибка запроса — одна строка под его заголовком, остальные
стенды отвечают. Строкиrun_selectи совпаденияsearch_schemaделятся между стендами, не меньше 10 на
стенд; вызов укладывается в 25 секунд, остальные стенды перечисляются как не проверенные. Журнал запросов
пишет на такой вызов одну запись с итогом по каждому стенду (stands). - Инструмент
compare_schemaв режиме стендов, во всех профилях: сравнивает структуру одной схемы на двух
стендах — таблицы и представления, колонки (тип,NOT NULL, значение по умолчанию), ограничения и
индексы — и показывает, что есть только на одном стенде и что отличается; данные не читаются. Структура
берётся из каталога под учёткой схемы на каждом стенде, три запроса на стенд. Схема, которой нет в базе
одного из стендов, — отдельная ошибка, а не «только на A: всё». - Тесты на то, что раньше проверялось только без базы: TLS во всех режимах
PGSSLMODEчерез
TLS-прослойку перед настоящим PostgreSQL (сертификат делаетopenssl), включая отказ от чужого
сертификата и несовпадение имени хоста; срабатываниеstatement_timeoutна долгом запросе и то, что
сокет его дожидается; подключение через Unix-сокет. - Архив для тех, у кого нет git: пуш тега
vX.Y.Zсобираетpg-mcp-X.Y.Z.zipиз дерева тега без
.github, проверяет, что сервер запускается из распакованного архива (install.py --check), и
публикует GitHub Release сSHA256SUMSи заметками из раздела этой версии здесь; версия тега сверяется
с версией в файлах. README: установка и обновление из архива. - Несколько баз из одного клона:
install.py --name salesрегистрирует серверpg-salesрядом сpg, со
своими подключением, профилем и языком.statusпоказывает имя сервера (PG_MCP_NAME). - Интеграционные тесты на Windows с настоящим PostgreSQL: файл паролей в
%APPDATA%,docs/role.sql
черезpsqlиinstall.py --checkчерез канал, как его запускает агент. install.pyбольше не падает, когда его вывод идёт через канал в кодировке без кириллицы или тире
(cp1252, cp866) или когда путь к профилю содержит такие символы: недостающие знаки заменяются на «?».- Проверка в настоящем клиенте: CI запускает Qwen Code с сервером, который зарегистрировал
install.py, —
клиент должен подключиться к нему и увидеть расширение.scripts/client_smoke.pyделает то же локально.