Пагинация MCP влияет на то, какие инструменты увидит AI-агент и насколько полным окажется его ответ. Если клиент прочитал первую страницу каталога, нужный инструмент может остаться за её пределами. Если бизнес-инструмент вернул только часть заявок, агент может принять её за весь набор и написать неверный отчёт. В обоих случаях сеть работает, запрос завершился успешно, а смысл результата потерян.
Надёжная интеграция отдельно описывает порядок обхода, границы выборки, права на продолжение и признак завершения. Ниже — практический проект такого контракта для команды, которая подключает корпоративные системы через MCP. Примеры правил и чисел иллюстративные: это рекомендации по проектированию, а не дополнительные требования протокола или результаты измерений Codenik.
Пагинация MCP бывает на двух разных уровнях
На уровне протокола постранично возвращаются каталоги: инструменты, ресурсы, шаблоны ресурсов и промпты. В проверенной версии спецификации MCP от 2025-11-25 используется непрозрачный курсор; сервер выбирает размер страницы, а продолжение обозначается nextCursor. Клиент передаёт полученную строку без разбора и изменения. Отсутствие продолжения означает конец списка. Эти положения относятся именно к операциям перечисления. Спецификация пагинации MCP.
Второй уровень — данные корпоративного инструмента. Вызов search_orders может возвращать заказы страницами, но устройство его аргументов и результата задаёт разработчик инструмента. Нельзя автоматически считать, что поле nextCursor внутри произвольного результата имеет все гарантии протокольной пагинации. Их нужно описать в схеме и документации интеграции.
Такое разделение помогает локализовать ошибку. Если инструмент отсутствует в доступном каталоге, проверяют обнаружение. Если инструмент есть, но отчёт пропускает заказы, проверяют бизнес-выборку. Повторное подключение MCP-сервера не исправит неверный фильтр дат внутри search_orders, а увеличение лимита заказов не исправит клиент, который не дочитал tools/list.
На ревью полезно показать обе последовательности отдельно. Для каждой указывают владельца кода, место проверки прав и условие остановки. Иначе одна общая настройка «лимит ответа» начинает отвечать сразу за несовместимые задачи.
Сначала задайте, что значит полный результат
Запрос «проверь все открытые обращения» ещё не задаёт конечного набора. Какие проекты включены? На какой момент считается статус? Нужно ли учитывать удалённые записи? Имеет ли пользователь доступ ко всем очередям? Без этих условий даже корректный обход страниц не доказывает полноту.
Для рабочего сценария зафиксируйте организацию, список проектов, часовой пояс, фильтр статусов и момент отсечения. Например, агент анализирует обращения выбранных проектов, созданные до начала запуска. После старта новые обращения относятся уже к следующему отчёту. Это осмысленная бизнес-граница, которую можно объяснить пользователю и воспроизвести при расследовании.
При этом момент создания не замораживает остальные поля. Обращение может сменить статус во время обхода. Если требуется точная картина на один момент, понадобится согласованный снимок или заранее построенная выгрузка. Если достаточно оперативного обзора, допустимая изменчивость должна быть названа прямо.
Отдельно решите, как обозначать ограничения прав. Формулировка «все обращения компании» неверна, если агент читал только видимые пользователю проекты. Лучше вернуть охват: выбранные проекты, интервал, число прочитанных страниц и состояние завершения. Такой результат остаётся полезным даже при частичном доступе, потому что читатель понимает границы вывода.
Проверьте фактическое поведение SDK
Высокоуровневая функция SDK иногда сама проходит все страницы, а низкоуровневая возвращает одну. Например, документация C# SDK различает удобные методы с автоматическим обходом и методы прямого управления страницами. В Ruby SDK операции списка возвращают отдельный результат с курсором. Это свойства конкретных интерфейсов, а не универсальное поведение любого MCP-клиента. C# SDK, Ruby SDK.
Поэтому начните с маленького воспроизводимого стенда. Сервер публикует набор инструментов, заведомо не помещающийся на одну страницу. На последней находится инструмент с уникальным именем. Клиент должен обнаружить именно его. Проверка первой страницы ничего не говорит о работоспособности продолжения.
Затем ограничьте доступ одному пользователю и повторите обнаружение. Клиент не должен подмешать каталог предыдущей учётной записи. Проверяйте также переподключение: старый курсор нельзя безоговорочно использовать в новой сессии. Ошибка продолжения должна приводить к явному перезапуску обнаружения или диагностике, а не к выдаче усечённого списка как полного.
Если SDK скрывает страницы, наблюдайте сетевые вызовы или внедрите тестовый транспорт. Это позволяет отличить внутренний автоматический обход от случайного успеха на небольшом каталоге. Версию библиотеки и выбранный метод стоит записать в техническое решение: после обновления зависимостей команда сможет повторить тот же эксперимент.
Для бизнес-выборки нужен самостоятельный контракт
Представим инструмент, который читает обращения поддержки. Его результат должен отвечать на два вопроса: что получено сейчас и осталось ли что-то за пределами страницы. Ниже условный формат прикладного результата, а не стандартная схема MCP:
{
"items": [{"id": "ticket-42", "status": "open"}],
"continuation": "opaque-value",
"coverage": {
"state": "partial",
"cutoff": "2026-10-22T09:00:00Z"
}
}
Значения partial, complete и failed здесь проектирует ваша команда. В реальной схеме нужно определить, когда продолжение отсутствует, что означает пустая страница и как передаются ошибки. Важно не оставлять модели задачу угадывать смысл полей по их названиям.
Аргументы продолжения привязывают к первоначальному фильтру. Если агент меняет проект, сортировку или интервал, сервер отвергает старый курсор. Иначе итоговый набор незаметно собирается из нескольких разных запросов. Для пользователя такой отчёт выглядит цельным, хотя сравнивать его строки уже нельзя.
Размер страницы и максимальный объём ответа ограничиваются сервером. Запрошенное клиентом значение может быть пожеланием, но не правом получить неограниченную выгрузку. Также полезен общий бюджет обхода: время, количество объектов и размер переданного текста. Достижение бюджета возвращает явную неполноту, а не красивое заключение по случайному подмножеству.
Уникальный порядок важнее номера страницы
Постраничная выборка по OFFSET понятна человеку: пропустить первые строки и взять следующие. Но при конкурентных вставках и удалениях границы смещаются. Кроме того, PostgreSQL предупреждает о необходимости уникального порядка при LIMIT и о стоимости вычисления строк, пропускаемых большим OFFSET. Документация PostgreSQL.
Для последовательного обхода часто удобнее keyset pagination: следующая страница начинается после последней пары значений сортировки. Например, после времени создания и уникального идентификатора. Второе поле нужно, потому что несколько обращений могут иметь одинаковую дату. Сортировка только по времени оставляет порядок между такими строками неопределённым.
SELECT id, created_at, status
FROM tickets
WHERE organization_id = $1
AND created_at < $2
AND (created_at, id) > ($3, $4)
ORDER BY created_at, id
LIMIT $5;
Это фрагмент запроса для последующих страниц. Он предполагает неизменяемые поля порядка, проверенный доступ и непустую предыдущую позицию. Для первой страницы нужен отдельный вариант без сравнения с предыдущей позицией. Индекс и план запроса проверяются на ваших данных; пример не обещает универсального ускорения.
Ключевой компромисс остаётся: курсор по позиции решает движение по порядку, но не превращает живую таблицу в снимок. Если статус меняется, принадлежность записи фильтру может измениться между запросами. Поэтому выбор keyset должен следовать требованиям к отчёту, а не подменять их.
Выберите стратегию согласованности под задачу
Для пользовательского списка часто допустимо видеть обновления по мере обхода. Для финансовой сверки это может быть неприемлемо. Между ними есть сценарии, где достаточно фиксированного набора идентификаторов, но сами карточки можно читать в актуальном состоянии. Каждая стратегия даёт разные ответы на вопрос, что именно агент проверил.
PostgreSQL описывает различия уровней изоляции: последовательные чтения в Read Committed могут видеть разные зафиксированные состояния, а Repeatable Read предоставляет более устойчивый снимок внутри транзакции. Это не означает, что нужно держать транзакцию открытой всё время общения модели с инструментами. Уровни изоляции PostgreSQL.
Практическая альтернатива для длительного отчёта — коротко сформировать ограниченный набор идентификаторов и сохранить его как объект задания. Агент затем получает страницы этого набора. Перед чтением содержимого права проверяются заново, поэтому фиксированная выборка не становится бессрочным разрешением на доступ.
Для такого задания нужны срок жизни, владелец и понятное поведение при удалении исходной записи. Можно вернуть отметку «недоступно» и продолжить, сохранив число пропусков. Нельзя тихо убрать запись и заявить, что проверен весь исходный набор. Если бизнес требует строгой полноты содержимого, отсутствие хотя бы одной записи делает итог неполным.
Курсор не должен расширять доступ
Непрозрачность курсора полезна для клиента, но сама по себе ничего не защищает на сервере. Строка может быть случайным идентификатором состояния или подписанным контейнером. В обоих вариантах сервер обязан связать продолжение с организацией, субъектом, фильтрами и сроком действия.
Не помещайте в открытый курсор секреты, исходные персональные данные или неограниченный SQL. Подпись защищает от изменения содержимого, но не скрывает его. Если курсор содержит чувствительную позицию, используйте подходящее шифрование или храните состояние на сервере. Выбор зависит от модели угроз и стоимости хранения, а не от желания сделать строку компактнее.
Повторная проверка прав выполняется на каждой странице. Пользователь может потерять доступ к проекту после первой. Продолжение с прежним курсором не должно обходить это изменение. В зависимости от контракта сервер завершает выборку ошибкой или возвращает только доступные объекты с явным предупреждением об изменении охвата.
Также ограничьте число активных обходов на субъект и организацию. Иначе дешёвый запрос первой страницы создаст дорогое серверное состояние тысячами экземпляров. Метрики должны показывать и число созданных обходов, и число завершённых. Накопление незавершённых состояний часто указывает на забытый клиент, ошибку продолжения или неподходящий срок хранения.
Клиент должен различать конец, остановку и ошибку
Нормальный конец списка определяется контрактом сервера. Остановка по локальному бюджету — отдельный исход. Сетевая ошибка — ещё один. Если все три свести к пустому массиву, агент получит повод объявить успешный результат там, где данные вообще не были прочитаны.
Клиент хранит последний подтверждённый шаг обхода и счётчик страниц. Дополнительно он замечает повтор одного и того же курсора. Зациклившийся сервер не должен заставлять агента бесконечно повторять один запрос. В таком случае правильный результат — техническая неполнота с диагностикой, а не попытка самостоятельно модифицировать непрозрачную строку.
При повторе запроса после таймаута возможно повторное получение страницы. Сборщик результата должен учитывать идентичность объектов. Однако удаление дублей нельзя использовать как средство скрыть дефекты протокола: число повторов фиксируют отдельно, чтобы команда увидела нестабильное продолжение.
Модели передают краткую сводку состояния: прочитано столько-то объектов, охват такой-то, обход завершён или прерван по указанной причине. Если задача требует всех объектов, модель не должна выдавать отсутствие найденных проблем за доказательство чистоты при незавершённом обходе. Это правило лучше закрепить в детерминированном сборщике результата до генерации текста.
Проверьте обход на изменениях и сбоях
Хорошая проверка начинается с набора, который не помещается на одну страницу, и заранее известного ожидаемого покрытия. Например, искусственные обращения распределяются по нескольким проектам, а нужная запись расположена после нескольких продолжений. Числа выбирают для удобства теста, а не как обещание производительности.
Проверьте одинаковые значения времени, пустую промежуточную страницу с продолжением, удаление объекта и изменение его статуса. В каждом случае заранее определите допустимый итог. Для живого списка и фиксированного снимка ответы могут различаться; тест должен проверять выбранную стратегию, а не абстрактное «всё работает».
Отдельные сценарии посвящают безопасности: курсор другого пользователя, другой организации, просроченный курсор, изменённый фильтр и отозванное право после первой страницы. Ещё один тест имитирует обрыв последнего запроса. Если система объявляет полноту только потому, что предыдущая страница была короткой, такой тест обнаружит ошибку.
На уровне агента задайте вопрос с проверяемым ответом: «найди обращение с уникальной меткой и назови его идентификатор». Затем дайте задачу, где нужна сумма или количество всего набора. Первый сценарий проверяет достижимость дальних страниц, второй — корректность агрегации. Оба нужны, потому что агент может найти одну запись и всё ещё неверно считать общий объём.
Встраивайте пагинацию в слой доступа
В архитектуре AI-агент → Codenik → корпоративная система границы доступа и контекст инструмента удобнее рассматривать вместе. Каталог должен показывать разрешённые возможности, а результаты — достаточно данных для задачи с понятным охватом. Codenik здесь выступает как управляемый слой доступа, а не как замена согласованности исходной базы.
При оценке интеграции проверьте, где фактически выполняется обход: в MCP-клиенте, адаптере или отдельном задании. Кто сохраняет курсор? Кто замечает отзыв прав? Кто сообщает модели о неполноте? Эти вопросы нужно проверить на пилоте; наличие шлюза само по себе не доказывает реализацию конкретной стратегии снимков или автоматического дочитывания.
Начните внедрение с одного инструмента и одного понятного отчёта. Сначала зафиксируйте контракт, затем сравните результат с контрольной выгрузкой, потом добавляйте конкурентные изменения. Увеличение каталога без такой проверки лишь переносит неясность на большее число интеграций.
Смежные аспекты разобраны в статьях про каталог инструментов MCP, ограничения и квоты и длительные задачи агентов. Пагинация соединяет эти вопросы: полный обход должен укладываться в бюджет и оставаться в пределах актуальных прав.
Разбор запуска: отчёт по обращениям поддержки
Допустим, руководитель просит составить список открытых обращений в двух проектах на начало рабочего дня. В учебном наборе есть несколько сотен записей, одинаковое время создания у части строк и обращения, закрывающиеся во время чтения. Задача агента — сгруппировать их по ответственным и выделить записи без следующего действия. Здесь полезно заранее разделить выборку и интерпретацию.
Первый этап выполняет адаптер: проверяет доступ к обоим проектам, фиксирует границу времени и создаёт идентификатор обхода. Если доступа ко второму проекту нет, результат сразу содержит ограничение. Не стоит сначала строить отчёт по одному проекту, а затем прятать отсутствие второго в общей фразе «данные актуальны на момент запроса».
Второй этап собирает страницы в пределах выбранного режима согласованности. Для оперативного обзора адаптер может фиксировать исходные идентификаторы, а карточки читать позже. Тогда он отдельно считает закрытые и удалённые записи. Для строгого отчёта сохраняют значения необходимых полей вместе со снимком. Выбор зависит от назначения отчёта: планирование работы допускает одну семантику, проверка исполнения обязательств может требовать другую.
Третий этап рассчитывает детерминированные показатели до обращения к модели: количество объектов по ответственным, число недоступных карточек и остаток необработанных страниц. Модель объясняет уже подготовленный набор. Ей не поручают одновременно держать курсор в памяти, считать уникальные идентификаторы и формулировать управленческие выводы. Такое разделение упрощает проверку и позволяет повторить расчёт без повторной генерации текста.
Предположим, последняя страница не ответила до истечения бюджета. Адаптер сохраняет промежуточный результат и возвращает состояние «обход не завершён». Руководитель видит предварительную группировку, но не получает заключение «обращений без действия нет». Для продолжения нужен действующий контекст доступа; если он истёк, запускают новый проход по явно указанной процедуре.
При расследовании команда сравнивает журнал обхода с контрольным набором. Если отсутствует только последний сегмент, вероятна ошибка продолжения или бюджета. Если пропуски распределены вокруг одинаковых дат, проверяют вторичный ключ сортировки. Если исчез целый проект, сначала проверяют права и фильтры. Такая диагностика связывает форму дефекта с конкретным уровнем интеграции и сокращает число случайных изменений настроек.
Что измерять после запуска
В журнал достаточно записывать идентификатор обхода, инструмент, версию схемы, номер шага, количество возвращённых объектов, время запроса и тип завершения. Полный курсор лучше не логировать: он может открывать продолжение или содержать внутреннюю информацию. Для сопоставления повторов используйте безопасный отпечаток, а доступ к журналу ограничьте отдельно.
Основной показатель — доля завершённых обходов среди начатых для конкретного сценария. Рядом нужны причины остановки: бюджет, сетевой сбой, изменение доступа, недействительный курсор и отказ источника. Одна средняя задержка инструмента скрывает ситуацию, когда быстрые первые страницы сочетаются с постоянно недоступными последними.
Следите за количеством объектов на проход и за изменением этого распределения. Резкое уменьшение может означать потерянный проект или новый фильтр, а рост — снятый лимит или ошибочную область запроса. Это повод проверить интеграцию, но не доказательство дефекта: бизнес-набор тоже меняется. Порог тревоги связывают с ожидаемым рабочим сценарием и подтверждают контрольным запросом.
После обновления SDK повторите тот же проверочный набор, который использовали при внедрении. Если каталог небольшой в production, ошибка автоматического обхода может долго оставаться незаметной. Искусственно многостраничный стенд сохраняет проверяемость механизма независимо от текущего размера компании и числа подключённых систем.
Частые вопросы о пагинации MCP
Нужно ли всегда загружать все инструменты? Если клиент строит полный каталог, он должен корректно пройти предусмотренные сервером страницы. Для контекста конкретной задачи можно выбирать подмножество разрешённых инструментов, но это уже отдельная стратегия обнаружения. Нельзя называть первую страницу осознанным выбором релевантных инструментов без соответствующей логики.
Можно ли определять конец по числу элементов? Только если это прямо гарантирует прикладной контракт. Для протокольного списка ориентируйтесь на документированный признак продолжения. Небольшая страница может возникнуть из-за фильтрации или ограничений ответа; её длина сама по себе не доказывает отсутствие следующей.
Стоит ли сохранять курсор в памяти агента? Для текущего прохода это техническое состояние, которое лучше держать в коде оркестратора. Переносить его между сессиями нельзя без явной поддержки прикладного механизма. В протокольной пагинации проверенной версии прямо указано не сохранять курсоры между сессиями.
Что делать, если права изменились посередине? Прекратить выдавать закрытые данные и явно отразить изменение охвата. Если нужен полный отчёт по первоначальным условиям, потребуется новый разрешённый запуск. Старое продолжение не даёт права закончить обход вопреки новой политике.
Как начать исправление существующей интеграции? Найдите один запрос, результат которого заведомо превышает страницу. Зафиксируйте ожидаемые идентификаторы, проследите продолжения и сравните покрытие. После этого проверьте отказ на чужом курсоре и обрыв последней страницы. Эти три эксперимента дают конкретную отправную точку для работы с полнотой, безопасностью и обработкой ошибок.
Источники
Материал проверен 22 октября 2026 года. Примеры архитектуры и процедуры — авторские рекомендации.