Перейти к содержимому
Elemctl
Русский
Esc
↑↓navigate↵open⌘Jpreview
На этой странице

MCP-сервер и редакторы

Работа с elemctl из ИИ-агента по MCP, плюс плагины и расширение VS Code.

MCP-сервер

Сервер отдаёт операции платформы как MCP-инструменты (транспорт stdio):

pip install "elemctl[mcp]"
claude mcp add elemctl -- elemctl mcp

Реквизиты подключения сервер берёт из тех же переменных ELEMENT_* / .env.

Инструменты

Инструмент Что делает
list_apps список приложений; удалённые скрыты, пока их не попросят (include_deleted), name фильтрует по подстроке имени на клиенте, status – по статусу целиком; в ответе счётчики и строка summary рядом с applications, brief (по умолчанию) оставляет от карточки id, имя, статус, uri и применённую версию
find_app найти приложение по точному имени: id и признак found; удалённые пропускаются, если не задан include_deleted
get_app карточка приложения: статус, uri, фактическая версия проекта; в applied-build – ветка и коммит сборки, на которой оно работает, из карточки сборки или из локального реестра загрузок
create_app создать приложение; по одному project_id источником берётся последняя сборка проекта. В ответе sign-in – способ войти; verify дожидается приложения и проверяет, на какой сборке оно правда работает
ensure_app создать приложение по имени, только если его ещё нет; существующее не пересоздаётся (created: false); verify проверяет, на какой сборке приложение правда работает
start_app запустить приложение
stop_app остановить приложение
delete_app удалить приложение. Отменить это нельзя: данные теряются, а пересозданное получит другой URL
list_app_tasks задачи приложений; app_id – необязательный фильтр
debug_info данные сессии отладки: debug-token и debug-address (нужна включённая отладка на сервере)
list_spaces список пространств
list_projects список проектов; name фильтрует по подстроке имени на клиенте, удалённые скрыты, пока не задан include_deleted; brief (по умолчанию) – id, имя, вид проекта, пространство, счётчик приложений, признак удаления
list_builds сборки проекта, свежие первыми; ответ – объект {total, shown, summary, builds}; limit (по умолчанию 10, 0 – все), brief (по умолчанию) оставляет ид, версии, дату, ветку и коммит и называет, откуда взяты ветка и коммит: из карточки или из локального реестра загрузок
get_build карточка одной сборки целиком; version – это версия сборки (1.0-42), ид тоже принимается и разрешается по перечню
build_assembly локально собрать архив .xasm/.xlib из исходников (к платформе не обращается)
inspect_assembly разобрать готовый архив: манифест, свойства проекта, подсистемы и глобальные типы с полными именами (локально)
deploy полный цикл из исходников с проверкой того, что сборка применилась; итог – поле ok, детали – problems и log; allow_data_loss пропускает то, что отклоняет сторож схемы (сужение, смену типа, снятый целиком справочник), как --allow-data-loss; сервер, который ещё стартует, инструмент пережидает не дольше server_start_timeout секунд (по умолчанию 900); необязательные expected_app_name / expected_app_uri отклоняют неверную цель до сборки
probe проверить компиляцию серверным компилятором, не трогая рабочее приложение; ошибки с файлом, строкой и колонкой, за собой убирает; с keep отчёт называет команду, которая уберёт оставленное
probe_cleanup убрать пробник, оставленный на стенде ключом keep или оборвавшейся уборкой, по его приложению: приложение, сборку пробника в его собственном проекте и проект, если в нём ничего не осталось; пробник со своими именем и версией узнаётся по локальному реестру загрузок, он же называет сборки, выкаченные в пробник; чужое приложение отклоняется; app_id может быть списком, и тогда пробники убираются по очереди, у каждого свой отчет, а отказ одного не останавливает остальных
apply_build применить загруженную сборку к приложению по её ид
verify_deploy проверить фактическое применение: задачи с ошибками, сверка примененной сборки (сборки расширения - по расширениям приложения), доступность uri
list_user_lists списки пользователей; name фильтрует по подстроке представления
configure_user_list самостоятельная регистрация и вход по паролю; без флагов только показывает состояние
list_app_users кто подключён к приложению: список пользователей, ид, представление, администратор ли и есть ли доступ по токену, со строкой итога; логина платформа здесь не отдаёт
token_access доступ пользователя к HTTP-сервисам приложения по токену – тот признак, без которого вызов получает 500 “Token access is denied”; показывает его, а с enabled переключает и перечитывает; пустой user – учётная запись, под которой работает elemctl; user может быть списком, и тогда у каждого пользователя своя запись, а сбой одного не останавливает остальных
export_app записать в файл сборку, на которой работает приложение; расширений, примененных в приложении, в архиве нет, их записывает export_extension; пустой output – текущий каталог сервера и имя {Имя} {Версия}.xasm; сервер без этого метода получает понятный отказ
export_extension записать в файл сборку расширения, примененного в приложении (Console API 2.1); extension – ид расширения, ид его проекта, имя или представление проекта, а промах называет расширения, которые в приложении есть; пустой output – текущий каталог сервера и имя {Имя} {Версия}.xasm; сервер без этого метода получает понятный отказ
list_branches список веток среды разработки; фильтры project_id и name необязательны
merge_branch принять изменения ветки среды разработки
debug_adapter путь к debug-адаптеру платформы из плагина; отсутствие плагина – это ответ (found: false), а не ошибка (локально)

Рядом с ними встают инструменты, которые приносят плагины, о них ниже.

Одним окружением дело не ограничено. У каждого инструмента, который обращается к платформе, есть необязательный env_file – путь к .env другого стенда. Так один сервер работает и с облаком, и с локальной установкой, а перезапускать его с другими реквизитами не нужно.

list_apps по умолчанию отдаёт краткие карточки: id, имя, статус, uri и применённую версию. Полные карточки пространства – это десятки тысяч символов в ответе агенту, за ними ходят с brief=false. Параметр name фильтрует по подстроке имени без учёта регистра и делает это на клиенте, потому что платформа query-параметр игнорирует. Параметр status фильтрует по статусу целиком. Удалённые приложения скрыты, пока их не попросят через include_deleted: на стенде, живущем не первый месяц, в перечне сотни карточек, из которых живых единицы. Молча ответ не режется. В нём лежат счётчики total (сколько карточек отдала платформа), live (сколько из них не удалено) и shown, готовая строка summary вида “живых 7 из 324”, а сами карточки – в applications.

list_projects ведёт себя так же и отдаёт id, имя, вид проекта, пространство, счётчик приложений и признак удаления. name у него тоже фильтрует по подстроке, а проекты с признаком удаления скрыты, пока не задан include_deleted: на стенде, живущем не первый месяц, их в перечне сотни против единиц живых.

list_builds тоже отвечает краткими карточками – ид, версии, дата, ветка, коммит – и десятью свежими сборками, пока limit не скажет иного; значение 0 снимает срез. Карточки лежат в builds, рядом с ними счётчики total (сколько сборок отдала платформа) и shown, а также строка summary. Перечень платформы – не вся история проекта: платформа сама удаляет сборки, которыми никто не пользуется, когда приложение проекта заканчивает применение сборки, и возраст тут ни при чем. Остаются сборка работающего приложения, сборка с наибольшим номером базы, релизная и загруженные без ид проекта, среди них первая сборка проекта. Страниц у перечня нет, и summary прямо говорит, что перед читателем остаток истории. Считает эта строка по фактам ответа: номера сборок одной базовой версии платформа выдаёт подряд, поэтому номер, которого в перечне нет, – это сборка, уже снятая уборкой, если это не скачок. Сборка, загруженная без ид проекта, сохраняет номер архива, и счет идет от него; пропуск под такой сборкой этой машины summary называет скачком, а не удалением. Пропуск, внутри которого есть загрузка этой машины в проект, – и скачок, и удаление сразу, и summary называет и то и другое. Проект-расширение уборка не трогает вовсе: его сборки остаются, пока их не удалят вручную, пропуск там и есть такое удаление, и summary так и говорит.

get_build отдаёт одну карточку целиком и адресуется версией сборки. Ид тоже принимается и находится по перечню, потому что адресом метод считает версию, а не ид карточки.

get_app, delete_app, start_app, stop_app и debug_info принимают ид приложения (UUID) либо его точное имя. Значение, не похожее на UUID, разрешается по списку. Несколько совпадений дают ошибку, а не догадку.

create_app и ensure_app добавляют к ответу поле sign-in – адрес и учётную запись, которой входят в только что созданное приложение. Запись эта от панели управления, учётные записи других приложений там не работают, а агент видит один только JSON. Параметр verify у обеих команд дожидается приложения и проверяет, что оно правда работает на запрошенной сборке: неудачное применение платформа откатывает молча, а созданное приложение раньше считали готовым на веру. Отчёт попадает в поле verify ответа. Ожидание стоит минут, поэтому такой вызов лучше запускать фоновой командой elemctl. Оборванное ожидание приложение не теряет: ответ сохраняет его ид, а поле wait-error говорит, что оборвалось.

version_id до создания ищется в перечне сборок проекта. Проект – project_id, а при пустом параметре – ELEMENT_PROJECT_ID стенда. Сборку, которой в этом проекте нет, инструмент ищет в других проектах стенда: сборка, загруженная без ид проекта, лежит в проекте, который ей выбрал сервер. Проект стенда уступает проекту сборки, а явный project_id получает отказ, который называет проект, где сборка лежит. Сборку, которой нет ни в одном проекте, инструмент отвергает до создания: платформа удаляет сборки, которыми никто не пользуется, и на создание из удаленной сборки отвечает голым 400. Отказ называет эту причину и сборку, на которой работает приложение проекта.

Плагины

elemctl подхватывает внешние пакеты через точки расширения importlib.metadata. В своём pyproject.toml он о плагинах ничего не объявляет и читает их при обращении. Так непубликуемые вендорские артефакты живут отдельным пакетом, а ядро elemctl остаётся чистым и общедоступным.

elemctl.debug_adapter: пакет-плагин объявляет каталог debug-адаптера платформы. Это проприетарные jar 1С, в состав elemctl они не входят. Значением точки расширения бывает путь либо функция без аргументов, возвращающая путь. Путь указывает на каталог с подкаталогом repo/, где и лежат jar-файлы адаптера.

elemctl.commands: пакет-плагин приносит собственные команды. Значением точки расширения бывает Command, их список либо функция без аргументов, возвращающая одно из двух. Одного объявления хватает на обе поверхности: elemctl строит по нему подкоманду CLI и инструмент MCP с настоящей схемой, а о том, что команда делает, ничего не знает. Там и место команде, которая знает про ваше окружение: внутренние контуры, смежные системы, ваши стенды. В публичном ядре такой команде жить нельзя.

# pyproject.toml пакета-плагина
[project.entry-points."elemctl.debug_adapter"]
имя = "мой_пакет:adapter_root"     # () -> Path на каталог, содержащий repo/

[project.entry-points."elemctl.commands"]
имя = "мой_пакет.commands:commands"   # () -> list[Command]
# мой_пакет/commands.py
from elemctl.plugins import Argument, Command

def warm_up(context, stand="", force=False):
    context.log(f"прогреваем {stand}")          # прогресс: stderr в CLI, поле log в MCP
    # context.surface называет, кто позвал: "cli" или "mcp"
    card = context.client.get_app(stand)        # клиент строится при первом обращении
    return {"ok": True, "status": card.get("status")}

def commands():
    return [Command(
        name="warm-up",
        help="открыть админку свежего стенда",
        handler=warm_up,
        arguments=[Argument("--stand", help="приложение"), Argument("--force", type=bool)],
    )]

Результат обработчика обязан быть JSON-сериализуемым: CLI его печатает, инструмент MCP возвращает. Из результата CLI берёт и код возврата. Целое от 0 до 255 в поле exit-code становится кодом возврата как есть, и команда с тремя исходами отдаёт сценарию “различий нет”, “есть различия” и “сбой шага” кодами 0, 1 и 2. Без этого поля словарь с "ok": false завершается кодом 1, по тому же соглашению, что у отчётов deploy и probe. Когда поле расходится с ok, решает поле. Строку, true или 300 CLI кодом не считает и смотрит на ok. Инструмент MCP возвращает поле вместе с остальным результатом. Вызывать sys.exit в обработчике ради кода нельзя: та же функция работает внутри сервера MCP, где вызов остался бы без ответа, а сервер остановился бы. Типы аргументов – str, int, float и bool для флага. Поле env_file к инструменту MCP добавляет сам elemctl, поэтому команда плагина дотягивается до других окружений так же, как инструменты ядра. Занять имя, которое уже есть у ядра, команда не может: такая команда остаётся за бортом. За бортом остаётся и плагин, который не загрузился, например написанный под более новое ядро. elemctl называет такие плагины в stderr и в elemctl plugins и работает с остальными.

Поле context.surface говорит, откуда пришел вызов: "cli" у подкоманды и "mcp" у инструмента. Команда, которая отвечает на двух поверхностях по-разному, например кратко в инструменте и целиком в терминале, берет ответ оттуда, а не угадывает по поведению context.log. В старом ядре такого атрибута нет, поэтому читайте его как getattr(context, "surface", None).

Позиционный аргумент может завести синоним-ключ, который действует только в CLI: Argument("page", cli_alias="--page") принимает и elemctl wiki-get 123, и elemctl wiki-get --page 123. Схема инструмента MCP от этого не меняется – у неё как был, так и остаётся один параметр page: cli_alias меняет только то, что принимает разборщик CLI, и никак не затрагивает объявленные аргументы. Обе формы взаимно исключают друг друга: разборщик отказывает и при обеих сразу, и при отсутствии обеих у обязательного аргумента. Плагин, не объявивший cli_alias, ведёт себя как раньше.

Опция может принимать несколько значений: Argument("--file", multiple=True) принимает elemctl wiki-attach --file a.png --file b.png, и обработчик получает ["a.png", "b.png"] в порядке командной строки. Без ключа он получает объявленное умолчание списком либо []. Инструмент MCP получает параметр-массив объявленного типа. Опция без multiple принимает одно значение, и повтор с другим значением CLI отвергает, как у любого ключа с одним значением. Объявляйте multiple там, где пользователь повторит ключ. Флаг повторяемым быть не может, а умолчание повторяемого аргумента – список или None. В старом ядре такого поля нет, и плагин остается за бортом целиком, поэтому плагин, которому приходится работать с обоими ядрами, сначала проверяет hasattr(Argument, "multiple").

Несколько значений может принимать и позиционный аргумент: Argument("page", multiple=True, cli_alias="--page") принимает и elemctl wiki-get 123 456, и elemctl wiki-get --page 123 --page 456, а обработчик в обоих случаях получает ["123", "456"]. Формы по-прежнему исключают друг друга, так что значения одного вызова приходят из одной формы. С required=True аргументу нужно хотя бы одно значение, а необязательный без значений передает объявленное умолчание списком либо []. Инструмент MCP получает тот же параметр-массив, что и у опции, а второго параметра для ключа у него нет. Старое ядро, которое уже знает multiple, принимает его только у опции: повторяемый позиционный аргумент там – PluginError, и плагин остается за бортом целиком. Проверка hasattr(Argument, "multiple") на таком ядре тоже проходит, поэтому плагин, которому приходится работать с обоими ядрами, читает признак из elemctl.plugins: getattr(plugins, "POSITIONAL_MULTIPLE", False) истинен только там, где позиционный аргумент может быть повторяемым.

# путь к адаптеру от установленного плагина (для расширения VS Code):
# {"path": "...", "found": true} либо {"path": null, "found": false}
elemctl debug-adapter

# что приносят плагины - каталоги адаптера и команды
elemctl plugins

Сам адаптер, те самые проприетарные jar 1С, достаёт из дистрибутива платформы скрипт tools/extract_adapter.py. Полученный каталог потом указывают вручную в xbsl.debug.adapterPath либо собирают из него пакет-плагин. В дистрибутив пакета скрипт не входит.

Обнаружение плагинов отключает переменная ELEMCTL_NO_PLUGINS=1: тогда работают только штатные возможности ядра.

VS Code

С редактором elemctl связывает расширение-спутник:

  • XBSL (проект xbsl) – подсветка, линтер, конструктор форм и дерево метаданных. Кнопка XBSL: деплой на стенд запускает elemctl deploy терминальной задачей и проверяет применение. Там же отладка приложений 1С:Элемента штатным DAP-адаптером платформы, данные сессии для которой даёт elemctl apps debug. Раньше отладка была отдельным расширением XBSL Debug в репозитории elemctl. С версии XBSL 0.57 она часть одного расширения, а в репозитории осталась только сторона elemctl.

Оно публикуется и в Open VSX.

Последнее обновление 7 октября 2026 г.

Эта страница была полезной?