Кожен сервер MCP – це ще одна конфіденційна інформація, яку ваш агент може витекти.
Кожен сервер MCP є ще однією „живою“ таємницею, яка розширює можливості шкідливого введення даних. Перевірте діапазони токенів та застосуйте чотири корекції, які зменшать радіус поширення проблеми.
Джерела: Every MCP Server You Add Gives Your Agent Another Credential
Усе починається безневинно. У понеділок під’єднується GitHub, у вівторок — Slack, потім Postgres, потім Notion, а ще — внутрішній сервер білінгу, який колега написав за один день і так і не задокументував. Кожне додавання робить цей агент більш здатним. Кожне з них також додає ще один елемент до „кільця“, яке він носить із собою.
Проблеми зазвичай виникають випадково, коли хтось виправляє щось не пов’язане та відкриває файл конфігурації. Шість серверів, шість конфіденційних даних у відкритому вигляді у домашньому каталозі, без терміну дії та без власника. У цей момент MCP перестає здаватися зручним інструментом та починає виглядати як тягар.
Арифметика
Через кілька місяців ентузіазму типова конфігурація виглядає ось так:
{
"mcpServers": {
"gh": { "cmd": "gh-mcp", "env": { "GH_TOKEN": "ghp_live_9f2a" } },
"db": { "cmd": "pg-mcp", "env": { "PG_URL": "postgres://app:hunter2@prod/main" } },
"sl": { "cmd": "slk-mcp", "env": { "SLACK_TOKEN": "xoxb-live-771" } }
}
}
Три сервери, три секрети, один файл та відсутність ротації. Ви можете перевірити свій власний пристрій протягом кількох секунд, шукаючи у звичайних папках конфігурації рядки, схожі на токени.
grep -rIl "ghp_\|xoxb-\|sk-" ~/.config ~/.claude ~/Library 2>/dev/null | wc -l
Люди, які ним керують, часто знаходять більше, ніж очікували. Коли ви очікували трьох, а знаходите одинадцять, це не є аномалією.
Частина, яка справді завдає проблем
Дані, які зберігаються на диску, — це менш серйозна половина проблеми. Справжня проблема полягає у тому, що кожен із цих ключів тепер знаходиться під контролем однієї особи, яка приймає рішення, а ця особа читає текст з Інтернету.
one agent loop
|
+---------+---------+---------+---------+
| | | | |
github slack postgres notion billing
(14 scp) (9 scp) (rw all) (rw ws) (rw all)
| | | | |
+---------+---------+---------+---------+
|
one poisoned input
Коментар до проблеми, сторінка в Notion чи рядок у таблиці можуть кожен запропонувати певні дії, а агент має всі необхідні засоби для їх виконання. Це є проявом проблеми „збентеженого заступника“ у новому вигляді. Агент не є під загрозою; він намагається допомогти, але не може відрізнити ваші інструкції від тексту, який лише їм схожий.
Вимірювання розриву
Корисним завданням є фіксування кожного виклику інструменту протягом двох тижнів, а потім порівняння того, що кожен токен може робити, з тим, що він насправді робив. Ось результат однієї такої перевірки:
| Service | Granted Scopes | Scopes Used | Utilization |
| -------- | --------------: | ------------------: | ----------: |
| GitHub | 14 | 3 | 21.4% |
| Slack | 9 | 2 | 22.2% |
| Postgres | Full RW | 1 table, reads only | Minimal |
| Notion | Whole workspace | 2 pages | Minimal |
Приблизно чотири п’ятих наданих прав доступу залишилися невикористаними. Ця прогалина — це не зручність; це ризик, який ви несете, не отримуючи за це нічого.
Рішення, впорядковані за ефективністю
Один токен на сервер, прив’язаний до конкретних завдань цього сервера. Спільні токени означають спільну відповідальність. Коли щось йде не так, журнал аудиту має вказувати на сервер, а не на конкретну особу.
За замовчуванням лише право на читання для всього, що зберігає дані. Дві рядки SQL, спеціальна роль та права на читання лише тих таблиць, які агент дійсно читає, дозволяють перетворити найгірший сценарій (втрату таблиці) на ситуацію витоку запиту.
create role agent login password 'rotate_me';
grant usage on schema public to agent;
grant select on orders, users to agent;
Тимчасові токени замість постійних. Нехай сховище видає облікові дані за запитом, термін дії яких становить кілька хвилин. Секрет, вкрадений у вівторок вранці, втрачає свою цінність вже у вівторок після обіду.
async function tok(srv) {
const r = await fetch(`${VAULT}/issue/${srv}`, { method: "POST" });
const { token, ttl } = await r.json();
return { token, exp: Date.now() + ttl * 1000 };
}
Журналізація дзвінків, а не лише чату. Тонкий обгорток, який записує інформацію про сервер, аргументи та часовий позначник навколо кожної функції інструменту, складається з кількох рядків коду. У згаданій вище аудиторській перевірці це виявило ситуацію, коли сервер викликав кінцеву точку, про яку ніхто не просив його торкатися.
function wrap(name, fn) {
return async (args) => {
log({ srv: name, args, at: Date.now() });
return fn(args);
};
}
Правило, яке варто прийняти
Перш ніж включати сервер, уявіть його як ворожий елемент та запитайте себе, що він може зробити без жодної допомоги. Якщо чесна відповідь викликає дискомфорт, скоротіть кількість доступних ресурсів або взагалі не використовуйте цей сервер. Не обіцяйте виправити ситуацію пізніше, адже «пізніше» рідко настає, тим більше у п’ятницю.
Усе це не є аргументом проти MCP. Він вирішив проблеми інтеграції, через які агенти ставали схожими на іграшки. Суть у тому, що кожен доданий сервер також додає нові облікові дані, і ці дані потребують такої ж уваги, як і будь-який інший ключ для роботи в продакшені.
Пов’язана література
- Практичні нотатки: Створення AI-фінансового агента за допомогою сервера MCP від EODHD — Покрокове керівництво з використанням Практичних нотаток: Створення AI-фінансового агента за допомогою сервера MCP від EODHD: контракти, перевірки та місця для вставки коду для команд, які розробляють системи MCP без цього інструменту.
- Практичні нотатки: Чи може ваш агент шукати MCP-інструменти — Покрокове керівництво з використанням Практичних нотаток: Чи може ваш агент шукати MCP-інструменти: контракти, перевірки та місця для вставки коду для команд, які використовують цю схему.