mcp-1c
Servidor MCP de estructura de configuraciones 1C
Referencia de metadatos de varias configuraciones 1C, de la sintaxis de la plataforma y del lenguaje de consultas — para agentes que escriben código en BSL. Devuelve un recorte mínimamente suficiente: resolución de una formulación humana al nombre exacto del objeto, búsqueda de procedimientos listos en la descarga de código, sus firmas, ventanas limitadas de cuerpos y relaciones inversas desde llamadas, metadatos y formularios, la estructura del objeto al nivel de detalle necesario, sus relaciones, la descripción de los métodos de la plataforma teniendo en cuenta la versión de la configuración concreta y las construcciones del lenguaje de consultas.
No sustituye al grep sobre los fuentes de trabajo del proyecto: el servidor busca procedimientos solo en la descarga cargada de la configuración a archivos y no ve las ediciones no cargadas. El límite de las fuentes está fijado en docs/data-sources.md.
Estado — a 2026-08-21
Etapa | Estado |
Procesamiento de descarga para 1C | ✅ 20 tipos de metadatos, 8.3.5 y 8.3.23, XML y JSON |
Formato de descarga | |
Cargador, modelo, grafo de relaciones, render | ✅ 5 configuraciones, 20 522 objetos, 322 mil aristas |
Ayuda de la plataforma | ✅ índice fusionado de tres versiones, 25 691 elementos, límites |
Lenguaje de consultas | ✅ |
Búsqueda | ✅ 97,1 % ayuda, 94,7 % lenguaje de consultas, 90,5 % metadatos — véase «Medido» |
Tablas virtuales de registros | ✅ nombres de campos de consulta listos ( |
Tabla de sustituciones para plataformas antiguas | ✅ lo no disponible no solo se prohíbe, sino que se sustituye por una receta |
Registro de fuentes, correspondencia de versiones | ✅ |
Servidor MCP, 10 herramientas | ✅ streamable-http y stdio |
Docker | ✅ un solo contenedor, |
Caché de índices de búsqueda | ✅ 12 MB, se levanta en lugar de volver a analizar |
Banco de mediciones | ✅ |
Pruebas | ✅ |
Panel | ✅ registro, fuentes, ejecución de consultas, grafo de relaciones, fichas, diccionario |
Autorización | ✅ |
Recepción de descarga de configuración a archivos | ✅ |
Índices de código de la descarga a archivos | ✅ búsqueda, ficha de procedimiento y búsqueda inversa de llamadas |
El tamaño de la imagen final se verificó el 2026-08-21: el comando
docker image ls mcp1c:latest --format '{{.Size}}' devolvió 357MB.
Este es el tamaño mostrado por Docker CLI. El comando
docker image inspect mcp1c:latest --format '{{.Size}}' devolvió 77950901 bytes
del campo interno;
esta es otra métrica, no una segunda medición del tamaño mostrado.
No hay restricciones sobre la configuración. Se carga cualquiera — típica (contabilidad, nóminas, gestión documental, retail) y sectorial: el procesamiento de descarga recorre los metadatos, no los conoce de memoria. Se analiza lo que se descargó.
Importa la versión de la plataforma en la que funciona la configuración: de ella
depende qué mostrará get_syntax como disponible y qué ocultará como más reciente.
Verificado en 8.3.5 y 8.3.23 — estos son los límites de lo que se ha encontrado; las
ayudas están fusionadas de tres versiones, 8.3.5, 8.3.23 y 8.3.27. El procesamiento de
descarga, por su parte, debe compilarse en 8.3.5: el límite inferior lo fija él, no el servidor.
Related MCP server: 1C_MCP_SERVER_OWN
Contenido
Arranque — Docker, panel, grafo de relaciones, sin Docker
Conexión del agente — cómo funciona MCP, si no se conecta, token, configuraciones de clientes: Claude Code, Codex CLI, Cursor, VS Code, Qwen Code, stdio
Herramientas — orden de llamadas, fuentes, lenguaje de consultas, versiones de plataforma, fusión de ayudas, sustituciones
Gestión de datos — fuentes, descarga de configuración a archivos, diccionario y claves de búsqueda, CLI, banco de mediciones, servidor manual, de dónde sacar los datos
Cómo está organizado — módulos, mediciones, pruebas
Seguridad — tokens, qué está abierto sin ellos
Licencia — Apache 2.0, relación con la empresa «1C»
1. Arranque
Docker (forma principal)
# 1. Положить исходные данные
mkdir -p data/bootstrap
cp ВыгрузкаКонфигурации.zip data/bootstrap/
cp /opt/1cv8/8.3.27.2130/shcntx_ru.hbk data/bootstrap/
# 2. Поднять
docker compose up -d --build
# 3. Проверить
curl http://localhost:5001/health{"status":"ok",
"configurations_total":2,
"syntax_loaded":true,
"query_language_loaded":true,
"configurations":["РозницаДляКазахстана","ОтраслеваяКонфигурация"],
"syntax":["8.3.5.1570","8.3.23.1997","8.3.27"]}La ayuda de la plataforma y el lenguaje de consultas son fuentes distintas y campos distintos:
syntax_loaded se refiere solo a la primera, syntax enumera las versiones
de las ayudas cargadas. Los nombres de las configuraciones y las versiones de las ayudas se entregan
solo a una solicitud que haya pasado la verificación de lectura; sin token quedan status,
el contador y dos indicadores.
Todo lo que está en data/bootstrap/ se indexa al arrancar: *.zip — descargas
de configuraciones, *.hbk — ayuda de la plataforma. Un mismo archivo no se
vuelve a analizar: la verificación se hace por hash.
Una descarga de configuración a archivos colocada en bootstrap/ por costumbre no
sirve: el servidor la reconoce por la composición del archivo (hay código, no hay
manifiesto manifest.json / manifest.xml) y no intenta analizarla: son gigabytes,
que no se pueden procesar en cada arranque. En lugar de un error, en la lista de mensajes
de arranque se menciona su nombre con un recordatorio de dónde colocar esos archivos —
data/incoming/, sección «Descarga de configuración a archivos»
más abajo.
El directorio ./data se monta en el contenedor como /data. Dentro de él el servidor guarda
los fuentes, los índices, la caché y registry.json; las rutas en el registro son relativas, por lo
que el directorio se puede trasladar entre la máquina del desarrollador y el contenedor.
data/ está completamente fuera de git — es un volumen, no parte del repositorio. Se traslada
copiando el directorio. Por eso, después de clonar, la ayuda hay que colocarla
uno mismo: el repositorio no la contiene ni puede contenerla, es contenido de la empresa
«1C».
Después de cambiar el código, el contenedor hay que recrearlo, no reiniciarlo:
docker compose up -d --build --force-recreaterestart levantará el contenedor anterior con la imagen anterior, y los cambios no se aplicarán.
Sobre el puerto. Hacia afuera el servidor está expuesto en 5001, dentro del contenedor escucha en 8000 —
reenvío 5001:8000 en docker-compose.yml. Todas las direcciones en ese archivo son externas,
es decir, 5001. Si está ocupado por otro servicio — cambie la parte izquierda del reenvío, la derecha
no la toque: de ella dependen EXPOSE y el healthcheck de la imagen.
Panel
http://localhost:5001/ — seis páginas:
Página | Qué hay allí |
Resumen | qué está cargado: objetos, relaciones, versión de la plataforma, advertencias de los manifiestos |
Fuentes | lista de lo cargado, tres tablas de cobertura de cada corpus de código, ruta al registro JSON completo, carga de |
Consultas | ejecución de una lista de formulaciones con evaluación y motivo del ranking |
Relaciones | grafo del entorno del objeto como imagen |
Ficha | composición del objeto o descripción del elemento de la plataforma — lo mismo que ve el agente |
Diccionario | reglas con procedencia; crear un alias o un grupo de sinónimos |
Carga — qué se ve y cuándo
La carga se realiza en dos etapas, y se muestran de manera diferente.
Transferencia del archivo — con una barra en la página «Fuentes»: porcentajes, volumen,
velocidad y estimación del resto. La calcula el navegador, y no es un capricho.
El servidor no ve el progreso de la transferencia: await request.form() devuelve
el control solo cuando el cuerpo ha llegado por completo, y la tarea se crea después de
eso. Verificado en un socket real: 40 MB tardaron 8,1 s, durante ese tiempo 32 sondeos
de /sources desde una segunda conexión no vieron ninguna tarea. En localhost
no hay diferencia, en un servidor remoto son minutos de pantalla vacía.
Además, el límite de 500 MB se verifica antes del envío: antes un archivo demasiado grande se subía por completo y solo después recibía el rechazo.
Análisis — con la tabla «Carga» en la misma página: «recibiendo» →
«analizando» → «listo» o «error» con el motivo. Mientras el trabajo está en curso, la página
se actualiza sola (meta refresh, cada 2 s).
La barra requiere JS, la tabla no. Con JS desactivado el formulario funciona como uno normal: el archivo se envía, la tarea se crea, el estado se ve en la tabla — solo falta la barra durante la transferencia.
Relaciones — grafo del objeto
/graph dibuja el entorno del objeto: color según el tipo, flecha según la dirección de la
referencia, etiqueta de la arista al pasar el cursor. Un clic en un nodo construye el grafo a su
alrededor, el arrastre mueve, la rueda escala. El límite de vecinos se elige en la
página (15…400), el recorte se indica con un número — «mostrados 30 de 102».
Responde a «qué se romperá si toco esto»: un registro rodeado de documentos naranjas dice de inmediato quién lo mueve.
La profundidad es siempre de un paso. A dos pasos de un directorio de uso frecuente se
obtienen mil objetos, a tres — un tercio de la configuración; más allá la relación pasa por mecanismos
comunes como los atributos adicionales, que conectan casi todo con
todo. No se pueden descartar con un umbral por número de relaciones: ese nodo tiene 34, y
un Directorio.Usuarios con sentido — 323. Por eso los nodos los expande una persona,
no una heurística — ella ve a dónde no conviene ir.
El agente no tiene esa herramienta a propósito. En dos pasos, el grafo crece hasta mil objetos, y no se pueden descartar los mecanismos comunes con un umbral simple: un nodo con sentido puede tener más conexiones que uno técnico. Una herramienta separada solo volverá junto con una regla medible de limitación de resultados; por ahora, el siguiente paso exacto lo elige una persona en el grafo interactivo.
El fallo se corrige sin salir del navegador: en la página de consultas, cada frase tiene un enlace «no es esto — crear un alias», que lleva al diccionario con la frase ya insertada. La edición surte efecto de inmediato: los índices no se reconstruyen y no hace falta reiniciar.
La lectura se cierra con API_TOKEN; la escritura, con ADMIN_TOKEN. Mientras API_TOKEN no esté definido, cualquiera que llegue a la dirección puede leer —incluida la estructura de configuraciones y las mejoras. Para localhost es aceptable; para un servidor en red, no.
Los tokens están separados porque el token de lectura reside en la configuración de cada cliente MCP y se filtra junto con ella; el agente no debería tener permisos para eliminar fuentes. El token de administrador también sirve como token de lectura: no hace falta mantener dos cabeceras.
// .mcp.json — как клиент передаёт токен
{"mcpServers": {"1c": {"type": "http", "url": "http://localhost:5001/mcp",
"headers": {"X-Api-Token": "..."}}}}Solo ASCII: las cabeceras HTTP se codifican en latin-1; la cirílica no llegará a través de ellas. /health permanece abierto para el healthcheck, pero solo devuelve los nombres de las configuraciones mediante token.
La carga, eliminación y edición del diccionario requieren ADMIN_TOKEN —el mismo que en /admin/reload; sin él, estas rutas no existen, no es que «estén cerradas». El token se introduce una sola vez en el formulario; al navegador no llega él, sino un identificador de sesión.
Se define mediante .env junto a docker-compose.yml —la plantilla con todas las variables está en .env.example:
cp .env.example .env
python3 -c "import secrets; print(secrets.token_urlsafe(32))" # значение
docker compose up -d --force-recreateEl nombre en los resultados es un enlace a la ficha: para un objeto, son los atributos con tipos, las partes tabulares y los movimientos; para un elemento de la plataforma, la firma, los parámetros, la disponibilidad y la versión de aparición. El mismo texto que recibe el agente, con el conmutador brief / fields / full. Un atributo no tiene ficha propia: el enlace lleva al objeto propietario.
La página «Consultas» responde a la pregunta «por qué el servidor devolvió exactamente esto»: junto a cada acierto aparece el motivo —coincidencia exacta, alias del diccionario, todas las palabras de la consulta. Con ella se ve con qué tratar el fallo: con un sinónimo, un alias o un peso.
El análisis de la ayuda tarda unos segundos: la página responderá después de él, pero esto no retrasa a los clientes MCP —la indexación va a un hilo separado.
Sin Docker
Desde una copia del repositorio —igual que se ejecutan las pruebas y la CLI:
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
PYTHONPATH=src .venv/bin/python -m mcp1c.server --host 0.0.0.0 --port 5001O como paquete —entonces PYTHONPATH no hace falta y aparecen tres comandos al lado:
pip install .
mcp1c-server --host 0.0.0.0 --port 5001 # = python -m mcp1c.server
mcp1c reg-list --data data # = python -m mcp1c.cli
mcp1c-bench --help # = python -m mcp1c.benchEl arranque modular (python -m mcp1c.server) sigue funcionando también en este caso: los comandos son los mismos puntos de entrada con otro nombre. Todas las claves están descritas en la sección «Gestión de datos».
2. Conexión del agente
El servidor implementa el protocolo MCP con los transportes estándar del SDK oficial, por lo que sirve para cualquier cliente MCP. No se necesita ningún envoltorio alrededor de HTTP.
Transporte | Cuándo | Dirección |
streamable-http | servidor en Docker o en una máquina aparte |
|
stdio | el cliente inicia el proceso localmente | — |
Ambos transportes admitidos están probados con el cliente MCP oficial: el apretón de manos initialize, tools/list, tools/call, protocolo 2025-11-25.
El transporte obsoleto HTTP+SSE no se admite: --transport sse se rechaza como valor no válido antes de leer los datos y de arrancar el servidor. Un cliente antiguo necesita el modo streamable-http o el arranque local mediante stdio.
Cómo funciona
Conviene entenderlo antes de que algo no se conecte. La dirección es una sola — /mcp; no hay rutas por herramienta; qué herramienta se invoca está escrito en el cuerpo de la petición, no en la ruta.
Luego hay dos mecánicas distintas, y no conviene confundirlas:
Descripciones de herramientas | Datos | |
Cuándo | una vez, al conectar | en cada invocación |
Quién inicia | el cliente, solo, sin participación del modelo | el modelo, por decisión |
Método |
|
|
Dónde acaba | en el prompt del sistema del modelo | en el cuerpo de la conversación |
Coste | una sola vez, permanece toda la sesión | por cada invocación |
Al conectar, el cliente hace POST initialize —el servidor responde con el nombre, la versión y el texto de instructions, y en la cabecera devuelve mcp-session-id. Luego POST tools/list entrega las herramientas de una vez: nombre, descripción, esquema JSON de parámetros. Todo esto se coloca en el contexto del modelo antes de que la persona haya escrito la primera palabra. El modelo no va a buscar la descripción cuando la necesite —ya la tiene.
De aquí se deduce una consecuencia importante al editar descripciones: ocupan espacio en la ventana durante toda la sesión, independientemente de si el modelo invoca una herramienta o ninguna.
Las herramientas son siempre diez, independientemente de lo que esté cargado. El conjunto es un contrato, no una variable: las herramientas están relacionadas entre sí, y en un servidor de producción las fuentes de configuración, código, ayuda de la plataforma y lenguaje de consultas pueden cargarse de forma independiente. El tamaño del contrato tools/list más instructions no depende del estado del registro.
De aquí se deduce directamente algo que hay que saber de antemano: si una fuente no está cargada, igual pagas por sus herramientas. Sin la ayuda de la plataforma, search_syntax y get_syntax están en el contexto y cuestan 1 185 tokens, respondiendo «ayuda no conectada»; compare_configurations con una sola configuración —262 tokens para la respuesta «se necesitan al menos dos». Esto se soluciona cargando la fuente, no seleccionando herramientas: el conjunto dinámico se probó el 2026-08-19 y se descartó, porque las fuentes independientes deben mantener un contrato de sesión único.
Por eso las descripciones se escriben de forma densa, y los detalles se van a la salida de la propia herramienta: por ellos solo se paga cuando se necesitan.
GET /mcp no es un «POST incorrecto», sino un tercer método en la misma dirección: abre un flujo de mensajes del servidor al cliente y requiere un mcp-session-id ya obtenido. DELETE /mcp cierra la sesión.
Si el cliente no se conecta
El código de respuesta en el registro (docker logs -f mcp1c) indica la causa:
Código | Qué falla |
| el cliente no envía |
| el cliente no devolvió la cabecera |
| el cliente comenzó el apretón de manos con |
| lo mismo: el transporte antiguo está completamente desactivado |
| no se envió |
el registro está vacío | el cliente no envió ninguna petición — el problema está en su configuración, no llegó al servidor |
Caso real: Qwen Code no se conectaba porque en su configuración estaba la clave url —en la familia Gemini CLI (Qwen hereda el formato) significa el transporte SSE antiguo, y el cliente empezaba con GET, recibiendo 400. Con httpUrl —es decir, streamable-http— la conexión se establece de inmediato.
Token: qué añadir a la configuración del cliente
Si en el servidor está definido API_TOKEN, cada cliente está obligado a enviarlo en la cabecera. Sin la cabecera, /mcp responde 401, y el agente simplemente no verá las herramientas.
Sirve cualquiera de las dos cabeceras: el servidor acepta ambas:
X-Api-Token: <токен>
Authorization: Bearer <токен>Tres cosas con las que se tropieza:
Solo ASCII. Las cabeceras HTTP se codifican en latin-1; un token cirílico no llegará a través de ellas. Generarlo así:
python3 -c "import secrets; print(secrets.token_urlsafe(32))".En el cliente se pone
API_TOKEN, noADMIN_TOKEN. El de administrador también lo aceptarán, pero la configuración del cliente va a git y a las copias de seguridad: un token de lectura filtrado permite ver; uno de administrador filtrado, borrar fuentes.stdiono requiere token en absoluto. Allí el cliente inicia el proceso él mismo, la red no participa y no hay nada que comprobar. Si el cliente no sabe definir cabeceras —esta es una vía alternativa viable.
Comprobar que el servidor ve el token, antes de cualquier configuración del cliente:
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
-H 'x-api-token: ВАШ_ТОКЕН' \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}' \
http://localhost:5001/mcp200 — token aceptado. 401 — token incorrecto o la cabecera no llegó.
Cómo no commitear un secreto
.mcp.json y archivos similares suelen estar en el repositorio. Opciones:
Sustitución de variable —si el cliente lo permite (Claude Code lo permite):
"X-Api-Token": "${MCP1C_API_TOKEN}", y la variable en~/.zshrc. A git va el nombre de la variable, no el valor.Sacar el archivo de git:
git rm --cached .mcp.json && echo ".mcp.json" >> .gitignore.Mantener la configuración no en el proyecto, sino en la configuración de usuario del cliente —entonces el repositorio no tiene nada que ver.
Claude Code
Archivo .mcp.json en la raíz del proyecto:
{
"mcpServers": {
"1c": {
"type": "http",
"url": "http://localhost:5001/mcp",
"headers": { "X-Api-Token": "${MCP1C_API_TOKEN}" }
}
}
}El bloque headers solo hace falta si en el servidor está definido API_TOKEN. El valor se toma de una variable de entorno para que el archivo pueda estar en el repositorio:
echo 'export MCP1C_API_TOKEN=ваш_токен' >> ~/.zshrc && source ~/.zshrcO mediante comando:
claude mcp add --transport http 1c http://localhost:5001/mcp \
--header "X-Api-Token: $MCP1C_API_TOKEN"Codex CLI
~/.codex/config.toml o .codex/config.toml en el proyecto:
[mcp_servers.mcp1c]
url = "http://localhost:5001/mcp"
# Только если задан API_TOKEN. Имя ключа для заголовков у Codex менялось между
# версиями — сверьтесь со своей (`codex --help`, раздел MCP). Не подхватилось —
# используйте stdio, там токен не нужен вовсе.
[mcp_servers.mcp1c.http_headers]
X-Api-Token = "ваш_токен"Cursor
.cursor/mcp.json:
{
"mcpServers": {
"1c": {
"type": "streamable-http",
"url": "http://localhost:5001/mcp",
"headers": { "X-Api-Token": "ваш_токен" }
}
}
}VS Code (Copilot)
.vscode/mcp.json —aquí la clave se llama servers:
{
"servers": {
"1c": {
"type": "http",
"url": "http://localhost:5001/mcp",
"headers": { "X-Api-Token": "ваш_токен" }
}
}
}Qwen Code
Formato de Gemini CLI, y la clave elige el transporte —esta es la única sutileza:
{
"mcpServers": {
"1c": {
"httpUrl": "http://localhost:5001/mcp",
"headers": { "X-Api-Token": "ваш_токен" }
}
}
}httpUrl — streamable-http, nuestro caso. url en este formato significa el transporte SSE antiguo: el cliente comenzará el apretón de manos con GET /mcp, recibirá 400 Missing session ID y no se conectará.
Otros clientes
Windsurf, Antigravity, Cline, Roo Code, agentes de consola —la forma de escritura es la misma: tipo de transporte, URL y, si está definido API_TOKEN, bloque de cabeceras. Las diferencias están solo en el nombre del archivo y en la clave de nivel superior (mcpServers o servers) —consulte la documentación del cliente concreto.
El cliente no sabe definir cabeceras —no es un callejón sin salida: conéctese mediante stdio, allí no se necesita token porque no hay red.
Arranque local mediante stdio
Cuando el cliente debe levantar el servidor él mismo. Aquí no se necesita token: el proceso lo inicia el cliente, la comunicación va por los canales del proceso, no por la red —no hay nada que comprobar ni de qué protegerse.
{
"mcpServers": {
"1c": {
"command": "python3",
"args": ["-m", "mcp1c.server", "--transport", "stdio", "--data", "/путь/к/data"],
"env": { "PYTHONPATH": "/путь/к/проекту/src" }
}
}
}3. Herramientas
El conjunto es fijo y deliberadamente pequeño: cada herramienta está permanentemente en el contexto del agente. Una herramienta nueva aparece solo para una tarea de usuario específica, no para cada índice interno.
Herramienta | Propósito |
| qué está cargado, qué proveedores están disponibles para cada configuración |
| formulación humana → nombre exacto del objeto |
| nombre exacto o palabras → procedimientos en el código de la configuración o de una extensión |
| índice del módulo o firma, contexto de compilación y ventana del cuerpo del procedimiento |
| lugares de llamada confirmados, enlaces de metadatos y manejadores de formulario |
| composición del objeto; |
| movimientos, referencias, dependencias — solo directas |
| un objeto en dos configuraciones |
| búsqueda en la ayuda de la plataforma y en el lenguaje de consultas |
| firma, parámetros, disponibilidad, versión, sustitución para plataforma antigua |
config es obligatorio cuando hay más de una configuración cargada: el servidor
deliberadamente no la sustituye en silencio — de lo contrario el agente escribiría
código basándose en una base ajena y nadie se enteraría.
list_configurations muestra el estado real del índice de código de la
configuración principal y de cada extensión: listo, en construcción con etapa y
progreso, error o código no cargado. Para una extensión lista se muestra el
número de solapamientos según las cuatro anotaciones, la cantidad de módulos
afectados y de procedimientos propios, así como el parámetro extension listo
para acceder a su código. Un corpus listo con variante desconocida o dañada se
denomina estado «listo con restricciones». Las tres envolturas reciben
agregados exactos de una misma generación, pero los muestran según su tarea.
list_configurations y reg-list conservan el diagnóstico detallado:
categorías, los primeros 20 problemas en orden estable y el número exacto de los
restantes; para un candidato no direccionable solo se muestra el número de orden,
sin nombre físico ni ruta local. /sources en lugar de la cinta de direcciones
muestra tres tablas contrastables con cantidad, porcentaje y denominador
explícito: módulos y procedimientos, estructuras de formularios, módulos de
formularios.
La lista completa de cada corpus se almacena atómicamente en un único archivo
actual data/logs/code-<sha256 source_id>.json. La configuración principal y
cada extensión tienen registros distintos; una recarga reemplaza solo su propio
archivo, la eliminación de la fuente elimina el suyo. Un registro dañado, de
generación ajena o que diverge sustancialmente de los índices actuales no se
muestra como actual y se reconstruye a partir de los índices listos. Las
estructuras de formularios muestran por separado cuántas están completamente,
parcialmente o no leídas.
El contrato y los invariantes de schema v1 se describen a continuación. La
advertencia está por encima de la respuesta incompleta y dice directamente: un
contador en cero no demuestra la ausencia de datos ocultos.
Registro de cobertura de código — schema v1
Un archivo pertenece a una única fuente eliminable de forma independiente
<Configuración>:modules o <Configuración>:ext:<Extensión>. El nombre
original no se incluye en la ruta: el archivo se denomina según el sha256
completo de source_id.
{
"schema_version": 1,
"kind": "module_coverage",
"source": {
"id": "Отраслевая конфигурация:modules",
"kind": "modules",
"sha256": "...",
"loaded_at": "2026-08-24T12:00:00+00:00",
"selection_version": 4,
"locator_generation": 3,
"code_version": "1.0.0"
},
"identity": {
"source_id": "Отраслевая конфигурация:modules",
"source_sha256": "...",
"generation": 3
},
"coverage": {
"modules": {
"total": 2,
"source_available": 1,
"empty": 0,
"partial": 0,
"unreadable": 0,
"conflict": 0,
"compiled_without_source": 1
},
"procedures": {"total": 1, "full": 1, "partial": 0},
"form_structures": {
"total": 1, "full": 0, "partial": 1, "unavailable": 0
},
"form_modules": {
"total": 1, "read": 1, "empty": 0, "missing": 0, "unreadable": 0
},
"limitations": {
"categories": {"compiled_without_source": 1, "unknown_marker": 1},
"occurrences_total": 2,
"problem_rows_total": 2,
"unknown_markers": 1,
"known_markers_incomplete": 0,
"unsupported_addresses": 0,
"broken_containers": 0,
"unreadable_bodies": 0,
"budget_exceeded": 0,
"body_conflicts": 0,
"compiled_without_source": 1
}
},
"problems": [
{
"category": "unknown_marker",
"address": "ОбщаяФорма.Пример",
"ordinal": 0,
"reason": "маркер form не поддержан",
"marker": 99
},
{
"category": "compiled_without_source",
"address": "ОбщийМодуль.Пример",
"ordinal": 0,
"reason": "скомпилированный модуль без исходника",
"marker": null
}
]
}Las categorías modules, procedures, form_structures y form_modules en
suma deben dar su total; ambas tablas de formularios tienen un mismo
denominador; problem_rows_total es igual a la longitud del problems completo.
address es igual a null si la dirección canónica no puede demostrarse,
entonces ordinal es el número determinista del candidato. marker almacena el
marcador leído de la estructura form o null si el problema no se refiere a
él. identity vincula el registro con el sha256 y la generación del catálogo de
localizadores.
En el archivo no entran rutas absolutas, excepciones crudas, traceback, tokens,
cuerpos BSL ni la escritura cruda de form. El catálogo se abre sin seguir el
enlace simbólico, el archivo temporal se crea dentro de él y reemplaza
atómicamente al final. El fallo de escritura no cancela la disponibilidad del
corpus.
get_object añade información sobre el código según detail: en brief no
recurre al proveedor de código, en fields da una sola línea con contadores, en
full enumera los módulos y todos los formularios del objeto sin su contenido.
El formulario permanece visible por cualquier evidencia: descriptor XML propio,
Form.xml, Form.bin, .Form plano o un único módulo de formulario.
Si el índice se está construyendo, terminó con error o no está cargado, los
metadatos del objeto se devuelven igualmente junto con el estado honesto del
código. get_related marca los objetos relacionados cuyos procedimientos están
realmente solapados por cualquier extensión cargada; un procedimiento propio de
la extensión no crea tal marca. En fields y full la tarjeta del objeto
enumera sin límite general las causas relativas a sus formularios, por lo que un
formulario no leído no se convierte en un falso «no hay formularios». Las
herramientas de procedimientos y relaciones también colocan la advertencia por
encima del resultado parcial; el cambio de generación repite toda la respuesta
junto con los contadores y problemas.
search_procedures combina dos niveles. La coincidencia exacta de nombre
encuentra cualquier procedimiento, incluido el no exportado; la búsqueda por
palabras, declinaciones y comentario de cabecera funciona solo con los
exportados. En cada nivel limit se establece por separado y debe ser un entero
de 1 a 50. En la respuesta llegan la dirección Módulo::Nombre, la firma desde
el disco, la exportabilidad, la línea, el número de lugares de llamada
confirmados y un contador separado de lugares homónimos cuya resolución no fue
posible. El índice booleano de anotación de extensión se denomina de forma
neutral: no presenta &Después o &Antes como solapamiento completo del
procedimiento original. Las firmas y los cuerpos no se almacenan en memoria
operativa. Los .bsl jerárquicos, los .txt planos y la escritura module de
los contenedores fuente Form.bin/.Form pasan por el mismo lexer; la búsqueda
y la tarjeta posterior usan el localizador de una misma generación y no
reconstruyen la ruta desde la dirección.
Sin scope la búsqueda es global. Un scope="Documento.ChequeKKM" explícito
eleva todos los módulos del objeto, y scope="ModuloComun.DeUsoGeneral" u otra
dirección exacta — un solo módulo; el resto de resultados queda por debajo. El
ámbito no se adivina a partir de query. extension selecciona exactamente una
extensión cargada; sin ella la búsqueda va solo por la configuración principal.
get_procedure acepta la dirección exacta de la búsqueda. La dirección de módulo
sin :: devuelve el índice sin cuerpos; Módulo::Nombre — la firma, el contexto
de compilación y el cuerpo. start_line comienza en 0, lines debe ser un
entero de 1 a 200; una respuesta larga contiene la llamada lista de la siguiente
ventana sin saltarse líneas. Para la extensión seleccionada &Después, &Antes
y &EnLugarDe muestran su cuerpo; &CambioYControl — el cuerpo de la
configuración principal y solo los bloques literales #Inserción/#Eliminación.
Sobre otras extensiones cargadas la herramienta advierte por encima del cuerpo,
pero no mezcla su código en la respuesta. Las firmas y los cuerpos se leen desde
el disco para una sola respuesta y no permanecen en memoria operativa.
El mismo localizador sobrevive a la caché y al reinicio: si la fuente se
reemplaza durante la lectura, toda la respuesta se repite según la nueva
generación y las partes de dos generaciones no se mezclan.
get_callers acepta solo la dirección exacta Módulo::Nombre. Primero agrupa
los lugares de llamada confirmados por módulo y nombra el procedimiento
propietario, luego muestra las suscripciones a evento y las tareas reglamentarias
del grafo de metadatos, después de ellas — el elemento y el evento de formulario
de Form.xml. limit debe ser un entero de 1 a 50; tras el truncamiento quedan
los números exactos de lugares y módulos. El descriptor o la escritura de
contenedor por sí solos no demuestran la ausencia de manejador: con semántica
posicional no demostrada la herramienta informa de cobertura parcial. El estado
de Form.xml se almacena por separado, por lo que los enlaces XML correctos
siguen disponibles incluso con un defecto del contenedor vecino. Las llamadas a
un procedimiento homónimo sin módulo resuelto se muestran por separado y no se
atribuyen a la dirección solicitada. Si dos procedimientos están en la misma
línea física, el propietario no se adivina. La herramienta no lee los textos de
los módulos. La respuesta vacía recuerda que las llamadas por cadena mediante
Ejecutar, DescripcionAviso y ConectarManejadorEspera no se indexan.
Lo que el proveedor no sabe
La búsqueda por palabras va solo por procedimientos exportados. El no exportado se puede encontrar por nombre exacto o mediante el índice de un módulo conocido.
Las llamadas dinámicas, donde el nombre se pasa como cadena en
Ejecutar,DescripcionAvisooConectarManejadorEspera, no se indexan.Un módulo común compilado no tiene fuente disponible: se ve la propia dirección, pero no los procedimientos, llamadas, firmas y cuerpos dentro de él.
En la estructura de contenedor
Form.bin/.Form, incluida la descarga plana, por ahora están demostradas la gramática de paréntesis y los marcadores raíz19,20,23,25,26,27, pero no la asignación de los campos posicionales. Por eso ese formulario se ve como parcialmente leído, y los atributos, elementos y eventos de él no se adivinan. La composición completa y los enlaces siguen disponibles solo desdeForm.xml; el descriptor XML por separado da UUID, nombre, sinónimo y tipo de formulario.Una llamada homónima que no se resuelve hasta un módulo exacto no se atribuye al procedimiento solicitado y se muestra por separado.
Un mismo nombre puede vivir en dos dominios a la vez: StrEncontrar está tanto
en la plataforma (desde 8.3.6) como en el lenguaje de consultas. Entonces
get_syntax enumera los homónimos con la dirección lista de cada uno, y se puede
repetir la llamada con una cadena de la salida:
get_syntax("СтрНайти") → Одноимённых элементов: 2
- `Глобальный контекст.СтрНайти` — Метод, с 8.3.6
- `Запрос.СтрНайти` — Функция запроса
get_syntax("Запрос.СтрНайти") → карточка функции языка запросовEl calificador Consulta. es necesario porque el elemento del lenguaje de
consultas no tiene propietario: no se puede nombrar mediante Objeto.Miembro,
como el de la plataforma.
Orden de llamadas — y qué se pierde si se viola
list_configurations
├─ search_objects → get_object → get_related
├─ search_procedures → get_procedure → get_callers
└─ search_syntax → get_syntaxEn la cadena de código cada paso añade información que el anterior no tiene. Sin
search_procedures hay que saber de antemano la dirección exacta y se pierde la
búsqueda por propósito y ámbito. Sin get_procedure no se muestran la firma, el
contexto de compilación, el cuerpo del procedimiento y la semántica exacta de la
extensión. Sin get_callers no hay verificación de las consecuencias directas
de la edición: lugares de llamada confirmados, enlaces de metadatos y eventos de
formulario.
El paso get_object no se puede omitir. La búsqueda devuelve solo nombres y
contadores; todo lo que afecta al código vive en la tarjeta del objeto:
tipo y periodicidad del registro.
CorteUltimosexiste solo en el registro de información periódico, y en el no periódico 566 de 603;nombres listos de los campos de tablas virtuales. En la consulta el recurso
Cantidadse llamaCantidadSaldo,CantidadMovimiento,CantidadEntrada— en el configurador esos nombres no se ven en ningún lado, los genera la plataforma;límite de subconto, correspondencia, recursos del gráfico — sin ellos no hay con qué nombrar campos del tipo
SubcontoDt1;líneas de longitud ilimitada. Marcadas directamente en el tipo:
Cadena (ilimit. — solo mediante SUBSTRING)frente aCadena(200). Ese campo no se puede poner en la consulta tal cual — la plataforma no permitirá ni compararlo, ni agruparlo, ni ordenarlo. Esos campos son del 23% al 38% de las cadenas en configuraciones reales, por eso en las tarjetas donde aparecen (2 474 de 20 522), antes de la lista de campos se imprime una salvedad con la receta.
Una consulta escrita inmediatamente después de search_objects parece correcta
y falla con «campo no encontrado». Ejemplo de lo que solo llega desde
get_object:
## Таблицы запроса
- `РегистрНакопления.ТоварыНаСкладах.Остатки`
измерения: Склад, Номенклатура, Характеристика
ресурсы: КоличествоОстаток, РезервОстатокUn segundo igual — y se encontró con un fallo real del 2026-08-18. El agente agrupó la consulta por una cadena sin límite de longitud; los datos los dimos correctos, pero la diferencia solo se leía por la ausencia del número entre paréntesis:
> **Строки неограниченной длины** помечены `(неогр.)`. Платформа не даёт их
> сравнивать, группировать и упорядочивать и не пускает в РАЗЛИЧНЫЕ,
> ОБЪЕДИНИТЬ и агрегатные КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ. Ограничивайте
> длину — одинаково в списке выборки и в группировке:
>
> ПОДСТРОКА(КодСкидки, 1, 100) КАК КодСкидки
>
> Длину подбирайте по смыслу поля: 100 — не универсальное число.
## Реквизиты
- `КодСкидки` — Строка (неогр. — только через ПОДСТРОКА) // Код скидки
- `КодМаркировки` — Строка(200) // Код маркировкиEl consejo está tanto en la advertencia como en la propia línea del campo, y no es redundancia.
La primera redacción imprimía la advertencia como último párrafo de la ficha. Un agente en vivo
del 2026-08-18 llamó a get_object con detail=fields, la recibió completa — y aun así
agrupó por ese campo. La advertencia estaba 721 tokens después de la línea del campo, y la decisión se toma donde se copia el nombre. La misma lección ya estaba registrada
en las descripciones de las herramientas: la regla funciona donde se lee, no donde
es más prolijo colocarla.
Cada prohibición está verificada: las agregadas — cita de la ayuda, las otras cinco —
pruebas en base real con textos de error registrados. La ayuda conoce la
restricción solo en tres de las seis funciones agregadas y calla sobre la
agrupación, el ordenamiento, РАЗЛИЧНЫЕ, ОБЪЕДИНИТЬ y la comparación — es decir, un
agente que la haya leído honestamente no podía enterarse. El desglose por
origen está en docs/data-sources.md, sección
«Advertencias en la ficha».
Antes de llamar a una función de la plataforma en configuración antigua — get_syntax.
Lo no disponible se marca, y allí mismo está el consejo de sustitución, si está registrado.
Las fuentes son independientes
Son cinco, y cada una se conecta por separado:
Fuente | Archivo | Qué aporta | Sin ella |
Metadatos de configuración |
| objetos, atributos, vínculos, movimientos |
|
Código de configuración | archivo de descarga de configuración a archivos | procedimientos de la configuración principal, firmas, cuerpos, contexto de compilación, lugares de llamada, eventos de formularios | sin el código de configuración, |
Código de extensión | archivo de descarga de extensión a archivos | procedimientos propios y modificados de la extensión seleccionada, sus cuerpos y lugares de llamada | sin el código de extensión, la configuración principal está disponible, pero |
Ayuda de la plataforma |
| métodos, propiedades, firmas, disponibilidad, versiones |
|
Lenguaje de consultas |
|
| las construcciones del lenguaje de consultas no se encuentran |
Qué está cargado | Qué funciona |
Todas las fuentes necesarias | todo |
Solo configuración | metadatos; la sintaxis responde «fuente no conectada» |
Solo ayuda | sintaxis sin filtrado por versión, |
Nada |
|
El lenguaje de consultas es una fuente aparte
shquery_ru.hbk del mismo directorio de instalación de la plataforma. 127 páginas:
52 funciones, 67 palabras clave, 8 artículos. Se carga como una fuente normal y
entra en el mismo índice de búsqueda que la ayuda de la plataforma — no hace falta
buscar con una herramienta aparte, search_syntax encuentra ambas cosas.
No hay versiones en el propio archivo — verificado en las 129 páginas: cero
menciones de «8.3.x» y «a partir de la versión». Pero el lenguaje de consultas cambia: la versión
8.3.20 añadió 25 funciones, entre ellas СтрНайти, Лев, Прав, ВРег, НРег,
СтрЗаменить, Окр, Цел y toda la trigonometría.
No hay de dónde sacar la versión: la ayuda de la plataforma no describe las funciones del lenguaje de consultas
en absoluto (ПОДСТРОКА — cero coincidencias en 25 511 elementos). Por eso las versiones
las fija la tabla curada query_versions.py — según la lista de 1C «Funciones
añadidas al lenguaje de consultas a partir de la versión 8.3.20». A las otras 27 funciones
no se les atribuye versión: siempre existieron.
Después funciona el filtro habitual: una configuración en 8.3.5 no verá estas funciones, en 8.3.23 las verá.
La tabla se verifica con datos — comparando dos ayudas de plataformas distintas. Lo que no está en la antigua y sí en la nueva, apareció entre ellas, y eso debe tener versión:
python3 tools/lab/compare_query_help.py <старая.hbk> <новая.hbk>Prueba del 2026-08-19, 8.3.5.1570 contra la actual: aparecieron 29, cubiertas 29, falsos positivos 0. Un falso positivo es el peor de los errores: un elemento que ya estaba en la ayuda antigua pero está marcado con versión, se ocultará de una configuración donde sí existe.
La instancia es una por servidor: la recarga reemplaza la anterior.
Las tablas de las páginas se muestran, pero no se buscan. En esta ayuda, las celdas de las tablas
están marcadas con párrafos dentro de <TD>, y sin un análisis aparte la ficha imprimía
la tabla como una columna de valores: «Товар / Количество / Номер / Сантехника / 104 / …»
dos docenas de líneas seguidas. Ahora las tablas se analizan en un campo aparte — 51
tablas en 31 de las 127 páginas — y se imprimen en su lugar dentro del texto:
una página con dos ejemplos muestra cada resultado bajo su ejemplo.
El contenido de las tablas no entra en el índice de búsqueda.
Las tablas de esta ayuda son de dos naturalezas distintas, y se analizan de forma diferente:
Qué | Cuántas | Cómo se ve en la ficha |
tabla de datos — resultado de una consulta de ejemplo | 51 en 31 páginas | como tabla markdown |
diagrama sintáctico dibujado — gramática de la construcción | 21 en 17 páginas | en escalera con sangría por nivel de ramificación |
Se distinguen por el marcado, no por la clase CSS: class=SimplyTable no está en
todas — 7 tablas reales van sin él. El indicio es la geometría: en una tabla de datos
todas las filas tienen el mismo ancho, en un diagrama los anchos son irregulares y hay celdas de una sola
barra vertical (es una línea dibujada, no un valor).
El marcado dañado se nombra en voz alta. Una página con <TABLE> sin cerrar
se analiza sin tablas, pero no se pierde, y su nombre entra en las advertencias
de la fuente: como línea en la salida de carga (mcp1c.cli reg-add) y como
línea aparte en la página «Fuentes» del panel. Devolver en silencio una ficha
más pobre de lo normal no se puede: de una ayuda donde simplemente no existe, eso es
indistinguible.
La mitad de los nombres coincide con los nombres de la plataforma (57 de 127) — ГОД, МЕСЯЦ,
ПРЕДСТАВЛЕНИЕ están en ambas. Para que una pregunta sobre consultas no desvíe al método de la
plataforma, expresiones como «en la consulta», «en el texto de la consulta», «en la selección» dan
a los elementos del lenguaje de consultas un impulso suave. Suave a propósito: ante una
separación clara, el elemento de la plataforma sigue siendo el primero — «cómo fijar un parámetro en
una consulta» puede ser también sobre Запрос.УстановитьПараметр.
El parámetro config es obligatorio si hay más de una configuración cargada.
Por defecto no se sustituye nada: una elección silenciosa hace que el
agente escriba código según una configuración ajena, y nadie lo nota.
La respuesta depende de la versión de la plataforma
La misma llamada, dos configuraciones:
get_syntax("СтрШаблон", config="Розница") → 8.3.23
# Метод: Глобальный контекст.СтрШаблон
с версии платформы 8.3.6
Доступность: ТонкийКлиент, ВебКлиент, Сервер, ТолстыйКлиент, …
get_syntax("СтрШаблон", config="Отраслевая") → 8.3.5
# `Глобальный контекст.СтрШаблон` недоступен в этой конфигурации
Элемент существует, но появился в 8.3.6, а конфигурация работает на 8.3.5.1570.
Использовать нельзя — код не скомпилируется.Para la plataforma 8.3.5 se eliminaron de la salida 6 539 elementos, para 8.3.23 — 874. No con una advertencia, sino con filtrado: el agente puede pasar por alto la advertencia, pero un método ausente en la salida, no.
El campo Disponibilidad (servidor / cliente fino / cliente web / móviles) hay que leerlo sí o sí: llamar a un método de servidor desde un contexto de cliente no compila.
Las ayudas de varias versiones se fusionan en un solo índice
Una sola ayuda reciente sobre una configuración antigua miente. Medido en 8.3.5:
199 elementos el servidor declararía inexistentes, 117 devolvería con una
firma ajena (ЗаписьXML.ОткрытьФайл en 8.3.5 toma dos parámetros, en 8.3.27 —
tres), 410 — con disponibilidad ajena. Todo esto son errores de compilación, no imprecisiones.
Por eso las ayudas de distintas versiones se colocan juntas y se fusionan en un solo índice con
límites since y until, y la respuesta se arma según la versión de la configuración
concreta. Se necesitan tantas ayudas como plataformas tengan las configuraciones
cargadas — dos extremas no sustituyen a las intermedias.
El costo está medido y es pequeño: la fusión de tres versiones da 25 691 claves frente a 24 777 de una sola, es decir, menos del uno por ciento. Un contenedor aparte por versión también funciona y sigue siendo la vía de emergencia, pero como principal pierde por números — 300–450 MB y una dirección propia por cada versión.
El servidor mismo indica qué ayudas faltan y cuáles sobran — en la salida
de list_configurations.
Sustitución en lugar de prohibición
Decir «la función no existe» es la mitad de la respuesta. La segunda mitad es con qué sustituirla, y de la ayuda no se deduce: la marca de obsolescencia está en 15 páginas de 25 mil.
Por eso existe la tabla de sustituciones (replacements.py), ahora 6 registros — funciones
de cadena, aparecidas en 8.3.6. En lugar de prohibir, get_syntax devuelve un consejo:
get_syntax("СтрРазделить", config="Отраслевая") → 8.3.5
# `СтрРазделить` недоступна: появилась в 8.3.6
Замена: РазложитьСтрокуВМассивПодстрок(<Строка>, <Разделитель>)
Оговорка: разделитель у `СтрРазделить` — набор символов, каждый из которых
самостоятельный разделитель; у замены это одна строка целиком.La advertencia es obligatoria. La sustitución casi nunca es equivalente, y pasar en silencio una función parecida es peor que no sugerir nada.
La tabla se amplía con casos reales, no a ciegas: inventar soluciones para funciones que nadie ha preguntado no tiene sentido.
4. Gestión de datos
Añadir una fuente
# в Docker
docker compose exec mcp1c python -m mcp1c.cli reg-add /data/bootstrap/Выгрузка.zip --data /data
docker compose exec mcp1c python -m mcp1c.cli reg-add /data/bootstrap/shcntx_ru.hbk --data /data
# без Docker
PYTHONPATH=src python3 -m mcp1c.cli reg-add Выгрузка.zipMás simple: colocar el archivo en data/bootstrap/ — se tomará en el siguiente inicio.
Descarga de configuración a archivos
El segundo tipo de fuente no son los metadatos (СтруктураКонфигурации_*.zip), sino la propia
descarga de configuración a archivos: el código de los módulos y los formularios. El servidor construye y almacena en caché
los índices internos de procedimientos, llamadas y formularios; search_procedures busca en el
conjunto ya preparado. Ante un fallo de caché, los índices se construyen en segundo plano: las herramientas
que no dependen del código siguen respondiendo, y las herramientas de código muestran la etapa X/4 y
los N de M elementos realmente procesados de la etapa actual. El conjunto
preparado se publica completo, sin estado intermedio de versiones distintas.
La compilación en segundo plano no sobrescribe registry.json mientras el inicio sigue
restaurando las siguientes fuentes. Si el inicio se interrumpió de forma anómala,
la instantánea completa anterior en disco permanece íntegra; una lista de fuentes parcialmente restaurada
no se guarda sobre ella.
Cuatro archivos de caché de gasto conservan localizadores seguros, agregados de cobertura
y los primeros 20 problemas anonimizados con el número exacto de los restantes. Los cuerpos de los módulos,
las firmas de los procedimientos y el registro crudo del formulario no entran allí. En el inicio en caliente
se verifican el sha256 de la fuente, la versión de selección, la generación de localizadores, los invariantes internos
de cada índice y su coherencia con un solo directorio. Por eso
un conjunto dañado estructural o semánticamente se considera un fallo completo,
no una fuente con respuesta parcialmente antigua. Una caché dañada o de solo lectura no
derrumba la fuente: el servidor ejecuta una recompilación en frío en memoria y publica el diagnóstico
completo, incluso si la nueva caché no se puede escribir. Las respuestas publicadas en frío y en
caliente coinciden en todos los contadores y categorías de causas.
Las causas locales de cada formulario se almacenan por separado de la lista limitada:
gracias a esto,
get_object después de un reinicio muestra todos los problemas de formularios del objeto seleccionado,
sin convertir el /sources general en una respuesta sin límite. El lector no lee el archivo de caché
de más de 256 MiB y no descomprime un payload de más de 512 MiB; superar cualquiera de los
límites es un fallo de caché normal hasta marshal.loads, no un intento de agotar la memoria.
La aceptación final en vivo de la selección v4 se realizó el 2026-08-21 sobre cuatro fuentes de código anonimizadas (tres descargas principales y una extensión):
PYTHONPATH=src .venv/bin/python \
tools/lab/measure_modules_acceptance.py --data data --timeout 120El script imprime un único JSON sin nombres ni rutas. El arranque en caliente tomó 3,676 s, startup_problems_total = 0, pico del proceso — 856,2 MiB. El catálogo demostró 8 650 .bsl jerárquicos, 828 módulos de Form.bin, 1 523 .txt planos, 1 079 módulos de .Form y 7 módulos compilados sin código fuente. Se detectaron 6 150 formularios: 3 331 completos, 1 330 parciales y 1 489 no leídos. Categorías exactas de restricciones: descriptor_only=671, invalid_syntax=1598, known_marker_semantics_incomplete=659, form_structure_missing=561, compiled_without_source=7; no hay marcadores desconocidos, excesos de presupuesto, contenedores rotos ni conflictos en este corpus. El cero aquí es el resultado de la medición de estas fuentes concretas, no una promesa de soporte para cualquier formato futuro.
La medición previa de capacidad de respuesta en segundo plano del 2026-08-21 con caché frío de tres fuentes de código: en 72,12 s se realizaron 73 llamadas de un segundo a cada ruta, sin fallos. Este temporizador comienza después de que /health esté listo, mientras que la medición de contenedor de 125 s más abajo va desde el arranque del contenedor hasta ready de todas las fuentes de código. /health respondió con una mediana de 5,76 ms y el peor tiempo de 171,01 ms; el search_objects real — 8,11 y 172,49 ms respectivamente. El contenedor alcanzó healthy, los 12 archivos de caché fueron publicados. Para repetir, monte en un contenedor separado una copia de data/ sin index/cache/*.modules-* y ejecute:
.venv/bin/python tools/lab/measure_background_responsiveness.py \
http://127.0.0.1:5002 /путь/к/копии/dataLa memoria de la imagen final se volvió a medir el 2026-08-21 después de la selección v4: cuatro fuentes de código y 16 archivos de caché de índices de módulos. El arranque en frío tras eliminar solo la caché de consumo tomó 111,216 s; el reinicio en caliente del mismo contenedor con dev, ino, tamaño y mtime_ns sin cambios de los 16 archivos — 11,495 s.
Estado |
|
| RSS PID 1 | HWM PID 1 |
|
reconstrucción en frío | 1 404 649 472 B (1 339,6 MiB) | 1 400 582 144 B (1 335,7 MiB) | 762 180 KiB (744,3 MiB) | 764 228 KiB (746,3 MiB) | 728,3 MiB |
arranque en caliente | 612 851 712 B (584,5 MiB) | 599 142 400 B (571,4 MiB) | 570 180 KiB (556,8 MiB) | 570 180 KiB (556,8 MiB) | 533,2 MiB |
En ambas ocasiones el contenedor alcanzó healthy; restart_count = 0, oom_killed = false. En cada una de las dos ejecuciones finales hubo exactamente 0 líneas con cada uno de los términos traceback, exception, critical y error. Los valores de cgroup incluyen la caché de páginas del kernel, por lo que difieren naturalmente del RSS del proceso y de la lectura de docker stats. Esto es una referencia del tamaño de este corpus concreto, no una base para asignar mem_limit.
El script imprime un único JSON solo con agregados: duración, cantidad de fuentes y cachés, campos de cgroup y PID 1, docker stats, salud, reinicios, OOM y contadores de términos del registro. Los nombres de las fuentes, las rutas locales y las líneas del registro no se imprimen. En el modo cold construye la imagen final, detiene previamente el contenedor y elimina solo los archivos exactos modules-toc, modules-calls, modules-forms y modules-search, calculados por la función de nombre de trabajo para las fuentes actuales. El directorio index/cache y los propios objetivos no pueden ser enlaces simbólicos; un conjunto de nombres sobrante o mezclado no se considera listo. Después de la detención, el directorio se abre con O_NOFOLLOW, y su dev/ino se verifican contra el directorio comprobado inicialmente. Los objetivos se enumeran y verifican a través de dir_fd, se eliminan solo los nombres base exactos a través del mismo descriptor: la sustitución del padre por un enlace simbólico no conduce hacia afuera, y un enlace duro pierde solo la referencia interna. Luego el script hace --force-recreate. El propio medidor no elimina ni reemplaza las fuentes, el código descomprimido ni registry.json. El servidor en ejecución actualiza atómicamente de forma normal los estados de registry.json durante el arranque y la compilación en segundo plano; la medición tiene en cuenta estas entradas en el marcador de generación. La disponibilidad requiere no solo healthy, sino también sha256, loaded_at y la vinculación de la propia fuente de código sin cambios, el mismo sha256 de la configuración propietaria, el estado ready y el conjunto exacto de cuatro cachés por fuente. En un reinicio normal, los metadatos de configuración se analizan de nuevo y reciben un nuevo loaded_at de runtime; el medidor permite solo esta transición y luego exige dos instantáneas idénticas de la nueva generación. Después de leer la memoria, docker stats y el registro, la verificación final lee el registro, luego la caché y de nuevo el registro; ambos marcadores deben coincidir con la generación lista. El marcador incluye también dev, ino, tamaño y mtime_ns del propio registry.json, por lo que incluso escribir los mismos bytes se considera una nueva generación. El modo warm antes de la detención recuerda dev, ino, tamaño y mtime_ns de cada archivo de caché exacto. Inmediatamente después de docker stop, aún antes de docker start, vuelve a abrir el directorio con O_NOFOLLOW, verifica su dev/ino y toda la instantánea de archivos a través del dir_fd retenido; la misma instantánea se requiere en la disponibilidad y en la verificación final. La reconstrucción, sobrescritura o corrupción de un archivo anula todo el resultado. --timeout y --poll-interval son segundos positivos finitos; el resto único de timeout limita cada comando de Docker.
.venv/bin/python tools/lab/measure_container_memory.py --mode cold --data data \
--timeout 300 --poll-interval 0.5
.venv/bin/python tools/lab/measure_container_memory.py --mode warm --data data \
--timeout 300 --poll-interval 0.5La descarga de la extensión se coloca en el mismo lugar, en data/incoming/, y se procesa con el mismo botón. El servidor determina el tipo de descarga por sí mismo, según el Configuration.xml dentro del archivo — la persona sigue eligiendo solo la configuración a la que se adjunta la extensión, no un botón separado ni un campo «esto es una extensión». La extensión se registra como fuente separada <NombreDeConfiguración>:ext:<NombreDeExtensión> (tipo extension), no <NombreDeConfiguración>:modules: el nombre de la extensión se toma de la etiqueta Name de su propia descarga, no lo inventa la persona. El código va a su propio directorio data/extensions/<NombreDeConfiguración>/<NombreDeExtensión>/ — junto a data/modules/<NombreDeConfiguración>/, pero no dentro de él, por lo que la segunda descarga no borra la primera. Una configuración puede tener tantas extensiones como se quiera — de módulos de configuración hay exactamente una descarga, como antes.
La identidad de la extensión es la etiqueta Name dentro de su descarga, no el nombre del archivo ni el contenido completo. La persona puede renombrar el archivo como quiera: dos archivos con nombres diferentes pero el mismo Name reprocesan UNA y la misma fuente — el segundo procesamiento simplemente actualiza el código y el origin (nombre del último archivo procesado), la clave y el directorio no cambian. La otra cara de la misma regla: si el Name de dos extensiones DIFERENTES coincide tras la limpieza de caracteres no permitidos para rutas (por ejemplo, Прайс/Розница y Прайс:Розница dan el mismo nombre de directorio), también se fusionan en una sola fuente — el segundo procesamiento sobrescribe el código de la primera. Para nombres normales (sin caracteres fuera de letras, dígitos, guion, guion bajo, punto y espacio), la limpieza no cambia nada y tal coincidencia no ocurre.
El reconocimiento es una regla positiva en ambos lados, y el orden de verificación es importante. Equivocarse a favor de la configuración es más peligroso: significa ir a la rama de módulos y eliminar por completo el código de configuración ya procesado. Por eso primero se buscan los indicadores fuertes de extensión (ObjectBelonging, ConfigurationExtensionPurpose) — si se ve al menos uno, no hay paso a la rama de módulos bajo ningún CompatibilityMode: a partir de ahí solo se decide entre «extensión» (coinciden las cuatro condiciones: ambos indicadores fuertes, NamePrefix no vacío, ausencia de CompatibilityMode) y rechazo. Y solo cuando no hay ningún indicador fuerte de extensión en absoluto, decide CompatibilityMode: no vacío — configuración, vacío o sin etiqueta — rechazo. Todo lo demás — también rechazo con explicación, sin tocar nada en el disco: Configuration.xml no se encontró (se busca no solo en la raíz del archivo, sino también en el único directorio de nivel superior — así se crea el archivo con el comando zip -r archivo.zip carpeta, y el __MACOSX/ de servicio con .DS_Store del archivo de Finder en macOS no lo impide), no se lee (CRC dañado, registro truncado), no se analiza como XML, no lleva una estructura reconocible, o el tamaño declarado del archivo es inverosímilmente grande.
Dónde colocarlo. En data/incoming/, en el disco, no a través del formulario de carga en «Fuentes» — este no tiene campo para ello. El directorio lo crea el propio servidor al arrancar, así que está en su lugar desde la primera ejecución. Luego, en la página «Fuentes» (solo para quien haya iniciado sesión con ADMIN_TOKEN) aparece el bloque «Descargas entrantes» con el botón «procesar».
Solo se escanea el propio directorio, sin subdirectorios anidados. Un archivo colocado en data/incoming/Розница/ el servidor no lo verá — y no dirá nada al respecto, porque no tendrá nada que mostrar.
Mientras el archivo se copia, no hay botón. cp de un gigabyte y medio tarda minutos, y el archivo es visible en el directorio desde el primer segundo: para un archivo modificado hace menos de cinco segundos, el estado se muestra con la marca «el archivo aún se está copiando», el sha256 no se calcula en absoluto (de todos modos quedará obsoleto), y el procesamiento de dicho archivo se rechaza con explicación. Espere a que termine la copia y actualice la página.
El reprocesamiento sobrescribe el directorio por completo — pero solo después del éxito. Para una descarga actualizada, el botón dice «reprocesar»: el contenido anterior de data/modules/<NombreDeConfiguración>/ (o del directorio de la extensión) se reemplaza por completo con el nuevo; de lo contrario, los archivos que no están en la nueva descarga (objeto eliminado, módulo renombrado) quedarían allí para siempre y las dos descargas se mezclarían. La descompresión se realiza en un directorio temporal contiguo y no afecta al procesamiento anterior: si extract falla a mitad de camino (CRC dañado en un módulo, espacio agotado, permisos) o extrae cero archivos, no se llega a escribir en el directorio de trabajo en absoluto — el registro y el disco no divergen. La sustitución no es derribar lo antiguo en su lugar, sino un intercambio («renombrar lo antiguo a un lado → renombrar lo nuevo a su lugar → eliminar lo apartado»): si el traslado de lo nuevo al lugar de lo antiguo falla, el servidor intenta devolver lo antiguo a donde estaba. Si tampoco se logra esto (la naturaleza del fallo de ambos renombrados suele ser la misma — permisos, el mismo bind-mount), el procesamiento rechaza explícitamente y nombra en el texto ambas rutas: dónde está físicamente el procesamiento anterior y dónde está el nuevo vacío o parcialmente descomprimido, para poder restaurar el directorio manualmente; el servidor no mostrará silenciosamente «procesado» para un directorio que no existe. Los restos de un proceso interrumpido a mitad (.tmp-*) se eliminan antes del siguiente procesamiento de la misma configuración o extensión — la copia guardada del procesamiento anterior (.old-*), si se llegó a eso, no se elimina por sí sola: la decisión sobre ella es de la persona. El reprocesamiento no cambia los permisos del directorio — el nuevo directorio recibe los permisos del anterior (o los normales, si el directorio aún no existía), no los reducidos con los que se crea el temporal.
Los procesamientos simultáneos de una misma fuente se ejecutan secuencialmente: una nueva solicitud cancela de inmediato la generación anterior, pero espera a que termine su trabajo con el directorio temporal. Por lo tanto, un procesamiento no puede eliminar un .tmp-* activo ajeno, y el directorio de trabajo y la caché los recibe solo la última generación. La solicitud cancelada termina con un error explícito; la solicitud obsoleta en espera no inicia la descompresión en absoluto. Diferentes configuraciones y extensiones con diferentes claves de fuente no se retrasan entre sí.
«Отбор устарел» — estado para cuando cambia no el archivo, sino la regla. Cada fuente analizada recuerda la versión de la regla de selección (el SELECTION_VERSION interno: qué tomamos del archivo y dónde lo colocamos). Si el código en disco fue analizado con una versión antigua de la regla, la fuente se muestra como «selección desactualizada», no como «analizada» — aunque el archivo en incoming/ sea el mismo, con el mismo sha256. El botón está etiquetado como «reanalizar», igual que en la descarga actualizada: el código en disco se sobrescribe de nuevo, ya según la regla actual. El análisis anterior en sí no se reescribe — la corrección de la regla de selección la ve la persona solo después de pulsar el botón. Una fuente analizada antes de la aparición de este campo (registro sin selection_version en el antiguo registry.json) también se considera desactualizada: su versión es desconocida, no «seguramente reciente» — de lo contrario, la persona nunca vería «reanalizar» para un código que nunca pasó por la regla actual.
La versión actual 4 conserva los descriptores XML de formularios y los Ext/Form.bin jerárquicos; por lo tanto, una fuente de la versión 3 se muestra obligatoriamente como desactualizada y recibe estos archivos solo tras un reanálisis explícito.
La versión de selección forma parte del sello de caché: la caché antigua no se acepta ni siquiera para el mismo ZIP sin cambios. Antes de reemplazar el directorio, el servidor escribe un breve registro de rotación; tras una detención abrupta, el siguiente arranque según registry.json o bien completa la nueva generación, o bien restaura el directorio anterior.
La basura del archivador de Finder en macOS no entra en el código. Un archivo creado con el comando «Comprimir objetos» lleva un __MACOSX/ de servicio con copias de las bifurcaciones de recursos de cada archivo (._Nombre, el mismo sufijo que el original) — la selección los omite, como cualquier nombre que comience con ._, sin importar dónde se encuentre.
La envoltura del archivo no se reproduce en la ruta en disco. Un archivo empaquetado con el comando zip -r archivo.zip carpeta o mediante Finder («Comprimir objetos») — toda la descarga está dentro de un único directorio de nivel superior —, al desplegarse en disco ese nivel no se repite: el código se coloca como data/modules/<NombreConfiguración>/Catalogs/…, no como data/modules/<NombreConfiguración>/carpeta/Catalogs/…. La regla de reconocimiento de la envoltura es común con la búsqueda de Configuration.xml dentro de ella (el mismo lugar del párrafo anterior, «Reconocimiento»): el __MACOSX/ de servicio y el .DS_Store raíz no cuentan, y varios directorios de nivel superior no se consideran envoltura — el servidor no adivinará cuál de ellos es «el correcto». La sanitización de rutas (rechazo de miembros que salen fuera de la raíz) se aplica después de quitar la envoltura, no en lugar de ella.
Eliminar una fuente se lleva también el código. El botón «eliminar» en una fuente <NombreConfiguración>:modules borra data/modules/<NombreConfiguración>/, y en una fuente de extensión <NombreConfiguración>:ext:<NombreExtensión> — solo su propio directorio data/extensions/<NombreConfiguración>/<NombreExtensión>/: los módulos de la configuración y otras extensiones de la misma configuración no se ven afectados. De lo contrario, cientos de megabytes quedarían ocupados de forma invisible: en la sección «Archivos fuente» no se muestran, allí solo está data/sources/.
Un archivo en el que no se encontraron ni módulos ni formularios se rechaza. La descarga de la estructura de metadatos también es un .zip, y sin esta comprobación crearía una fuente con cero archivos y estado «analizada». Se envía mediante el formulario «Cargar» en esta misma página.
Por qué no a través del navegador. El archivo pesa más de un gigabyte — en la configuración típica de ventas minoristas 2.3.10.5 son 1 380 MB. El formulario de carga en «Fuentes» está pensado para metadatos de unos pocos megabytes y con un archivo así no funciona por tres razones: el límite de carga es de 500 MB; la triple copia con un pico de unos 4 GB — el búfer de recepción del cuerpo de la solicitud, la copia temporal en mkdtemp() y la copia al propio volumen; y la propia transferencia de más de un gigabyte por HTTP sin posibilidad de reanudar tras una interrupción. El archivo en el volumen evita las tres limitaciones: se copia con un cp normal, y el servidor lee el archivo miembro a miembro, sin descomprimirlo nunca por completo.
Qué queda en disco. No todo el archivo — solo los módulos (.bsl en la descarga jerárquica, .txt y los compilados canónicos CommonModules/<Nombre>.Module o CommonModule.<Nombre>.Module en la plana) y los formularios: descriptor XML, Form.xml y Form.bin en la jerárquica, el contenedor .Form completo en la plana. Form.bin y .Form se conservan sin cambios como fuente para el proveedor de código; el .bsl derivado no se crea al recibir. Las maquetas de texto *.Template.txt no se consideran módulos. El contenedor se conserva tal cual, junto con el registro binario del formulario: el código de un formulario normal está dentro de él como registro module, y analizar el contenedor al recibir significaría traer aquí el análisis del formato 1C.
Después de descomprimir, el árbol físico se enumera una vez en un directorio inmutable de direcciones canónicas y localizadores seguros. El índice, las llamadas, los formularios y la búsqueda reciben la misma instantánea: los .bsl/.txt normales se leen como archivos, el código de Form.bin/.Form — como registro module del contenedor original, el .Module compilado sigue siendo una dirección sin cuerpo inventado. Los textos idénticos de una misma dirección se deduplican tras la normalización común; los diferentes no reciben prioridad silenciosa y se excluyen como conflicto.
El código de la configuración se coloca en data/modules/<NombreConfiguración>/, el código de la extensión — en su propio directorio data/extensions/<NombreConfiguración>/<NombreExtensión>/; los registros de cobertura actuales — en data/logs/. Los tres tipos están protegidos por las reglas **/modules/, **/extensions/ y **/logs/ en .gitignore. Medición con python3 tools/lab/measure_intake.py <archivo>..., ejecución del 2026-08-19:
Qué | Archivo | Desplegado | Seleccionamos |
configuración típica de ventas minoristas 2.3.10.5 | 1 380 MB | 2 063 MB, 33 188 archivos | 351,4 MB, 11 072 archivos |
extensión para ella | 1 MB | 8 MB, 453 archivos | 6,9 MB, 155 archivos |
La ejecución real del propio proceso de recepción sobre los mismos archivos — no una estimación por el directorio del zip, sino una llamada real a intake.planned_size, intake.enough_space e intake.extract, medición con python3 tools/lab/measure_intake_run.py <directorio para descomprimir> <archivo>..., ejecución del 2026-08-19: estimación del espacio requerido para un archivo de 1,4 GB — 0,15 s (solo se lee el directorio central del zip, el cuerpo no se toca en absoluto), descompresión — 3,1 s, pico de RSS del proceso — 111 MB. Archivos y bytes devueltos por extract() y lo que realmente se colocó en disco — en igual cantidad, el script lo verifica por sí mismo.
El servidor no elimina el archivo fuente. Al servidor le está prohibido eliminar el directorio data/incoming/ — el archivo permanece en su lugar incluso después de un análisis exitoso; un reanálisis del mismo archivo no lo toca, la verificación se hace por sha256 con la caché en la página (no se puede calcular el hash de un gigabyte en cada actualización de la lista).
La fuente se crea bajo la clave <NombreConfiguración>:modules, no con el nombre de la configuración: la misma clave que la de los metadatos, al cargar, los expulsaría del registro. Qué configuración es la dueña de la descarga lo decide la persona. Si en el registro está cargada exactamente una, no se necesita elección: no hay campos junto al botón en la página, el análisis toma la única por sí mismo. Si hay dos o más cargadas, junto al botón aparece una lista desplegable de los nombres cargados — a la que se elija, a esa se vincula el código. El nombre del formulario se contrasta con la lista de cargados: un nombre desconocido se rechaza antes de comenzar el análisis, con una explicación. La vinculación automática según el manifiesto de la descarga (sin intervención humana) aún no está hecha. La plataforma de la fuente de módulos se toma de la configuración a la que está vinculada — la propia descarga no contiene en los archivos la compilación exacta de la plataforma, solo el modo de compatibilidad, y eso es otro número. En la extensión, la elección de configuración funciona igual (ver arriba «La descarga de la extensión se coloca en el mismo lugar»); el tipo de descarga — módulos o extensión — el servidor lo distingue por sí mismo según Configuration.xml, no hay un campo ni un botón separado para ello en la página.
Falta de espacio — rechazo antes de comenzar. Después de elegir la configuración y el tipo de fuente, el registro verifica el espacio libre en el volumen antes de descomprimir. Se requiere el volumen de los archivos seleccionados de forma segura más la reserva del índice: 15% redondeado hacia arriba, pero no menos de 25 MB. La fórmula es la misma para la primera carga y para el reanálisis: el volumen ocupado por la raíz anterior ya está excluido del valor de espacio libre, no se puede volver a sumar. Si no hay suficiente, el análisis no comienza, y la razón con ambas cifras en megabytes permanece en la página «Fuentes» y sobrevive al reinicio. La llamada directa al registro pasa la misma comprobación; en caso de error o de llenado del volumen, el análisis anterior permanece en su lugar.
El *.Module compilado se ve en el resumen y en la lista de módulos como ОбщийМодуль.<Nombre>, pero no tiene procedimientos ni cuerpo: search_procedures, get_procedure y get_callers lo dicen directamente y no presentan un índice vacío como prueba de que no existe un procedimiento.
El botón «analizar» requiere ADMIN_TOKEN — como cualquier otra escritura: sin el token, esa ruta no existe, no es que «esté cerrada».
Aplicar cambios sin reiniciar
El servidor en funcionamiento mantiene el registro en memoria, por lo que después de reg-add hay que empujarlo. O bien reiniciar (docker compose restart mcp1c, unos 2 segundos), o bien mediante el manejador de administración:
# включается переменной ADMIN_TOKEN; без неё маршрут отключён
ADMIN_TOKEN=секрет docker compose up -d
curl -X POST -H "x-admin-token: секрет" http://localhost:5001/admin/reloadDiccionario: cómo se dice frente a cómo se llama
La principal dificultad de la búsqueda es la brecha entre las palabras de la persona y los nombres en la configuración. «Pedido del cliente» — y el objeto se llama ЗаказПокупателя. El diccionario está en data/dictionary.json, se edita sin reconstruir la imagen.
Dos mecanismos, y son diferentes.
Sinónimos de palabras — comunes para todas las configuraciones:
python3 -m mcp1c.cli dict-synonyms клиент покупатель заказчикAlias de objetos — indicación directa de «cuando digo esto, me refiero a estos objetos», peso mayor que cualquier coincidencia textual. Dos docenas de frases típicas («archivos», «productos», «clientes», «empleados», «tareas») están integradas y funcionan de inmediato; si el objeto no existe en la configuración, el alias no se aplica. Los propios se añaden con vinculación a la configuración:
python3 -m mcp1c.cli dict-alias "справочник физлиц" \
Справочник.ФизическиеЛица Справочник.Пользователи \
--config РозницаДляКазахстана«справочник физлиц»
Справочник.ФизическиеЛица псевдоним из словаря
Справочник.Пользователи псевдоним из словаряLa existencia de los objetos se comprueba al añadirlos — un alias para un error tipográfico es inútil. Ver el contenido: dict-show, eliminar: dict-alias «frase» --remove.
Los cambios se aplican reiniciando el contenedor o con POST /admin/reload — no es necesario reconstruir la imagen. La recarga se realiza fuera del event loop, por lo que /health y las solicitudes MCP siguen atendiéndose durante la restauración.
Las claves de búsqueda del lenguaje de consultas — el tercer mecanismo, y solo se edita en el código (search_keys.py) con la comprobación habitual de cambios. La brecha aquí es de otra naturaleza: la persona no llama a una construcción con una palabra ajena, sino que describe la tarea. «Cantidad de días entre dos fechas» frente a РАЗНОСТЬДАТ, «quitar repeticiones» frente a РАЗЛИЧНЫЕ — palabras comunes cero, y un sinónimo no ayuda, no hay nada que reemplazar.
Por eso, a 116 de 127 páginas se les han asignado formulaciones con las que se las pregunta, y entran en el índice de búsqueda como un campo separado. En tiempo de ejecución no pesan nada. Resultado en un conjunto real: 57,9% → 94,7% en primer lugar, sin regresión en 61 mil consultas automáticas.
Las claves las hemos inventado nosotros, no se descargan, y de ahí tres limitaciones:
viven como una capa separada en git, no se atribuyen al elemento analizado;
no llegan a la respuesta del agente — la respuesta sigue construyéndose solo a partir de la ayuda, las claves funcionan exclusivamente para acertar en el artículo correcto;
están vinculadas a las páginas por identificador, y si la ayuda da otro conjunto de páginas, la discrepancia se señala al cargar, no se manifiesta silenciosamente con una búsqueda degradada.
La regla completa está en docs/data-sources.md, sección «Capas generadas sobre las fuentes».
Ver qué está cargado
docker compose exec mcp1c python -m mcp1c.cli reg-list --data /dataРозницаДляКазахстана 2.3.10.5 платформа 8.3.23.1997
объектов 5637, связей 44034, загружено 2026-08-18T12:22:16+00:00
метаданные : да
синтаксис : справка 8.3.27, новее конфигурации, скрыто 874
модули : не загружен
язык запросов: подключён, 127 страницPuede que no haya configuraciones en absoluto — el servidor funciona igualmente si hay al menos una ayuda cargada: responden search_syntax y get_syntax, no es necesario indicar config. reg-list en ese caso enumera lo conectado y devuelve 0:
Конфигурации не загружены. Подключено:
язык запросов, 127 страниц
Работают search_syntax и get_syntax, без фильтра по версии.En un registro completamente vacío — «Nada cargado.» y código de retorno 1. Cualquier comando que necesite configuración dirá allí mismo qué falta exactamente y con qué se cubre cada cosa. reg-list no espera la compilación en frío: para la configuración principal y cada extensión muestra el mismo estado atómico que /sources y list_configurations — contadores listos, etapa y progreso, error o ausencia de código.
Depuración sin agente — mcp1c.cli
La CLI accede al mismo registro y a las mismas funciones que las herramientas MCP. Si responde correctamente — el problema está en la configuración del cliente, no en el servidor.
Los comandos se dividen en tres grupos. Sobre el registro — lo mismo que ve el agente:
PYTHONPATH=src python3 -m mcp1c.cli reg-list [--data data]
PYTHONPATH=src python3 -m mcp1c.cli reg-add Выгрузка.zip [--data data]
PYTHONPATH=src python3 -m mcp1c.cli reg-add shcntx_ru.hbk [--data data]
PYTHONPATH=src python3 -m mcp1c.cli reg-search "чек ккм" --config РозницаДляКазахстана
PYTHONPATH=src python3 -m mcp1c.cli reg-search "разделить строку" --syntax --limit 5
PYTHONPATH=src python3 -m mcp1c.cli reg-search-procedures "провести документ" \
--config Пример --scope Документ.Чек --limit 10
PYTHONPATH=src python3 -m mcp1c.cli reg-get-procedure \
'Документ.Чек.МодульОбъекта::ОбработкаПроведения' \
--config Пример --start-line 0 --lines 200
PYTHONPATH=src python3 -m mcp1c.cli reg-get-callers \
'Документ.Чек.МодульОбъекта::ОбработкаПроведения' \
--config Пример --limit 20reg-search sin --syntax busca por metadatos; con él, por ayuda y lenguaje de consultas. Tres comandos de código reflejan las herramientas MCP homónimas e imprimen la misma respuesta: reg-search-procedures QUERY acepta --config, --extension, --scope, --limit (por defecto 10); reg-get-procedure ADDRESS — --config, --extension, --start-line (0) y --lines (200); reg-get-callers ADDRESS — --config, --extension y --limit (20). En los tres, --data por defecto es igual a data. En una ejecución única en frío, estos comandos esperan la compilación en segundo plano no más de 90 segundos, para que el proceso no termine los hilos daemon antes del resultado y de la escritura de los cuatro archivos de caché. Si el límite no fue suficiente, el comando devuelve un error explícito; el servidor no usa esta espera y continúa mostrando el progreso.
Directamente sobre el archivo, sin registro — ver la descarga antes de que llegue al servidor:
PYTHONPATH=src python3 -m mcp1c.cli info Выгрузка.zip
PYTHONPATH=src python3 -m mcp1c.cli stats Выгрузка.zip
PYTHONPATH=src python3 -m mcp1c.cli show Выгрузка.zip Документ.ЧекККМ --detail full
PYTHONPATH=src python3 -m mcp1c.cli related Выгрузка.zip Документ.ЧекККМ --depth 2
PYTHONPATH=src python3 -m mcp1c.cli find Выгрузка.zip реализация --limit 10La ruta es un ZIP o un directorio descomprimido; el formato se determina por el manifiesto.
Diccionario de búsqueda — sinónimos comunes, alias vinculados a la configuración:
PYTHONPATH=src python3 -m mcp1c.cli dict-show # правила и их происхождение
PYTHONPATH=src python3 -m mcp1c.cli dict-show --all --config Розница...
PYTHONPATH=src python3 -m mcp1c.cli dict-synonyms чек ккм касса # группа взаимозаменяемых слов
PYTHONPATH=src python3 -m mcp1c.cli dict-synonyms чек ккм --remove
PYTHONPATH=src python3 -m mcp1c.cli dict-alias "справочник физлиц" Справочник.ФизическиеЛица
PYTHONPATH=src python3 -m mcp1c.cli dict-alias "справочник физлиц" --removedict-show muestra el origen de cada regla — con esto comienza el análisis de «por qué la búsqueda se comporta así».
Medición de calidad de búsqueda — mcp1c.bench
Un banco de pruebas aparte, porque «mejoró» sin cifras es una opinión.
PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
--data data --config РозницаДляКазахстана \
--auto --sets query-language,roznica-metadata,modules-procedures \
--check-notesClave | Qué hace |
| directorio de datos del servidor, por defecto |
| conjuntos manuales schema v1 de |
| conjuntos automáticos según la ayuda: nombres exactos y homónimos |
| configuración; obligatoria si hay varias cargadas |
| corpus de código separado de la extensión para conjuntos de procedimientos; sin la clave se mide el código base |
| profundidad de la salida, por defecto 10 |
| guardar la ejecución para comparar; por convenio |
| comparar con la ejecución anterior — nombrará uno por uno quién cambió de lugar |
| verificar las notas del conjunto con el lugar que ocupó la consulta |
Cada JSON manual contiene schema_version: 1, un domain explícito — syntax, metadata o procedures — y un array cases. El nombre del archivo no selecciona el índice. En un conjunto de procedures, expected guarda nombres bare de BSL sin nombres de módulos; el banco de pruebas, sin distinguir mayúsculas, expande el nombre a todas las direcciones exactas del corpus seleccionado. Esto permite publicar formulaciones reproducibles sin revelar la estructura de una implementación concreta. Los opcionales expected_miss: true y expected_rank basado en cero verifican mecánicamente el baseline fijado con --check-notes; esto no es un umbral de pytest. El antiguo array JSON raíz y los baselines antiguos sin versión se rechazan explícitamente: hay que recrearlos. --save primero reemplaza atómicamente el archivo de informe y solo después imprime los resultados: un error de escritura no deja un informe parcial ni en disco ni en stdout.
Imprime P@1/P@3/P@5/P@10, MRR, la proporción de «dominio ajeno primero» y la separación mediana del primer resultado respecto del segundo. No hay umbrales en assert a propósito: los conjuntos de consultas no son pruebas; los porcentajes se romperían con cada edición del diccionario. El código 1 significa discrepancia de notas; el código 2 — que toda la medición se cancela antes de imprimir y guardar por un conjunto inválido, una elección ambigua o un índice no listo. Al cambiar el código durante un conjunto de procedimientos, todo el conjunto se repite desde el principio con una sola generación de índice.
La comparación de dos ejecuciones se ve así (los deterioros primero):
=== сравнение с прошлым прогоном ===
- «как прибавить месяц к дате в запросе»: 1 -> промах
- «как отсортировать результат запроса»: 1 -> 5
+ «в чем разница между внутренним и левым соединением»: 5 -> 4Los conjuntos no entran en la imagen (tests/ en .dockerignore) — ejecutar desde la copia de trabajo, no desde el contenedor.
Servidor manualmente — mcp1c.server
PYTHONPATH=src python3 -m mcp1c.server --data data # streamable-http на :8000/mcp
PYTHONPATH=src python3 -m mcp1c.server --transport stdio # локальному клиенту
PYTHONPATH=src python3 -m mcp1c.server --host 0.0.0.0 --port 5001No hay otros valores para --transport. El HTTP+SSE obsoleto está completamente desactivado: la bandera --transport sse se rechaza antes de leer los datos y de iniciar el servidor.
De dónde salen los datos de origen
Estructura de configuración — mediante el procesamiento de exporter-1c/. Cuatro variantes del módulo para forma normal y gestionada, XML y JSON; las variantes XML son compatibles con 8.3.5. Dos procesamientos ya están compilados y se abren tal cual: ВыгрузкаСтруктурыКонфигурации_ОбычнаяФорма_XML.epf (8.3.5 y superior) y ВыгрузкаСтруктурыКонфигурации_УправляемаяФорма_XML_JSON.epf (8.3.6 y superior, el formato se elige en el formulario).
Ayuda de la plataforma — el archivo shcntx_ru.hbk del directorio de instalación de 1C:
/opt/1cv8/<версия>/shcntx_ru.hbk
C:\Program Files\1cv8\<версия>\bin\shcntx_ru.hbkEl nombre debe coincidir por completo. En el mismo directorio hay cientos de archivos .hbk — 38 ayudas distintas, cada una en unas veinte lenguas. Parecidos al necesario:
Archivo | Qué es | Por qué no sirve |
| la misma ayuda, parte independiente del idioma | 25 508 elementos, pero ni una sola descripción: solo el árbol de páginas e identificadores en inglés, sin versiones de aparición |
| descripción del lenguaje integrado | no es un contenedor 1C en absoluto |
| lenguaje de consultas | lo mismo |
| ayuda del configurador | es un contenedor, pero no hay páginas del asistente de sintaxis dentro |
| manual del usuario | no es un contenedor |
Por tamaño no se distinguen: shcntx_root.hbk pesa 33 MB frente a los 39 MB del necesario. El sufijo _ru es el idioma, _root — la parte común sin textos.
Si el archivo no es el correcto, el servidor explica por qué exactamente y deja la ayuda anterior en su lugar.
Basta con una ayuda de la plataforma disponible más reciente: cada elemento lleva la versión de aparición, y para configuraciones antiguas lo superfluo se filtra. Si la versión no está en la ruta, se deduce de los propios datos.
También se aceptan ayudas de plataformas antiguas — están marcadas de otra manera (secciones con div en lugar de p), esto está contemplado. Será útil si se levanta un servidor aparte para implementaciones antiguas: la ayuda de 8.3.5 da 18 936 elementos y no contiene СтрНайти, СтрРазделить, ЗаписьJSON — que en 8.3.5 tampoco existían. Pero esa ayuda no informa su versión: no tiene marcas de «a partir de la versión», porque entonces todo era actual. Por eso la versión se toma del nombre del archivo o del directorio — colóquela como 8.3.5.1570.hbk o en data/hbk/8.3.5.1570/, de lo contrario la correspondencia con la configuración no funcionará.
5. Cómo está organizado
src/mcp1c/
v8container.py контейнер 1С — общий для .hbk, .cf, .epf
syntax_parser.py разбор справки платформы
syntax_model.py модель элемента справки, виды, границы версий
syntax_merge.py слияние справок разных версий в один индекс
query_parser.py разбор справки по языку запросов (shquery_ru.hbk)
replacements.py чем заменить функцию, которой нет в старой платформе
virtual_tables.py таблицы запроса регистров и имена их полей
loader.py чтение выгрузок, XML и JSON в одну модель
model.py модель конфигурации
graph.py граф связей
graph_view.py окрестность объекта для картинки на дашборде
search.py лексический поиск
search_keys.py формулировки, которыми спрашивают язык запросов
synonyms.py встроенный словарь: как говорят против того, как названо
dictionary.py локальный словарь поверх встроенного
index_cache.py кэш поисковых индексов, расходный
modules_index.py оглавление, вызовы и формы для get_callers
store.py чтение и запись разобранных справок
render.py markdown-карточки объектов и элементов
intake.py отбор и распаковка выгрузки в файлы, санитизация имён
incoming.py состояние data/incoming: кэш sha256, причина отказа
registry.py реестр источников, сопоставление версий
tools.py десять инструментов, без зависимости от MCP
server.py протокольный слой (единственная внешняя зависимость)
dashboard.py веб-интерфейс: реестр, запросы, словарь
cli.py отладочный CLI
bench.py стенд замеров качества поискаUn solo modelo para dos formatos. XML y JSON son serializaciones distintas de un mismo esquema; el cargador lleva ambos al mismo diccionario. Verificado: ambas descargas dan el mismo conjunto de 30 claves.
El grafo lo construye el cargador, no 1C. Las aristas se deducen de los tipos de atributos, movimientos de documentos, bases de entrada, propietarios, manejadores de suscripciones y métodos de tareas programadas. Las reglas se pueden cambiar sin recargar.
Aristas débiles. Atributos como ЗначениеДоступа enumeran cientos de tipos y vinculan casi todo con todo. Esas conexiones se marcan como débiles y por defecto están ocultas — de lo contrario las útiles se ahogan en ellas.
Niveles de detalle. La descripción completa de Документ.ЧекККМ (50 atributos, 17 partes tabulares) consume el contexto por completo. brief — un par de líneas, fields — la composición, full — con las conexiones.
Sin bases externas. Los índices de producción permanecen en un solo proceso: los arrays compactos de código responden sin una transición de red separada, y la búsqueda toma 0,18–1,5 ms. Elasticsearch, el almacenamiento vectorial y la base de datos de grafos no amortizan un proceso aparte y su mantenimiento en ese volumen. La búsqueda vectorial además requeriría un modelo codificador (+185–620 MB a la imagen) y 16–32 ms solo para codificar la consulta.
Medido con datos reales — 2026-08-18
Lo que está cargado en el servidor de trabajo:
Configuración | Plataforma | Objetos | Aristas |
Contabilidad para Kazajistán | 8.3.27.1936 | 3 492 | 84 426 |
Flujo documental KORP | 8.3.27.1936 | 4 596 | 50 554 |
Salario y gestión de personal | 8.3.27.1936 | 5 181 | 100 136 |
Retail para Kazajistán | 8.3.23.1997 | 5 637 | 58 345 |
Configuración sectorial | 8.3.5.1570 | 1 616 | 29 288 |
Total | 20 522 | 322 749 |
El conjunto es aleatorio — es lo que había a mano. Lo esencial no es la configuración en sí, sino la dispersión de plataformas: 8.3.5, 8.3.23 y 8.3.27 en un mismo registro, y cada configuración responde según la suya.
Además, la ayuda de la plataforma — índice fusionado de tres versiones (8.3.5, 8.3.23, 8.3.27), 25 691 elementos, y el lenguaje de consultas — 127 páginas como fuente separada.
Arranque en caliente de la imagen final con 12 archivos de caché de índices modulares — 19 s en el corpus de trabajo medido el 2026-08-21. En el arranque en frío, los fuentes se analizan, los índices se construyen y se guardan en data/index/cache/, las ayudas analizadas — en data/index/syntax/. Después se levantan desde allí.
La caché es derivada y desechable: está vinculada a la versión de Python, a la huella del código del paquete y al hash del origen. Si algo no coincide — los índices se reconstruyen. El directorio se puede eliminar en cualquier momento; se restaurará solo. Si el volumen de caché es de solo lectura, la imposibilidad de eliminar un archivo obsoleto no interrumpe la baja del origen del registro.
El orden de las entradas en registry.json no importa: el código se restaura solo después de su configuración. Si no hay entrada de esta, la eliminaron o la reemplazaron durante la ejecución, la entrada antigua de módulos o extensión no se publica sin propietario.
Los postings de los índices de búsqueda están en arrays numpy; el llenado temporal de diccionarios se libera inmediatamente después de la congelación. El RSS total del servidor no se puede obtener sumando capas aisladas: el pico en frío y el estado calentado del contenedor se toman por separado después de levantar todas las fuentes.
Textos de módulos — herramientas de código conectadas
La recepción de la descarga de configuración en archivos está implementada — sección «Descarga de configuración en archivos» arriba: el código y los formularios se guardan en disco, la fuente queda registrada en el registro, cuatro índices internos se construyen y se cachean. search_procedures busca nombres exactos y procedimientos exportados por palabras, get_procedure devuelve el sumario del módulo o una tarjeta con la ventana del cuerpo, y get_callers combina los lugares de llamada confirmados, los enlaces de metadatos y los manejadores de formulario sin leer los cuerpos.
El corte de producción actual de la configuración principal al 2026-08-21: 137 116 procedimientos, 619 029 lugares de llamada, 3 194 formularios, 89 528 elementos de formularios y 24 202 líneas de enlaces de eventos.
Se reproduce en su propia descarga sin imprimir su nombre ni ruta:
MODULES_ROOT=/путь/к/выгрузке
.venv/bin/python tools/lab/measure_modules_cache.py "$MODULES_ROOT"El medidor imprime agregados JSON con las claves procedures, calls,
forms, elements y event_rows. El último contador son las filas crudas
<Event> antes del agrupamiento y la eliminación de duplicados en los enlaces públicos.
La instantánea histórica del prototipo se tomó el 2026-08-20 sobre una exportación jerárquica anonimizada en archivos: 7 878 módulos, 137 115 procedimientos y 260 MB de texto. A continuación se conservan precisamente sus cifras, no los agregados actuales.
Capa | En disco | En memoria |
índice de 137 115 procedimientos | 14,9 MB | 62 MB |
619 030 lugares de llamada resueltos y no resueltos | 12,0 MB | 51 MB |
búsqueda entre 49 181 procedimientos exportados | 4,27 MB | 173 MB |
formularios: 3 194 archivos, 69 769 elementos | 5,8 MB | 44 MB |
textos de módulos y firmas | 260 MB | 0 |
La latencia de búsqueda es de 1,2–1,5 ms. La compilación completa en frío de los cuatro índices con escritura de caché tarda unos 50 s.
Existen dos exportaciones a archivos diferentes, y la segunda se midió por separado: la configuración
sectorial 10.5.1.3 sobre 8.3.5: disposición plana, módulos en .txt, código de formularios ordinarios
dentro de contenedores binarios .Form. 2 603 módulos, 33 555 procedimientos, análisis
de 1,1 s, búsqueda en los 94 MB completos con una mediana de 0,2 ms. Este formato no contiene
las estructuras de formulario, y parte de los módulos comunes se suministran compilados; no contienen
código fuente en absoluto. Dichos módulos son visibles en la dirección ОбщийМодуль.<Имя>, pero los
procedimientos y llamadas internos no se pueden leer. Por eso los resúmenes, la búsqueda, el índice de
un módulo ordinario, la búsqueda inversa y la información sobre solapamientos advierten sobre el
resultado de que los agregados se ofrecen únicamente a partir de los fuentes disponibles y pueden
estar incompletos.
Los scripts de medición están en tools/lab/; con ellos se reproduce cada cifra anterior:
.venv/bin/python tools/lab/measure_modules_cache.py <каталог выгрузки в файлы>
.venv/bin/python tools/lab/measure_modules.py <каталог выгрузки в файлы>
.venv/bin/python tools/lab/measure_resident.py <каталог> <файл индекса> собрать
.venv/bin/python tools/lab/measure_search.py <файл индекса> экспортные
.venv/bin/python tools/lab/measure_forms.py <каталог>
.venv/bin/python tools/lab/measure_flat.py <каталог плоской выгрузки>
.venv/bin/python tools/lab/measure_container_memory.py --mode cold --data data \
--timeout 300 --poll-interval 0.5
.venv/bin/python tools/lab/measure_container_memory.py --mode warm --data data \
--timeout 300 --poll-interval 0.5Calidad de búsqueda
Se obtiene con un banco de pruebas y se reproduce con un solo comando:
PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
--data data --config РозницаДляКазахстана \
--auto --sets query-language,roznica-metadata,modules-procedures \
--check-notesConjunto | Consultas | P@1 | P@3 | P@5 | P@10 | MRR | Distancia |
Lenguaje de consultas | 21 | 85,7% | 85,7% | 90,5% | 90,5% | 0,869 | 35,0% |
Metadatos de Retail | 21 | 81,0% | 90,5% | 90,5% | 95,2% | 0,862 | 93,2% |
Procedimientos de módulos | 3 | 0% | 0% | 0% | 33,3% | 0,047619 | 0% |
Nombres exactos de ayuda | 50 926 | 97,1% | 98,3% | 98,7% | 98,9% | 0,978 | 91,7% |
Homónimos | 10 544 | 98,7% | 99,8% | 99,9% | 100% | 0,992 | 93,9% |
Toda la tabla se tomó el 2026-08-21 con el comando exacto anterior en modo de solo lectura, sin
--save; el comando terminó con código 0. Los tres conjuntos manuales se recopilaron a partir de
formulaciones reales y fallos; los dos últimos se construyen a partir de los propios datos. En los
procedimientos los rangos son [fallo, fallo, 7]. Esto es la línea base para mejoras, no un umbral
de aceptación.
La fila de procedimientos se reproduce por separado más rápido:
PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
--data data --config РозницаДляКазахстана \
--sets modules-procedures«Distancia»: cuánto se separa el primer resultado del segundo, por mediana. Responde a la pregunta «¿acertamos con seguridad o de milagro?»: un 35% en el lenguaje de consultas frente al 91,7% en la ayuda significa que esas victorias se sostienen tres veces más débil y un ajuste del ranquin puede invertirlas sin mover ni un punto porcentual de P@1.
La latencia de búsqueda es de 0,18–1,4 ms por consulta según el conjunto.
Los conjuntos de consultas no entran en la imagen (tests/ en .dockerignore): hay que medir
desde la copia de trabajo, no desde el contenedor.
Pruebas
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest # 1100 тестов (прогон 2026-08-21)No dependen del contenido de data/: no hay exportaciones propietarias en el repositorio;
todo lo necesario se genera sintéticamente en tests/conftest.py.
La calidad de búsqueda no se comprueba con pruebas; se mide con el banco de pruebas
(mcp1c.bench, véase «Medido»). Los umbrales en porcentajes se romperían con cada cambio del
diccionario, por eso el banco imprime cifras y la decisión la toma una persona.
pytest comprueba el comportamiento observable: «el índice no se ha reconstruido»,
«la salida ha coincidido», «el arranque no ha fallado».
6. Seguridad
Dos tokens, ambos se definen mediante variables de entorno. Mientras el token no esté definido, el acceso correspondiente está abierto a cualquiera que llegue a la dirección.
Variable | Qué protege | No definida |
| lectura: herramientas MCP y páginas del panel | la estructura de configuraciones está abierta a todos |
| escritura: carga y eliminación de fuentes, análisis de la exportación entrante ( | estas rutas están desactivadas, responden 404 |
La diferencia entre «abierto» y «desactivado» es intencionada. La lectura sin token funciona; en tu propia máquina es cómodo y no supone ningún riesgo. La escritura sin token no funciona en absoluto: una única edición fallida del diccionario rompe silenciosamente la búsqueda para todos los que estén conectados al servidor compartido.
El token se transmite mediante una cabecera: o X-Api-Token, o
Authorization: Bearer <token>. El administrativo también sirve para la lectura:
de lo contrario, el propietario tendría que mantener dos cabeceras en el cliente en lugar de una.
El token debe estar en caracteres latinos. Las cabeceras HTTP se codifican en latin-1 y un token cirílico físicamente no llega al servidor: a través del formulario de inicio de sesión en el navegador funcionará; a través de la cabecera del cliente, no.
Se omiten dos rutas en la comprobación: /health (por ella pasa el healthcheck
del contenedor y no ofrece información más allá del derecho de lectura) y /login; de lo contrario,
el formulario de inicio de sesión quedaría detrás de esa misma autorización que emite.
Dos reglas más, que no son sobre tokens:
El endpoint MCP entrega la estructura de configuraciones completa. Defina
API_TOKENante cualquier despliegue fuera de su máquina; el acceso de red no es suficiente.El directorio
data/está completo en.gitignore— tanto los.hbkcon las exportaciones como los índices analizados. El índice de ayuda es el mismo contenido de la empresa «1C», solo que desempaquetado. Una vez llegó allí y permaneció durante 20 commits; la historia se reescribió congit filter-repoy la regla se reformuló por directorio, no por extensiones: no hay que comprobar «¿es un.hbk?», sino «¿está endata/?».
7. Documentos
Archivo | De qué trata |
qué se ha hecho y qué se ha averiguado sobre 1C | |
contrato del formato de exportación | |
qué tomamos de cada fuente | |
estructura de la fuente del lenguaje de consultas | |
estructura del panel | |
recepción de la exportación de configuración en archivos: planteamiento | |
índices y herramientas del proveedor de código | |
procesamiento de la exportación para 1C | |
cómo editar el proyecto: idioma, commits, comprobaciones | |
cómo informar de una vulnerabilidad |
Se publican seis documentos-contrato autosuficientes: el formato de exportación, el límite de las fuentes, la estructura del lenguaje de consultas y del panel, la recepción de la exportación de código y el proveedor de código. Cada enlace de un archivo público debe llevar a un material que también forme parte del repositorio.
La base de datos externa, los vectores, la base de datos de grafos, el transporte SSE y la carga perezosa se rechazaron con las mediciones del corpus actual. Solo se puede volver a ellos con nuevas mediciones que refuten el coste anterior o muestren un nuevo escenario real.
8. Licencia
Apache License 2.0. Merece la pena leer por separado NOTICE; allí hay dos cosas que la licencia no dice por sí misma:
el proyecto se ha desarrollado de forma independiente y no está afiliado a ООО «1С»; «1С» y «1С:Предприятие» son marcas comerciales de ООО «1С», y la licencia no otorga derechos sobre ellas (Apache 2.0, sección 6);
en el repositorio no hay ayuda de la plataforma ni exportaciones de configuraciones — ni en su forma original ni analizadas. Ese es contenido de la empresa «1С» y datos de implementaciones concretas; cada uno los toma de su propia distribución y los coloca en
data/. La licencia se aplica al código, no a los datos que usted cargue en él.
Available Tools
11 toolscompare_configurationsA
Сравнить один и тот же объект в двух конфигурациях: чем различаются имена реквизитов. Типы и содержимое табличных частей не сравниваются. Дочитайте все страницы по готовому вызову продолжения.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Число различий на странице суммарно для обеих сторон, от 1 до 100. | |
| cursor | No | Непрозрачный курсор из продолжения. Привязан к паре, объекту и содержимому сравнения. | |
| configs | No | Ровно два разных имени из `list_configurations`. Не заданы — автоматический выбор только при ровно двух загруженных конфигурациях; иначе выберите пару явно. | |
| full_name | Yes | Полное имя объекта, которое ищется в обеих конфигурациях. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It discloses the comparison limitation (only attribute names, not tabular-section types/contents) and warns that all pages must be read through the continuation call. This is meaningful behavioral context, though it does not address permissions or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: main purpose, comparison scope, and pagination instruction in three tight sentences. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the fully documented schema and existing output schema, the description covers the important behavioral details: what is compared, what is ignored, and pagination. It could slightly improve by referencing list_configurations for pair selection, but the schema already handles that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented. The description adds no additional parameter-level meaning beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: compare the same object across two configurations by attribute names. It also distinctly scopes what is compared and explicitly excludes tabular-section types and contents, making it clearly distinguishable from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context is given for when to use the tool: comparing one object's attribute names in two configurations. It does not explicitly name alternatives or when-not conditions, but the scope caveat and sibling list make the intended usage reasonably obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_callersA
Кто вызывает точную процедуру: подтверждённые места в коде с процедурой-владельцем, привязки подписок и регламентных заданий из метаданных, элементы и события формы. Одноимённые вызовы без разрешённого модуля показываются отдельно и не приписываются запрошенному адресу. Тела модулей не читаются.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Сколько мест вызова показать: целое число от 1 до 50. Оставшееся число подтверждённых мест и модулей указывается отдельно; одноимённые места без разрешённой цели тоже не выводятся без границы. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. | |
| address | Yes | Точный адрес процедуры `Модуль::Имя`, полученный из `search_procedures` или оглавления `get_procedure`. | |
| extension | No | Имя одного загруженного расширения. Не задано — места в коде ищутся только в основной конфигурации; чужой код не подмешивается. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it delivers. It discloses that only confirmed locations are returned, that unresolved same-name calls are shown separately, and that module bodies are not read. These are meaningful behavioral details beyond a generic 'returns callers' statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: three dense sentences that front-load the main purpose, then add scope caveats and a limitation. Every sentence earns its place, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and all parameters have rich schema descriptions, the definition is complete. The tool description covers scope, edge-case handling for unresolved same-name calls, and the fact that module bodies are not read, which is enough for an agent to use it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well documented in the schema. The tool description does not add extra parameter semantics, but it does not need to; the schema already explains address, limit, config, and extension. A baseline of 3 is appropriate here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Кто вызывает точную процедуру' — who calls the exact procedure. It then enumerates exact kinds of call sites (code locations, subscription/scheduled-job bindings, form items/events), making it clearly distinct from siblings like search_procedures or get_procedure.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the intended use clear: given an exact procedure address, identify its confirmed callers. It also communicates an important scope rule by stating that unresolved same-name calls are not attributed to the requested address. It does not explicitly name alternatives or exclusion conditions, but the context is unambiguous enough for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_objectA
Структура объекта конфигурации: реквизиты с типами, табличные части, движения, предопределённые. detail: brief | fields | full. Обязательный шаг перед написанием кода или запроса. Только здесь видно то, от чего код зависит и чего нет в поиске: вид и периодичность регистра (СрезПоследних есть лишь у периодического регистра сведений, а непериодических большинство), корреспонденция, предел субконто, и — для регистров — раздел «Таблицы запроса» с уже подставленными именами полей: ресурс Количество в запросе называется КоличествоОстаток или КоличествоОборот, и в конфигураторе таких имён не видно. Большие HTTP-сервисы и подсистемы дочитываются тем же get_object по готовому вызову с непрозрачным cursor; после смены поколения чтение нужно начать заново.
| Name | Required | Description | Default |
|---|---|---|---|
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. | |
| cursor | No | Непрозрачный cursor из ответа get_object для продолжения HTTP-сервиса или подсистемы. Передавайте без изменений с теми же full_name, config и detail. | |
| detail | No | Уровень детализации: `brief` — пара строк со счётчиками, `fields` — состав для написания кода, `full` — со свойствами и связями. Полное описание крупного документа занимает много контекста, поэтому `full` только когда связи действительно нужны. | fields |
| full_name | Yes | Полное имя объекта: `Документ.ЧекККМ`, `Справочник.Номенклатура`. Получается из `search_objects`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It reveals the cursor-based continuation mechanism for large HTTP services and subsystems, warns that reading must restart after a generation change, and explains that the 'full' detail level consumes a lot of context. These are valuable behavioral traits beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long and dense, but the core purpose is front-loaded and the examples (e.g., 'СрезПоследних', 'КоличествоОстаток') justify the tool's necessity. Some redundancy exists with the schema's parameter descriptions, but overall each sentence contributes useful context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, when to use it, parameter semantics, detail-level trade-offs, and the cursor/generation-change behavior. An output schema exists, so return values are covered elsewhere. The description is sufficiently complete for an agent to invoke and interpret this complex tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaningful guidance: it explains the detail levels in context, warns about the context cost of 'full', and clarifies cursor usage with same full_name, config, and detail. This exceeds simple schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the configuration object structure: attributes with types, tabular sections, movements, and predefined data. It goes beyond a generic 'get object' by explaining what is included and why it is unique compared to search results. This differentiates it from sibling tools like search_objects and search_procedures.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says this is a mandatory step before writing code or a query, and notes that only here can one see details not available in search. It gives a clear usage context but does not explicitly name alternatives or state when not to use it. Still, the guidance is concrete and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_procedureA
Оглавление модуля либо карточка одной процедуры из загруженной выгрузки кода. Адрес модуля без :: возвращает только оглавление без тела; Модуль::Имя возвращает сигнатуру, контекст компиляции и окно тела до 200 строк с готовым вызовом продолжения. Выбранное расширение читается отдельно от основной конфигурации; смысл его аннотации показывается явно.
| Name | Required | Description | Default |
|---|---|---|---|
| lines | No | Размер окна тела: целое число от 1 до 200. Если тело длиннее, ответ содержит готовый вызов следующего окна без пропусков. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. | |
| address | Yes | Точный адрес модуля (`ОбщийМодуль.ОбщегоНазначения`) или процедуры (`ОбщийМодуль.ОбщегоНазначения::Проверить`). | |
| extension | No | Имя одного загруженного расширения. Не задано — читается код основной конфигурации; чужие расширения в тело не подмешиваются. | |
| start_line | No | Номер первой строки окна тела, начиная с 0. Значение берётся из готового вызова продолжения в предыдущем ответе. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does meaningful work: it discloses that a bare address returns no body, that the body window is capped at 200 lines, that a ready continuation call is included, and that a selected extension is read separately from the main configuration. It does not cover error/not-found behavior, but the core execution traits are clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, each earning its place: the general purpose, the two address-mode behaviors, and the extension-isolation behavior. Key information is front-loaded and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with no annotations and an output schema, the description is complete enough: it covers address semantics, body windowing, continuation pagination, and extension handling. Config disambiguation is already documented in the schema, and the output schema covers return structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema for `address` by explaining the `::` distinction that controls whether the body is returned, and for `extension` by noting it is read separately with explicit annotation meaning. The remaining parameters are already well documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and distinct behaviors: it returns either a module's table of contents or a single procedure card from the loaded code export. It also explains the two address modes (`Module` vs `Module::Name`) and lists included elements (signature, compilation context, up-to-200-line body window), so an agent can distinguish it from sibling tools like search_procedures or get_syntax.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use a bare module address for a table of contents without the body, and use `Модуль::Имя` for a full procedure card with body window and continuation call. It does not explicitly name alternative tools or exclusion conditions, but the intended invocation patterns are unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_syntaxA
Полное описание элемента платформы 1С (сигнатура, параметры, тип возврата, доступность, версия появления, предупреждение об устаревании с рекомендуемой заменой, пример). Для объекта detail=full также открывает список связанных методов, свойств и страниц «См. также» с точными адресами для следующего вызова; после 50 ссылок продолжайте через detail=links и links_offset. Вызывать перед использованием функции на старой конфигурации: недоступное в её версии помечается, и там же лежит рецепт замены, если он записан (СтрРазделить появилась в 8.3.6 — на 8.3.5 нужен обход). Поле «Доступность» — тоже ошибка компиляции: серверный метод из клиентского контекста не соберётся. Режим совместимости проверяется отдельно: по одной версии платформы успешную компиляцию в старом режиме утверждать нельзя.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Имя элемента платформы: `СтрНайти`, `ЗаписьJSON.ЗаписатьНачалоОбъекта`, `ValueTable.Columns`. Для членов объектов надёжнее указывать `Объект.Член`. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. | |
| detail | No | Уровень карточки синтаксиса: `brief`, `fields` (по умолчанию), `full` (описание и первые 50 связей) или `links` (только связи, по 50 на страницу). Для следующей страницы `links` передайте `links_offset` из ответа. Связи показываются только по справке точного релиза конфигурации; без конфигурации доступность не проверена. | fields |
| links_offset | No | Смещение страницы связей для `detail=links`, от нуля. В остальных режимах оставьте 0. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses that `full` opens the related-methods/properties list capped at 50 links with continuation via `links_offset`, that the config must be specified when more than one is loaded, and that availability is a compile-error concept (server method from client context will not build). It even warns that compatibility mode must be verified separately, which is non-obvious behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the core capability leads, followed by paging and the availability/compatibility caveats. The final two sentences on availability and compatibility are valuable but slightly tangential to the call itself, keeping it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return format need not be explained; the description still covers paging behavior, the config-selection requirement, and the compatibility caveat, which is what an agent needs. It is complete enough for a complex lookup tool, though the interplay between config and link availability could be slightly tighter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline would be 3, but the description adds real meaning beyond the schema: how the detail tiers differ, that links paginate at 50, that `links_offset` is only meaningful for `detail=links`, and that links are shown only for the exact release help of the configuration. This goes past restating field docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (retrieve the full description) and an exhaustively enumerated resource: signature, parameters, return type, availability, version-of-appearance, deprecation with replacement, and an example. This clearly distinguishes it from the search-oriented siblings like search_syntax and search_procedures.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete when-to-use rule: call it before using a function on an old configuration, since unavailable members are flagged and a replacement recipe is stored there. It also explains the paging path (detail=links, links_offset). It does not explicitly name a sibling alternative (e.g. search_syntax for lookup), so it falls short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_configurationsA
Какие конфигурации 1С загружены, на какой платформе и что по ним доступно. Вызывать первым: если конфигураций больше одной, параметр config обязателен во всех остальных инструментах, а имя для него берётся отсюда.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the behavioral burden. It discloses that the tool is a read-oriented listing, reveals the returned concepts (configurations, platform, availability), and explains an important behavioral consequence: the config name should be sourced from this tool. It does not explicitly state read-only or side-effect-free behavior, but the query-like phrasing makes the intent clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with no filler. The core purpose is front-loaded, followed immediately by the most important usage rule. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema present, the description provides the essential context an agent needs: what the tool lists, why it exists, and how its output feeds into other tools. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description correctly mentions `config` as a parameter for other tools, not this one, and adds no unnecessary parameter detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what the tool reports: which 1C configurations are loaded, on which platform, and what is available for them. It also distinguishes itself from siblings by framing itself as the entry point that supplies the `config` value other tools need.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: call this tool first, and if more than one configuration exists, all other tools require the `config` parameter whose value comes from this result. This directly tells an agent when and why to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_extensionsA
Показать расширения, фактически действовавшие в снятом сеансе 1С, не применённые расширения и порядок элементов в ответе API платформы. Вызывать после list_configurations, когда задача зависит от активности расширений. Без отдельного runtime-снимка возвращает unknown; позиция API не выдаётся за доказанный порядок исполнения модулей.
| Name | Required | Description | Default |
|---|---|---|---|
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that without a separate runtime snapshot it returns 'unknown', and that API position order is not presented as proven module execution order. These caveats are valuable and go beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with purpose, followed by usage and caveats. Every sentence serves a distinct informative role, with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description does not need to explain return values. It covers purpose, usage context, prerequisite, and important behavioral caveats. It adequately equips an agent to determine when and how to call the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the `config` parameter is already well-described (name as returned by `list_configurations`, mandatory when multiple configurations). The tool's description adds no additional parameter detail beyond what the schema provides, so a baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: showing extensions that were actually active in a captured 1C session, unapplied extensions, and the order of elements in the platform API response. It references the prerequisite `list_configurations` and differentiates itself by focusing on extension activity within a specific session context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance to call after `list_configurations` when the task depends on extension activity. Gives a clear context and prerequisite, though it doesn't list when-not to use alternatives. No direct sibling for extensions exists, so the contextual direction is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_objectsA
Найти объект конфигурации по описанию или части имени. Запрос можно писать по-человечески: «расходная накладная», «цены номенклатуры». Отдаёт только имена и счётчики — состава полей здесь нет. Прежде чем писать код или запрос по найденному объекту, вызовите get_object: вид и периодичность регистра, готовые имена полей виртуальных таблиц (КоличествоОстаток, СубконтоДт1) приходят только оттуда. Запрос, написанный сразу после поиска, выглядит правильным и падает на «поле не найдено».
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Ограничить вид: Документ, Справочник, РегистрСведений, РегистрНакопления, Перечисление, ОбщийМодуль и т. п. | |
| limit | No | Сколько результатов вернуть. По умолчанию 10, максимум 50 (большее молча урезается). Поднимать выше 10 стоит только когда нужного не оказалось в первой десятке: правильный ответ почти всегда в первой пятёрке, а длинная выдача тратит контекст. | |
| query | Yes | Формулировка по-человечески («расходная накладная») или часть имени объекта. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It clearly states the limited output shape (names and counters only) and the failure mode when field information is missing. It does not mention auth or rate limits, but for a search tool the output limitation is the most important behavioral trait.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each earning its place: purpose, natural-language input, output scope, and the required follow-up with failure warning. There is no filler, and the most actionable guidance is clear and memorable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with a complete schema and an output schema, the description covers purpose, output limitations, and the follow-up needed to write correct code. It could mention alternatives like search_procedures, but the tool relationships are otherwise well handled by naming get_object explicitly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents query, kind, limit, and config. The description adds examples and a limit heuristic but no genuinely new parameter semantics; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: find configuration objects by natural-language description or partial name, and explicitly notes it returns only names and counters. This distinguishes it from get_object, which must be called afterward for field metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Directly instructs the agent to call get_object after searching before writing code or queries, and warns that queries written immediately after search will fail with 'поле не найдено'. Also gives actionable guidance on keeping limit at 10 unless the needed result is absent from the first ten.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_proceduresA
Найти процедуру или функцию в загруженном коде конфигурации либо одного выбранного расширения. Точное имя находит и неэкспортные процедуры; поиск по словам — только экспортные. Расширенная фраза о 12 типовых событиях разрешается в точное имя, но без scope не выбирает случайную реализацию. Для обычного поиска scope задаёт приоритет модулей, для распознанного события — ограничивает его реализации. Из query область не угадывается. Сигнатуры читаются из выгрузки в файлы только для показанных результатов.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Сколько результатов вернуть отдельно на каждом уровне поиска: по точному имени и по словам. Целое число от 1 до 50; значение вне диапазона отклоняется, чтобы не скрывать ошибку вызова. | |
| query | Yes | Точное имя процедуры (`ПриЗаписи`) или слова из имени и комментария-шапки (`проверить остатки`), в том числе фраза о поддержанном типовом событии (`что выполняется при записи объекта`). Объект поиска из этого текста не угадывается — для него есть `scope`. | |
| scope | No | Необязательный явный scope: объект (`Документ.ЧекККМ`) или точный адрес (`ОбщийМодуль.ОбщегоНазначения`). В обычном поиске его модули поднимаются, а распознанное типовое событие разрешается только внутри scope. Из query область не выводится. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. | |
| extension | No | Имя одного загруженного расширения. Не задано — поиск идёт только по коду основной конфигурации, без примеси расширений. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly. It discloses that event phrases resolve without picking an arbitrary implementation, that scope changes priority or constraint semantics, that query does not imply scope, and that signatures are read from file dumps only for displayed results. These are non-obvious behavioral details beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and each sentence adds meaningful detail. However, it is somewhat dense and partially repeats scope/query semantics already documented in the input schema, so it is not maximally tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the presence of an output schema, and full parameter coverage in the schema, the description covers all necessary operational aspects: search modes, event recognition behavior, scope semantics, config/extension context, and result-dependent signature reading. An agent has enough information to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The narrative description mostly restates scope semantics already present in the input schema and adds no new parameter-level detail beyond it. The schema itself is doing the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Найти процедуру или функцию' in loaded configuration code or one selected extension. It further differentiates exact-name search from word-based search and notes exported versus non-exported coverage, making the tool's purpose immediately recognizable among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical usage context: exact names find non-exported procedures, word search finds only exported ones, scope behaves differently for ordinary search versus recognized events, and config is tied to the loaded configuration. It does not explicitly name sibling alternatives or state when not to use this tool, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_syntaxA
Найти метод, свойство или объект платформы 1С. Для вызываемого действия задайте kind=method: иначе в выдаче могут оказаться свойства и сходные по названию механизмы. Даёт только строку списка. Сигнатура, параметры, доступность по контекстам, версия появления, порог устаревания и рекомендуемая замена — в get_syntax по найденному имени. При режиме совместимости компиляция метода остаётся непроверенной и помечается unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Ограничить вид: method, property, event, object, query_table, query_field. | |
| limit | No | Сколько результатов вернуть. По умолчанию 10, максимум 50 (большее молча урезается). Поднимать выше 10 стоит только когда нужного не оказалось в первой десятке: правильный ответ почти всегда в первой пятёрке, а длинная выдача тратит контекст. | |
| query | Yes | Что ищем: «разделить строку», «ЗаписьJSON», «StrFind» по платформе. Русские и английские имена равнозначны. | |
| config | No | Имя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does real work: it discloses that output is only a list row (not detail), and that under compatibility mode method compilation is left unverified and marked unknown. It does not discuss permissions, ordering, or rate behavior, but the output-scope and edge-case disclosure is above average.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four front-loaded sentences with no filler: purpose, kind caveat, output scope, and where the detail lives. The most decision-relevant constraint (kind=method) is placed early, and the redirection to get_syntax closes the loop.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and 100% parameter coverage, the description need not explain returns or params, and it correctly focuses on the search-vs-detail boundary and the compatibility-mode caveat. It is essentially complete for this tool's complexity, with only minor gaps around result ordering.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, and the description adds genuine meaning beyond the bare enum list by explaining why kind=method matters for callable actions and that Russian/English names are equivalent. It enriches the semantics of kind rather than merely restating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (find a 1C platform method/property/object) and immediately scopes the return to a list row only, explicitly contrasting with get_syntax which carries the full detail. An agent can separate this from siblings like get_syntax and search_objects without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete routing advice: set kind=method for callable actions to avoid properties and similarly named mechanisms, and directs the agent to get_syntax for signature/params/deprecation. It stops short of stating when to prefer the sibling search_objects or search_procedures, so it is clear context without full exclusion coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v4.2.0- Removed
get_module_source_file
2 tool updates
v4.1.0- Added
get_module_source_file - Changed
get_syntax2 fields changed- changed
Input schema / properties / detail / descriptionPrevious value: -"Уровень детализации: `brief` — пара строк со счётчиками, `fields` — состав для написания кода, `full` — со свойствами и связями. Полное описание крупного документа занимает много контекста, поэтому `full` только когда связи действительно нужны."New value: +"Уровень карточки синтаксиса: `brief`, `fields` (по умолчанию), `full` (описание и первые 50 связей) или `links` (только связи, по 50 на страницу). Для следующей страницы `links` передайте `links_offset` из ответа. Связи показываются только по справке точного релиза конфигурации; без конфигурации доступность не проверена." - added
Input schema / properties / links_offsetAdded value: +{ + "default": 0, + "description": "Смещение страницы связей для `detail=links`, от нуля. В остальных режимах оставьте 0.", + "title": "Links Offset", + "type": "integer" +}
1 tool update
v3.3.0- Changed
get_object1 field changed- added
Input schema / properties / cursorAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Непрозрачный cursor из ответа get_object для продолжения HTTP-сервиса или подсистемы. Передавайте без изменений с теми же full_name, config и detail.", + "title": "Cursor" +}
1 tool update
v3.0.0- Changed
compare_configurations3 fields changed- changed
Input schema / properties / configs / descriptionPrevious value: -"Имена конфигураций из `list_configurations`. Не заданы — берутся все загруженные."New value: +"Ровно два разных имени из `list_configurations`. Не заданы — автоматический выбор только при ровно двух загруженных конфигурациях; иначе выберите пару явно." - added
Input schema / properties / cursorAdded value: +{ + "anyOf": [ + { + "maxLength": 2048, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Непрозрачный курсор из продолжения. Привязан к паре, объекту и содержимому сравнения.", + "title": "Cursor" +} - added
Input schema / properties / limitAdded value: +{ + "default": 40, + "description": "Число различий на странице суммарно для обеих сторон, от 1 до 100.", + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" +}
11 tool updates
v2.0.0- First observed
compare_configurations - First observed
get_callers - First observed
get_object - First observed
get_procedure - First observed
get_related - First observed
get_syntax - First observed
list_configurations - First observed
list_extensions - First observed
search_objects - First observed
search_procedures - First observed
search_syntax
TDQS
Scored across 11 tools
The set follows a clean search_X (find) vs get_X (detail) pattern that the descriptions explicitly reinforce (e.g. search_objects returns names/counters only, get_object returns field structure). Each tool targets a distinct resource or action, with even subtle cases like get_object vs get_related and search_syntax vs search_procedures clearly differentiated.
Every tool uses a consistent snake_case verb_noun convention (list_configurations, search_procedures, get_object, compare_configurations). No mixing of styles or vague standalone verbs.
11 tools is well-scoped for a rich configuration-analysis domain, covering listings, search/detail pairs for objects, procedures, and platform syntax plus relation/caller/comparison utilities. Each tool earns its place with no redundant entries.
The surface covers the full read-only analysis lifecycle: discovery, structure, relations, callers, cross-config comparison, and platform syntax lookup. Minor gaps remain—procedure bodies are capped at ~200 lines and multi-hop dependency chains require manual repeated calls—but these are workable.
Maintenance
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Get up-to-date, version-specific documentation and code examples from official sources directly in…
Versioned documentation registry and semantic search for AI tools and coding assistants.
RU INN/OGRN, banks, geo, WHOIS. Agent self-registers via register_agent. 20 free/day.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceProvides a RAG-based search system for 1C:Enterprise platform documentation using hybrid BM25 and semantic search across multiple versions. It enables developers to retrieve API signatures, methods, and usage examples directly within IDEs or through a REST API.23MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with 1C:Enterprise databases through natural language, providing metadata retrieval, configuration analysis, and code generation.9-
- AlicenseNot gradedqualityAmaintenanceMCP server for 1C:Enterprise that provides precise syntax reference cards (call signatures, parameters, return types, examples) by element name and lists object members. It helps AI agents answer 1C development questions using the official Russian help book.MIT
- AlicenseNot gradedqualityCmaintenanceProvides AI assistants in Cursor with local access to 1C platform documentation and XML configuration exports, enabling metadata lookup, BSL code search, and platform help queries without manual file copying.MIT