# Инструменты

Описание готовых инструментов для разработки и руководство по созданию собственных.

## Готовые инструменты

В файле `ИнструментыДляРазработки.xml` содержатся инструменты для вайб-кодинга — разработки с помощью ИИ-ассистентов.

### vcexecutecode

Выполняет произвольный код на языке 1С в базе данных.

| Параметр  | Тип    | Описание                       |
| --------- | ------ | ------------------------------ |
| `bslcode` | Строка | Код на языке 1С для выполнения |

**Возврат**: Значение переменной `Результат` или описание ошибки.

#### Пример использования

ИИ-агент может выполнить код:

```
bslcode: "Результат = Строка(ТекущаяДатаСеанса())"
```

Результат: `19.03.2026 14:30:45`

#### Реализация

```bsl
Результат = "ошибок нет";
Попытка
    Выполнить(КодДляВыполнения)
Исключение
    Результат = ОписаниеОшибки();
КонецПопытки;
```

{% hint style="danger" %}
**Безопасность**: Инструмент выполняет произвольный код в базе данных. Используйте только в доверенном окружении с соответствующими ограничениями прав доступа.
{% endhint %}

***

### vcexecutequery

Выполняет запрос на языке запросов 1С и возвращает результат в текстовом табличном виде.

| Параметр    | Тип    | Описание                                        |
| ----------- | ------ | ----------------------------------------------- |
| `querytext` | Строка | Текст запроса на языке 1С (без переносов строк) |

**Возврат**: Таблица с заголовками и данными, разделёнными символом `|`.

#### Пример использования

```
querytext: "ВЫБРАТЬ ПЕРВЫЕ 10 Контрагенты.Наименование КАК Наименование, Контрагенты.ИНН КАК ИНН ИЗ Справочник.Контрагенты КАК Контрагенты"
```

Результат:

```
Наименование | ИНН
ООО Ромашка | 7701234567
ИП Иванов | 772012345678
```

#### Реализация

```bsl
Результат = "пустой";
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;

РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультата = РезультатЗапроса.Выгрузить();

Разделитель = " | ";

ЧастиЗаголовка = Новый Массив;
Для Каждого Колонка Из ТаблицаРезультата.Колонки Цикл
    ЧастиЗаголовка.Добавить(Колонка.Имя);
КонецЦикла;

Результат = СтрСоединить(ЧастиЗаголовка, Разделитель);

Для Каждого СтрокаТаблицы Из ТаблицаРезультата Цикл
    ЧастиСтроки = Новый Массив;
    Для Каждого Колонка Из ТаблицаРезультата.Колонки Цикл
        Значение = СтрокаТаблицы[Колонка.Имя];
        ЧастиСтроки.Добавить(Строка(Значение));
    КонецЦикла;
    Результат = Результат + Символы.ПС + СтрСоединить(ЧастиСтроки, Разделитель);
КонецЦикла;
```

{% hint style="warning" %}
**Ограничение**: Запрос должен быть в одну строку, без переносов. Все параметры запроса должны быть заданы непосредственно в тексте.
{% endhint %}

***

### vcvalidatequery

Проверяет синтаксическую корректность запроса без его выполнения.

| Параметр    | Тип    | Описание                   |
| ----------- | ------ | -------------------------- |
| `querytext` | Строка | Текст запроса для проверки |

**Возврат**: `нет ошибок` или описание найденной ошибки.

#### Пример использования

```
querytext: "ВЫБРАТЬ Контрагенты.Ссылка ИЗ Справочник.Контрагенты КАК Контрагенты"
```

Результат: `нет ошибок`

#### Пример с ошибкой

```
querytext: "ВЫБРАТЬ НесуществующееПоле ИЗ Справочник.Контрагенты"
```

Результат: `Поле "НесуществующееПоле" не найдено...`

#### Реализация

```bsl
Результат = "нет ошибок";
Запрос = Новый Запрос();
Запрос.Текст = ТекстЗапроса;
Попытка
    Запрос.НайтиПараметры();
Исключение
    Результат = ОписаниеОшибки();
КонецПопытки
```

***

### vcloggetlasterror

Возвращает последнюю ошибку из Журнала регистрации за последние 24 часа.

| Параметр | Тип | Описание              |
| -------- | --- | --------------------- |
| —        | —   | Параметры отсутствуют |

**Возврат**: Информация об ошибке или `ошибок не найдено`.

#### Пример результата

```
Дата: 19.03.2026 14:32:15
Событие: Данные.Ошибка
Метаданные: Документ.РеализацияТоваровУслуг
Данные: РеализацияТоваровУслуг 00001234
Описание: Поле объекта не обнаружено (НесуществующееПоле)
```

#### Реализация

```bsl
Результат = "ошибок не найдено";
Отбор = Новый Структура;
Отбор.Вставить("ДатаНачала", ТекущаяДатаСеанса() - 86400);
Отбор.Вставить("Уровень", УровеньЖурналаРегистрации.Ошибка);

Колонки = "Дата, Комментарий, ПредставлениеМетаданных, ПредставлениеСобытия, ПредставлениеДанных";

СобытияЖурнала = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(СобытияЖурнала, Отбор, Колонки, , 1);

Если СобытияЖурнала.Количество() = 0 Тогда
    Результат = "ошибок не найдено";
КонецЕсли;

Запись = СобытияЖурнала[0];

Части = Новый Массив;
Части.Добавить("Дата: " + Формат(Запись.Дата, "ДЛФ=ДВ"));
Части.Добавить("Событие: " + Запись.ПредставлениеСобытия);
Части.Добавить("Метаданные: " + Запись.ПредставлениеМетаданных);
Части.Добавить("Данные: " + Запись.ПредставлениеДанных);
Части.Добавить("Описание: " + Запись.Комментарий);

Результат = СтрСоединить(Части, Символы.ПС);
```

***

## Создание собственных инструментов

### Структура инструмента

Каждый инструмент в справочнике `APA_Инструменты` содержит:

| Реквизит     | Тип             | Описание                                |
| ------------ | --------------- | --------------------------------------- |
| Наименование | Строка          | Системное имя инструмента (латиница)    |
| Описание     | Строка          | Описание для ИИ — что делает инструмент |
| ЗапросКод    | Строка          | Код на языке 1С                         |
| Параметры    | Табличная часть | Входные параметры инструмента           |

### Табличная часть «Параметры»

| Колонка  | Описание                              |
| -------- | ------------------------------------- |
| Имя      | Имя параметра на русском (для кода)   |
| ИмяEn    | Имя параметра на английском (для MCP) |
| Описание | Описание параметра для ИИ             |

### Правила написания кода

1. **Переменная `Результат`**: Определите переменную `Результат` — её значение будет возвращено ИИ.
2. **Параметры**: Параметры из табличной части автоматически доступны в коде по русскому имени (`Имя`).
3. **Обработка ошибок**: Оборачивайте код в `Попытка...Исключение` для возврата понятных сообщений об ошибках.
4. **Текстовый результат**: Возвращайте результат в текстовом виде — ИИ лучше работает с текстом.

### Пример: получение информации о контрагенте

```bsl
// Имя: ПолучитьКонтрагента
// Параметр: ИНН (inn) — ИНН контрагента для поиска

Результат = "Контрагент не найден";

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Контрагенты.Наименование КАК Наименование,
    |    Контрагенты.ИНН КАК ИНН,
    |    Контрагенты.КПП КАК КПП,
    |    Контрагенты.ЮридическийАдрес КАК Адрес
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |    Контрагенты.ИНН = &ИНН";
Запрос.УстановитьПараметр("ИНН", ИНН);

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    Части = Новый Массив;
    Части.Добавить("Наименование: " + Выборка.Наименование);
    Части.Добавить("ИНН: " + Выборка.ИНН);
    Части.Добавить("КПП: " + Выборка.КПП);
    Части.Добавить("Адрес: " + Выборка.Адрес);
    Результат = СтрСоединить(Части, Символы.ПС);
КонецЕсли;
```

### Пример: создание документа

```bsl
// Имя: СоздатьЗаказПокупателя
// Параметры:
//   КонтрагентИНН (customer_inn) — ИНН покупателя
//   Сумма (amount) — сумма заказа

Результат = "Ошибка создания заказа";

Попытка
    // Поиск контрагента
    Контрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", КонтрагентИНН);
    Если Не ЗначениеЗаполнено(Контрагент) Тогда
        Результат = "Контрагент с ИНН " + КонтрагентИНН + " не найден";
        Возврат;
    КонецЕсли;
    
    // Создание документа
    Заказ = Документы.ЗаказПокупателя.СоздатьДокумент();
    Заказ.Дата = ТекущаяДатаСеанса();
    Заказ.Контрагент = Контрагент;
    Заказ.СуммаДокумента = Число(Сумма);
    Заказ.Записать();
    
    Результат = "Создан заказ " + Заказ.Номер + " от " + Формат(Заказ.Дата, "ДЛФ=D");
Исключение
    Результат = "Ошибка: " + ОписаниеОшибки();
КонецПопытки;
```

## Рекомендации по созданию инструментов

### Именование

* Используйте понятные имена на латинице: `getCustomer`, `createOrder`, `validateDocument`
* Имя должно отражать действие инструмента

### Описание

* Пишите подробное описание для ИИ
* Укажите, какие данные принимает и возвращает инструмент
* Приведите примеры использования

### Безопасность

* Ограничивайте права пользователя, от имени которого работает MCP
* Не давайте инструментам доступ к критичным операциям без необходимости
* Логируйте вызовы инструментов для аудита

### Производительность

* Избегайте тяжёлых операций в инструментах
* Ограничивайте количество возвращаемых записей
* Используйте параметризованные запросы
