odata1c-gate
Локальный MCP-шлюз между Claude Code и стандартным OData-интерфейсом 1С:Предприятие 8.3.
Модель получает доступ к данным базы — справочникам, документам, регистрам, — но между ней и 1С
стоит гейт псевдонимизации: реквизиты (ИНН, счета, паспорта, телефоны) и, на выбранном уровне,
названия организаций и ФИО заменяются токенами вида [[type:tail]] до того, как данные увидит
модель. Обратная подмена происходит только внутри шлюза, перед отправкой запроса в 1С.
Один пользователь, одна машина, несколько сессий агентов одновременно, несколько баз 1С. Клиент — Claude Code (другие клиенты MCP работают иначе, см. раздел «Ограничения» ниже и docs/install.md).
Зачем это
Дать модели читать рабочую базу 1С — значит отдать ей персональные данные и коммерческую тайну: ИНН контрагентов, расчётные счета, телефоны и адреса физических лиц, названия клиентов. Обезличивать выгрузку заранее не всегда удобно (модель должна видеть свежие данные и уметь дозапрашивать их при необходимости), а инструктировать модель «не показывай ИНН» бессмысленно: инструкция — не механизм, да и провайдер модели всё равно увидит даже то, что не было «показано» пользователю.
Шлюз решает это подменой на границе: модель работает с живой базой, но защищаемые значения
заменяются токенами до того, как попадут в её контекст. Токен детерминирован (одно значение — один
токен), поэтому по нему можно отбирать, связывать записи и вести разговор, не зная исходного
значения. Разработчик, который читает ответы модели, видит [[inn:M4T2Q9XZ7K]], а не ИНН — и при
необходимости раскрывает его сам, командой в терминале, мимо модели.
Что видит модель, а что нет
Что уходит модели. Структура базы (сущности, поля, ключи, навигация) и данные, прошедшие
гейт. Номера и даты документов, суммы, количества, коды, GUID, значения перечислений не
защищаются ни на одном уровне — без них работа с базой теряет смысл. Названия организаций и ФИО
(классы org и person) и защищаемые реквизиты — ИНН, КПП, ОГРН, счета, БИК, карты, СНИЛС,
документы, телефоны, почта, даты рождения, адреса — приходят токенами [[type:tail]] по правилам
политики базы. Уровень задаётся на базу: off — гейт выключен, identifiers — реквизиты,
identifiers+names — реквизиты плюс названия и ФИО.
Что не уходит никогда. Реальные значения защищаемых классов не выходят через MCP ни в одном
ответе: ни в данных, ни в текстах ошибок 1С, ни в превью записи, ни в журнале, ни в
odata1c_raw_get, ни в вопросах подтверждения. Это инвариант, а не тест: последний проход по
готовому ответу делает страж утечек — он ищет в сериализованном ответе известные словарю значения
и заменяет их токенами, если что-то прошло мимо гейта. Учётные данные 1С модель не получает:
пароль не покидает домашнего каталога вовсе, имя пользователя 1С не попадает ни в один ответ, а
адрес публикации базы не возвращает ни один тул. О самой базе модель узнаёт ровно то, что
перечисляет odata1c_bases: имя, подпись, роль, уровень гейта, разрешена ли запись, состояние
индекса (собран ли, когда, сколько сущностей) и конфигурацию 1С, к которой база отнесена.
Единственное исключение по адресу — текст сетевого сбоя, в который его может вписать HTTP-клиент.
Хук плагина вдобавок запрещает модели читать файлы домашнего каталога шлюза. Раскрыть токен может
только владелец машины, командой odata1c reveal в своём терминале.
Кто подтверждает запись. Тулы записи ничего не пишут в 1С: они готовят операцию, показывают
превью в токенах и возвращают pending_id. Выполняет её отдельный вызов odata1c_commit, и
только после подтверждения человека механизмом клиента — в Claude Code это диалог разрешения,
у клиентов с elicitation — вопрос шлюза. Реплика «да» в чате подтверждением не считается: модель
не может подтвердить запись сама себе. Каждая выполненная запись попадает в локальный журнал и
откатывается тулом odata1c_undo. Записи в базах с ролью prod по умолчанию нет вовсе, а состав
разрешённого сужается флагами разрешений в настройках базы.
Установка
Нужны uv (сам поставит подходящий Python) и Claude Code. Дальше
три команды в терминале:
claude plugin marketplace add Romandredan/odata1c-gate
claude plugin install odata1c@odata1c-gate
uv tool install odata1c-gate
Первые две ставят плагин Claude Code: MCP-сервер шлюза, четыре навыка, хук подтверждения записи и
агента-следователя. Версия пакета закреплена в plugin/.mcp.json, поэтому claude plugin update odata1c обновляет и плагин, и шлюз.
Третья ставит отдельно командную строку — она нужна владельцу базы, а не модели (описать базу,
собрать индекс, раскрыть токен, править политику гейта). После неё команда odata1c доступна в
терминале; без установки то же самое запускается как uvx --from odata1c-gate odata1c <команда>.
Подробности, Linux, обновление и разбор типовых сбоев — docs/install.md.
Сразу после установки
Откройте Claude Code и скажите: «подключи базу 1С». Навык odata1c-setup спросит, как назвать
базу и какая у неё роль, и даст одну команду для вашего терминала. Команда запросит адрес
публикации, пользователя 1С и пароль. Пароль вводится только там, модель его не видит. После
этого Claude сам построит индекс метаданных, проверит, что база отвечает, и расскажет, что в ней
защищено.
То же самое можно сделать вручную:
odata1c base add ut_test --role test --recipes ut # спросит адрес, подпись, пользователя, пароль
odata1c reindex ut_test # построить индекс метаданных
Первая команда сама создаёт домашний каталог шлюза, отдельный odata1c init не нужен. Если что-то
не работает, odata1c doctor покажет, где именно: uv, настройки, базы, шлюз, Claude Code.
Адрес базы — это адрес публикации OData 1С, он оканчивается на /odata/standard.odata/
(например https://server/base/odata/standard.odata/). Пользователь 1С заводится
отдельный, с правами только на то, что нужно читать, — например odata_user. Пароль вводится в
терминале и на экране не отображается; он ложится в bases.yaml домашнего каталога открытым
текстом под правами владельца — сознательное решение: файл не покидает диск владельца, это не
сетевой секрет.
Роль базы задаёт умолчания записи и гейта:
| Роль | Уровень гейта | Запись | Проведение документов | Пометка удаления | Удаление записей независимых регистров | Лимит коммитов за 10 минут |
|---|---|---|---|---|---|---|
prod |
identifiers+names |
нет | да | да | нет | 20 |
test |
identifiers |
да | да | да | нет | 50 |
dev |
off |
да | да | да | да | без лимита |
Роль — только набор умолчаний: любое поле записи базы его перекрывает (например, role: prod +
write: true — боевая база с разрешённой записью). Флаги записи из последних четырёх столбцов
действуют, только когда запись включена (write: true) — у базы без записи они значения не имеют.
Уровень гейта: off — гейт выключен, модель видит значения как в 1С; identifiers — реквизиты
(ИНН, счета, телефоны и подобные) идут токенами, названия и ФИО открыты; identifiers+names —
вдобавок названия организаций и ФИО тоже токенами. Готовая запись базы выглядит так (адрес,
пользователь и пароль — плейсхолдеры):
bases:
ut_test:
label: УТ 11, тестовая
url: https://server/base/odata/standard.odata/
user: odata_user
password: qwerty123
role: test
config: ut
Файлы настроек
Все настройки шлюза хранятся в домашнем каталоге ~/.claude/odata1c/. Создавать эти файлы
вручную не нужно: каждый появляется при выполнении соответствующей команды и уже содержит
закомментированный образец всех допустимых полей с пояснениями. Те же образцы лежат в репозитории,
в каталоге src/odata1c/templates/, и по ним удобно заранее посмотреть, что и как настраивается.
| Файл в домашнем каталоге | Что в нём настраивается | Когда создаётся | Образец в репозитории |
|---|---|---|---|
bases.yaml |
перечень баз: адрес публикации, пользователь и пароль 1С, подпись, роль, уровень защиты, разрешения на запись | odata1c init или первый запуск шлюза; записи добавляет odata1c base add |
bases.example.yaml |
daemon.yaml |
порт шлюза, лимиты, поведение с клиентами, которые не умеют подтверждать запись | odata1c init или первый запуск шлюза |
daemon.example.yaml |
bases/<база>/policy.yaml |
что именно скрывать в этой базе: скрытые сущности, открытые поля, собственные классы защиты | odata1c base add |
policy.example.yaml |
bases/<база>/recipes.yaml |
рецепты этой базы | odata1c base add с ключом --recipes |
recipes/ut.yaml |
recipes/<конфигурация>/<имя>.yaml |
библиотека рецептов, общая для баз одной конфигурации | сохранением рецепта в разговоре с моделью | пример в разделе «Рецепты» |
Чаще всего правится bases.yaml. В записи базы меняют подпись (label), по которой модель
выбирает базу, роль (role), разрешение записи (write), уровень защиты (gate.mode), состав
разрешённых операций (permissions) и конфигурацию 1С (config), от которой зависит библиотека
рецептов. Изменения в bases.yaml и policy.yaml действуют со следующего запроса модели,
перезапуск шлюза не требуется. Политику защиты надёжнее менять не в редакторе, а командами
odata1c policy: они проверяют имена сущностей и полей по метаданным базы.
Остальное содержимое домашнего каталога служебное, и править его не следует. Это
policy.auto.yaml (разметка защищаемых полей, которую шлюз строит сам по метаданным базы),
launcher.key, файлы *.sqlite (индекс метаданных, словарь токенов, журнал записей) и каталог
logs/.
Файл правит владелец, не модель. Модель его штатно не читает и не правит — хук плагина
PreToolUse перехватывает такие обращения к домашнему каталогу шлюза и требует решения человека.
Это дополнительная защита, а не единственная: реальные значения не выходят через MCP ни при каком
обращении, а пароль 1С модели попросту не нужен — этого достаточно, даже если бы хука не было.
Базу заводит владелец сам, в своём терминале — просить модель «пропиши базу» бессмысленно, у неё
нет для этого инструмента. Подробнее — docs/install.md.
Первый реиндекс долгий: у типовой УТ $metadata — это около 17 МБ описания и больше семи тысяч
сущностей. Дальше индекс пересобирается, только если у публикации изменилась контрольная сумма
$metadata.
Теперь можно спрашивать в Claude Code:
- «какие базы 1С мне доступны?» — модель вызовет
odata1c_bases; - «найди справочник контрагентов и покажи состав его полей» —
odata1c_find_entity, затемodata1c_describe_entityс классами гейта у каждого поля; - «возьми любого контрагента и покажи его пять последних заказов клиента» —
odata1c_query; название контрагента придёт токеном, номера и суммы документов — как есть.
Что модель видит и в каком порядке ходит — навык odata1c из плагина; справочные темы об
устройстве OData 1С, токенах, политике и протоколе записи — тул odata1c_info.
Что внутри
Два процесса из одного пакета: демон (odata1c daemon) — единственный на машину, держит
соединения с базами, индекс, словарь и журнал, отвечает по MCP Streamable HTTP на
127.0.0.1:7171; лаунчер (odata1c mcp) — тонкий stdio-процесс на сессию, который поднимает
демон при необходимости и проксирует ему вызовы. Собственной логики у лаунчера нет.
Тулы чтения
| Тул | Что делает | Когда нужен |
|---|---|---|
odata1c_bases |
список видимых баз: подпись, роль, уровень гейта, статус индекса | в начале новой сессии — узнать, какие базы доступны |
odata1c_find_entity |
нечёткий поиск справочника, документа или регистра по названию | когда точное имя сущности неизвестно |
odata1c_describe_entity |
состав полей сущности: типы, ключи, связи, классы гейта | перед выборкой — чтобы выбрать нужные поля |
odata1c_query |
выборка записей сущности: отбор, сортировка, страницы | основной способ читать данные — списки, поиск, фильтры |
odata1c_get |
один объект по ключу | когда ключ объекта уже известен |
odata1c_info |
справочник по устройству OData 1С и самого шлюза, по темам | разобраться в токенах, политике, порядке записи |
odata1c_reindex |
обновить индекс метаданных базы | 1С отвечает «сущность не найдена» на объект, который точно есть, или после обновления конфигурации |
odata1c_raw_get |
произвольный запрос по пути публикации | когда query и get не выражают нужное обращение |
odata1c_recipe |
список готовых запросов базы или выполнение одного из них | вместо того чтобы собирать сложную выборку (остатки, задолженность) вручную |
Тулы записи
Пишущие тулы ничего не пишут сами: каждый готовит операцию и показывает превью в токенах. В 1С
пишет только odata1c_commit — и только после подтверждения пользователя. Любую выполненную
запись можно откатить тулом odata1c_undo.
| Тул | Что делает | Когда нужен |
|---|---|---|
odata1c_create |
подготовить создание объекта — справочника или документа | завести новую запись в базе |
odata1c_update |
подготовить изменение полей существующего объекта | поправить значения по ключу |
odata1c_mark_for_deletion |
подготовить пометку удаления (или её снятие) | «удалить» объект — в 1С это всегда пометка, не физическое удаление |
odata1c_delete_record |
подготовить физическое удаление записи независимого регистра сведений | единственный тул с настоящим удалением — только для регистров без регистратора |
odata1c_action |
подготовить проведение или отмену проведения документа | провести или распровести документ |
odata1c_commit |
выполнить подготовленную операцию в 1С | после того как пользователь увидел превью и подтвердил запись |
odata1c_undo |
подготовить откат уже выполненной записи | отменить результат коммита — по его commit_id |
odata1c_journal |
последние выполненные записи с исходом и способом подтверждения | посмотреть историю записи или найти commit_id для отката |
Командная строка
Команды odata1c — для владельца машины, не для модели. Общий ключ --home <путь> (или
переменная окружения ODATA1C_HOME) у любой команды меняет домашний каталог шлюза.
Базы
| Команда | Что делает |
|---|---|
odata1c init |
создать домашний каталог и шаблоны настроек |
odata1c base add <имя> [--role prod|test|dev] [--recipes ut|bp|zup] |
добавить базу — адрес, подпись, пользователя и пароль спросит сама |
odata1c base import <путь> |
перенести базы из env-файла прежнего сервера |
odata1c base list |
список описанных баз |
odata1c base test <имя> |
проверить соединение с базой |
odata1c reindex <имя> [--force] |
обновить индекс метаданных базы |
Политика гейта
| Команда | Что делает |
|---|---|
odata1c policy show <имя> |
показать действующую политику базы |
odata1c policy check <имя> |
проверить файл владельца по индексу |
odata1c policy hide <имя> <сущность> [--yes] |
скрыть сущность целиком, вместе с дочерними |
odata1c policy open <имя> <Сущность.Поле> |
открыть поле (класс keep) |
odata1c policy set <имя> <Сущность.Поле> <класс> |
назначить полю класс защиты |
Рецепты
| Команда | Что делает |
|---|---|
odata1c recipe check <config> |
проверить библиотеку рецептов конфигурации |
odata1c recipe list <имя> |
список рецептов базы с источником каждого |
Служебные
| Команда | Что делает |
|---|---|
odata1c doctor [--online] |
проверка окружения: Python, uv, дом, базы, индекс, демон, Claude Code (--online — ещё и соединение с базами) |
odata1c daemon [--foreground] |
запустить демон вручную (обычно его поднимает лаунчер сам) |
odata1c daemon stop |
остановить демон |
odata1c mcp [--bases ...] [--default ...] [--url ...] |
лаунчер — то, что прописывается в .mcp.json; руками обычно не вызывается |
odata1c reveal <токен> [--base ...] [--field ...] |
реальное значение токена — только для владельца, в терминале |
odata1c --version |
версия пакета |
Рецепты
Рецепт — это заранее составленный и проверенный запрос к базе, которому дано имя и у которого объявлены параметры. Остатки товаров на складе, задолженность покупателей, выручка за период: всё это типовые вопросы, и ответ на каждый из них в 1С требует знать, в каком регистре лежат данные, как называется его виртуальная таблица и какие у неё поля. Рецепт хранит это знание в готовом виде.
Без рецептов модель каждый раз заново исследует структуру базы и собирает запрос с нуля. Это занимает несколько обращений к 1С и не защищает от ошибки в имени регистра или поля. С рецептом тот же вопрос решается одним вызовом, и каждый раз одинаково, потому что запрос уже сверен с метаданными конфигурации.
От пользователя рецепты ничего не требуют. Достаточно спросить обычными словами, например
«покажи остатки по основному складу на сегодня». Модель запрашивает у шлюза перечень рецептов
базы, выбирает подходящий и выполняет его со своими параметрами, в этом примере с датой и
складом. Для этого служит один инструмент, odata1c_recipe: вызов без имени возвращает перечень
с описаниями и параметрами, вызов с именем выполняет рецепт.
Рецепты собираются из трёх источников. Если имя встречается в нескольких, действует рецепт из источника, который стоит в списке выше.
- Рецепты базы лежат в файле
bases/<база>/recipes.yamlи действуют только для неё. Здесь уместны запросы, которые учитывают доработки конкретной базы. - Библиотека конфигурации лежит в каталоге
~/.claude/odata1c/recipes/<конфигурация>/, по одному файлу на рецепт, и общая для всех баз этой конфигурации. К какой конфигурации относится база, определяет полеconfigв её настройках:ut,bp,zupили собственное обозначение. - Стартовый набор из поставки копируется в базу ключом
--recipesкомандыodata1c base add. Сейчас он заполнен для «Управления торговлей».
Библиотека пополняется в ходе обычной работы. Когда запрос, найденный в разговоре, дал нужный
результат и пригодится снова, достаточно попросить модель сохранить его как рецепт. Навык плагина
odata1c-recipe заменит конкретные значения параметрами и запишет файл в библиотеку конфигурации.
Команда odata1c recipe check <конфигурация> сверяет рецепты библиотеки с метаданными базы, а
odata1c recipe list <база> показывает все рецепты базы с указанием источника каждого.
Рецепт записывается обычным файлом YAML. В нём есть описание, сущность 1С, параметры и сам запрос. Данных базы в нём нет: ни значений, ни токенов.
title: Остатки по складу
description: Количество в наличии на указанный момент.
entity: AccumulationRegister_ТоварыНаСкладах_Balance
params:
period: { type: datetime, required: true, description: момент остатков }
warehouse: { type: guid, required: false, description: Ref_Key склада }
virtual:
Period: "{period}"
Condition:
- Склад_Key eq {warehouse}
select: [Номенклатура_Key, ВНаличииBalance]
filter: ВНаличииBalance gt 0
top: 200
Библиотека задумана как растущая: чем дольше шлюз работает с базой, тем больше вопросов решается одним вызовом. В планах поставлять наборы рецептов для типовых конфигураций вместе с плагином и обновлять их вместе с ним.
Ограничения
- Физического удаления объектов нет. «Удаление» для объектов и подчинённых регистров — только
пометка удаления (
DeletionMark = true). Из тулов записи физически удаляет толькоodata1c_delete_record, и только записи независимых регистров сведений. - Через
odata1c_updateнельзя вписать открытым текстом телефон, почту, адрес или дату рождения — только токеном или при создании объекта (odata1c_create): иначе ответ «изменений нет» позволял бы подбирать чужие данные перебором значений. - Сокращённое название в свободном тексте проходит открытым. Словарь знает полные написания названия; если в комментарии документа человек написал узнаваемое сокращение, которого нет в справочнике, гейт его не заменит. Ловить «ядро» названия отвергнуто: ядра — обычные слова, их замена портила бы данные ложными срабатываниями.
- Аутентификации у демона нет. Он слушает только
127.0.0.1; модель угроз — диск и машина владельца. Публикации по сети с аутентификацией и TLS пока нет. - Записи в регистры, подчинённые регистратору, нет ни при каком разрешении: их пишет проведение документа, а не прямая запись.
- Шаблоны рецептов заполнены только для УТ. Для БП и ЗУП шаблоны пока пустые: базы для сверки имён нет, а невыверенный рецепт хуже пустого.
- Проверен шлюз только с Claude Code. Другие клиенты MCP по stdio (Cursor, VS Code, Claude
Desktop) подключаются и читают; там, где нет диалога разрешения Claude Code или elicitation,
запись по умолчанию выключена (
write_confirm_fallback: deny). Навыки, хук и агент — часть плагина Claude Code, в других клиентах их нет. Cowork запускает MCP-серверы в изолированной среде без доступа к демону на127.0.0.1— с ним шлюз не работает.
Документы
| Файл | Что внутри |
|---|---|
| docs/install.md | установка на Windows и Linux, обновление, doctor, типовые сбои |
| CHANGELOG.md | что вошло в выпуск |
| CONTRIBUTING.md | для тех, кто хочет разрабатывать шлюз |
Лицензия
MIT.
Release files for odata1c-gate 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| odata1c_gate-0.2.0.tar.gz | 539.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| odata1c_gate-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / odata1c_gate-0.2.0.tar.gz
| Download URL | odata1c_gate-0.2.0.tar.gz |
|---|---|
| Size | 539.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4283505fc86c2c5126822c456495f915ab085d8c0899d84b630faf3c8b49ac27
|
|
BLAKE2b-256 checksum How to use checksums |
121480d285ddaf324d7ff66e4bc9e848f1e073fa67d311c02e9ddb127a65047c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / odata1c_gate-0.2.0-py3-none-any.whl
| Download URL | odata1c_gate-0.2.0-py3-none-any.whl |
|---|---|
| Size | 583.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
69608794e047c2394a08b0559b88ee817ebde0ac0157dcbc4c2d7534b0a4542f
|
|
BLAKE2b-256 checksum How to use checksums |
3bb6fd658d4d984d591c6a1a862691ce2e311e78d6345ca65eb0f2c8bdddfbd9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log