5.8.3.3. MCP-сервер (readonly)¶
Added in version 1.29.0-ms2.
Attention
Экспериментальная функциональность. Состав инструментов, поля их ответов и секция
конфигурации Configuration.Mcp могут измениться в следующих версиях без
сохранения совместимости. По умолчанию сервер закрыт: без секции <mcp> в
global3.config.xml действует политика default="deny", override="off", и агенту
не видна ни одна выборка. Для использования секцию нужно включить вручную
(см. Политика доступа агента к выборкам).
5.8.3.3.1. Обзор¶
Readonly MCP-сервер — реализация Model Context Protocol поверх сервера приложений Global3, дающая внешнему агенту (LLM-клиенту) доступ к прикладным выборкам (Selection) только на чтение. Сервер выступает MCP-сервером для агента-клиента: агент через свой MCP-транспорт вызывает инструменты (tools), которыми сервер публикует метаданные выборок для discovery и постраничное чтение их строк.
Ключевые свойства:
Протокол — JSON-RPC 2.0 поверх транспорта Streamable HTTP (без SSE-стрима).
Область (Этап 1, readonly-MVP) — discovery выборок, разрешённых агенту серверной политикой доступа, и headless-чтение их строк. Инструменты записи (
set_field,run_operation,commitи т.п.) намеренно исключены.Exclusive Session —
initializeсоздаёт монопольный серверный рабочий сеанс (по образцу сервиса es/pkg); каждый вызов инструмента исполняется под монопольным захватом сессии («один tool-call за раз»).Политика доступа — какие выборки видны агенту, определяет серверная политика в секции конфига
Configuration.Mcp(см. Политика доступа агента к выборкам).
Внешний путь эндпоинта — /app/sys/rest/es/mcp (см. Справочник URI эндпоинтов).
Attention
MCP-сервер поддерживается только на решениях PostgreSQL (база с секцией
eclipseLink в конфиге, режим соединений proxyShared). Oracle-режим
не поддерживается: там применяется другой контур работы с БД —
соединение захватывается на всё время жизни выборки, а курсор остаётся открытым
до её закрытия, поэтому долгоживущие открытые выборки MCP удерживали бы
соединения пула.
5.8.3.3.2. Подключение и транспорт¶
Адрес сервиса
http://{server:port}/app/sys/rest/es/mcp
Ресурс смонтирован Jersey-сервлетом /app/sys/rest/*; отдельной настройки
web.xml для MCP не требуется — контейнерная аутентификация уже покрывает эту зону.
5.8.3.3.2.1. HTTP-методы¶
Метод |
Назначение |
|---|---|
|
Единая точка входа: диспетчеризация конверта JSON-RPC 2.0
( |
|
Закрытие сессии по заголовку |
|
Не поддерживается: всегда |
Транспорт — Streamable HTTP: тело запроса и ответа несёт конверт JSON-RPC 2.0, SSE-стрим не используется.
5.8.3.3.2.2. Заголовки запроса¶
Заголовок |
Обяз. |
Значение |
|---|---|---|
|
да |
|
|
нет |
Алиас целевой БД/решения; при отсутствии берётся
|
|
для |
Идентификатор сессии, выданный сервером в ответе на |
|
нет |
Проверяется на НЕ- |
Note
Заголовок Database можно слать в любом регистре — сервер приводит имя
решения к верхнему регистру. Но для схемы Bearer claim sln внутри JWT
сверяется с нормализованным именем побайтно (регистрозависимо), поэтому имя
решения в самом токене должно быть уже в ВЕРХНЕМ регистре, иначе 401. См.
Аутентификация.
5.8.3.3.2.3. Версии протокола MCP¶
Версия по умолчанию — 2025-06-18. Поддерживаемый набор (от новой к старой):
2025-06-182025-03-26
Согласование: в initialize берётся params.protocolVersion, если он входит
в набор, иначе — дефолт; согласованная версия возвращается в result.protocolVersion.
На последующих запросах заголовок MCP-Protocol-Version, если присутствует,
должен принадлежать этому же набору, иначе ответ — 400 с JSON-RPC-ошибкой
Invalid Request.
5.8.3.3.2.4. Методы JSON-RPC и коды ответа¶
Диспетчер поддерживает ровно пять методов; прочие → METHOD_NOT_FOUND (-32601).
Метод |
Назначение и результат |
|---|---|
|
Запрос (обязан нести |
|
Нотификация (без |
|
Запрос. |
|
Запрос. |
|
Запрос. Требует валидный |
Код |
Условие |
|---|---|
|
Успешный JSON-RPC-ответ. Важно: протокольные ошибки JSON-RPC
( |
|
Принята нотификация (запрос без |
|
|
|
Единственный случай не-200 для JSON-RPC-ошибки: неподдерживаемая
|
|
Нет/невалидные учётные данные; ответ несёт |
|
|
|
|
|
Сервер в режиме обслуживания (пользователь не SYSTEM); тело text/plain. |
5.8.3.3.2.5. Порядок хендшейка¶
POST initialize(сAuthorizationиDatabase) →200; из заголовков ответа клиент запоминаетMcp-Session-Id, из тела —result.protocolVersion/serverInfo.POST notifications/initialized(безid) →202.Рабочие запросы:
tools/list(сессия не нужна),tools/call(обязателенMcp-Session-Id). Каждыйtools/callисполняется монопольно.POST ping— опциональная проверка живости эндпоинта. Сессию не продлевает (исполняется без неё), поэтому от закрытия по простою не спасает.DELETE(сMcp-Session-Id) →204; сессия и её открытые выборки закрываются каскадно.
5.8.3.3.2.6. Пример: initialize¶
curl -sS -D - "http://localhost:8080/app/sys/rest/es/mcp" \
-H "Authorization: Bearer $JWT" -H "Database: GSTEST" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}'
Ответ — HTTP 200, заголовок Mcp-Session-Id: <uuid>, тело:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {"tools": {"listChanged": false}},
"serverInfo": {"name": "Global3 AS MCP", "version": "1.29.0"}
}
}
Конфигурация MCP-клиента (Streamable HTTP):
{
"type": "http",
"url": "http://localhost:8080/app/sys/rest/es/mcp",
"headers": {"Authorization": "Bearer <jwt>", "Database": "GSTEST"}
}
5.8.3.3.3. Аутентификация¶
MCP-эндпоинт не содержит собственного кода логина: аутентификацию выполняет
транспортный слой (сервлет-фильтр), а ресурс дополнительно делает defense-in-depth
(проверяет режим обслуживания и наличие principal) и берёт готовый principal из
контейнера. Запрос без валидных учётных данных → 401 с
WWW-Authenticate: Bearer.
Эндпоинт принимает обе HTTP-схемы — Basic
и Bearer (один фильтр обслуживает обе;
источники учётных данных перебираются в порядке: cookie access_token →
заголовок Authorization → параметр access_token).
Выбор решения (алиас БД) резолвится единой цепочкой fallback: request-атрибут →
заголовок Database → request-параметр Database → defaultDatabaseAlias
из global3.config.xml. Прежде чем использовать, сервер нормализует имя решения
в UPPER-CASE.
Warning
Для схемы Bearer имя решения зашито в JWT как приватный claim sln и
сверяется с нормализованным (UPPER-CASE) значением побайтно. Поэтому токен,
выпущенный с решением в нижнем регистре (sln="gstest"), даёт 401 —
имя БД в токене должно совпадать с нормализованным, то есть быть в ВЕРХНЕМ
регистре (sln="GSTEST"). Токены, которые сервер выпускает сам после логина,
всегда несут уже заглавное имя решения; проблема воспроизводится для токенов,
собранных вне сервера.
Пример «сырого» запроса:
POST /app/sys/rest/es/mcp HTTP/1.1
Authorization: Bearer ast_<jwt...>
Database: GSTEST
MCP-Protocol-Version: 2025-06-18
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}
Полное описание типов аутентификации — Аутентификация в HTTP сервисах.
5.8.3.3.4. Сессия и её жизненный цикл¶
MCP-сессия — это серверный рабочий сеанс (Exclusive Session), создаваемый обработкой
метода initialize (только запрос с id; initialize без id сессию НЕ
создаёт). При создании сервер генерирует случайный UUID и возвращает его клиенту
в заголовке Mcp-Session-Id ответа. Внутренний ключ рабочего сеанса
детерминирован от тройки (db, user, mcpSessionId) (вид
MCP-{db}/{user}[mcp-{mcpSessionId}]); последующие tools/call и DELETE
реконструируют его из principal и заголовка Mcp-Session-Id. Сессия строго
привязана к тому же principal (db + user).
5.8.3.3.4.1. Открытые выборки¶
Инструмент open_selection открывает выборку в собственном рабочем контексте,
переживающем вызов, и регистрирует её в реестре сессии по handle (UUID),
возвращаемому агенту как sessionRef. Инструменты get_opened_meta/read_rows
резолвят выборку по sessionRef. Отдельного инструмента close_selection в
каталоге НЕТ — открытые выборки закрываются только вместе со всей сессией
(каскадно).
Что открытая выборка удерживает до закрытия сессии: сам объект выборки с
DataStore и прочитанными строками в памяти сервера, свой
WorkSessionContext и объект соединения движка. Физическое соединение с БД
при этом НЕ занимается: на PostgreSQL оно берётся из пула на время выполнения
запроса и сразу возвращается (короткая транзакция), серверный курсор между
вызовами не живёт — строки уже прочитаны в кэш выборки. Поэтому цена открытой
выборки измеряется памятью сервера, а не занятыми соединениями пула.
5.8.3.3.4.2. Когда сессия закрывается¶
Единый путь закрытия каскадно закрывает все открытые выборки сессии (а затем и их контексты). Триггеры:
Явный
DELETEсMcp-Session-Id→204. Закрытие идёт под монитором сессии: если параллельно исполняетсяtools/call,DELETEдождётся его завершения.Простой по таймауту. Если клиент разорвал HTTP без
DELETE, сессию закрывает фоновый поток-уборщикRestSession-Eviction(общий для всех Rest-сессий). Таймаут простоя — 15 минут, период обхода — тоже 15 минут, поэтому фактическая зачистка простаивающей сессии наступает через 15–30 минут после последней активности. Уборщик закрывает только ПРОСТАИВАЮЩИЕ просроченные сессии (не рвёт активныйtools/call).Остановка сервера (
contextDestroyed) — закрываются все Rest-сессии.
5.8.3.3.4.3. Лимиты¶
Лимит |
Значение |
Поведение при достижении |
|---|---|---|
Открытых выборок на сессию |
32 |
|
Живых MCP-сессий на пользователя |
8 |
|
Оба значения — константы кода (McpSessionAbst, McpRestServiceImpl);
конфигом они не настраиваются.
Note
Утечки выборок и их контекстов в штатных путях нет: каждый open_selection
завершается либо регистрацией в сессии (гарантированное каскадное закрытие),
либо немедленным закрытием на месте (при исчерпании лимита или гонке с закрытием
сессии). Брошенная клиентом сессия не живёт вечно — её закроет уборщик простоя
за 15–30 минут. Накопление сверху ограничено произведением лимитов (8 × 32).
5.8.3.3.5. Политика доступа агента к выборкам¶
Какие выборки доступны агенту, решает серверная политика — секция конфига
Configuration.Mcp файла global3.config.xml. Это отдельный слой
поверх обычной авторизации: даже успешно аутентифицированный агент видит через MCP
только разрешённые политикой выборки. Права самого пользователя политика не меняет
и строки данных не фильтрует — она сужает перечень выборок, которые агенту вообще
можно назвать.
Проверку проходит каждый инструмент, называющий выборку: find_selections
ищет только среди разрешённых имён, а адресные инструменты (включая
open_selection) отвергают выборку вне перечня ошибкой «Выборка ‘…’ не найдена
или недоступна для MCP-discovery».
5.8.3.3.5.1. Два атрибута и правило их чтения¶
Политика описывается элементом Configuration.Mcp.AgentAccess с двумя
атрибутами, и они не равноправны — у каждого своя роль:
Configuration.Mcp.AgentAccess.override— рубильник: переключает весь MCP-контур целиком, не трогая базовую политику. По умолчаниюoff— «не вмешиваться».Configuration.Mcp.AgentAccess.default— базовая политика: ответ сервера, когда рубильник отпущен. По умолчаниюdeny— «запрещено».
Отсюда правило чтения ровно в два шага:
Сервер смотрит
override. Любое значение, кромеoff, определяет исход само —defaultпри этом не читается вовсе.И только при
override="off"исход задаётdefault.
|
Агенту доступны |
Читается ли |
|---|---|---|
|
при |
да, это единственный такой режим |
|
все выборки |
нет |
|
ни одной выборки |
нет |
|
только перечисленные в |
нет |
«Все выборки» здесь — все существующие в решении (*.avm.xml). Открыть
несуществующее имя не даёт ни один режим: в list лишние имена перечня просто
ни на что не отображаются, а allowAll открывает ровно то, что в решении есть.
Attention
Конфигурация без секции <mcp> — равно как и пустой <agentAccess> —
означает override="off" плюс default="deny": внешний агент не видит
ни одной выборки, пока доступ не открыт явно (fail-closed).
Note
Двух атрибутов кажется много там, где исход почти всегда решает один. Они
отвечают за разное: default описывает намерение решения («в норме доступ
закрыт»), а override — рубильник поверх него.
Положения allowAll и denyAll при этом отладочные: они открывают или
закрывают контур целиком, не читая ни default, ни перечень
Configuration.Mcp.Selections, — место им на стендах разработки и
тестирования (allowAll стоит в dev-конфиге). Рабочий контур на Этапе 1
настраивают перечнем: default="deny" плюс override="list" — так
выглядит пример в шаблоне конфига дистрибутива.
5.8.3.3.5.2. Примеры XML-конфигурации¶
Режим list — рабочая настройка: агенту разрешены ровно перечисленные выборки:
<mcp>
<agentAccess default="deny" override="list"/>
<selections>
<selection name="Gs3_McpOrder"/>
<selection name="Gs3_McpCustomer"/>
</selections>
</mcp>
Режим allowAll — отладочный: агенту открыты все выборки решения. Так
публикует их dev-конфиг стенда разработки:
<mcp>
<agentAccess default="deny" override="allowAll"/>
</mcp>
Атрибут Configuration.Mcp.captionSearchLimit секции включает поиск выборок по заголовку в
find_selections (по умолчанию 0 — выключен, см. описание инструмента). Это
временная настройка для отладки и тестирования: она исчезнет, когда заголовки
выборок станут доступны дёшево через прикладной сервис индекса:
<mcp captionSearchLimit="-1">
<agentAccess default="deny" override="allowAll"/>
</mcp>
В обоих примерах default="deny" записан для явности намерения, но на исход не
влияет: рубильник переведён. Перечень допустимых значений обоих атрибутов — в
справочнике XSD: Configuration.Mcp.DefaultAccess и
Configuration.Mcp.OverrideMode.
5.8.3.3.6. Инструменты¶
Каталог публикует ровно 10 readonly-инструментов в стабильном порядке
регистрации. Все вызываются методом tools/call (params.name +
params.arguments); inputSchema каждого — JSON Schema draft-07.
5.8.3.3.6.1. Упаковка результата и ошибки¶
Результат любого инструмента — MCP-контент {content:[{type:"text",text}], isError};
полезная нагрузка лежит строкой JSON в content[0].text. Успех — isError:false.
Любая прикладная ошибка (неизвестный sessionRef, недоступная выборка, отсутствующий
обязательный аргумент, неизвестное имя инструмента) — НЕ протокольная ошибка
JSON-RPC, а нормальный result с isError:true и текстом сообщения. Протокольную
ошибку INVALID_PARAMS даёт лишь невалидный конверт вызова (отсутствующий/нестроковый
name).
Инструмент |
Группа |
Назначение |
|---|---|---|
|
|
Найти выборки по подстроке в имени/заголовке. |
|
|
Сквозной поиск операций/атрибутов/полей фильтра по подстроке. |
|
|
Узкие метаданные выборки: caption, description, представления (с caption/description/documentation), поля фильтра. |
|
|
Список атрибутов выборки. |
|
|
Статические метаданные одного атрибута. |
|
|
Список операций выборки (без служебных). |
|
|
Поля фильтра представления (ключи для |
|
|
Открыть выборку headless, вернуть |
|
|
Метаданные открытой выборки с наложенными настройками администрирования. |
|
|
Страница строк открытой выборки. |
Attention
Расхождение discovery ↔ open: инструменты группы A отдают статическое описание из
метаданных выборки, к которому ещё не применены настройки системы администрирования.
Поэтому в get_attribute_meta поля visible/readOnly приходят нейтральными
заглушками (жёстко true/false), а fieldType у прикладных сущностных
атрибутов — ftUnknown: реальный тип движок разворачивает лишь при активации
выборки. Значения, отражающие открытую выборку — с наложенными настройками
администрирования и развёрнутым типом поля, — даёт ТОЛЬКО get_opened_meta.
5.8.3.3.6.2. Группа A. Discovery без открытия выборки¶
Семь инструментов читают статические и рантайм-метаданные разрешённых агенту выборок
(политика доступа) без открытия выборки — каждый
работает под своим короткоживущим контекстом с соединением, освобождаемым по выходу
из вызова. Типичный
маршрут: find_selections → get_selection_meta →
list_attributes/list_operations/get_attribute_meta/get_filter_meta →
переход к open_selection.
5.8.3.3.6.2.1. find_selections¶
Назначение: найти доступные агенту выборки по подстроке в имени и, если включено настройкой, в заголовке.
Аргументы:
query(string, обязателен).Результат:
{selections:[{name, caption, module}], truncatedResults?, truncatedCaptionSearch?, note?}.caption— заголовок выборки из того же источника, что уget_selection_meta(представлениеDefault); при временной недоступности метаданных может быть заголовком загруженного представления.Ограничения/флаги: список усечён верхним пределом 200 результатов (
truncatedResults:true). Поиск по caption по умолчанию выключен: заголовок требует загрузки метаданных выборки (порядка 100 мс на выборку), и на широком allowlist первый поиск занял бы минуты. Его включает временный атрибутConfiguration.Mcp.captionSearchLimitсекции<mcp>:-1— проверять заголовки всех выборок, не совпавших по имени (первый поиск на образе решения грузит метаданные каждой, повторные берут заголовки из кеша сервера),N— первыеNпо алфавиту. Если заголовки части выборок не проверялись (поиск выключен, предел исчерпан или результат уже заполнен совпадениями по имени), ответ несётtruncatedCaptionSearch:true. Каждый флаг сопровождается человекочитаемымnote. При флаге клиент должен сузитьqueryили указать точное имя.Ошибки: пустой
query→ «Не задан обязательный аргумент ‘query’».
5.8.3.3.6.2.2. find_in_selection¶
Назначение: поиск операций и/или атрибутов (и полей фильтра) по подстроке — по всем доступным выборкам или в одной.
Аргументы:
query(string, обязателен);selection(string, опц.) — имя выборки;scope(string enum, опц.) — строгоoperation|attribute.Результат:
{matches:[{selection, kind, name, caption, description}], truncated?, note?};kind∈ {operation,attribute,filter} (filter— только когдаscopeне задан).Ограничения/флаги: без
selectionобход ограничен 200 просмотренными выборками, совпадений — не более 500; достижение любого лимита →truncated:true.Ошибки: пустой
query; недопустимыйscope→ «Недопустимый scope ‘…’. Допустимые значения: operation, attribute (или не задавать).»
5.8.3.3.6.2.3. get_selection_meta¶
Назначение: метаданные выборки —
caption,description(человекочитаемое описание выборки из<documentation>уровня view), представления (сcaption/description/documentation) и поля фильтра (список атрибутов НЕ возвращает — для негоlist_attributes).Аргументы:
name(string, обязателен).Результат:
{caption, description, representations:[{name, caption, description, documentation}], detailSelections:[string], filters:[{name, caption, fieldType, defaultValue, editorType}]}. Собственного заголовка у выборки нет, заголовки есть только у представлений, поэтомуcaptionвыборки — заголовок представленияDefault(его наследуют остальные представления); заголовки самих представлений — вrepresentations. Если уDefaultзаголовок не задан или слитые метаданные недоступны,caption— заголовок того представления, под которое загружена мета (обычноList). Ключи локализации ([#key]) в заголовках разрешены так же, как в метаданных выборки. Тексты представлений (caption/description/documentation) могут бытьnull, если соответствующий узел метаданных не заведён. Замечание:detailSelectionsлёгким путём не резолвятся — всегда пустой список.Ограничения: при недоступности живых метаданных деградирует до минимальной нагрузки (
captionравен имени,description=null,representationsи прочие списки пусты) без падения. Метаданные читаются под одним из представлений выборки: стандартнымList/Card/Lookupлибо тем, что класс выборки назначает черезdefList/defCard/defLookup. Выборка только с именованными представлениями и без такого назначения (например,Btk_Textсmemo/memo_Input) деградирует так же; открыть её можноopen_selectionс явнымrepresentation.Ошибки: пустой
name; выборка не разрешена политикой доступа.
5.8.3.3.6.2.4. list_attributes¶
Назначение: список атрибутов выборки (статические discovery-метаданные).
Аргументы:
name(string, обязателен).Результат:
{attributes:[{name, caption, description}]}.Ошибки: пустой
name; выборка не разрешена политикой доступа.
5.8.3.3.6.2.5. get_attribute_meta¶
Назначение: статические метаданные одного атрибута.
Аргументы:
name(string, обязателен) — имя выборки;attr(string, обязателен) — имя атрибута.Результат:
{name, caption, fieldType, visible, readOnly, required}.Ограничения:
visibleвсегдаtrue,readOnlyвсегдаfalse— заглушки, НЕ реальные права (см.get_opened_meta);fieldTypeчастоftUnknown.Ошибки: пустой
name/attr; атрибут не найден → «Атрибут ‘<attr>’ не найден в выборке ‘<name>’.»; выборка не разрешена политикой доступа.
5.8.3.3.6.2.6. list_operations¶
Назначение: список операций выборки (служебные исключены).
Аргументы:
name(string, обязателен).Результат:
{operations:[{name, caption, description}]}.Ошибки: пустой
name; выборка не разрешена политикой доступа.
5.8.3.3.6.2.7. get_filter_meta¶
Назначение: поля фильтра представления; их имена — КЛЮЧИ объекта
filterвopen_selection.Аргументы:
name(string, обязателен).Результат:
{filters:[{name, caption, fieldType, defaultValue, editorType}]}.Ограничения: при недоступности метаданных фильтра деградирует до пустого списка без падения. Для detail-представлений ключ мастера —
super$id.Ошибки: пустой
name; выборка не разрешена политикой доступа.
5.8.3.3.6.3. Группа B. Работа по открытой выборке¶
Три инструмента работают ТОЛЬКО по уже открытой выборке, адресуемой sessionRef.
Жизненный цикл и лимиты — см. Сессия и её жизненный цикл.
5.8.3.3.6.3.1. open_selection¶
Назначение: открыть выборку headless на чтение и вернуть
sessionRef.Аргументы:
name(string, обязателен);representation(string, опц.) — имя представления (по умолчанию основное);filter(object, опц.) — свободный объект имя_поля→значение (additionalProperties:true). Имена полейfilterберутся изget_filter_meta(напримерflt_dOrderDateFrom); для detail-представлений ключ мастера —super$id.Результат:
{sessionRef, name, representation}.Ограничения: регистрация в сессии с лимитом 32 открытых выборок; открытие выборки, не разрешённой политикой доступа, запрещено.
Ошибки: пустой
name; выборка не разрешена политикой доступа; превышение лимита 32; ошибка активации/сборки выборки (какisError, ресурсы освобождаются).
5.8.3.3.6.3.2. get_opened_meta¶
Назначение: прочитать метаданные открытой выборки — поля и операции с наложенными настройками системы администрирования.
Аргументы:
sessionRef(string, обязателен).Результат:
{name, representation, caption, attributes:[{name, caption, fieldType, visible, readOnly, required}], operations:[{name, caption, description, visible, enabled}]}. У атрибутовvisible/readOnly— значения системы администрирования (Attribute.isAdminVisible/isAdminReadOnly),fieldType— развёрнутый тип живой выборки. У операцийvisible/enabled— настройки администрирования вместе с прикладной логикой (isVisible() && isAdminVisible(),isEnabled() && isAdminEnabled()).Ошибки: пустой
sessionRef; неизвестный/закрытыйsessionRef→ «Неизвестный sessionRef: <ref>» / «Открытая выборка не найдена по ссылке ‘…’ (не открыта или уже закрыта).»
5.8.3.3.6.3.3. read_rows¶
Назначение: прочитать страницу строк открытой выборки. Фильтр задаётся ТОЛЬКО в
open_selection— повторная фильтрация не поддерживается.Аргументы:
sessionRef(string, обязателен);page(object, опц.) —{offset, limit}. По умолчаниюoffset=0,limit=100.Результат:
{columns:[string], rows:[{колонка→значение}], offset, loadedCount, allFetched}.Ограничения:
limitограничивается сверху значением 1000 (защита от вычитывания всей таблицы); отрицательныеoffset/limitнормализуются к 0; читается только запрошенная страница. Пагинация: увеличиватьoffset, покаallFetched=false;allFetched=trueозначает конец данных.Ошибки: пустой
sessionRef; неизвестныйsessionRef(те же два слоя, что уget_opened_meta).
5.8.3.3.7. Типовой сценарий¶
Discovery → открытие заказа → чтение строк → lookup клиента (на фикстурах
Gs3_McpOrder/Gs3_McpCustomer). Заголовки во всех запросах: Authorization,
Database, Content-Type: application/json, а для tools/call — ещё
Mcp-Session-Id (из ответа на initialize).
1. Найти выборку заказов (find_selections):
{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"find_selections","arguments":{"query":"Gs3_McpOrder"}}}
Ответ (нагрузка — строкой JSON в content[0].text):
{"jsonrpc":"2.0","id":3,"result":{
"content":[{"type":"text",
"text":"{\"selections\":[{\"name\":\"Gs3_McpOrder\",\"caption\":\"Заказы\",\"module\":\"gs3\"}]}"}],
"isError":false}}
2. Открыть выборку в списочном представлении (open_selection) — возвращает
sessionRef:
{"jsonrpc":"2.0","id":4,"method":"tools/call",
"params":{"name":"open_selection",
"arguments":{"name":"Gs3_McpOrder","representation":"List"}}}
{"jsonrpc":"2.0","id":4,"result":{
"content":[{"type":"text",
"text":"{\"sessionRef\":\"a1b2c3d4-...\",\"name\":\"Gs3_McpOrder\",\"representation\":\"List\"}"}],
"isError":false}}
3. Прочитать первую страницу строк (read_rows) по полученному sessionRef:
{"jsonrpc":"2.0","id":5,"method":"tools/call",
"params":{"name":"read_rows",
"arguments":{"sessionRef":"a1b2c3d4-...","page":{"offset":0,"limit":100}}}}
В ответе content[0].text несёт {columns, rows, offset, loadedCount, allFetched}.
Если allFetched=false — продолжать, увеличивая offset.
4. Lookup клиента: взять из строки заказа идентификатор клиента, открыть
Gs3_McpCustomer (шаг open_selection с filter по нужному полю, имена полей
берутся из get_filter_meta) и прочитать его строку через read_rows.
5. Завершить диалог — DELETE с Mcp-Session-Id → 204 (открытые
выборки закрываются каскадно).
5.8.3.3.8. За рамками Этапа 1¶
Этап 1 намеренно ограничен чтением и грубой серверной политикой доступа. Ниже перечислено то, чего в нём нет, — чтобы отсутствие не выглядело недоработкой.
Note
Состав и сроки следующего этапа не зафиксированы, имена настроек и аннотаций в этом разделе рабочие и могут измениться. Раздел описывает направление, а не принятые решения.
5.8.3.3.8.1. Запись¶
Инструментов записи (set_field, set_param, run_operation,
run_validate, commit) в каталоге нет. Дело не в правах и не в headless:
открытым остаётся вопрос транзакционной границы. insert/edit/установка
значений копят черновик в памяти DataStore, фиксация идёт отдельной операцией —
и между двумя вызовами инструментов агент может оставить наполовину заполненный
объект или частично зафиксированные данные. Этап записи начинается с прототипа
именно этой границы, а не с добавления инструментов.
5.8.3.3.8.2. Права: декларация на уровне выборки¶
Сегодня доступ агента задаётся только серверной секцией <mcp>: она одна на весь
контур и ничего не знает о конкретной выборке. Прорабатывается отдельная ось
«доступно агенту» — декларативная характеристика в самом прикладном коде: признак
на классе выборки плюс свойство операции, наследуемое от выборки по умолчанию.
Смысл оси в том, что права пользователя не отличают «человек осознанно нажал
кнопку» от «модель решила вызвать операцию», и решать это должен прикладной
разработчик, а не только администратор контура.
Когда декларации появятся, перечень доступного агенту переедет в код выборок, а серверная секция останется тем, чем она полезна на стенде, — переключателем контура целиком.
5.8.3.3.8.3. Описания для агента¶
Качество работы агента упирается в описания: у многих выборок description пуст,
а у атрибутов роль описания играет заголовок. Поэтому Этап 1 отдаёт ровно то, что
уже есть в коде — @Oper и заголовки avm/dvm. Отдельный слой описаний,
написанных специально для агента (в том числе примеры значений), в рантайм MCP не
загружается и остаётся предметом проработки.
See also
Справочник URI эндпоинтов — справочник URI (пункт
/es/mcp).Аутентификация в HTTP сервисах — типы HTTP-аутентификации (Basic/Bearer).
Прикладные пакеты — соседний сервис
es/pkgв режиме Exclusive Session.Configuration.Mcp— секция конфига с политикой доступа, а такжеConfiguration.Mcp.AgentAccess,Configuration.Mcp.AgentAccess.default,Configuration.Mcp.AgentAccess.override,Configuration.Mcp.Selections.