Skip to main content
Glama
README.md
# 1C Meta MCP

MCP-сервер на Node.js для поиска по метаданным конфигурации 1С и коду BSL. В проекте нет нативных модулей и обязательного Docker: достаточно Node.js >= 22.13, потому что используется встроенный `node:sqlite`.

## Что нужно выгрузить из 1С

Сервер загружает данные из двух источников, и нужны оба:

1. `metadata/*.txt` — один текстовый файл `Отчет по конфигурации`.
2. `code/` — полная XML-выгрузка конфигурации в файлы.

Без TXT-отчета не загрузятся паспорт конфигурации, список объектов, реквизиты, табличные части, формы, команды и полнотекстовый поиск по описаниям. Без XML-выгрузки не будет GUID, движений по регистрам, прав ролей, предопределенных данных, состава подсистем и исходников BSL.

### Как именно выгрузить данные из 1С

Делайте выгрузку из конфигуратора 1С для той конфигурации, по которой хотите искать.

1. Откройте базу в режиме `Конфигуратор`.
2. Сформируйте `Отчет по конфигурации` в текстовый файл. Обычно это меню `Конфигурация -> Отчет по конфигурации...`.
3. Сохраняйте полный отчет, а не выборочный.
4. Убедитесь, что файл сохранен в текстовом формате Unicode UTF-16LE с BOM.
5. Положите этот файл в папку `metadata/`.
6. Выполните команду `Выгрузить конфигурацию в файлы`. Обычно это меню `Конфигурация -> Выгрузить конфигурацию в файлы...`.
7. В качестве каталога выгрузки укажите папку `code/`.
8. Нужна полная выгрузка, чтобы внутри оказались XML-описания объектов, каталоги модулей и `.bsl`-файлы в `Ext/`.

Практически это должно выглядеть так:

```text
prj1/
  metadata/
    ОтчетПоКонфигурации.txt
  code/
    ConfigDumpInfo.xml
    Configuration.xml
    Catalogs/
    Documents/
    CommonModules/
    Roles/
    Subsystems/
    EventSubscriptions/
    ...
```

Сервер ожидает именно такую структуру относительно `DATA_DIR`:

```text
DATA_DIR/
  metadata/
    *.txt
  code/
    ConfigDumpInfo.xml
    Configuration.xml
    ... XML и BSL-выгрузка конфигурации ...
```

Требования к данным:

- В `metadata/` должен лежать ровно один `.txt`-файл с отчетом по конфигурации. Имя файла может быть любым.
- В `code/` должна быть полная файловая выгрузка, а не отдельные выборочные каталоги.
- Для загрузки BSL в `code/` должны присутствовать модули вида `Ext/*.bsl`, формы `Forms/*/Ext/Form/Module.bsl`, командные модули и общие модули.
- Для прав ролей нужны файлы `Roles/*/Ext/Rights.xml`.
- Для предопределенных элементов используются `Ext/Predefined.xml` у соответствующих объектов.

Если ваши данные лежат не в `./prj1`, просто укажите правильный путь в `DATA_DIR`.

## Быстрый старт

```powershell
npm install
$env:DATA_DIR = 'C:\Golden\Andersen\1c-meta-mcp\prj1'
npm run dev
```

На первом запуске сервер загружает выгрузку в SQLite, после чего поднимает MCP-эндпоинт `http://localhost:6101/mcp` и UI со статусом загрузки на `http://localhost:6102`.

Полезные команды:

- `npm run dev` — загрузить данные при необходимости и запустить MCP-сервер.
- `npm run load` — только выполнить загрузку и завершиться.
- `npm run serve` — то же поведение, что и `npm run dev`.
- `npm run parity` — сравнить ответы с оригинальным сервером.
- `npm test` — запустить тесты.

Пример конфигурации MCP-клиента:

```json
{
  "mcpServers": {
    "onec-meta": {
      "url": "http://localhost:6101/mcp",
      "type": "streamable-http"
    }
  }
}
```

## Docker

Для `docker compose` подготовьте выгрузку, например так:

```text
data/
  prj1/
    metadata/
      ОтчетПоКонфигурации.txt
    code/
      ConfigDumpInfo.xml
      Configuration.xml
      ...
```

Дальше:

```bash
docker compose up -d
docker compose logs -f
```

Контейнер монтирует выгрузку 1С в `/data` только на чтение, а SQLite хранит в именованном volume `onec_db_prj1`, поэтому база переживает перезапуск контейнера и обновление образа.

Повторная загрузка после изменения конфигурации:

```bash
FULL_RELOAD=true docker compose up -d --force-recreate
```

Альтернатива — удалить volume с базой и поднять контейнер заново. Для нескольких конфигураций продублируйте сервис в `docker-compose.yml` и задайте отдельные `PROJECT_NAME`, `DATA_DIR`, volume и порт.

Образ основан на `node:22-slim`, запускает TypeScript через `tsx`, использует `tini` как PID 1 и проверяет готовность через `tools/list` по MCP.

## Переменные окружения

| Переменная | По умолчанию | Значение |
|---|---|---|
| `DATA_DIR` | `../prj1` | Корневая папка данных, внутри которой должны быть `metadata/*.txt` и `code/` |
| `PROJECT_NAME` | `prj1` | Метка проекта в qualified names |
| `DB_PATH` | `./onec-meta.db` | Путь к SQLite-базе |
| `MCP_HOST` | `0.0.0.0` | Хост MCP-сервера |
| `MCP_PORT` / `MCP_PATH` | `6101` / `/mcp` | HTTP-эндпоинт MCP |
| `UI_PORT` / `UI_ENABLED` | `6102` / `true` | Веб-панель статуса загрузки и индексации |
| `FULL_RELOAD` | `false` | Принудительно перезагрузить проект, даже если отпечаток TXT-отчета не изменился |
| `LOAD_BSL` | `true` | Загружать модули BSL |
| `LOAD_RIGHTS` | `true` | Загружать права ролей из `Rights.xml` |
| `LOAD_PREDEFINED` | `true` | Загружать предопределенные данные из `Predefined.xml` |
| `CHECKS_DIR` | `./checks` | Папка с YAML-наборами SQL-проверок |
| `ENABLE_ROUTINE_EMBEDDING` / `ENABLE_METADATA_EMBEDDING` | `false` / `false` | Включить семантический индекс для кода и метаданных |
| `EMBEDDING_API_BASE` | `http://localhost:1234/v1` | OpenAI-совместимый endpoint для эмбеддингов |
| `EMBEDDING_MODEL` | `text-embedding-qwen3-embedding-0.6b` | Модель эмбеддингов |
| `HYBRID_FT_WEIGHT` / `HYBRID_VEC_WEIGHT` | `0.3` / `0.7` | Веса гибридного поиска |

## Что умеет сервер

### Фазы 1-2: TXT-отчет

- `get_config_passport` — имя, версия, поставщик и счетчики объектов конфигурации.
- `list_categories`, `list_objects` — обзор объектов с фильтром по происхождению.
- `get_object_structure` — реквизиты, ресурсы, измерения, табличные части, формы и значения перечислений.
- `find_object_usages` — кто использует объект как тип.
- `search_metadata_by_description` — полнотекстовый поиск FTS5 по имени, синониму и комментарию.
- `run_sql_readonly` — защищенный `SELECT` по SQLite для аналитики и проверок.

### Фаза 3: XML-выгрузка

- `find_register_movements` — связи документы ↔ регистры.
- `list_predefined` — предопределенные элементы, включая иерархию плана счетов и флаги.
- `get_subsystem_content` — состав подсистем и принадлежность объектов.
- `list_event_subscriptions` — подписки на события, источник, событие и обработчик.
- `get_role_rights` — права ролей по объектам.
- `find_by_guid` — поиск объекта по UUID.

### Фаза 4: код BSL

- `search_code` — поиск по именам процедур и функций, doc-comment и фильтрам.
- `grep_code` — поиск по телам процедур и функций с номерами строк.
- `get_routine` — исходник процедуры или функции по `routine_id` либо `name + owner`.
- `list_routines` — список процедур и функций модуля с метриками.
- `get_call_graph` — вызывающие и вызываемые процедуры, глубина 1-10.

Загрузка возобновляемая: прогресс хранится по фазам в таблице `load_phases`, поэтому после прерывания сервер продолжает с места остановки. Полная перезагрузка выполняется при `FULL_RELOAD=true` или при изменении TXT-отчета.

## Семантический поиск

`search_code` и `search_metadata_by_description` поддерживают `mode: fulltext | semantic | hybrid`. Если эмбеддинги отключены, используется полнотекстовый режим.

Минимальная конфигурация:

```text
ENABLE_ROUTINE_EMBEDDING=true
ENABLE_METADATA_EMBEDDING=true
EMBEDDING_API_BASE=http://localhost:1234/v1
EMBEDDING_MODEL=text-embedding-qwen3-embedding-0.6b
```

Индексация запускается в фоне после старта сервера. Векторы хранятся в той же SQLite-базе, а смена модели автоматически запускает переиндексацию.

## Проверки соответствия

`list_checks` и `run_checks` выполняют SQL-проверки из `checks/*.yaml`. Каждое правило описывает идентификатор, заголовок, уровень серьезности, категорию и read-only SQL-запрос, строки которого трактуются как нарушения.

Стартовый набор `checks/1c-standards.yaml` включает проверки на:

- префиксы именования кастомных объектов;
- экспортные процедуры без doc-comment;
- слишком длинные процедуры и функции;
- использование `Выполнить()`;
- использование `ВЫБРАТЬ *`;
- отсутствие структуры `#Область`;
- TODO-маркеры;
- административные и интерактивные права удаления;
- неиспользуемые экспортные процедуры;
- доступ к БД на клиенте в формах.

Для новых правил удобно сначала отладить SQL через `run_sql_readonly`, а затем сохранить запрос в YAML-пакет.

## Паритет с оригинальным сервером

`npm run parity` запускает набор сравнительных запросов из `test/parity.ts` против оригинального сервера и этого клона. Результат сохраняется в `test/parity-report.json`. Оба сервера должны быть подняты с одной и той же загруженной конфигурацией.

Известные допустимые расхождения:

- наборы реквизитов могут немного отличаться из-за стандартных реквизитов;
- ранжирование кодового поиска может отличаться между Lucene-подобным поиском и SQLite FTS5 BM25;
- граф вызовов может немного различаться из-за эвристик динамических вызовов.

Результат запуска от 2026-06-08: `13 exact / 1 ranking-info / 3 reference-server bugs / 0 clone defects`.

## Статус

Реализованы фазы 1-4: загрузка TXT-отчета, XML-объектов и кода BSL, права ролей, подписки, предопределенные данные, граф вызовов и инструменты поиска.

Фазы 5-7 требуют отдельной проверки в вашей среде:

```bash
npm install
npx tsc --noEmit
npm run parity
```

Для проверок соответствия можно начать с быстрого smoke-теста через `run_checks` и одно правило, а для семантического поиска — поднять LM Studio или другой OpenAI-совместимый endpoint и отслеживать `get_semantic_index_status`.

## Ограничения

- стандартные реквизиты хранятся в `properties_json`, а не отдельными строками в таблице полей;
- внутренности `Form.xml` уровня контролов, событий и привязок пока не загружаются;
- детали HTTP-сервисов и web-service operations отложены на следующую фазу;
- тексты RLS-условий загружаются только там, где они присутствуют в `Rights.xml`.