# Безопасность MCP-инструментов: права, подтверждение и журнал

Источник: https://modelium.tech/zhurnal/mcp-bezopasnost-instrumentov/

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

**Проверено по документации 28 сентября 2026 года.** MCP specification 2026-07-28 и документация Open WebUI закреплены за ревизиями в источниках. Ниже — план испытаний для **вашего** стенда: Modelium не запускал клиент, сервер, модель и не подтвердил чью-либо конфигурацию. Проверка инструментов — не проверка того, что языковая модель не передаёт данные в облако. [s2](#src-s2) [s7](#src-s7)

## Что именно нужно защитить?

MCP-клиент получает список инструментов (`tools/list`), а для исполнения отправляет `tools/call` с именем и аргументами. Инструменты могут быть вызваны моделью; протокол не закрепляет единственный пользовательский интерфейс. Видимое «модель обещала ничего не удалять» не является серверной политикой доступа. Спецификация требует от **сервера** проверки входа, контроля доступа, ограничения частоты вызовов и очистки результатов, а **клиенту рекомендует** показывать входные параметры, спрашивать согласие на чувствительные операции и вести журнал. [s2](#src-s2)

Маршрут: **тестовые данные и роль → список инструментов → изолированный сервер → разрешённый и запрещённый вызовы → журнал и сверка состояния**. Не путайте безопасность интерфейса вызова с качеством ответа модели или общесистемной проверкой изоляции. Даже у сервера без сетевого порта локальный процесс получает права своей ОС-учётной записи; документация MCP отдельно предупреждает о вредоносной команде запуска и рекомендует песочницу и минимум привилегий. [s1](#src-s1) [s5](#src-s5)

## Чек-лист перед подключением

- **Источник и команда.** Проверьте репозиторий, закреплённую версию, точную команду запуска, аргументы и переменные окружения. Не устанавливайте неизвестную сборку по подсказке из чата: локальный MCP-сервер исполняет код от имени запускающего пользователя. Официальные практики требуют показывать команду целиком и получать согласие при автоматическом подключении; они также рекомендуют ограничивать доступ к файлам, сети и секретам. [s1](#src-s1)

- **Граница данных.** Подготовьте синтетические записи и отдельную учётную запись с доступом лишь к нужной тестовой папке или тестовому API. Выдайте только требуемое право чтения для инструмента чтения; право записи должно иметь отдельное обоснование и независимую серверную проверку. Ограничение набора доступных инструментов в клиенте снижает экспозицию модели, но само по себе не заменяет прав в сервере и целевой системе. [s1](#src-s1) [s2](#src-s2)

- **Транспорт.** Для одного локального процесса `stdio` использует stdin/stdout и не требует HTTP-адреса. Если нужен Streamable HTTP, проверьте сетевой bind: стандарт рекомендует локальную привязку к `127.0.0.1`, требует проверять `Origin` и рекомендует аутентификацию соединений. Открытый `0.0.0.0` без отдельного периметра не равен «локально и безопасно». [s5](#src-s5) [s6](#src-s6)

- **Права и токены для защищённого HTTP.** OAuth-авторизация в MCP описана для HTTP, не превращайте её в обязательное требование для учебного `stdio`. Для защищённого ресурса сервер должен валидировать токен и его назначение именно этому MCP-серверу; не принимайте и не пересылайте чужой bearer-токен как есть в последующий API. Клиент должен запрашивать минимально необходимые scopes и передавать токен в заголовке, а не в URL. [s1](#src-s1) [s3](#src-s3) [s4](#src-s4)

- **Клиент и подтверждение.** Выясните на конкретной версии хоста, показывает ли он название инструмента **и аргументы** до вызова и можно ли отклонить чувствительную операцию. Спецификация это рекомендует, но не гарантирует интерфейс подтверждения в каждой реализации; для высокорисковых действий отсутствие такой функции — причина не включать инструмент, пока нет компенсирующего контроля. [s2](#src-s2)

- **Журнал.** Включите запись идентификатора операции, роли, имени инструмента, решения политики (`allow`/`deny`), факта согласия и результата без секретов и полного содержимого документа. Сверьте запись клиента с серверным журналом/состоянием. Это рекомендуемая конструкция стенда, а не обещание встроенного аудита MCP: спецификация рекомендует клиентам вести логи, но сервер или приложение должны реализовать их собственное хранение, защиту и сроки. Токены могут быть украдены из логов, поэтому маскируйте их до записи. [s2](#src-s2) [s4](#src-s4)

## Как проверить разрешённый и запрещённый вызовы?

Создайте на тестовом сервере только `read_sample` с доступом к одной синтетической записи и, если тестируете контроль записи, отдельный `write_sample` с политикой «только роль editor, только тестовый объект». Это **схема испытания**, не утверждение, что готовый сервер имеет такие имена. Выделите роль viewer и роль editor в целевой системе; запрет должен действовать в сервере даже если клиент ошибочно покажет `write_sample`. Проверяйте идентификатор и область объекта **до** модификации, затем независимо считывайте запись. Требование серверного контроля доступа и проверки входа содержится в спецификации инструментов. [s2](#src-s2)

- **Допустимое чтение:** `viewer → read_sample(test-001)`; ожидайте возвращённую тестовую метку и строку `allow` в журнале. Само появление `read_sample` в `tools/list` не доказывает успешный вызов — нужна трасса `tools/call` и ответ. Официальный Inspector CLI умеет оба метода. [s2](#src-s2) [s8](#src-s8)

- **Запрещённая запись:** `viewer → write_sample(test-001, changed)`; даже при прямом вызове без окна клиента ожидайте отказ на сервере, запись `deny` и неизменённую тестовую запись. Если «отказ» существует только в ответе модели или UI, испытание не пройдено. Сервер обязан проверять права сам. [s2](#src-s2)

- **Подтверждаемая запись:** `editor → write_sample(test-001, changed)` в клиенте с подтверждением; сначала отклоните действие и проверьте отсутствие изменения, затем отдельно разрешите и проверьте изменение и пару журналов. Если клиент не показывает аргументы или не умеет остановить вызов, не объявляйте этот шаг пройденным. Наличие подтверждения у вашего клиента проверяется экспериментом, не выводится из стандарта. [s2](#src-s2)

- **Неверный объект или данные:** вызовите `read_sample` для объекта вне разрешённой области и `write_sample` с недопустимым полем; ожидайте отказ и отсутствие эффекта. Для HTTP дополнительно проверяйте соединение без надлежащей авторизации и нежелательный `Origin` на отдельном тестовом endpoint, не подвергая рабочий сервер намеренному внешнему сканированию. [s2](#src-s2) [s3](#src-s3) [s6](#src-s6)

В отчёте стенда запишите время, версии клиента/сервера, транспорт, учётную роль, входной аргумент без чувствительных данных, ответ инструмента, решение политики и снимок тестовой записи до/после. Чистый текст ответа модели без трассы не подтверждает выполненное действие; отсутствие изменения без записи отказа тоже не объясняет, **где** возник запрет. Здесь «успех» — наблюдаемый допуск по правилам и воспроизводимый отказ. [s2](#src-s2) [s8](#src-s8)

## Как развести права сервера и настройки Open WebUI?

На зафиксированной документации Open WebUI регистрацию MCP-серверов выполняет администратор в **Settings → Admin → Integrations**; обычным пользователям доступна отдельная настройка OpenAPI, не регистрация MCP. Администратор ограничивает доступ к подключению по пользователям или группам через **Access Control**. WebUI работает с MCP через Streamable HTTP, поэтому локальную `stdio`-команду нельзя просто вставить вместо HTTP URL. [s7](#src-s7)

Поле **Function Name Filter List** ограничивает видимые модели инструменты; пустое значение по документации открывает все. Используйте фильтр как дополнительный контроль выдачи, но проверяйте серверный отказ отдельным вызовом без фильтра: доступность в UI, серверная авторизация и право целевого API — разные границы. Авторизация `None` у закрытого локального тестового endpoint не означает, что публично доступному endpoint она не нужна; для защищённого HTTP действуют условия токенов и scopes выше. [s7](#src-s7) [s2](#src-s2) [s3](#src-s3)

## Что делать при провале проверки?

- **Отклонение в UI, но запись всё же поменялась:** остановите инструмент и выясните, какой путь обошёл подтверждение; добейтесь серверного `deny`. Нельзя считать UI-подтверждение единственной линией защиты. [s2](#src-s2)

- **Неизвестный инструмент в **`**tools/list**`**:** отключите сервер или ограничьте публикацию набора инструментов и исследуйте происхождение команды/пакета до нового теста. Не полагайтесь на обещание модели игнорировать имя. [s1](#src-s1) [s2](#src-s2)

- **Успешный вызов без нужного токена или с токеном чужого ресурса:** закрывайте HTTP-доступ и исправляйте валидацию audience; token passthrough официально запрещён. Не сохраняйте сами токены в снимках расследования. [s1](#src-s1) [s3](#src-s3) [s4](#src-s4)

- **Журнал содержит секреты:** ограничьте доступ к журналу, удалите или ротируйте скомпрометированные секреты по процедуре владельца системы, после исправления повторите тест; защищённость лога не менее важна, чем его наличие. [s4](#src-s4)

**Следующий шаг:** начните с [безвредного локального MCP-сервера](/zhurnal/mcp-server-lokalno/) и подтвердите прямой вызов инструмента; только затем примените матрицу `allow/deny` к своему тестовому инструменту с настоящей серверной политикой. Без сохранённого отрицательного теста и сравнения состояния публикация инструмента для рабочих данных преждевременна. [s2](#src-s2) [s8](#src-s8)

## Источники

1. [MCP security best practices 2026-07-28 — local server and token passthrough](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/docs/2026-07-28/tutorials/security/security_best_practices.mdx) — получено 2026-09-28
2. [MCP specification 2026-07-28 — tools and security considerations](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2026-07-28/server/tools.mdx) — получено 2026-09-28
3. [MCP specification 2026-07-28 — HTTP authorization and scope selection](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2026-07-28/basic/authorization/index.mdx) — получено 2026-09-28
4. [MCP specification 2026-07-28 — authorization security considerations](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2026-07-28/basic/authorization/security-considerations.mdx) — получено 2026-09-28
5. [MCP specification 2026-07-28 — stdio transport](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2026-07-28/basic/transports/stdio.mdx) — получено 2026-09-28
6. [MCP specification 2026-07-28 — Streamable HTTP transport security](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2026-07-28/basic/transports/streamable-http.mdx) — получено 2026-09-28
7. [Open WebUI — MCP admin registration, access control and tool filter](https://github.com/open-webui/docs/blob/6602effdb92ce647f2abe6dbb61e136b62191d7a/docs/features/extensibility/mcp.mdx) — получено 2026-09-28
8. [MCP Inspector CLI — list and call methods](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/docs/2026-07-28/tools/inspector/cli.mdx) — получено 2026-09-28
