MAATRIX / Блог / Подключаем к ассистенту свою базу через MCP: что даёт, а что ломает

Подключаем к ассистенту свою базу через MCP: что даёт, а что ломает

MAATRIX

Ассистент отлично рассказывает про архитектуру PostgreSQL, но ничего не знает про таблицу orders в вашей базе — потому что она появилась после того, как модель обучили. Подключить свою базу через MCP звучит как решение: ассистент видит актуальные данные и сам пишет SQL по вашему вопросу на естественном языке. Разберём честно, что это реально даёт и что может сломать, если сделать подключение небрежно.

Что такое MCP и при чём тут USB

Model Context Protocol (MCP) — открытый протокол, который стандартизирует то, как ИИ-ассистент обнаруживает и вызывает внешние инструменты и источники данных. До MCP у каждого ассистента была своя схема интеграции: чтобы подключить, скажем, Claude к вашей базе, нужно было писать кастомный код именно под Claude, под конкретный формат его вызовов функций. Захотели подключить ту же базу к другому ассистенту — пишите интеграцию заново.

MCP убирает это дублирование за счёт одного стандарта. Есть MCP-сервер — программа, которая знает, как говорить с конкретным источником данных (базой, файловой системой, API) и предоставляет ассистенту список «инструментов» в едином формате: имя, описание, какие параметры принимает, что возвращает. Есть MCP-клиент — часть ассистента, которая умеет читать этот список и вызывать инструменты. Написали MCP-сервер для PostgreSQL один раз — и он работает с любым ассистентом, который умеет быть MCP-клиентом (Claude Desktop, Claude Code, Cursor и другие).

Аналогия с USB тут почти буквальная. До USB каждое устройство требовало своего порта и своего драйвера — принтер по одному интерфейсу, сканер по другому. USB стандартизировал физическое подключение и протокол обмена: устройство описывает себя хосту («я клавиатура», «я накопитель»), хост понимает, как с ним работать, не зная заранее, какая именно клавиатура к нему воткнута. MCP делает то же самое для связки «ассистент — источник данных»: сервер описывает, какие у него есть инструменты и данные, ассистент подключается по стандартному протоколу и не должен знать заранее внутреннее устройство именно вашей базы.

Важно понимать границу: MCP — это протокол обнаружения и вызова, а не сама база и не сама модель. Он не решает, какие права выдать серверу, не проверяет корректность сгенерированного SQL и не защищает данные — за это отвечает то, как вы настроите MCP-сервер и подключение к базе. Отсюда и все риски ниже: они не в протоколе, а в конкретной реализации подключения.

Если нужен более развёрнутый разбор самого протокола — есть отдельная статья что такое MCP простыми словами.

Практический пример: подключаем PostgreSQL через MCP-сервер

Возьмём типичный сценарий: у вас есть PostgreSQL с рабочими данными (заказы, клиенты, метрики), и вы хотите, чтобы ассистент отвечал на вопросы вроде «сколько заказов на сумму больше 10000 рублей пришло за последнюю неделю» — без того, чтобы вы сами писали SQL каждый раз.

MCP-сервер для работы с базой обычно запускается как отдельный процесс, который слушает stdio или локальный сокет и получает от клиента (Claude Desktop, Claude Code) вызовы инструментов. Конфигурация в claude_desktop_config.json (или аналогичном файле настроек клиента) выглядит примерно так:

{
  "mcpServers": {
    "my-postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://mcp_readonly:пароль@127.0.0.1:5432/mydb"
      ]
    }
  }
}

После перезапуска клиента ассистент видит новый набор инструментов — обычно что-то вроде «получить схему таблиц», «выполнить запрос», «список таблиц в схеме». Дальше вы пишете вопрос на естественном языке, ассистент сам формулирует SQL, вызывает инструмент через MCP-сервер, получает результат и превращает его в человеческий ответ.

Практический нюанс, который легко упустить: разные MCP-серверы для баз данных ведут себя по-разному — одни оборачивают любой запрос в BEGIN ... READ ONLY транзакцию и физически не дадут выполнить INSERT/DELETE, другие честно выполняют любой SQL, который сгенерирует модель, без ограничений на уровне сервера. Прежде чем подключать сервер к реальной базе, откройте его исходный код (если он открытый) или документацию и проверьте это явно — не предполагайте безопасное поведение по умолчанию.

Если поднимаете MCP-сервер на собственном VPS, а не локально, пригодится отдельный разбор как поднять MCP-сервер на VPS — там про сетевые нюансы и автозапуск сервиса.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Что это даёт: актуальные данные, а не слепок на момент обучения

Главная практическая польза честная и конкретная: модель обучена на данных до определённой даты и ничего не знает про то, что происходит в вашей базе прямо сейчас. Подключение через MCP убирает этот разрыв — ассистент не угадывает и не сочиняет цифры, а реально идёт в базу за актуальным состоянием.

Это работает для двух типов запросов:

  • Фактические вопросы о текущем состоянии. «Сколько активных подписок у клиента ID 4521» или «когда был последний платёж по заказу №8890» — ассистент формулирует SELECT под вопрос, выполняет его через инструмент MCP-сервера и отвечает по свежим данным, а не по тому, что «обычно бывает».
  • Агрегации и аналитика на естественном языке. «Покажи топ-10 товаров по выручке за август» превращается в GROUP BY с ORDER BY и LIMIT без того, чтобы вы сами вспоминали синтаксис оконных функций. Экономия времени тут реальная — не нужно каждый раз открывать консоль и писать запрос руками.

Второй практический эффект — снижение порога входа для тех, кто не пишет SQL свободно: менеджер или аналитик может спросить базу человеческим языком, а не идти к разработчику с просьбой «выгрузи мне цифры». Это удобство одновременно и создаёт риски, о которых ниже: чем проще спросить у базы что угодно, тем проще случайно спросить то, что спрашивать не следовало.

Отдельно стоит сказать: MCP-подключение к базе — это доступ к сырым данным, а не к готовой аналитике. Ассистент не знает бизнес-контекст ваших таблиц, если вы явно не объяснили его (в системном промпте, в описании инструмента или в комментариях к схеме). Он может написать технически корректный, но бессмысленный по сути запрос — например, посчитать «активных пользователей» по полю, которое на самом деле помечает совсем другое состояние. Проверяйте логику ответов на реальных данных, особенно в первые недели использования.

Риск первый: ассистент с правом на любой SQL

Если MCP-сервер даёт ассистенту возможность выполнять произвольный SQL без ограничений — на уровне прав пользователя базы или на уровне логики самого сервера, — вы фактически даёте модели ключи от продакшена. Это не абстрактная угроза, а прямое следствие того, как работают языковые модели: они генерируют текст (в данном случае SQL) на основе вероятностей, и генерация время от времени ошибается.

Реалистичный сценарий: вы просите «удали тестовые записи из таблицы orders, где status = 'test'», а модель неверно интерпретирует границы условия или упускает WHERE при генерации многошагового запроса — и DELETE уходит по более широкому набору строк, чем вы имели в виду. Или вы просите «обнови статус заказа №123 на отменён», а модель, работая с похожими по смыслу именами полей в нетривиальной схеме, обновляет не ту строку или не ту таблицу.

Здесь важно не путать причины: дело не в том, что модель «злонамеренная» — дело в том, что естественный язык неоднозначен, а SQL исполняется буквально. Разночтение между тем, что вы имели в виду, и тем, что понял ассистент, конвертируется прямо в изменение данных, если у подключения есть права на запись.

Отдельная грань риска — многошаговые агентные сценарии, где ассистент сам решает, что делать дальше, на основе результата предыдущего запроса. Если в цепочке рассуждений закралась ошибка, а прав достаточно, чтобы её исполнить, — откат придётся делать вручную из бэкапа, а не отменой одного неудачного ответа в чате. Здесь тот же принцип, что для любого автоматизированного доступа к боевой базе: чем меньше прав у процесса, который может ошибиться, тем меньше цена ошибки. Общий разбор этой логики есть в статье про антипаттерн «всё под root» — принцип минимальных привилегий там расписан на примере системного администрирования, но для MCP-подключения к базе он работает один в один.

Риск второй: база отвечает больше, чем должна

Второй риск тоньше первого и его легче не заметить, потому что он не ломает данные, а тихо их раскрывает. Если MCP-подключение даёт доступ ко всей базе без разграничения по таблицам, схемам или строкам, ассистент технически способен вернуть в ответе данные, которые не должны быть доступны в конкретном контексте разговора.

Конкретные примеры, где это стреляет:

  • Таблицы с персональными и платёжными данными. Если у подключения есть доступ к таблице с email, телефонами или частичными данными карт, любой вопрос, который случайно затрагивает эту таблицу через JOIN, может вернуть в ответе информацию, не относящуюся к делу — например, вместе с агрегатом по заказам ассистент процитирует пример строки с реальным email клиента.
  • Многопользовательские сценарии (multi-tenant). Если один MCP-сервер обслуживает вопросы разных сотрудников или разных клиентов вашего сервиса, а разграничение по правам на уровне базы не настроено, ассистент физически может ответить на вопрос про данные чужого клиента — просто потому, что подключение видит всю таблицу целиком, а не только строки, относящиеся к текущему пользователю.
  • Служебные и внутренние поля. Таблицы нередко содержат поля, не предназначенные для внешнего взгляда — внутренние заметки, флаги мошенничества, служебные комментарии. Без разграничения на уровне колонок ассистент может вставить их в ответ, даже не пометив как чувствительные, — потому что для него это просто ещё одно значение из результата запроса.

Ключевой момент: это не баг конкретного MCP-сервера и не ошибка модели — это прямое следствие того, что доступ выдан на уровне всей базы, а не на уровне того, что действительно нужно для задачи. Протокол MCP тут ни при чём, он честно передаёт то, что ему разрешили передать. Разграничение — это ваша ответственность, и настраивается оно средствами самой СУБД, а не MCP.

Как подключать безопасно: минимальные права, тестовый контур, логирование

Три практические меры покрывают основную часть риска и не требуют сложной инфраструктуры.

1. Отдельный пользователь БД с ограниченными правами. Никогда не подключайте MCP-сервер под пользователем-владельцем базы или под postgres/root. Создайте отдельного пользователя только для этой задачи и выдайте ровно те права, которые нужны:

-- создаём пользователя только для MCP-подключения
CREATE ROLE mcp_readonly WITH LOGIN PASSWORD 'сложный-пароль-сюда';

-- доступ только на чтение, только к нужным таблицам
GRANT CONNECT ON DATABASE mydb TO mcp_readonly;
GRANT USAGE ON SCHEMA public TO mcp_readonly;
GRANT SELECT ON orders, order_items, products TO mcp_readonly;

-- явно НЕ выдаём права на другие таблицы и на запись
REVOKE INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public FROM mcp_readonly;

Если по задаче ассистенту всё же нужно писать в базу (например, обновлять статус тикета), выдайте UPDATE точечно на конкретную таблицу и конкретные колонки (GRANT UPDATE (status) ON tickets TO mcp_readonly), а не на схему целиком. Для более широкого разбора модели доступа без раздачи полных прав есть статья как раздать доступ команде без выдачи root — принцип тот же: описываете задачу, потом смотрите, какой минимальный набор прав её закрывает.

2. Явное разделение окружений на этапе освоения технологии. Пока вы не понимаете, как именно конкретный MCP-сервер формирует и исполняет запросы, не подключайте его к боевой базе вообще. Разверните тестовую копию — pg_dump продакшена в отдельную базу на том же или соседнем сервере, с масками на чувствительных полях, если это персональные данные:

pg_dump -Fc mydb > mydb_snapshot.dump
createdb mydb_test
pg_restore -d mydb_test mydb_snapshot.dump

На этой копии можно спокойно поэкспериментировать с формулировками вопросов, посмотреть, какой SQL реально генерирует модель в разных случаях, и только после того, как поведение станет предсказуемым, переключать подключение на ограниченного пользователя боевой базы — не раньше.

3. Логирование всех запросов, сделанных через MCP. Включите логирование на уровне PostgreSQL для роли, под которой ходит MCP-сервер, — это даёт возможность разобраться постфактум, что именно спросил ассистент и какой SQL был выполнен:

ALTER ROLE mcp_readonly SET log_statement = 'all';

Логи стоит выводить в отдельный файл или в централизованный сборщик, а не смешивать с общим логом сервера — так проще быстро найти нужный запрос при разборе инцидента. Если у вас уже есть стек для логов, подойдёт связка с Graylog или Loki; если аудита в принципе ещё нет — начните с базового аудита логов сервера через auditd, а логирование именно SQL-запросов настройте отдельно поверх него. Ротацию логов не забудьте настроить сразу — статья лога на все запросы за пару недель активного использования вырастет заметно.

Эти три меры не устраняют риск полностью — модель всё равно может ошибиться в пределах выданных ей прав, — но сокращают возможный ущерб до предсказуемых границ и дают возможность разобраться, что произошло, если что-то пошло не так.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

MCP-сервер для базы данных — это то же самое, что обычный API?

Похоже по идее, но не по механике: обычный REST API вы проектируете сами под конкретные эндпоинты, а MCP-сервер описывает набор инструментов в стандартном формате, который любой MCP-клиент понимает без индивидуальной интеграции. Технически MCP-сервер может быть реализован поверх обычного HTTP или через stdio — снаружи для ассистента это выглядит одинаково.

Можно ли ограничить MCP-сервер только чтением на уровне самого сервера, а не базы?

Некоторые серверы это умеют (флаг read-only, обёртка в транзакцию только для чтения), но полагаться только на это рискованно — если в самом сервере есть баг или он неверно настроен, ограничение на уровне СУБД (права пользователя) остаётся последним рубежом защиты, и настраивать его нужно всегда, независимо от того, что заявляет сервер.

Стоит ли подключать через MCP таблицу с паролями пользователей или платёжными токенами?

Нет — эти данные вообще не должны попадать в контекст, который проходит через языковую модель, независимо от прав доступа. Помимо риска утечки в ответе, часть провайдеров может логировать содержимое запросов на своей стороне для отладки — не отправляйте туда то, что не готовы увидеть в чужом логе.

Как понять, какие права реально нужны MCP-серверу для моей задачи?

Начните с формулировки задач текстом («отвечать на вопросы по заказам и товарам», «обновлять статус тикета») и для каждой определите минимальный набор таблиц и операций. Выдайте ровно это, протестируйте на копии базы неделю-две реального использования, и только потом расширяйте права точечно под конкретные запросы, которые не смогли выполниться из-за нехватки прав — а не заранее «на всякий случай».

Что делать, если ассистент уже выполнил ошибочный DELETE или UPDATE?

Восстановление из бэкапа — единственный надёжный путь, если транзакция уже закоммичена. Это ещё один аргумент в пользу read-only подключения на первом этапе и регулярных бэкапов боевой базы независимо от того, подключён к ней ИИ-ассистент или нет.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →