MCP дошёл до Go: как не утонуть в интеграциях агентов и собрать production-ready сервер без самописного glue-кода
Я — Denis Shokhirev, Agentic AI Systems Architect из Freiburg im Breisgau, Germany, и в DennisCraft AI Studio я собираю production-системы на Claude, Supabase, n8n, Doppler и self-hosted Postgres для B2B-клиентов в DACH. Самая неприятная точка в реальных agent workflows обычно не модель и не prompt, а слой интеграций: 6 инструментов, 3 схемы авторизации, разные форматы ошибок, и через 2 недели у команды уже больше glue-кода, чем бизнес-логики. С появлением MCP в Go стало проще собрать сервер, к
Я — Denis Shokhirev, Agentic AI Systems Architect из Freiburg im Breisgau, Germany, и в DennisCraft AI Studio я собираю production-системы на Claude, Supabase, n8n, Doppler и self-hosted Postgres для B2B-клиентов в DACH. Самая неприятная точка в реальных agent workflows обычно не модель и не prompt, а слой интеграций: 6 инструментов, 3 схемы авторизации, разные форматы ошибок, и через 2 недели у команды уже больше glue-кода, чем бизнес-логики.
С появлением MCP в Go стало проще собрать сервер, который агент понимает предсказуемо: единый контракт на tools, ресурсы и вызовы, меньше самодельных адаптеров, меньше скрытого состояния между компонентами. Но сам факт поддержки Go ничего не решает, если вы сразу тащите в проект динамические tool registry, неконтролируемые права на SQL и дебаг через print. Ниже — как я смотрю на MCP-сервер для production: не как на витрину для демо, а как на контролируемую точку доступа между моделью и вашей инфраструктурой.
Почему интеграции агентов ломаются быстрее, чем сами модели
Когда команда впервые собирает multi-agent систему, она обычно оптимизирует выбор модели и orchestration. На практике сбои приходят из другого места: tool contracts расползаются, retries дублируют побочные эффекты, а логирование не позволяет восстановить цепочку решений. Если agent может вызвать SQL, HTTP и внутренний workflow, то у вас уже не “чат с функциями”, а распределённая система с требованиями к идентичности, наблюдаемости и контролю прав.
Типичный анти-паттерн
Я регулярно вижу один и тот же сценарий: сначала делают 2–3 helper-функции “на скорую руку”, потом оборачивают их в кастомный JSON-формат, потом добавляют ручную валидацию параметров, а потом пишут ещё один слой, чтобы один и тот же tool понимали Claude и внутренний runner. Формально всё работает. Фактически команда сама построила нестабильный протокол, который теперь обязана поддерживать.
MCP здесь полезен не потому, что это модная аббревиатура, а потому что он задаёт границу. Агент видит описанные capabilities, сервер отвечает в ожидаемом формате, а вы можете централизованно решать, что именно разрешено в production. Для regulated environments это важнее, чем “гибкость любой ценой”.
Что именно я считаю production-ready MCP-сервером
Production-ready MCP-сервер — это не “сервер, который отвечает на list_tools”. Это сервис, который можно обновлять, логировать, ограничивать и проверять до релиза. Минимальный набор у меня такой:
| Слой | Что должно быть | Зачем |
|---|---|---|
| Контракт | Строгие схемы входа и выхода | Исключить неявные поля и разъезд типов |
| Авторизация | Разделение прав по tool и среде | Не давать agent лишний доступ |
| Наблюдаемость | Request ID, audit log, trace связи tool вызовов | Разбор инцидентов и воспроизводимость |
| Безопасность | Secret isolation, SQL allowlist, статический анализ | Снизить риск утечек и опасных вызовов |
| Эксплуатация | Health checks, timeouts, retries с идемпотентностью | Переживать сетевые сбои без побочного хаоса |
Если хотя бы 2 строки из этой таблицы у вас пока нет, не надо называть это agent platform. Это ранний integration layer, и к нему нужно относиться честно.
Go здесь удобен по практическим причинам
Для MCP-сервера Go хорош тем, что позволяет держать небольшой бинарник, предсказуемые зависимости и понятную модель конкурентности. В среде, где есть n8n, Postgres, внутренние API и очереди задач, это часто выгоднее, чем плодить ещё один тяжёлый runtime ради 5–7 tools. Особенно если сервер нужно self-hosted разворачивать у клиента.
Минимальный каркас без лишней магии
Ниже не “фреймворк ради фреймворка”, а обычный принцип: один tool — одна явная функция, валидируемый вход, ограниченный side effect. Даже если дальше вы подключите Anthropic SDK или Claude Code в контур разработки, граница сервера должна остаться скучной и предсказуемой.
export DATABASE_URL="postgres://app:***@db.internal:5432/app"
export MCP_ALLOWED_TABLES="customers,orders"
export TOOL_TIMEOUT_SECONDS="8"
gitleaks detect --source . --no-banner
semgrep --config p/owasp-top-ten .
bandit -r scripts/
go test ./...
go build -o mcp-server ./cmd/server
./mcp-serverДаже в Go-проекте я часто гоняю semgrep и gitleaks вокруг обвязки, инфраструктурных скриптов и CI-конфигов. OWASP ASVS и OWASP Top 10 остаются полезной рамкой для проверки того, как ваш сервер работает с секретами, вводом и авторизацией. Если в проекте есть Python-утилиты для миграций или data tasks, bandit тоже уместен.
version: "3.9"
services:
mcp-server:
image: ghcr.io/example/mcp-server:latest
environment:
DATABASE_URL: ${DATABASE_URL}
MCP_ALLOWED_TABLES: customers,orders
TOOL_TIMEOUT_SECONDS: "8"
read_only: true
restart: unless-stopped
healthcheck:
test: ["CMD", "/app/mcp-server", "healthcheck"]
interval: 30s
timeout: 3s
retries: 3Ключевой момент: MCP-сервер не должен получать unrestricted database credentials. Если tool нужен только для чтения заказов и клиентов, дайте ему read-only роль и ограничьте SQL на уровне приложения. На 3 моих последних проектах с агентами именно чрезмерные права на DB были самым частым техническим риском, который всплывал ещё до выхода в production.
Где чаще всего ошибаются при сборке tool layer
1. Пытаются сделать универсальный tool executor
Идея “один executor на всё” почти всегда заканчивается размытым контрактом. Агенту лучше отдать 6 узких tools с ясными схемами, чем 1 мегатул с 14 режимами работы.
2. Смешивают orchestration и policy
n8n подходит для orchestration и интеграционных маршрутов, но policy-решения вроде “какие таблицы можно читать” или “какие домены можно вызывать” лучше фиксировать в сервере и конфиге. Иначе вы теряете одну точку контроля.
3. Не хранят достаточно аудита
Для production мало знать, что tool был вызван. Нужно видеть входные параметры, caller identity, результат, длительность, код ошибки и связанный trace ID. Иначе разбор инцидента превращается в реконструкцию по косвенным признакам.
4. Проверяют только happy path
Я бы отдельно тестировал timeout, отмену запроса, битые аргументы, пустые выборки и повторный вызов после частичного сбоя. Именно эти сценарии бьют по SLA, а не успешный демо-запрос из IDE.
Что говорят внешние источники и почему это важно
Anthropic в документации по Model Context Protocol описывает MCP как стандартный способ давать моделям доступ к tools и данным через единый интерфейс: docs.anthropic.com. Практический смысл для архитектуры простой: чем меньше у вас кастомных протоколов между агентом и инфраструктурой, тем проще обеспечивать тестируемость и заменяемость компонентов.
OWASP Top 10 2021 отдельно подчёркивает риски, связанные с broken access control и insecure design: owasp.org/www-project-top-ten. MCP-сервер как раз становится местом, где эти риски либо локализуются, либо разрастаются. Если вы строите agent layer поверх Postgres, Supabase и внутренних API, вопрос не в том, “умеет ли агент вызывать tool”, а в том, при каких условиях этот вызов безопасен и воспроизводим.
FAQ
MCP подходит только для Claude?
Нет, ценность MCP в самом контракте между моделью и инструментами. Даже если у вас несколько моделей или свой orchestration layer, единый протокол снижает количество переходников.
Нужно ли сразу поднимать много tools?
Нет. Я бы начинал с 3–5 критичных tools с узкими правами и хорошим audit trail. Широкий каталог инструментов без дисциплины обычно только увеличивает площадь ошибок.
Можно ли использовать Supabase за MCP-сервером?
Да, если вы чётко разделяете service-role доступ, read-only сценарии и то, что вообще разрешено агенту. MCP не заменяет политику доступа к данным, он делает точку вызова более управляемой.
Где лучше держать секреты?
Не в prompt и не в коде tool-обвязки. Я обычно выношу их в Doppler или другой менеджер секретов, а в сам сервер подаю только то, что нужно конкретной среде.
Когда не стоит использовать MCP?
Если у вас 1 локальный скрипт и 1 внешний API, отдельный MCP-сервер может быть лишним. Но как только появляется несколько tools, разные роли доступа и требования к аудиту, стандартизованная граница быстро окупается.
На каком этапе у вас сейчас теряется больше всего времени: описание tool contracts, контроль прав, аудит вызовов или разбор сбоев после релиза? Мне правда интересно, потому что именно эта точка обычно и определяет, станет ли agent system продуктом, а не затянувшимся прототипом.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.
Превратить процесс в систему, которая работает
Продакшн-качество, а не демо.