MCP-сервер 2ГИС: как заставить LLM не выдумывать адреса и координаты

2ГИС выпустили MCP-сервер, который даёт ИИ-агентам прямой доступ к геосервисам через Model Context Protocol — открытый протокол подключения внешних инструментов к моделям. На первый взгляд, задача проста: модель без инструментов придумывает адреса, дай ей доступ к базе — и готово. На практике получилось иначе: модель начинает врать иначе, что гораздо трудней заметить и отловить. Проблема решается архитектурой, а не уговорами. Инженеры 2ГИС разделили cервер на каркас (общая логика, ошибки, HTTP-пулы, логирование) и тонкие адаптеры-инструменты. Так каждый новый инструмент добавляется одного файла, без копипаста обработки ошибок. Главное — строгий контракт: JSON-схема параметров и чёткое описание для модели, а не попытки её «уговорить» через system prompt. • **Шесть инструментов**: поиск мест и организаций, прямое геокодирование, обратное геокодирование, построение маршрутов, изохроны, статические карты • **Разделение ошибок**: бизнес-ошибки (нет доступа, неверный ключ) идут модели как результат инструмента, сетевые сбои — как падение протокола • **Типизированный контракт**: Pydantic-модели на входе/выходе, JSON Schema для параметров, description для разумного вызова — модель видит только то, что нужно

AI-обработка оригинала Habr AI; редакция Hamidun News
MCP-сервер 2ГИС: как заставить LLM не выдумывать адреса и координаты
Источник: Habr AI. Коллаж: Hamidun News.
Слушать статью
Паспорт материала и цифры
ПараметрДанные
ПервоисточникHabr AI ↗
Главный редактор
Шесть инструментовпоиск мест и организаций, прямое геокодирование, обратное геокодирование, построение маршрутов, изохроны, статические карты
Разделение ошибокбизнес-ошибки (нет доступа, неверный ключ) идут модели как результат инструмента, сетевые сбои — как падение протокола
Типизированный контрактPydantic-модели на входе/выходе, JSON Schema для параметров, description для разумного вызова — модель видит только то, что нужно

2ГИС выпустили MCP-сервер (mcp-2gis) — инструмент, который подключает ИИ-агентов напрямую к геосервисам API-платформы 2ГИС. На данный момент это шесть инструментов: поиск мест и организаций, прямое геокодирование, обратное геокодирование, построение маршрутов, изохроны и статические карты.

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

Архитектура: каркас плюс тонкие адаптеры

Ключевое решение — масштабируемая архитектура. Вместо того чтобы делать каждый инструмент полносамостоятельным с собственной обработкой ошибок, логированием и HTTP-пулами, 2ГИС разделили систему на слои:

1. FastMCP middleware — аутентификация, allowlist, метрики, таймауты 2. tools/<domain>.py — MCP-схема, Pydantic-валидация входа/выхода, маппинг результата 3. tools/gis.py — lifespan-зависимости и общая граница обработки ошибок 4. integrations/<domain>_api.py — URL, параметры и JSON-взаимодействие конкретного API 2ГИС 5. integrations/gis_client.py — общий httpx-пул для всех запросов, инъекция API-ключа, преобразование HTTP-ошибок

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

Как вызывающая сторона

Одна функция-помощник `run_gis_tool` собирает все зависимости, открывает span на инструмент и переводит ошибки в два разных контракта. Это реализация критичного требования: бизнес-ошибку (неверный ключ, отсутствие доступа) агент должен получить как результат инструмента с машиночитаемым кодом, а не как падение протокола. Иначе модель не понимает, что делать, и вызывает инструмент заново.

Сетевой сбой или таймаут, напротив, обязаны остаться ошибкой MCP — рассуждать о них нет смысла, есть смысл повторить запрос.

Контракт вместо уговоров

Добавление нового инструмента требует:

• Pydantic-моделей входа/выхода с типами и валидацией • JSON Schema — контракт параметров (что обязательно, что опционально, какие значения допустимы) • Description инструмента — текст, который модель читает, решая, вызывать ли инструмент и с какими аргументами • Unit и in-process интеграционные тесты

Описание (description) в MCP — это не комментарий, а часть продукта. С кривым описанием модель может либо не понять, что инструмент нужен, либо вызвать его некорректно. JSON Schema отклоняет неизвестные значения до самого запроса, а не после.

Итог

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

Сюжет

Вопросы и ответы по материалу

Что известно по теме: архитектура: каркас плюс тонкие адаптеры?

Ключевое решение — масштабируемая архитектура. Вместо того чтобы делать каждый инструмент полносамостоятельным с собственной обработкой ошибок, логированием и HTTP-пулами, 2ГИС разделили систему на слои: 1. FastMCP middleware — аутентификация, allowlist, метрики, таймауты 2. tools/<domain>.py — MCP-схема, Pydantic-валидация входа/выхода, маппинг результата 3. tools/gis.py — lifespan-зависимости и общая граница обработки ошибок 4. integrations/<domain>_api.py — URL, параметры и JSON-взаимодействие конкретного API 2ГИС 5. integrations/gis_client.py — общий httpx-пул для всех

Что известно по теме: как вызывающая сторона?

Одна функция-помощник `run_gis_tool` собирает все зависимости, открывает span на инструмент и переводит ошибки в два разных контракта. Это реализация критичного требования: бизнес-ошибку (неверный ключ, отсутствие доступа) агент должен получить как результат инструмента с машиночитаемым кодом, а не как падение протокола. Иначе модель не понимает, что делать, и вызывает инструмент заново. Сетевой сбой или таймаут, напротив, обязаны остаться ошибкой MCP — рассуждать о них нет смысла, есть смысл повторить запрос.

Что известно по теме: контракт вместо уговоров?

Добавление нового инструмента требует: Pydantic-моделей входа/выхода с типами и валидацией JSON Schema — контракт параметров (что обязательно, что опционально, какие значения допустимы) Description инструмента — текст, который модель читает, решая, вызывать ли инструмент и с какими аргументами Unit и in-process интеграционные тесты Описание (description) в MCP — это не комментарий, а часть продукта. С кривым описанием модель может либо не понять, что инструмент нужен, либо вызвать его некорректно. JSON Schema отклоняет неизвестные значения до самого запроса, а не после.

ЖХ
Жемал Хамидун — CPO Alpina Digital, продакт-менеджер AlpinaGPT. Делает AI-продукты с 2019 года. Hamidun News — pet project, который вырос в production-агрегатор с 6000+ читателей.
✦ Автономные AI-агенты

Делегируйте ресёрч, код и рутину автономному AI-агенту

Интеллектуальная агентная среда NomadNet Agent (agent.nomadnet.ai) выполняет многошаговые задачи: глубокий веб-ресёрч, анализ данных, написание кода и автоматизацию браузера.

Запустить NomadNet Agent →Платформа NomadNet AI
Что вы думаете?
Загружаем комментарии…