15 сентября 2026 г.
Автоматический рефакторинг BSL-кода с помощью Claude 3.7 Sonnet и MCP-сервера Графон
Почему Claude 3.7 Sonnet «слепнет» на реальных конфигурациях 1С
Claude 3.7 Sonnet — сильная модель для кода, но её контекстное окно (200k токенов) конечно. Типовая ERP или УТ — это гигабайты XML-метаданных и сотни тысяч строк BSL. Даже один общий модуль вроде ОбщегоНазначения или УправлениеЗапасами — это десятки тысяч строк, а рефакторинг почти никогда не локален: правка метода в модуле менеджера тянет за собой подписки на события, вызовы из форм, обращения к регистрам и запросы.
Если скормить агенту «весь проект» или папку модулей целиком, происходит предсказуемое:
- Переполнение контекста. Модули обрезаются посередине, модель теряет сигнатуры и начинает «дорисовывать» несуществующие методы.
- 10-кратный перерасход токенов. Агент читает десятки нерелевантных файлов на каждую итерацию.
- Галлюцинации. Claude уверенно вызывает
ПолучитьЦенуНоменклатурыНаДату()там, где в конфигурации такого метода нет и никогда не было. - Потеря связей. Формальные параметры подписок, экспортные методы, обращения к реквизитам — всё это не видно без графа зависимостей.
Именно эту проблему решает Графон — локальный инструмент и MCP-сервер для конфигураций 1С:Предприятие.
Архитектура: локальный граф Графона + Claude 3.7 Sonnet
[Выгрузка конфигурации 1С: XML + BSL]
│ индексация (полная / инкрементальная)
▼
[Графон: граф метаданных, вызовов, подписок, запросов]
│ MCP (stdio / localhost)
▼
[Claude Code | Cursor | Windsurf] ──► Claude 3.7 Sonnet
Что именно строит Графон
| Слой графа | Узлы | Рёбра |
|---|---|---|
| Метаданные | Справочники, документы, регистры, формы | Владелец → реквизит, ТЧ → реквизит |
| Код | Модули, процедуры, функции | Кто вызывает кого, экспорт/локальный |
| События | Подписки, ПередЗаписью, ПриПроведении | Обработчик ↔ объект-источник |
| Запросы | Тексты запросов, таблицы | Запрос → таблица метаданных |
| Формы | Элементы, обработчики, команды | Форма → модуль → процедура |
Построение индексируется один раз. Для ERP первичный проход — десятки минут, дальше — инкрементально, секунды на изменённый файл.
Как это выглядит со стороны агента
Агент не читает файлы — он вызывает инструменты Графона через MCP.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "grafon_find_routine",
"arguments": {
"name": "ПересчитатьСуммы",
"includeCallers": true,
"includeCallees": true,
"depth": 2
}
}
}
Ответ — компактный срез, а не файлы:
{
"routine": "Документ.РеализацияТоваровУслуг.МодульОбъекта.ПересчитатьСуммы",
"signature": "Процедура ПересчитатьСуммы(Документ) Экспорт",
"callers": [
"ОбщийМодуль.РеализацияТоваровУслугСервер.ПровестиДокумент",
"Подписка.ПередЗаписьюРеализацияТоваровУслуг.ОбработчикПередЗаписью"
],
"callees": ["ОбщегоНазначения.СообщитьПользователю"],
"touched_metadata": [
"РегистрСведений.ЦеныНоменклатуры",
"Документ.РеализацияТоваровУслуг.Товары"
],
"tokens_estimate": 1840
}
Второй ключевой вызов — получение точного среза модулей и проверка подписок:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "grafon_get_context_slice",
"arguments": {
"roots": ["Документ.РеализацияТоваровУслуг.МодульОбъекта.ПересчитатьСуммы"],
"include_metadata": ["РегистрСведений.ЦеныНоменклатуры"],
"include_event_subscriptions": true,
"max_tokens": 12000
}
}
}
Агент получает ровно те сигнатуры, тела методов и описания метаданных, которые нужны для правки. Ничего лишнего.
Сценарий 1. Устранение «запроса в цикле»
Классическая проблема производительности. Агент находит её так: grafon_find_query_usage по таблице РегистрСведений.ЦеныНоменклатуры, затем grafon_get_context_slice по найденному методу.
Было:
Процедура ПересчитатьСуммы(Документ) Экспорт
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура = &Номенклатура
| И Цены.Период <= &Период
|УПОРЯДОЧИТЬ ПО
| Цены.Период УБЫВ";
Запрос.УстановитьПараметр("Номенклатура", СтрокаТЧ.Номенклатура);
Запрос.УстановитьПараметр("Период", Документ.Дата);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СтрокаТЧ.Цена = Выборка.Цена;
КонецЕсли;
СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецЦикла;
КонецПроцедуры
Стало (после рефакторинга агентом):
Процедура ПересчитатьСуммы(Документ) Экспорт
СписокНоменклатуры = Новый Массив;
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
СписокНоменклатуры.Добавить(СтрокаТЧ.Номенклатура);
КонецЦикла;
Если СписокНоменклатуры.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура КАК Номенклатура,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура В (&СписокНоменклатуры)
| И Цены.Период <= &Период
| И Цены.Период В
| (ВЫБРАТЬ
| МАКСИМУМ(Последние.Период)
| ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Последние
| ГДЕ
| Последние.Номенклатура = Цены.Номенклатура
| И Последние.Период <= &Период)";
Запрос.УстановитьПараметр("СписокНоменклатуры", СписокНоменклатуры);
Запрос.УстановитьПараметр("Период", Документ.Дата);
СоответствиеЦен = Новый Соответствие;
Для Каждого СтрокаЦены Из Запрос.Выполнить().Выгрузить() Цикл
СоответствиеЦен.Вставить(СтрокаЦены.Номенклатура, СтрокаЦены.Цена);
КонецЦикла;
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Цена = СоответствиеЦен[СтрокаТЧ.Номенклатура];
Если Цена <> Неопределено Тогда
СтрокаТЧ.Цена = Цена;
КонецЕсли;
СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецЦикла;
КонецПроцедуры
Что здесь критично: агент не меняет контракт процедуры (сигнатура и экспортность сохранены) и не трогает подписки, потому что Графон отдал список вызывающих. Без графа модель с высокой вероятностью переписала бы метод в локальный или поменяла набор параметров.
Сценарий 2. Распутывание подписок на события
Подписки — главная зона галлюцинаций. Агент спрашивает:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "grafon_get_event_subscriptions",
"arguments": {
"source": "Документ.РеализацияТоваровУслуг",
"event": "ПередЗаписью"
}
}
}
И получает точный список обработчиков с модулями и порядком. Дальше — рефакторинг с гарантией, что ни один обработчик не остался висеть на удалённом методе.
С Графоном vs без Графона: измеримое сравнение
Замеры на выгрузке ERP (≈ 220 тыс. строк BSL, 41 тыс. файлов XML):
| Метрика | Без Графона | С Графоном |
|---|---|---|
| Токенов контекста на задачу | 150 000 – 220 000 | 8 000 – 20 000 |
| Итераций агента | 9 – 14 | 3 – 5 |
| Время до готового diff | 2 – 4 часа | 15 – 40 минут |
| Ссылки на несуществующие методы | 5 – 12 | 0 – 1 |
| Правки, ломающие подписки | 1 – 3 | 0 |
| Ревью | со сплошным чтением | по карте вызовов |
| Тип задачи | Токенов без Графона | Токенов с Графоном | Экономия |
|---|---|---|---|
| Извлечение общего метода | 210 000 | 18 000 | 11,7× |
| Оптимизация запроса в цикле | 165 000 | 12 000 | 13,8× |
| Переименование экспортного метода | 240 000 | 21 000 | 11,4× |
| Ревизия подписок объекта | 180 000 | 9 500 | 18,9× |
Как формулировать задачу агенту
Рабочий шаблон промпта для Claude Code / Cursor:
- Контекст добывай через Графон, файлы не читай. Явно укажи: «используй MCP-инструменты
grafon_*, не открывай модули напрямую». - Границы правки. Перечисли неизменяемые контракты: экспортные методы, сигнатуры подписок, реквизиты метаданных.
- Проверка перед правкой. Требуй сначала отчёт
grafon_find_routineсо списком вызывающих, потом diff. - Проверка после правки. Требуй повторный вызов графа и подтверждение, что все вызывающие по-прежнему разрешаются.
- Один метод — один патч. Не давай агенту «отрефактори всё».
Ограничения и границы применимости
- Графон строит граф по выгрузке конфигурации. Держите её актуальной: инкрементальная индексация дешёвая, но не мгновенная.
- Динамические вызовы через
Вычислить()иВыполнить()в графе не видны — их нужно помечать вручную и запрещать агенту считать их «мёртвым кодом». - Объекты, расширяющие чужие модули (
.Расширение), требуют отдельной ветки графа. - Модель остаётся моделью: финальное ревью 1С-разработчиком обязательно. Графон убирает галлюцинации по связям, но не по бизнес-логике.
Чеклист внедрения
- Выгрузить конфигурацию и расширения в файловую структуру XML.
- Запустить индексацию Графона, дождаться построения графа.
- Подключить MCP-сервер в Claude Code, Cursor или Windsurf (stdio-транспорт).
- Прогнать пилотную задачу: один метод, обязательный
grafon_find_routineдо и после. - Сравнить токены и время с историей «ручных» рефакторингов, зафиксировать регламент.
- Добавить в CI проверку: после правки BSL — повторная индексация и валидация разрешимости вызовов.
Автоматический рефакторинг BSL перестаёт быть лотереей ровно в тот момент, когда у агента появляется точный граф связей вместо всего проекта в контексте. Claude 3.7 Sonnet даёт качество рассуждений, Графон — точность входа. Вместе это 10-кратная экономия токенов и предсказуемый diff.