{"id":"53b82852-e35a-4148-aa35-ccd7ce60f5e9","slug":"odata1c-gate","kind":"mcp","name":"odata1c-gate","summary":"Local MCP gateway to 1C:Enterprise OData with a pseudonymisation gate: AI agents query a live 1C base, but tax IDs, accounts, phones and names reach the model only as tokens. · MCP-шлюз к OData 1С с г","owner":"Romandredan","repoUrl":"https://github.com/Romandredan/odata1c-gate","license":"MIT","licenseTier":"permissive","trust":"community","stars":7,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-09-29T07:02:01.000Z","addedAt":"2026-10-21T05:12:53.343Z","logoUrl":"https://avatars.githubusercontent.com/u/201019150?u=7f6dc8689ec031793851b2f3dd8271bb7b7bff73&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","cloud-infra","data-analytics"],"tags":["1c","1c-enterprise","ai-agents","claude-code","claude-code-plugin","data-masking","llm","odata"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T18:32:10.203Z","sample":false,"url":"https://conduits.dev/tools/odata1c-gate","language":"Python","transports":["stdio"],"install":{"pypi":"odata1c-gate"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# odata1c-gate\n\n[![CI](https://github.com/Romandredan/odata1c-gate/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Romandredan/odata1c-gate/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/odata1c-gate.svg)](https://pypi.org/project/odata1c-gate/)\n[![Release](https://img.shields.io/github/v/release/Romandredan/odata1c-gate.svg)](https://github.com/Romandredan/odata1c-gate/releases)\n[![Last commit](https://img.shields.io/github/last-commit/Romandredan/odata1c-gate/dev.svg)](https://github.com/Romandredan/odata1c-gate/commits/dev)\n[![AGENTS.md](https://img.shields.io/badge/AGENTS.md-compatible-brightgreen.svg)](https://agents.md)\n\n[![Claude Code](https://img.shields.io/badge/Claude%20Code-plugin-d97757.svg)](https://code.claude.com/docs/en/plugins)\n[![MCP](https://img.shields.io/badge/MCP-server-6e56cf.svg)](https://modelcontextprotocol.io)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Romandredan/odata1c-gate/blob/main/LICENSE)\n[![Python](https://img.shields.io/badge/python-%E2%89%A53.12-3776ab.svg)](https://www.python.org/)\n[![1C:Enterprise](https://img.shields.io/badge/1C%3AEnterprise-8.3-ffd200.svg)](https://v8.1c.ru/)\n![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux-lightgrey.svg)\n\n**Claude работает с живой базой 1С и не видит персональных данных.** odata1c-gate — локальный\nMCP-шлюз между Claude Code и стандартным OData-интерфейсом 1С:Предприятие 8.3. Модель читает\nсправочники, документы и регистры и может записывать в базу с вашего подтверждения, а ИНН, счета,\nпаспорта, телефоны и, на выбранном уровне, названия организаций и ФИО заменяются токенами до того,\nкак ответ попадёт к модели и к её провайдеру. Реальные значения остаются на вашей машине.\n\nОбезличивать выгрузку заранее неудобно: модели нужны свежие данные и возможность дозапросить их.\nИнструкция «не показывай ИНН» — не механизм, а провайдер модели в любом случае получает всё, что\nпопало в её контекст. Шлюз делает подмену на границе, до контекста модели.\n\nОдин пользователь, одна машина, несколько сессий агентов и несколько баз 1С одновременно. Основной\nклиент — Claude Code; как работают другие клиенты MCP, сказано в разделе [«Ограничения»](#ограничения).\n\n> **English.** A local MCP gateway between Claude Code and the standard OData interface of\n> 1C:Enterprise 8.3. The model reads catalogs, documents and registers, and can write to the\n> database after human confirmation, while personal data (tax IDs, bank accounts, passports, phone\n> numbers and, optionally, company and person names) is replaced with deterministic tokens before\n> it reaches the model or its provider. Tokens still work for search, filtering and joins; only the\n> machine owner can reveal a real value, from the terminal. Ships as a Claude Code plugin with\n> ready-made query recipes for typical 1C configurations (Trade, Accounting, Payroll). Docs and\n> messages are in Russian.\n\n<details>\n<summary><b>Содержание</b></summary>\n\n- [Как это выглядит](#как-это-выглядит)\n- [Возможности](#возможности)\n- [Быстрый старт](#быстрый-старт)\n- [Настройка](#настройка)\n- [Как это устроено](#как-это-устроено)\n- [Командная строка](#командная-строка)\n- [Рецепты](#рецепты)\n- [Ограничения](#ограничения)\n- [Документы](#документы)\n- [Лицензия](#лицензия)\n\n</details>\n\n## Как это выглядит\n\nВопрос в Claude Code и ответ модели. Данные вымышлены; номера, даты и суммы приходят как есть,\nназвание контрагента и его ИНН — токенами:\n\n```text\nВы:      Кто поставщик последнего поступления и какие у него ещё документы за сентябрь?\n\nClaude:  Последнее поступление — № 0000-000412 от 14.09.2026 от [[org:16]]\n         (ИНН [[inn:M4T2Q9XZ7K]]). У этого контрагента за сентябрь ещё два документа:\n           № 0000-000388 от 03.09.2026    184 500,00 ₽\n           № 0000-000401 от 09.09.2026     42 120,00 ₽\n```\n\nТокен работает как значение: на просьбу «покажи все документы [[org:16]] за год» шлюз сам\nподставит в запрос к 1С реальное название, а ответ снова придёт в токенах. Реальное значение за\nтокеном видите только вы, в своём терминале:\n\n```text\n$ odata1c reveal \"[[inn:M4T2Q9XZ7K]]\"\n7701234567\n```\n\n## Возможности\n\n| | Возможность | Что это даёт |\n|---|---|---|\n| 🔒 | Модель не видит персональные данные | реквизиты, названия организаций и ФИО приходят к модели токенами |\n| 🔎 | Защита не мешает работе | по токену можно искать, отбирать и связывать записи |\n| ✍️ | Безопасная запись в 1С | превью, подтверждение человеком, откат и журнал |\n| 🎚️ | Свои правила для каждой базы | рабочая база закрыта и только для чтения, база разработки открыта |\n| 📋 | Готовые ответы на типовые вопросы | рецепты для УТ, БП и ЗУП и свои рецепты из разговора |\n| 🔌 | Подключение базы одной командой | остальное модель делает сама, пароль она не видит |\n| 🧩 | Доработанная конфигурация под защитой | свои правила для нетиповых объектов и реквизитов |\n\n### 🔒 Модель не видит персональные данные\n\nИНН, КПП, счета, карты, СНИЛС, паспорта, телефоны, почта и адреса физических лиц заменяются\nтокенами вида `[[inn:M4T2Q9XZ7K]]` до того, как ответ 1С попадёт к модели и к её провайдеру. На\nрабочей базе токенами приходят и названия организаций с ФИО — в полях и в свободном тексте\nкомментариев. Для типовых УТ, БП и ЗУП ничего настраивать не нужно: при подключении базы шлюз сам\nопределяет по её метаданным, какие поля скрывать.\n\n> **Как включить.** Защита включена сразу; её уровень задаёт роль базы или ключ `--gate` команды\n> `odata1c base add`. Что именно скрыто в базе, показывает `odata1c policy show <база>`. Подробнее —\n> в разделе [«Что видит модель, а что нет»](#что-видит-модель-а-что-нет).\n\n### 🔎 Защита не мешает работе\n\nОдно значение всегда даёт один и тот же токен. Поэтому модель находит контрагента по токену его\nИНН, отбирает его документы, связывает записи из разных справочников и ведёт разговор, так и не\nузнав реального значения: шлюз подставляет его сам, внутри, перед запросом к 1С. Реальное значение\nза токеном можете увидеть только вы, в своём терминале.\n\n> **Как пользоваться.** Ничего включать не нужно. Раскрыть токен — `odata1c reveal \"[[inn:M4T2Q9XZ7K]]\"`.\n\n### ✍️ Безопасная запись в 1С\n\nМодель может создавать и изменять объекты, проводить и распроводить документы, ставить пометку\nудаления и записывать независимые регистры сведений. Сама она при этом ничего не пишет: готовит\nизменение и показывает превью, а в 1С оно уходит только после вашего подтверждения в диалоге\nClaude Code — реплика «да» в чате подтверждением не считается. Каждую запись можно откатить, а\nистория хранится в журнале.\n\n> **Как включить.** Умолчания задаёт роль базы — [таблица ролей](#роли-баз). У отдельной базы\n> запись включает или выключает поле `write` в `bases.yaml`, а что именно разрешено — раздел\n> `permissions` той же записи (образец —\n> [bases.example.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/bases.example.yaml)).\n\n### 🎚️ Свои правила для каждой базы\n\nРабочая база закрыта полностью и доступна только для чтения, тестовая скрывает реквизиты, база\nразработки открыта — уровень защиты и права на запись у каждой базы свои. Внутри базы можно скрыть\nот модели объект целиком, открыть поле, которое не нужно прятать, или закрыть то, что шлюз\nпропустил. Изменения действуют со следующего запроса, перезапуск не нужен.\n\n> **Как настроить.** Роль задаётся при подключении (`--role prod|test|dev`, что она означает —\n> [таблица ролей](#роли-баз)). Правила внутри базы — командами `odata1c policy hide | open | set`\n> (раздел [«Командная строка»](#командная-строка)); они пишут файл `policy.yaml` (образец —\n> [policy.example.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/policy.example.yaml)).\n\n### 📋 Готовые ответы на типовые вопросы\n\nОстатки на складе, задолженность покупателей, оборотно-сальдовая ведомость, работающие\nсотрудники, задолженность по зарплате — на такие вопросы модель отвечает одним вызовом готового\nрецепта, запрос в котором уже сверен с конфигурацией. Удачный запрос из разговора можно сохранить\nфразой «сохрани как рецепт» — он станет доступен всем базам той же конфигурации.\n\n> **Как включить.** Укажите конфигурацию при подключении: `odata1c base add <база> --recipes ut`\n> (или `bp`, `zup`). У уже подключённой базы — поле `config` её записи в `bases.yaml`. Подробнее —\n> в разделе [«Рецепты»](#рецепты).\n\n### 🔌 Подключение базы одной командой\n\nОт вас — одна команда в терминале, где вы вводите пароль 1С; всё остальное модель делает сама.\nПароль она не видит.\n\n> **Как начать.** Скажите в Claude Code «подключи базу 1С». Что произойдёт дальше и как то же\n> сделать вручную — в разделе [«Подключение базы»](#подключение-базы).\n\n### 🧩 Доработанная конфигурация под защитой\n\nШлюз знает типовые объекты УТ, БП и ЗУП. Если в вашей конфигурации есть свои справочники,\nрегистры или реквизиты с персональными данными, опишите их — и шлюз будет скрывать их так же, как\nтиповые. Одно описание действует на всех базах, где есть названные объекты.\n\n> **Как включить.** Создайте в каталоге `~/.claude/odata1c/gate/` файл, например `my-config.yaml`,\n> по образцу [common.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/gate/common.yaml)\n> и назначьте полям классы защиты. Затем выполните `odata1c reindex <база>`.\n>\n> ```yaml\n> version: 1\n> fields:\n>   Catalog_МойСправочник.НомерПаспорта: doc   # поле одной сущности\n> names:\n>   ФИОКлиента: person                          # поле с таким именем в любой сущности\n> ```\n\n**Кроме того:**\n\n- несколько баз в одном разговоре — рабочие, тестовые, разных конфигураций;\n- поиск справочника, документа или регистра по примерному названию среди тысяч объектов\n  конфигурации;\n- текст из полей 1С модель считает данными, а не командами, — запись всё равно требует вашего\n  подтверждения;\n- проверка окружения одной командой `odata1c doctor`, без вывода паролей;\n- чтение из других клиентов MCP (Cursor, VS Code, Claude Desktop), запись в них по умолчанию\n  выключена.\n\n## Быстрый старт\n\n### Что нужно\n\n- [`uv`](https://docs.astral.sh/uv/) — он сам поставит подходящий Python — и Claude Code;\n- база 1С:Предприятие 8.3, опубликованная на веб-сервере со стандартным интерфейсом OData (см. ниже);\n- отдельный пользователь 1С с правами только на нужные данные — например `odata_user`.\n\n**Подготовка 1С.** Стандартный интерфейс OData по умолчанию выключен, и включают его в два шага.\n\n1. **Опубликовать интерфейс.** При публикации базы на веб-сервере (в конфигураторе:\n   «Администрирование» → «Публикация на веб-сервере») отметьте «Публиковать стандартный интерфейс\n   OData».\n2. **Включить объекты в его состав.** Шлюз видит только объекты, включённые в состав стандартного\n   интерфейса OData. В типовых конфигурациях на БСП для этого есть форма «Настройка стандартного\n   интерфейса OData» в разделе «Администрирование»; в любой конфигурации то же делает метод платформы\n   `УстановитьСоставСтандартногоИнтерфейсаOData()`. Если состав потом изменится, выполните\n   `odata1c reindex <база>`.\n\nПроверка: откройте в браузере `https://server/base/odata/standard.odata/` под пользователем 1С —\nдолжен прийти перечень сущностей.\n\n### Установка\n\nТри команды в терминале:\n\n```text\nclaude plugin marketplace add Romandredan/odata1c-gate\nclaude plugin install odata1c@odata1c-gate\nuv tool install odata1c-gate\n```\n\nПервые две ставят плагин Claude Code: MCP-сервер шлюза, четыре навыка, хук подтверждения записи и\nагента-следователя. Версия пакета закреплена в `plugin/.mcp.json`, поэтому `claude plugin update\nodata1c` обновляет и плагин, и шлюз.\n\nТретья ставит отдельно командную строку — она нужна владельцу базы, а не модели (описать базу,\nсобрать индекс, раскрыть токен, править политику гейта). После неё команда `odata1c` доступна в\nтерминале; без установки то же самое запускается как `uvx --from odata1c-gate odata1c <команда>`.\n\nПодробности, Linux, обновление и разбор типовых сбоев —\n[docs/install.md](https://github.com/Romandredan/odata1c-gate/blob/main/docs/install.md).\n\n### Подключение базы\n\nОткройте Claude Code и скажите: **«подключи базу 1С»**. Навык `odata1c-setup` спросит, как назвать\nбазу и какая у неё роль, и даст одну команду для вашего терминала. Команда запросит адрес\nпубликации, пользователя 1С и пароль. Пароль вводится только там, модель его не видит. После\nэтого Claude сам построит индекс метаданных, проверит, что база отвечает, и расскажет, что в ней\nзащищено.\n\nТо же самое можно сделать вручную:\n\n```text\nodata1c base add ut_test --role test --recipes ut   # спросит адрес, подпись, пользователя, пароль\nodata1c reindex ut_test                             # построить индекс метаданных\n```\n\nПервая команда сама создаёт домашний каталог шлюза, отдельный `odata1c init` не нужен. Если что-то\nне работает, `odata1c doctor` покажет, где именно: `uv`, настройки, базы, шлюз, Claude Code.\n\nАдрес базы — это адрес публикации 1С, тот же, по которому открывается веб-клиент (например\n`https://server/base`); окончание `/odata/standard.odata/` шлюз допишет сам. Пароль вводится в\nтерминале и на экране не отображается; он ложится в `bases.yaml` домашнего каталога открытым\nтекстом под правами владельца — сознательное решение: файл не покидает диск владельца, это не\nсетевой секрет.\n\nПервый реиндекс долгий: у типовой УТ `$metadata` — это около 17 МБ описания и больше семи тысяч\nсущностей. Дальше индекс пересобирается, только если у публикации изменилась контрольная сумма\n`$metadata`.\n\n### Первые вопросы\n\n- «какие базы 1С мне доступны?» — модель вызовет `odata1c_bases`;\n- «найди справочник контрагентов и покажи состав его полей» — `odata1c_find_entity`,\n  затем `odata1c_describe_entity` с классами гейта у каждого поля;\n- «возьми любого контрагента и покажи его пять последних заказов клиента» — `odata1c_query`;\n  название контрагента придёт токеном, номера и суммы документов — как есть.\n\nЧто модель видит и в каком порядке ходит — навык `odata1c` из плагина; справочные темы об\nустройстве OData 1С, токенах, политике и протоколе записи — тул `odata1c_info`.\n\n## Настройка\n\n### Роли баз\n\nРоль базы задаёт умолчания записи и гейта:\n\n| Роль | Уровень гейта | Запись | Проведение документов | Пометка удаления | Удаление записей независимых регистров | Лимит коммитов за 10 минут |\n|---|---|---|---|---|---|---|\n| `prod` | `identifiers+names` | нет | да | да | нет | 20 |\n| `test` | `identifiers` | да | да | да | нет | 50 |\n| `dev` | `off` | да | да | да | да | без лимита |\n\nРоль — только набор умолчаний: любое поле записи базы его перекрывает (например, `role: prod` +\n`write: true` — боевая база с разрешённой записью). Флаги записи из последних четырёх столбцов\nдействуют, только когда запись включена (`write: true`) — у базы без записи они значения не имеют.\nВсе эти поля, включая уровень гейта, задаются для каждой базы отдельно: у боевой и тестовой базы\nуровни могут быть разными. Уровень при подключении задаёт ключ `odata1c base add --gate`, а\nдействующие роль и уровень каждой базы показывает `odata1c base list`.\n\nГотовая запись базы выглядит так (адрес, пользователь и пароль — плейсхолдеры):\n\n```yaml\nbases:\n  ut_test:\n    label: УТ 11, тестовая\n    url: https://server/base\n    user: odata_user\n    password: qwerty123\n    role: test\n    config: ut\n```\n\n### Файлы настроек\n\nВсе настройки шлюза хранятся в домашнем каталоге `~/.claude/odata1c/`. Создавать эти файлы\nвручную не нужно: каждый появляется при выполнении соответствующей команды и уже содержит\nзакомментированный образец всех допустимых полей с пояснениями. Те же образцы лежат в репозитории,\nв каталоге `src/odata1c/templates/`, и по ним удобно заранее посмотреть, что и как настраивается.\n\n| Файл в домашнем каталоге | Что в нём настраивается | Когда создаётся | Образец в репозитории |\n|---|---|---|---|\n| `bases.yaml` | перечень баз: адрес публикации, пользователь и пароль 1С, подпись, роль, уровень защиты, разрешения на запись | `odata1c init` или первый запуск шлюза; записи добавляет `odata1c base add` | [bases.example.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/bases.example.yaml) |\n| `daemon.yaml` | порт шлюза, лимиты, поведение с клиентами, которые не умеют подтверждать запись | `odata1c init` или первый запуск шлюза | [daemon.example.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/daemon.example.yaml) |\n| `bases/<база>/policy.yaml` | что именно скрывать в этой базе: скрытые сущности, открытые поля, собственные классы защиты | `odata1c base add` | [policy.example.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/policy.example.yaml) |\n| `bases/<база>/recipes.yaml` | рецепты этой базы | `odata1c base add` с ключом `--recipes` | [recipes/ut.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/recipes/ut.yaml) |\n| `recipes/<конфигурация>/<имя>.yaml` | библиотека рецептов, общая для баз одной конфигурации | сохранением рецепта в разговоре с моделью | пример в разделе [«Рецепты»](#рецепты) |\n| `gate/<имя>.yaml` | правила защиты для доработанной конфигурации: какие поля нетиповых объектов скрывать и какие ложные срабатывания снять; действуют на любой базе, где есть названные объекты | вручную, если конфигурация доработана | [common.yaml](https://github.com/Romandredan/odata1c-gate/blob/main/src/odata1c/templates/gate/common.yaml) (формат описан в его заголовке) |\n\nЧаще всего правится `bases.yaml`. В записи базы меняют подпись (`label`), по которой модель\nвыбирает базу, роль (`role`), разрешение записи (`write`), уровень защиты (`gate.mode`), состав\nразрешённых операций (`permissions`) и конфигурацию 1С (`config`), от которой зависит библиотека\nрецептов. Изменения в `bases.yaml` и `policy.yaml` действуют со следующего запроса модели,\nперезапуск шлюза не требуется. Политику защиты надёжнее менять не в редакторе, а командами\n`odata1c policy`: они проверяют имена сущностей и полей по метаданным базы.\n\nОстальное содержимое домашнего каталога служебное, и править его не следует. Это\n`policy.auto.yaml` (разметка защищаемых полей, которую шлюз строит сам по метаданным базы),\n`launcher.key`, файлы `*.sqlite` (индекс метаданных, словарь токенов, журнал записей) и каталог\n`logs/`.\n\n**Файлы правит владелец, не модель.** Модель их штатно не читает и не правит — хук плагина\n`PreToolUse` перехватывает такие обращения к домашнему каталогу шлюза и требует решения человека.\nЭто дополнительная защита, а не единственная: реальные значения и пароль 1С не выходят через MCP\nни при каком обращении. Подробнее —\n[docs/install.md](https://github.com/Romandredan/odata1c-gate/blob/main/docs/install.md).\n\n## Как это устроено\n\n### Что видит модель, а что нет\n\n**Что уходит модели.** Структура базы (сущности, поля, ключи, навигация) и данные, прошедшие\nгейт. Номера и даты документов, суммы, количества, коды, GUID, значения перечислений не\nзащищаются ни на одном уровне — без них работа с базой теряет смысл. Названия организаций и ФИО\n(классы `org` и `person`) и защищаемые реквизиты — ИНН, КПП, ОГРН, счета, БИК, карты, СНИЛС,\nрегистрационные номера в СФР, документы, телефоны, почта, даты рождения, адреса — приходят\nтокенами `[[type:tail]]` по правилам политики базы. Уровень задаётся на базу: `off` — гейт\nвыключен, `identifiers` — реквизиты, `identifiers+names` — реквизиты плюс названия и ФИО.\n\n**Что не уходит никогда.** Реальные значения защищаемых классов не выходят через MCP ни в одном\nответе: ни в данных, ни в текстах ошибок 1С, ни в превью записи, ни в журнале, ни в\n`odata1c_raw_get`, ни в вопросах подтверждения. Это инвариант, а не тест: последний проход по\nготовому ответу делает страж утечек — он ищет в сериализованном ответе известные словарю значения\nи заменяет их токенами, если что-то прошло мимо гейта. Учётные данные 1С модель не получает:\nпароль не покидает домашнего каталога вовсе, имя пользователя 1С не попадает ни в один ответ, а\nадрес публикации базы не возвращает ни один тул. О самой базе модель узнаёт ровно то, что\nперечисляет `odata1c_bases`: имя, подпись, роль, уровень гейта, разрешена ли запись, состояние\nиндекса (собран ли, когда, сколько сущностей) и конфигурацию 1С, к которой база отнесена.\nЕдинственное исключение по адресу — текст сетевого сбоя, в который его может вписать HTTP-клиент.\nРаскрыть токен может только владелец машины, командой `odata1c reveal` в своём терминале.\n\n### Архитектура\n\nДва процесса из одного пакета: **демон** (`odata1c daemon`) — единственный на машину, в нём\nработают все компоненты из таблицы ниже; **лаунчер** (`odata1c mcp`) — тонкий stdio-процесс на\nсессию, который поднимает демон при необходимости и проксирует ему вызовы. Собственной логики у\nлаунчера нет.\n\n![Архитектура odata1c-gate: сессии Claude Code через лаунчеры обращаются к единственному демону; гейт в демоне делит поток на токены со стороны модели и реальные значения со стороны 1С; владелец настраивает шлюз из своего терминала, хук не пускает модель к файлам шлюза](https://raw.githubusercontent.com/Romandredan/odata1c-gate/main/docs/images/architecture.svg)\n\nГейт стоит в демоне между тулами и клиентом 1С: всё, что левее пунктирной границы, видит только\nтокены, реальные значения живут правее неё и в словаре. Настройки и учётные данные лежат в\nдомашнем каталоге шлюза; их правит владелец из своего терминала, а модель к этим файлам не\nдопускается.\n\n| Компонент | Что делает | На чём построен |\n|---|---|---|\n| Тулы MCP | принимают вызовы модели: чтение, запись, рецепты, справка по OData 1С | официальный SDK `mcp`, MCP Streamable HTTP на `127.0.0.1:7171` |\n| Гейт | назначает полям классы защиты; в ответе 1С заменяет значения токенами, в запросе — токены значениями; страж утечек проверяет каждый готовый ответ последним | классы — из авторазметки по метаданным, каталога правил и `policy.yaml`; реквизиты распознаются регулярными выражениями с проверкой контрольных сумм; собственный разбор `$filter`; страж ищет все значения словаря сразу алгоритмом Aho–Corasick (`ahocorasick_rs`) |\n| Словарь | хранит пары «значение ↔ токен» и все встреченные написания значения | SQLite, `gate.sqlite`, один на домашний каталог; токен — HMAC-SHA256 от значения с секретом шлюза, поэтому одно значение всегда даёт один токен |\n| Индекс | сущности, поля, ключи и связи базы; поиск объекта по примерному названию | SQLite, `bases/<база>/metadata.sqlite`; полнотекстовый поиск FTS5 с триграммами; строится потоковым разбором `$metadata` (`lxml`) |\n| Клиент 1С | единственный, кто обращается к базе | `httpx`, пул соединений на базу; стандартный интерфейс OData v3 (`/odata/standard.odata/`), JSON; сеанс 1С (`IBSession`) переиспользуется, число одновременных запросов ограничено |\n| Запись | превью, подтверждение, выполнение, журнал, откат | подготовленная операция живёт 10 минут и привязана к сессии; журнал — SQLite, `journal.sqlite` |\n| Плагин | методика работы для модели, подтверждение записи, защита файлов шлюза | навыки и агент Claude Code; хук `PreToolUse` на Python |\n\nБазы SQLite работают в режиме WAL: несколько сессий читают и пишут одновременно.\n\n### Тулы чтения\n\n| Тул | Что делает | Когда нужен |\n|---|---|---|\n| `odata1c_bases` | список видимых баз: подпись, роль, уровень гейта, статус индекса | в начале новой сессии — узнать, какие базы доступны |\n| `odata1c_find_entity` | нечёткий поиск справочника, документа или регистра по названию | когда точное имя сущности неизвестно |\n| `odata1c_describe_entity` | состав полей сущности: типы, ключи, связи, классы гейта | перед выборкой — чтобы выбрать нужные поля |\n| `odata1c_query` | выборка записей сущности: отбор, сортировка, страницы | основной способ читать данные — списки, поиск, фильтры |\n| `odata1c_get` | один объект по ключу | когда ключ объекта уже известен |\n| `odata1c_info` | справочник по устройству OData 1С и самого шлюза, по темам | разобраться в токенах, политике, порядке записи |\n| `odata1c_reindex` | обновить индекс метаданных базы | 1С отвечает «сущность не найдена» на объект, который точно есть, или после обновления конфигурации |\n| `odata1c_raw_get` | произвольный запрос по пути публикации | когда `query` и `get` не выражают нужное обращение |\n| `odata1c_recipe` | список готовых запросов базы или выполнение одного из них | вместо того чтобы собирать сложную выборку (остатки, задолженность) вручную |\n\n### Тулы записи\n\nПишущие тулы ничего не пишут сами: каждый готовит операцию, показывает превью в токенах и\nвозвращает `pending_id`. В 1С пишет только `odata1c_commit` — и только после подтверждения\nчеловека механизмом клиента: в Claude Code это диалог разрешения, у клиентов с elicitation — вопрос\nшлюза. Любую выполненную запись можно откатить тулом `odata1c_undo`.\n\n| Тул | Что делает | Когда нужен |\n|---|---|---|\n| `odata1c_create` | подготовить создание объекта — справочника или документа | завести новую запись в базе |\n| `odata1c_update` | подготовить изменение полей существующего объекта | поправить значения по ключу |\n| `odata1c_mark_for_deletion` | подготовить пометку удаления (или её снятие) | «удалить» объект — в 1С это всегда пометка, не физическое удаление |\n| `odata1c_delete_record` | подготовить физическое удаление записи независимого регистра сведений | единственный тул с настоящим удалением — только для регистров без регистратора |\n| `odata1c_action` | подготовить проведение или отмену проведения документа | провести или распровести документ |\n| `odata1c_commit` | выполнить подготовленную операцию в 1С | после того как пользователь увидел превью и подтвердил запись |\n| `odata1c_undo` | подготовить откат уже выполненной записи | отменить результат коммита — по его `commit_id` |\n| `odata1c_journal` | последние выполненные записи с исходом и способом подтверждения | посмотреть историю записи или найти `commit_id` для отката |\n\n## Командная строка\n\nКоманды `odata1c` — для владельца машины, не для модели. Общий ключ `--home <путь>` (или\nпеременная окружения `ODATA1C_HOME`) у любой команды меняет домашний каталог шлюза.\n\n**Базы**\n\n| Команда | Что делает |\n|---|---|\n| `odata1c init` | создать домашний каталог и шаблоны настроек |\n| `odata1c base add <имя> [--role prod\\|test\\|dev] [--gate off\\|identifiers\\|identifiers+names] [--recipes ut\\|bp\\|zup]` | добавить базу — адрес, подпись, пользователя и пароль спросит сама; `--gate` задаёт уровень гейта этой базы вместо умолчания роли |\n| `odata1c base import <путь>` | перенести базы из env-файла прежнего сервера |\n| `odata1c base list` | список описанных баз |\n| `odata1c base test <имя>` | проверить соединение с базой |\n| `odata1c reindex <имя> [--force]` | обновить индекс метаданных базы |\n\n**Политика гейта**\n\n| Команда | Что делает |\n|---|---|\n| `odata1c policy show <имя>` | показать действующую политику базы |\n| `odata1c policy check <имя>` | проверить файл владельца по индексу |\n| `odata1c policy hide <имя> <сущность> [--yes]` | скрыть сущность целиком, вместе с дочерними |\n| `odata1c policy open <имя> <Сущность.Поле>` | открыть поле (класс `keep`) |\n| `odata1c policy set <имя> <Сущность.Поле> <класс>` | назначить полю класс защиты |\n\n**Рецепты**\n\n| Команда | Что делает |\n|---|---|\n| `odata1c recipe check <config>` | проверить библиотеку рецептов конфигурации |\n| `odata1c recipe list <имя>` | список рецептов базы с источником каждого |\n\n**Служебные**\n\n| Команда | Что делает |\n|---|---|\n| `odata1c doctor [--online]` | проверка окружения: Python, `uv`, дом, базы, индекс, демон, Claude Code (`--online` — ещё и соединение с базами) |\n| `odata1c daemon [--foreground]` | запустить демон вручную (обычно его поднимает лаунчер сам) |\n| `odata1c daemon stop` | остановить демон |\n| `odata1c mcp [--bases ...] [--default ...] [--url ...]` | лаунчер — то, что прописывается в `.mcp.json`; руками обычно не вызывается |\n| `odata1c reveal <токен> [--base ...] [--field ...]` | реальное значение токена — только для владельца, в терминале |\n| `odata1c --version` | версия пакета |\n\n## Рецепты\n\nРецепт — это заранее составленный и проверенный запрос к базе, которому дано имя и у которого\nобъявлены параметры. Остатки товаров на складе, задолженность покупателей, выручка за период:\nвсё это типовые вопросы, и ответ на каждый из них в 1С требует знать, в каком регистре лежат\nданные, как называется его виртуальная таблица и какие у неё поля. Рецепт хранит это знание в\nготовом виде.\n\nБез рецептов модель каждый раз заново исследует структуру базы и собирает запрос с нуля. Это\nзанимает несколько обращений к 1С и не защищает от ошибки в имени регистра или поля. С рецептом\nтот же вопрос решается одним вызовом, и каждый раз одинаково, потому что запрос уже сверен с\nметаданными конфигурации.\n\nОт пользователя рецепты ничего не требуют. Достаточно спросить обычными словами, например\n«покажи остатки по основному складу на сегодня». Модель запрашивает у шлюза перечень рецептов\nбазы, выбирает подходящий и выполняет его со своими параметрами, в этом примере с датой и\nскладом. Для этого служит один инструмент, `odata1c_recipe`: вызов без имени возвращает перечень\nс описаниями и параметрами, вызов с именем выполняет рецепт.\n\nРецепты собираются из трёх источников. Если имя встречается в нескольких, действует рецепт из\nисточника, который стоит в списке выше.\n\n1. **Рецепты базы** лежат в файле `bases/<база>/recipes.yaml` и действуют только для неё. Здесь\n   уместны запросы, которые учитывают доработки конкретной базы.\n2. **Библиотека конфигурации** лежит в каталоге `~/.claude/odata1c/recipes/<конфигурация>/`, по\n   одному файлу на рецепт, и общая для всех баз этой конфигурации. К какой конфигурации относится\n   база, определяет поле `config` в её настройках: `ut`, `bp`, `zup` или собственное обозначение.\n3. **Стартовый набор из поставки** — для «Управления торговлей», «Бухгалтерии предприятия» и\n   «Зарплаты и управления персоналом». Его видит любая база, у которой задана конфигурация\n   (`config`); ключ `--recipes` команды `odata1c base add` задаёт её и заодно копирует набор в\n   файл рецептов базы.\n\nБиблиотека пополняется в ходе обычной работы. Когда запрос, найденный в разговоре, дал нужный\nрезультат и пригодится снова, достаточно попросить модель сохранить его как рецепт. Навык плагина\n`odata1c-recipe` заменит конкретные значения параметрами и запишет файл в библиотеку конфигурации.\nКоманда `odata1c recipe check <конфигурация>` сверяет рецепты библиотеки с метаданными базы, а\n`odata1c recipe list <база>` показывает все рецепты базы с указанием источника каждого.\n\nРецепт записывается обычным файлом YAML. В нём есть описание, сущность 1С, параметры и сам запрос.\nДанных базы в нём нет: ни значений, ни токенов.\n\n```yaml\ntitle: Остатки по складу\ndescription: Количество в наличии на указанный момент.\nentity: AccumulationRegister_ТоварыНаСкладах_Balance\nparams:\n  period: { type: datetime, required: true, description: момент остатков }\n  warehouse: { type: guid, required: false, description: Ref_Key склада }\nvirtual:\n  Period: \"{period}\"\n  Condition:\n    - Склад_Key eq {warehouse}\nselect: [Номенклатура_Key, ВНаличииBalance]\nfilter: ВНаличииBalance gt 0\ntop: 200\n```\n\nБиблиотека задумана как растущая: чем дольше шлюз работает с базой, тем больше вопросов\nрешается одним вызовом. Наборы для типовых конфигураций поставляются вместе с плагином и\nобновляются вместе с ним.\n\n## Ограничения\n\n- **Физического удаления объектов нет.** «Удаление» для объектов и подчинённых регистров — только\n  пометка удаления (`DeletionMark = true`). Из тулов записи физически удаляет только\n  `odata1c_delete_record`, и только записи независимых регистров сведений.\n- **Через `odata1c_update` нельзя вписать открытым текстом телефон, почту, адрес или дату\n  рождения** — только токеном или при создании объекта (`odata1c_create`): иначе ответ «изменений\n  нет» позволял бы подбирать чужие данные перебором значений.\n- **Сокращённое название в свободном тексте проходит открытым.** Словарь знает полные написания\n  названия; если в комментарии документа человек написал узнаваемое сокращение, которого нет в\n  справочнике, гейт его не заменит. Ловить «ядро» названия отвергнуто: ядра — обычные слова, их\n  замена портила бы данные ложными срабатываниями.\n- **Одиночное название или имя в свободном тексте без кавычек проходит открытым.** Короткое\n  название организации или имя человека, встретившееся в тексте одним словом без кавычек и без\n  организационно-правовой формы (Мост вместо ООО «Мост», Мария вместо полного ФИО), гейт не\n  отличает от обычного слова того же написания и не заменяет: иначе обычные слова в комментариях и\n  именах объектов базы заменялись бы токенами по ошибке. Название с формой собственности (в том\n  числе вплотную через точку или дефис, латиницей и полной записью: «ООО-Мост», «OOO Мост», «Общество с\n  ограниченной ответственностью Мост»), в кавычках или апострофах, из нескольких слов, как и\n  полное ФИО, закрывается как прежде. Открытыми остаются и редкие написания: угловые кавычки\n  (‹Мост›, <<Мост>>) и чужая форма собственности (АО Мост при ООО «Мост»).\n- **Аутентификации у демона нет.** Он слушает только `127.0.0.1`; модель угроз — диск и машина\n  владельца. Публикации по сети с аутентификацией и TLS пока нет.\n- **Записи в регистры, подчинённые регистратору, нет** ни при каком разрешении: их пишет\n  проведение документа, а не прямая запись.\n- **Шаблоны рецептов — только для типовых УТ, БП и ЗУП.** Имена в них сверены с реальными базами\n  этих конфигураций; у доработанной конфигурации рецепт, чьей сущности в базе нет, помечается\n  неприменимым, и его правят в собственном файле рецептов базы.\n- **Проверен шлюз только с Claude Code.** Другие клиенты MCP по stdio (Cursor, VS Code, Claude\n  Desktop) подключаются и читают; там, где нет диалога разрешения Claude Code или elicitation,\n  запись по умолчанию выключена (`write_confirm_fallback: deny`). Навыки, хук и агент — часть\n  плагина Claude Code, в других клиентах их нет. Cowork запускает MCP-серверы в изолированной\n  среде без доступа к демону на `127.0.0.1` — с ним шлюз не работает.\n\n## Документы\n\n| Файл | Что внутри |\n|---|---|\n| [docs/install.md](https://github.com/Romandredan/odata1c-gate/blob/main/docs/install.md) | установка на Windows и Linux, обновление, `doctor`, типовые сбои |\n| [CHANGELOG.md](https://github.com/Romandredan/odata1c-gate/blob/main/CHANGELOG.md) | что вошло в выпуск |\n| [CONTRIBUTING.md](https://github.com/Romandredan/odata1c-gate/blob/main/CONTRIBUTING.md) | для тех, кто хочет разрабатывать шлюз |\n| [SECURITY.md](https://github.com/Romandredan/odata1c-gate/blob/main/SECURITY.md) | как сообщить об уязвимости |\n\n## Лицензия\n\n[MIT](https://github.com/Romandredan/odata1c-gate/blob/main/LICENSE).\n"}