# GraphQL

## 1. Роль протокола в проекте

GraphQL поддерживается как отдельный тип интеграции, но на слое MCP намеренно ограничивается. Цель платформы не в том, чтобы дать LLM универсальный доступ ко всему GraphQL endpoint, а в том, чтобы превратить конкретный GraphQL-запрос в узкий и предсказуемый MCP tool.

## 2. Что поддерживается в целевом продукте

- `query`
- `mutation`
- один GraphQL endpoint на operation
- фиксированный `query_template`
- фиксированный `selection set`
- загрузка примера выходного `JSON`
- схема переменных
- variables mapping
- response extraction из `data`
- разбор `errors`
- auth и headers
- автогенерация чернового mapping
- ручная донастройка через `JSONPath`
- тестовый вызов перед публикацией

## 3. Что отложено

- `subscription`
- универсальный GraphQL explorer для LLM
- передача произвольного GraphQL-документа от LLM
- визуальный конструктор сложных selection set
- обязательная зависимость от introspection
- автоматическое построение любого запроса по полной GraphQL schema

`subscription` допускается только как future scope после появления отдельного websocket/subscription adapter и controlled streaming lifecycle.

## 4. Ключевое архитектурное ограничение

Платформа не должна публиковать в MCP общий GraphQL tool, который умеет получать любые поля и принимать любые параметры в зависимости от намерения LLM.

Правильная модель только одна:

- один tool;
- один конкретный `query` или `mutation`;
- один заранее зафиксированный `selection set`;
- фиксированный набор входных параметров;
- один предсказуемый формат ответа.

Иными словами, на MCP-слое GraphQL сознательно сужается до модели, близкой к RPC или REST operation. Это делается потому, что LLM должен работать с понятным контрактом, а не конструировать произвольный GraphQL-запрос на лету.

## 5. Внутренняя модель GraphQL operation

GraphQL operation должна включать:

- `endpoint`
- `operation_type`
- `operation_name`
- `query_template`
- `variables_schema`
- `input_mapping`
- `response_path`
- `error_policy`
- `headers`
- `auth_profile`

## 6. Как оператор настраивает GraphQL operation

1. Указывает GraphQL endpoint.
2. Выбирает `query` или `mutation`.
3. Задает имя операции.
4. Вставляет готовый шаблон запроса.
5. Описывает переменные, которые разрешено передавать в эту операцию.
6. При необходимости загружает пример JSON-ответа.
7. Система строит черновую схему ответа и стартовый mapping.
8. Настраивает маппинг `MCP input -> GraphQL variables`.
9. Указывает `response_path`, по которому извлекается полезный результат из `data`.
10. При необходимости уточняет mapping через `JSONPath`.
11. Выполняет тест.
12. Публикует operation как MCP tool.

## 7. Поведение runtime

При выполнении GraphQL operation runtime должен:

1. Валидировать вход по фиксированной схеме переменных.
2. Применить input mapping.
3. Собрать GraphQL payload вида `query + variables`.
4. Выполнить HTTP request.
5. Отдельно разобрать `data` и `errors`.
6. Применить output mapping или `response_path`.
7. Вернуть нормализованный результат.

## 8. Критические нюансы

- HTTP `200 OK` не означает успешное выполнение, если в теле присутствует `errors`.
- структура ответа зависит от `selection set`, значит она должна быть фиксирована заранее;
- GraphQL endpoint обычно один, поэтому операция определяется не URL, а телом запроса;
- variables должны быть строго ограничены, иначе один tool станет слишком широким и плохо управляемым;
- `subscription` не входит в текущий scope, потому что требует отдельной lifecycle-модели, близкой к `session` mode, и отдельного transport adapter.
- `JSONPath` используется для точечного извлечения вложенных данных из `data` и для управления структурой итогового ответа.

## 9. Почему GraphQL не считается "почти REST"

GraphQL похож на REST только тем, что часто передается по HTTP. Но с точки зрения платформы это другой тип контракта:

- смысл операции задается не endpoint, а запросом;
- ответ зависит от `selection set`;
- ошибки живут в теле ответа, а не только в HTTP status;
- одна и та же точка входа может обслуживать много операций.

Поэтому GraphQL в системе должен иметь отдельный адаптер и отдельную конфигурационную модель.
