Skip to main content
Glama

MCP-Server für 1C-Konfigurationsstrukturen

tests license python

Nachschlagewerk zu den Metadaten mehrerer 1C-Konfigurationen, zur Plattformsyntax und zur Abfragesprache – für Agenten, die Code in BSL schreiben. Liefert einen minimal ausreichenden Ausschnitt: Auflösung einer menschlichen Formulierung in den exakten Objektnamen, Suche nach fertigen Prozeduren im Code-Export, deren Signaturen, begrenzte Fenster der Rümpfe und Rückverweise aus Aufrufen, Metadaten und Formularen, die Objektstruktur auf der benötigten Detailebene, deren Verknüpfungen, die Beschreibung der Plattformmethoden unter Berücksichtigung der Version der jeweiligen Konfiguration und die Konstrukte der Abfragesprache.

Ersetzt kein grep über die Arbeitsquellen des Projekts: Der Server sucht Prozeduren nur im geladenen Konfigurations-Export in Dateien und sieht nicht ungeladene Änderungen. Die Grenze der Quellen ist in docs/data-sources.md festgehalten.

Stand – 2026-08-21

Phase

Status

Verarbeitung des Exports für 1C

✅ 20 Arten von Metadaten, 8.3.5 und 8.3.23, XML und JSON

Exportformat

✅ schema v1

Lader, Modell, Verknüpfungsgraph, Render

✅ 5 Konfigurationen, 20 522 Objekte, 322 Tsd. Kanten

Plattformhilfe

✅ zusammengeführter Index von drei Versionen, 25 691 Elemente, Grenzen since/until

Abfragesprache

✅ shquery_ru.hbk, 127 Seiten, separate Quelle ohne Versionen

Suche

✅ 97,1 % Hilfe, 94,7 % Abfragesprache, 90,5 % Metadaten – siehe „Gemessen“

Virtuelle Registertabellen

✅ fertige Abfragefeldnamen (КоличествоОстаток)

Ersetzungstabelle für alte Plattformen

✅ Nicht Verfügbares wird nicht nur verboten, sondern durch ein Rezept ersetzt

Quellenregister, Versionszuordnung

✅

MCP-Server, 10 Werkzeuge

✅ streamable-http und stdio

Docker

✅ ein Container, 357MB laut Docker-CLI-Ausgabe

Cache der Suchindizes

✅ 12 MB, wird statt erneuter Analyse geladen

Messstand

✅ python -m mcp1c.bench, P@k, MRR, Abstand, Abgleich der Markierungen

Tests

✅ .venv/bin/python -m pytest, 1100

Dashboard

✅ Register, Quellen, Abfragelauf, Verknüpfungsgraph, Karten, Wörterbuch

Autorisierung

✅ API_TOKEN für Lesen, ADMIN_TOKEN für Schreiben

Annahme des Konfigurations-Exports in Dateien

✅ data/incoming/, Auswahl und Erfassung der Quelle

Code-Indizes aus dem Export in Dateien

✅ Suche, Prozedurkarte und Rückwärtssuche von Aufrufen

Die Größe des finalen Images wurde am 2026-08-21 geprüft: Der Befehl docker image ls mcp1c:latest --format '{{.Size}}' ergab 357MB. Das ist die von der Docker-CLI angezeigte Größe. Der Befehl docker image inspect mcp1c:latest --format '{{.Size}}' lieferte 77950901 Bytes des internen Feldes; das ist eine andere Metrik, keine zweite Messung der angezeigten Größe.

Es gibt keine Einschränkungen bei der Konfiguration. Jede wird geladen – typische (Buchhaltung, Gehalt, Dokumentenfluss, Einzelhandel) und branchenspezifische: Die Exportverarbeitung durchläuft die Metadaten, statt sie auswendig zu kennen. Verarbeitet wird, was exportiert wurde.

Entscheidend ist die Plattformversion, auf der die Konfiguration läuft: Von ihr hängt ab, was get_syntax als verfügbar anzeigt und was es als später ausblendet. Geprüft auf 8.3.5 und 8.3.23 – das sind die Grenzen dessen, was vorkam; die Hilfen sind aus drei Versionen zusammengeführt, 8.3.5, 8.3.23 und 8.3.27. Die Exportverarbeitung muss dabei auf 8.3.5 kompilieren: Die Untergrenze wird durch sie gesetzt, nicht durch den Server.

Related MCP server: 1C_MCP_SERVER_OWN

Inhalt

  1. Start – Docker, Dashboard, Verknüpfungsgraph, ohne Docker

  2. Agentenverbindung – wie MCP funktioniert, wenn keine Verbindung zustande kommt, Token, Client- Konfigurationen: Claude Code, Codex CLI, Cursor, VS Code, Qwen Code, stdio

  3. Werkzeuge – Aufrufreihenfolge, Quellen, Abfragesprache, Plattformversionen, Zusammenführung der Hilfen, Ersetzungen

  4. Datenverwaltung – Quellen, Konfigurations-Export in Dateien, Wörterbuch und Suchschlüssel, CLI, Messstand, Server manuell, woher die Daten kommen

  5. Wie es aufgebaut ist – Module, Messungen, Tests

  6. Sicherheit – Token, was ohne sie offen ist

  7. Dokumente

  8. Lizenz – Apache 2.0, Verhältnis zur Firma „1С“


1. Start

Docker (Hauptweg)

# 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"]}

Die Plattformhilfe und die Abfragesprache sind verschiedene Quellen und verschiedene Felder: syntax_loaded bezieht sich nur auf erstere, syntax listet die Versionen der geladenen Hilfen auf. Die Konfigurationsnamen und Hilfversionen werden nur einer Anfrage gegeben, die die Leseprüfung bestanden hat; ohne Token bleiben status, der Zähler und zwei Flags.

Alles, was in data/bootstrap/ liegt, wird beim Start indiziert: *.zip – Konfigurations- Exporte, *.hbk – Plattformhilfe. Dieselbe Datei wird nicht erneut analysiert: Der Abgleich erfolgt über den Hash.

Ein Konfigurations-Export in Dateien, der aus Gewohnheit in bootstrap/ gelegt wurde, passt nicht – der Server erkennt ihn an der Zusammensetzung des Archivs (Code ist da, Manifest manifest.json / manifest.xml fehlt) und versucht nicht, ihn zu analysieren: Das sind Gigabytes, die man bei jedem Start nicht durchlaufen lassen kann. Statt eines Fehlers wird in der Liste der Startmeldungen sein Name mit einem Hinweis genannt, wohin solche Dateien gehören – data/incoming/, Abschnitt „Konfigurations-Export in Dateien“ weiter unten.

Das Verzeichnis ./data wird in den Container als /data eingehängt. Darin hält der Server Quellen, Indizes, Cache und registry.json; die Pfade im Register sind relativ, daher kann das Verzeichnis zwischen Entwicklungsrechner und Container verschoben werden.

data/ liegt vollständig außerhalb von git – es ist ein Volume, kein Teil des Repositories. Es wird durch Kopieren des Verzeichnisses übertragen. Daher muss die Hilfe nach dem Klonen selbst hineingelegt werden: Das Repository enthält sie nicht und kann sie nicht enthalten, es ist Inhalt der Firma „1С“.

Nach einer Codeänderung muss der Container neu erstellt, nicht neu gestartet werden:

docker compose up -d --build --force-recreate

restart startet den bisherigen Container mit dem bisherigen Image, und die Änderungen werden nicht übernommen.

Zum Port. Nach außen ist der Server auf 5001 freigegeben, im Container lauscht er auf 8000 – die Weiterleitung 5001:8000 in docker-compose.yml. Alle Adressen in dieser Datei sind extern, also 5001. Ist er von einem anderen Dienst belegt – ändern Sie die linke Seite der Weiterleitung, die rechte nicht anfassen: An ihr hängen EXPOSE und der Healthcheck des Images.

Dashboard

http://localhost:5001/ – sechs Seiten:

Seite

Was dort ist

Übersicht

was geladen ist: Objekte, Verknüpfungen, Plattformversion, Warnungen aus den Manifesten

Quellen

Liste des Geladenen, drei Abdeckungstabellen jedes Code-Korpus, Pfad zum vollständigen JSON-Protokoll, Laden von .zip und .hbk mit Übertragungsbalken, Löschen, Block „Eingehende Exporte“ – Dateien aus data/incoming/, Analyse per Knopf

Abfragen

Lauf einer Liste von Formulierungen mit Bewertung und Grund der Rangfolge

Verknüpfungen

Graph der Umgebung eines Objekts als Bild

Karte

Zusammensetzung eines Objekts oder Beschreibung eines Plattformelements – dasselbe, was der Agent sieht

Wörterbuch

Regeln mit Herkunft; Alias oder Synonymgruppe anlegen

Laden – was sichtbar ist und wann

Das Laden läuft in zwei Phasen, und sie werden unterschiedlich angezeigt.

Dateiübertragung – mit Balken auf der Seite „Quellen“: Prozent, Volumen, Geschwindigkeit und Schätzung des Rests. Berechnet wird er vom Browser, und das ist keine Marotte. Der Server sieht den Übertragungsfortschritt nicht: await request.form() gibt die Kontrolle erst zurück, wenn der Body vollständig angekommen ist, und der Auftrag wird erst danach angelegt. Geprüft an einem echten Socket: 40 MB brauchten 8,1 s, in dieser Zeit sahen 32 Abfragen von /sources von einer zweiten Verbindung keinen einzigen Auftrag. Auf localhost macht das keinen Unterschied, auf einem entfernten Server sind das Minuten eines leeren Bildschirms.

Zugleich wird das Limit von 500 MB vor dem Senden geprüft: Früher wurde eine überdimensionierte Datei vollständig hochgeladen und erst danach abgelehnt.

Analyse – mit der Tabelle „Laden“ auf derselben Seite: „wird angenommen“ → „wird analysiert“ → „fertig“ oder „Fehler“ mit Grund. Während die Arbeit läuft, aktualisiert sich die Seite selbst (meta refresh, alle 2 s).

Der Balken benötigt JS, die Tabelle nicht. Bei deaktiviertem JS funktioniert das Formular wie ein normales: Die Datei geht raus, der Auftrag wird angelegt, der Zustand ist in der Tabelle sichtbar – nur der Balken während der Übertragung fehlt.

Verknüpfungen – Objektgraph

/graph zeichnet die Umgebung eines Objekts: Farbe nach Art, Pfeil nach Richtung der Referenz, Kantenbeschriftung beim Überfahren. Ein Klick auf einen Knoten baut den Graphen um ihn herum, Ziehen verschiebt, das Rad skaliert. Das Nachbarlimit wird auf der Seite gewählt (15…400), der Beschnitt wird mit einer Zahl benannt – „30 von 102 angezeigt“.

Beantwortet die Frage „was bricht, wenn man etwas anfasst“: Ein Register, umgeben von orangefarbenen Belegen, sagt sofort, wer es bewegt.

Die Tiefe ist immer ein Schritt. Bei zwei Schritten von einem gängigen Nachschlagewerk erhält man tausend Objekte, bei drei – ein Drittel der Konfiguration; weiter geht die Verknüpfung über gemeinsame Mechanismen wie zusätzliche Attribute, die fast alles mit allem verbinden. Sie durch einen Schwellenwert nach der Anzahl der Verknüpfungen abzuschneiden geht nicht: Ein solcher Knoten hat 34 davon, und ein sinnvoller Справочник.Пользователи – 323. Daher entfaltet Knoten ein Mensch, nicht eine Heuristik – er sieht, wohin man nicht gehen sollte.

Ein solches Tool hat der Agent bewusst nicht. In zwei Schritten wächst der Graph auf tausend Objekte an, und gemeinsame Mechanismen lassen sich nicht durch einen einfachen Schwellenwert abtrennen: Ein sinnvoller Knoten kann mehr Verbindungen haben als ein technischer. Ein separates Tool kommt nur zusammen mit einer messbaren Regel zur Begrenzung der Ausgabe zurück; bis dahin wählt der Mensch den genauen nächsten Schritt im interaktiven Graphen.

Ein Fehltreffer wird behoben, ohne den Browser zu verlassen: Auf der Abfrageseite hat jede Phrase einen Link „nicht das – Alias anlegen“, der ins Wörterbuch mit bereits eingefügter Phrase führt. Die Änderung wirkt sofort – Indizes werden nicht neu aufgebaut, ein Neustart ist nicht nötig.

Lesen wird durch API_TOKEN geschützt, Schreiben durch ADMIN_TOKEN. Solange API_TOKEN nicht gesetzt ist, kann jeder lesen, der die Adresse erreicht – einschließlich der Struktur von Konfigurationen und Anpassungen. Für localhost ist das akzeptabel, für einen Server im Netzwerk nicht.

Die Tokens sind getrennt, weil das Lesetoken im Config jedes MCP-Clients liegt und mit ihm abfließt; der Agent soll keine Rechte haben, Quellen zu löschen. Das Admin-Token taugt auch als Lesetoken – man muss nicht zwei Header halten.

// .mcp.json — как клиент передаёт токен
{"mcpServers": {"1c": {"type": "http", "url": "http://localhost:5001/mcp",
                       "headers": {"X-Api-Token": "..."}}}}

Nur ASCII: HTTP-Header werden in latin-1 kodiert, Kyrillisch kommt darin nicht an. /health bleibt für Healthchecks offen, gibt aber Konfigurationsnamen nur mit Token zurück.

Laden, Löschen und Bearbeiten des Wörterbuchs erfordern ADMIN_TOKEN – dasselbe wie bei /admin/reload; ohne ihn existieren diese Endpunkte nicht, nicht „sie sind gesperrt“. Das Token wird einmal im Formular eingegeben, in den Browser geht nicht es, sondern eine Session-ID.

Wird über .env neben docker-compose.yml gesetzt – eine Vorlage mit allen Variablen liegt in .env.example:

cp .env.example .env
python3 -c "import secrets; print(secrets.token_urlsafe(32))"   # значение
docker compose up -d --force-recreate

Der Name in den Ergebnissen ist ein Link zur Karte: Bei einem Objekt sind das die Requisiten mit Typen, Tabellenteile und Bewegungen, bei einem Plattformelement – Signatur, Parameter, Verfügbarkeit und Version des Erscheinens. Derselbe Text, den der Agent erhält, mit dem Umschalter brief / fields / full. Eine Requisite hat keine eigene Karte – der Link führt zum Besitzerobjekt.

Die Seite „Abfragen“ beantwortet die Frage „warum hat der Server genau das ausgegeben“: Neben jedem Treffer steht der Grund – exakte Übereinstimmung, Alias aus dem Wörterbuch, alle Wörter der Abfrage. Daran sieht man, womit man einen Fehltreffer behandelt – mit Synonym, Alias oder Gewicht.

Die Verarbeitung der Hilfe dauert einige Sekunden: Die Seite antwortet danach, aber MCP-Clients werden dadurch nicht aufgehalten – die Indizierung läuft in einem separaten Thread.

Ohne Docker

Aus einer Kopie des Repositories – genauso, wie Tests und CLI ausgeführt werden:

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 5001

Oder als Paket – dann ist PYTHONPATH nicht nötig, und daneben erscheinen drei Befehle:

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.bench

Der Modulstart (python -m mcp1c.server) bleibt auch in diesem Fall funktionsfähig: Die Befehle sind dieselben Einstiegspunkte unter anderem Namen. Alle Schlüssel sind im Abschnitt „Datenverwaltung“ beschrieben.


2. Anbindung des Agents

Der Server implementiert das MCP-Protokoll mit den Standardtransporten des offiziellen SDK und passt daher zu jedem MCP-Client. Es sind keine Wrapper um HTTP erforderlich.

Transport

Wann

Adresse

streamable-http

Server in Docker oder auf einer separaten Maschine

http://adresse:5001/mcp

stdio

Client startet den Prozess selbst lokal

—

Beide unterstützten Transporte sind mit dem offiziellen MCP-Client geprüft: Handshake initialize, tools/list, tools/call, Protokoll 2025-11-25.

Der veraltete Transport HTTP+SSE wird nicht unterstützt: --transport sse wird als ungültiger Wert abgelehnt, bevor Daten gelesen und der Server gestartet werden. Ein alter Client benötigt den Modus streamable-http oder einen lokalen Start über stdio.

So funktioniert es

Es ist nützlich, das zu verstehen, bevor etwas keine Verbindung herstellt. Die Adresse ist eine – /mcp, es gibt keinen Endpunkt pro Tool; welches Tool aufgerufen wird, steht im Request-Body, nicht im Pfad.

Weiter – zwei verschiedene Mechanismen, die man nicht verwechseln sollte:

Tool-Beschreibungen

Daten

Wann

einmal, beim Verbinden

bei jedem Aufruf

Wer beginnt

Client, selbst, ohne Beteiligung des Modells

Modell, nach Entscheidung

Methode

POST initialize, dann POST tools/list

POST tools/call

Wohin geht es

Systemprompt des Modells

Gesprächsbody

Preis

einmalig, liegt die ganze Sitzung über

pro Aufruf

Beim Verbinden macht der Client POST initialize – der Server antwortet mit Name, Version und Text der instructions und gibt im Header mcp-session-id zurück. Dann liefert POST tools/list die Tools auf einmal: Name, Beschreibung, JSON-Schema der Parameter. All das wird in den Kontext des Modells gelegt, bevor der Mensch das erste Wort getippt hat. Das Modell holt die Beschreibung nicht, wenn sie gebraucht wird – sie ist bereits bei ihm.

Daraus folgt eine Konsequenz, die beim Bearbeiten von Beschreibungen wichtig ist: Sie belegen die ganze Sitzung über Platz im Fenster, unabhängig davon, ob das Modell auch nur ein Tool aufruft oder keins.

Es sind immer zehn Tools, unabhängig davon, was geladen ist. Der Satz ist ein Vertrag, keine Variable: Die Tools hängen miteinander zusammen, und auf einem Produktionsserver können Quellen für Konfiguration, Code, Plattformhilfe und Abfragesprache unabhängig geladen sein. Die Größe des Vertrags tools/list plus instructions hängt nicht vom Zustand des Registers ab.

Daraus folgt direkt eine Konsequenz, die man im Voraus kennen muss: Wenn eine Quelle nicht geladen ist, zahlt man trotzdem für ihre Tools. Ohne Plattformhilfe liegen search_syntax und get_syntax im Kontext und kosten 1 185 Tokens, mit der Antwort „Hilfe nicht verbunden“; compare_configurations bei einer Konfiguration – 262 Tokens für die Antwort „es werden mindestens zwei benötigt“. Behandelt wird das durch Laden der Quelle, nicht durch Auswahl der Tools: Ein dynamischer Satz wurde am 2026-08-19 ausprobiert und verworfen, weil unabhängige Quellen einen einheitlichen Sitzungsvertrag bewahren müssen.

Beschreibungen werden daher dicht geschrieben, und Details wandern in die Ausgabe des Tools selbst: Dafür zahlt man nur, wenn sie gebraucht wird.

GET /mcp – nicht „falsches POST“, sondern eine dritte Methode auf derselben Adresse: Sie öffnet einen Nachrichtenstrom vom Server zum Client und erfordert eine bereits erhaltene mcp-session-id. DELETE /mcp schließt die Sitzung.

Wenn der Client keine Verbindung herstellt

Der Antwortcode im Log (docker logs -f mcp1c) nennt die Ursache:

Code

Was nicht stimmt

406

Client sendet kein Accept: application/json, text/event-stream – beide Typen sind nötig

400 Missing session ID

Client hat den bei initialize erhaltenen Header mcp-session-id nicht zurückgegeben

400 beim ersten GET /mcp

Client hat den Handshake mit GET begonnen – er spricht den alten Transport HTTP+SSE, und auf dieser Adresse liegt streamable-http

404 auf /sse

dasselbe: der alte Transport ist vollständig deaktiviert

401

X-Api-Token nicht übergeben, obwohl API_TOKEN gesetzt ist

Log ist leer

Client hat gar keine Anfrage gesendet – es liegt an seiner Config, bis zum Server ist nichts angekommen

Ein realer Fall: Qwen Code stellte keine Verbindung her, weil in seiner Config der Schlüssel url stand – in der Gemini-CLI-Familie (Qwen erbt das Format) bedeutet er den alten SSE-Transport, und der Client begann mit GET und erhielt 400. Mit httpUrl – also streamable-http – klappt die Verbindung sofort.

Token: Was in die Client-Einstellungen aufzunehmen ist

Wenn auf dem Server API_TOKEN gesetzt ist, muss jeder Client ihn als Header senden. Ohne Header antwortet /mcp mit 401, und der Agent sieht die Tools einfach nicht.

Einer der beiden Header ist geeignet – der Server akzeptiert beide:

X-Api-Token: <токен>
Authorization: Bearer <токен>

Drei Dinge, an denen man stolpert:

  • Nur ASCII. HTTP-Header werden in latin-1 kodiert, ein kyrillisches Token kommt darin nicht an. So generieren: python3 -c "import secrets; print(secrets.token_urlsafe(32))".

  • In den Client kommt API_TOKEN, nicht ADMIN_TOKEN. Das Admin-Token wird auch akzeptiert, aber die Client-Config wandert in git und in Backups: Ein ausgelaufenes Lesetoken erlaubt das Ansehen, ein ausgelaufenes Admin-Token – das Recht, Quellen zu löschen.

  • stdio benötigt überhaupt kein Token. Dort startet der Client den Prozess selbst, das Netz ist nicht beteiligt und es gibt nichts zu prüfen. Wenn der Client keine Header setzen kann – das ist ein funktionierender Ausweg.

Prüfen, dass der Server das Token sieht, vor jeder Client-Einrichtung:

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/mcp

200 – Token akzeptiert. 401 – falsches Token oder Header nicht angekommen.

Wie man kein Geheimnis committet

.mcp.json und ähnliche Dateien liegen normalerweise im Repository. Optionen:

  1. Variablensubstitution – wenn der Client das kann (Claude Code kann es): "X-Api-Token": "${MCP1C_API_TOKEN}", und die Variable selbst in ~/.zshrc. In git wandert der Variablenname, nicht der Wert.

  2. Datei aus git herausnehmen: git rm --cached .mcp.json && echo ".mcp.json" >> .gitignore.

  3. Die Einstellung nicht im Projekt, sondern in der Benutzer-Config des Clients halten – dann hat das Repository damit gar nichts zu tun.

Claude Code

Datei .mcp.json im Projektstamm:

{
  "mcpServers": {
    "1c": {
      "type": "http",
      "url": "http://localhost:5001/mcp",
      "headers": { "X-Api-Token": "${MCP1C_API_TOKEN}" }
    }
  }
}

Der Block headers wird nur benötigt, wenn auf dem Server API_TOKEN gesetzt ist. Der Wert stammt aus einer Umgebungsvariable, damit die Datei im Repository gehalten werden kann:

echo 'export MCP1C_API_TOKEN=ваш_токен' >> ~/.zshrc && source ~/.zshrc

Oder per Befehl:

claude mcp add --transport http 1c http://localhost:5001/mcp \
  --header "X-Api-Token: $MCP1C_API_TOKEN"

Codex CLI

~/.codex/config.toml oder .codex/config.toml im Projekt:

[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 – hier heißt der Schlüssel servers:

{
  "servers": {
    "1c": {
      "type": "http",
      "url": "http://localhost:5001/mcp",
      "headers": { "X-Api-Token": "ваш_токен" }
    }
  }
}

Qwen Code

Format von Gemini CLI, und der Schlüssel wählt den Transport – das ist die einzige Feinheit:

{
  "mcpServers": {
    "1c": {
      "httpUrl": "http://localhost:5001/mcp",
      "headers": { "X-Api-Token": "ваш_токен" }
    }
  }
}

httpUrl – streamable-http, unser Fall. url bedeutet in diesem Format den alten SSE-Transport: Der Client beginnt den Handshake mit GET /mcp, erhält 400 Missing session ID und verbindet sich nicht.

Weitere Clients

Windsurf, Antigravity, Cline, Roo Code, Konsolen-Agents – die Schreibweise ist dieselbe: Transporttyp, URL und, wenn API_TOKEN gesetzt ist, ein Header-Block. Unterschiede nur im Dateinamen und im Schlüssel der obersten Ebene (mcpServers oder servers) – prüfen Sie die Dokumentation des jeweiligen Clients.

Der Client kann keine Header setzen – keine Sackgasse: Verbinden Sie sich über stdio, dort ist kein Token nötig, weil es kein Netz gibt.

Lokaler Start über stdio

Wenn der Client den Server selbst hochziehen soll. Token ist hier nicht nötig: Der Prozess wird vom Client gestartet, die Kommunikation läuft über Prozesskanäle, nicht über das Netz – es gibt nichts zu prüfen und nichts, wogegen man sich schützen müsste.

{
  "mcpServers": {
    "1c": {
      "command": "python3",
      "args": ["-m", "mcp1c.server", "--transport", "stdio", "--data", "/путь/к/data"],
      "env": { "PYTHONPATH": "/путь/к/проекту/src" }
    }
  }
}

3. Tools

Der Satz ist fest und bewusst klein: Jedes Tool hängt ständig im Kontext des Agents. Ein neues Tool erscheint nur für eine separate Benutzeraufgabe, nicht für jeden internen Index.

Werkzeug

Zweck

list_configurations

was geladen ist, welche Anbieter je Konfiguration verfügbar sind

search_objects(query, config, kind, limit)

menschliche Formulierung → exakter Objektname

search_procedures(query, config, extension, scope, limit)

exakter Name oder Wörter → Prozeduren im Konfigurationscode oder einer Erweiterung

get_procedure(address, config, extension, start_line, lines)

Inhaltsverzeichnis des Moduls oder Signatur, Kompilierungskontext und Fenster des Prozedurrumpfs

get_callers(address, config, extension, limit)

bestätigte Aufrufstellen, Metadatenbindungen und Formularhandler

get_object(full_name, config, detail)

Zusammensetzung des Objekts; detail: brief / fields / full

get_related(full_name, config)

Bewegungen, Verweise, Abhängigkeiten — nur direkte

compare_configurations(full_name, configs)

ein Objekt in zwei Konfigurationen

search_syntax(query, config, kind, limit)

Suche in der Plattformhilfe und in der Abfragesprache

get_syntax(name, config, detail)

Signatur, Parameter, Verfügbarkeit, Version, Ersatz für alte Plattform

config ist erforderlich, wenn mehr als eine Konfiguration geladen ist: Der Server setzt sie bewusst nicht stillschweigend ein — sonst schreibt der Agent Code auf Basis einer fremden Datenbank, und niemand erfährt davon.

list_configurations zeigt den tatsächlichen Zustand des Code-Index der Hauptkonfiguration und jeder Erweiterung: fertig, wird mit Phase und Fortschritt erstellt, Fehler oder Code nicht geladen. Für eine fertige Erweiterung werden die Anzahl der Überlappungen nach vier Annotationen, die Anzahl der betroffenen Module und eigener Prozeduren sowie der fertige Parameter extension für den Zugriff auf ihren Code ausgegeben. Ein fertiger Korpus mit unbekannter oder beschädigter Variante wird als Zustand „fertig mit Einschränkungen“ bezeichnet. Alle drei Shells erhalten exakte Aggregate einer Generation, zeigen sie aber je nach Aufgabe. list_configurations und reg-list speichern detaillierte Diagnosen: Kategorien, die ersten 20 Probleme in stabiler Reihenfolge und die genaue Anzahl der verbleibenden; für einen nicht adressierbaren Kandidaten wird nur die laufende Nummer ausgegeben, ohne physischen Namen und lokalen Pfad. /sources zeigt statt eines Adressfeeds drei vergleichbare Tabellen mit Anzahl, Prozentsatz und explizitem Nenner: Module und Prozeduren, Formularstrukturen, Formularmodule.

Die vollständige Liste jedes Korpus wird atomar in einer einzigen aktuellen Datei data/logs/code-<sha256 source_id>.json gespeichert. Die Hauptkonfiguration und jede Erweiterung haben unterschiedliche Protokolle; erneutes Laden ersetzt nur die eigene Datei, das Löschen einer Quelle entfernt sie. Ein beschädigtes, generationsfremdes oder inhaltlich von den aktuellen Indizes abweichendes Protokoll wird nicht als aktuell angezeigt und wird aus fertigen Indizes neu aufgebaut. Formularstrukturen zeigen separat, wie viele vollständig, teilweise und nicht gelesen sind. Der Vertrag und die Invarianten von schema v1 sind unten beschrieben. Die Warnung steht über einer unvollständigen Antwort und sagt direkt: Ein Nullzähler beweist nicht das Fehlen versteckter Daten.

Code-Abdeckungsprotokoll — schema v1

Eine Datei gehört zu einer unabhängig löschbaren Quelle <Konfiguration>:modules oder <Konfiguration>:ext:<Erweiterung>. Der Quellname wird nicht in den Pfad aufgenommen: Die Datei heißt nach der vollständigen sha256 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
    }
  ]
}

Die Kategorien modules, procedures, form_structures und form_modules müssen in der Summe ihren total ergeben; beide Formulartabellen haben einen Nenner; problem_rows_total entspricht der Länge des vollständigen problems. address ist null, wenn die kanonische Adresse nicht bewiesen werden kann, dann ist ordinal eine deterministische Kandidatennummer. marker speichert den gelesenen Marker der Struktur form oder null, wenn das Problem nicht dazu gehört. identity verbindet das Protokoll mit sha256 und der Generation des Locator-Katalogs.

In die Datei gelangen keine absoluten Pfade, rohe Ausnahmen, Tracebacks, Token, BSL-Rümpfe und rohe form-Einträge. Der Katalog wird ohne Verfolgen eines symbolischen Links geöffnet, die temporäre Datei wird darin erstellt und ersetzt die endgültige atomar. Ein Schreibfehler hebt die Fertigkeit des Korpus nicht auf.

get_object fügt je nach detail Codeinformationen hinzu: Bei brief greift es nicht auf den Code-Anbieter zu, bei fields liefert es eine Zeile mit Zählern, bei full listet es Module und alle Formulare des Objekts ohne deren Inhalt auf. Ein Formular bleibt bei jedem Nachweis sichtbar: eigenständiger XML-Deskriptor, Form.xml, Form.bin, flaches .Form oder ein einzelnes Formularmodul. Wenn der Index gerade erstellt wird, mit einem Fehler endete oder nicht geladen ist, werden die Objektmetadaten trotzdem zusammen mit dem ehrlichen Codestatus zurückgegeben. get_related markiert verknüpfte Objekte, deren Prozeduren tatsächlich von einer geladenen Erweiterung überlappt werden; eine eigene Prozedur der Erweiterung erzeugt eine solche Markierung nicht. Bei fields und full listet die Objektkarte ohne gemeinsames Limit die Gründe auf, die ihre Formulare betreffen, sodass ein ungelesenes Formular nicht zu einem falschen „keine Formulare“ wird. Die Werkzeuge für Prozeduren und Verknüpfungen setzen die Warnung ebenfalls über das Teilergebnis; ein Generationswechsel wiederholt die gesamte Antwort zusammen mit Zählern und Problemen.

search_procedures vereint zwei Ebenen. Eine exakte Namensübereinstimmung findet jede Prozedur, einschließlich nicht exportierter; die Suche nach Wörtern, Beugungen und Kopfkommentar funktioniert nur bei exportierten. Auf jeder Ebene wird limit separat festgelegt und muss eine ganze Zahl von 1 bis 50 sein. In der Antwort kommen die Adresse Modul::Name, die Signatur von der Festplatte, der Exportstatus, die Zeile, die Anzahl bestätigter Aufrufstellen und ein separater Zähler gleichnamiger Stellen, deren Ziel nicht aufgelöst werden konnte. Der boolesche Index der Erweiterungsannotation wird neutral genannt: Er gibt &Nachher oder &Vorher nicht als vollständige Überlappung der ursprünglichen Prozedur aus. Signaturen und Rümpfe werden nicht im Arbeitsspeicher gehalten. Hierarchische .bsl, flache .txt und der module-Eintrag der Quellcontainer Form.bin/.Form durchlaufen denselben Lexer; Suche und anschließende Karte verwenden einen Locator derselben Generation und stellen den Pfad nicht aus der Adresse wieder her.

Ohne scope ist die Suche global. Explizites scope="Dokument.CheckKKM" hebt alle Module des Objekts an, und scope="GemeinsamesModul.AllgemeinerZweck" oder eine andere exakte Adresse — ein Modul; die übrige Ausgabe bleibt darunter. Der Bereich wird nicht aus query erraten. extension wählt genau eine geladene Erweiterung; ohne sie wird nur in der Hauptkonfiguration gesucht.

get_procedure akzeptiert eine exakte Adresse aus der Suche. Eine Moduladresse ohne :: gibt ein Inhaltsverzeichnis ohne Rümpfe zurück; Modul::Name — Signatur, Kompilierungskontext und Rumpf. start_line beginnt bei 0, lines muss eine ganze Zahl von 1 bis 200 sein; eine lange Antwort enthält einen fertigen Aufruf des nächsten Fensters ohne Zeilenüberspringen. Für die ausgewählte Erweiterung zeigen &Nachher, &Vorher und &Stattdessen ihren Rumpf; &ÄnderungUndKontrolle — den Rumpf der Hauptkonfiguration und nur wörtliche Blöcke #Einfügen/#Löschen. Über fremde geladene Erweiterungen warnt das Werkzeug über dem Rumpf, mischt deren Code aber nicht in die Antwort. Signaturen und Rümpfe werden für eine Antwort von der Festplatte gelesen und bleiben nicht im Arbeitsspeicher. Derselbe Locator überlebt Cache und Neustart: Wenn die Quelle während des Lesens ersetzt wird, wird die gesamte Antwort nach der neuen Generation wiederholt, und Teile zweier Generationen werden nicht vermischt.

get_callers akzeptiert nur eine exakte Adresse Modul::Name. Zuerst gruppiert es bestätigte Aufrufstellen nach Modul und nennt die Besitzerprozedur, dann zeigt es Ereignisabonnements und geplante Aufgaben aus dem Metadatengraphen, danach Element und Ereignis des Formulars aus Form.xml. limit muss eine ganze Zahl von 1 bis 50 sein; nach dem Abschneiden bleiben genaue Zahlen von Stellen und Modulen. Ein Deskriptor oder Containereintrag allein beweist nicht das Fehlen eines Handlers: Bei unbewiesener Positionssemantik meldet das Werkzeug eine teilweise Abdeckung. Der Status von Form.xml wird separat gespeichert, sodass intakte XML-Bindungen auch bei einem Defekt des benachbarten Containers verfügbar bleiben. Aufrufe einer gleichnamigen Prozedur ohne aufgelöstes Modul werden separat ausgegeben und nicht der angefragten Adresse zugeschrieben. Wenn zwei Prozeduren auf derselben physischen Zeile liegen, wird der Besitzer nicht erraten. Modultexte liest das Werkzeug nicht. Eine leere Antwort erinnert daran, dass Zeichenfolgenaufrufe über Ausführen, BeschreibungBenachrichtigung und VerbindungWarteHandler nicht indiziert werden.

Was der Anbieter nicht weiß

  • Die Wortsuche funktioniert nur bei exportierten Prozeduren. Eine nicht exportierte kann über den exakten Namen oder das Inhaltsverzeichnis eines bekannten Moduls gefunden werden.

  • Dynamische Aufrufe, bei denen der Name als Zeichenfolge an Ausführen, BeschreibungBenachrichtigung oder VerbindungWarteHandler übergeben wird, werden nicht indiziert.

  • Bei einem kompilierten gemeinsamen Modul gibt es keinen verfügbaren Quelltext: Die Adresse selbst ist sichtbar, aber nicht Prozeduren, Aufrufe, Signaturen und Rümpfe darin.

  • In der Containerstruktur Form.bin/.Form, einschließlich flachem Export, sind bisher die Klammergrammatik und die Wurzelmarker 19, 20, 23, 25, 26, 27 bewiesen, aber nicht die Bedeutung der Positionsfelder. Daher ist ein solches Formular als teilweise gelesen sichtbar, und Attribute, Elemente und Ereignisse daraus werden nicht erraten. Der vollständige Aufbau und die Bindungen sind weiterhin nur aus Form.xml verfügbar; der XML-Deskriptor liefert separat UUID, Name, Synonym und Formulartyp.

  • Ein gleichnamiger Aufruf, der nicht bis zum genauen Modul aufgelöst wird, wird nicht der angefragten Prozedur zugeschrieben und separat angezeigt.

Ein Name kann in zwei Domänen gleichzeitig leben: StrFinden gibt es sowohl in der Plattform (seit 8.3.6) als auch in der Abfragesprache. Dann listet get_syntax gleichnamige mit fertiger Adresse jedes auf, und der Aufruf kann mit einer Zeile aus der Ausgabe wiederholt werden:

get_syntax("СтрНайти")                    → Одноимённых элементов: 2
                                            - `Глобальный контекст.СтрНайти` — Метод, с 8.3.6
                                            - `Запрос.СтрНайти` — Функция запроса
get_syntax("Запрос.СтрНайти")             → карточка функции языка запросов

Der Qualifikator Abfrage. ist nötig, weil ein Element der Abfragesprache keinen Besitzer hat: Es kann nicht wie ein Plattformelement über Objekt.Mitglied benannt werden.

Aufrufreihenfolge — und was verloren geht, wenn man sie verletzt

list_configurations
├─ search_objects → get_object → get_related
├─ search_procedures → get_procedure → get_callers
└─ search_syntax → get_syntax

In der Codekette fügt jeder Schritt Informationen hinzu, die der vorherige nicht hat. Ohne search_procedures muss man die genaue Adresse im Voraus kennen und verliert die Suche nach Zweck und Bereich. Ohne get_procedure werden Signatur, Kompilierungskontext, Prozedurrumpf und die genaue Erweiterungssemantik nicht angezeigt. Ohne get_callers fehlt die Prüfung direkter Folgen einer Bearbeitung: bestätigte Aufrufstellen, Metadatenbindungen und Formularereignisse.

Den Schritt get_object darf man nicht überspringen. Die Suche liefert nur Namen und Zähler; alles, wovon der Code abhängt, lebt in der Objektkarte:

  • Art und Periodizität des Registers. SchnittLetzte gibt es nur bei einem periodischen Informationsregister, nicht bei nicht periodischen 566 von 603;

  • fertige Feldnamen virtueller Tabellen. In der Abfrage heißt die Ressource Menge MengeRest, MengeUmsatz, MengeEingang — im Konfigurator sind solche Namen nirgends sichtbar, sie werden von der Plattform erzeugt;

  • Subconto-Grenze, Korrespondenz, Zeitplanressourcen — ohne sie gibt es nichts, womit Felder wie SubcontoDt1 benannt werden könnten;

  • Zeichenfolgen unbegrenzter Länge. Sie sind direkt im Typ markiert: Zeichenfolge (unbegr. — nur über UNTERZEICHENFOLGE) gegenüber Zeichenfolge(200). Ein solches Feld kann nicht unverändert in eine Abfrage gestellt werden — die Plattform lässt es weder vergleichen, noch gruppieren, noch sortieren. Solche Felder machen 23% bis 38% der Zeichenfolgenfelder in realen Konfigurationen aus, daher wird auf Karten, wo sie vorkommen (2 474 von 20 522), vor der Feldliste ein Hinweis mit Rezept gedruckt.

Eine Abfrage, die direkt nach search_objects geschrieben wird, sieht korrekt aus und scheitert an „Feld nicht gefunden“. Ein Beispiel dafür, was nur aus get_object kommt:

## Таблицы запроса
- `РегистрНакопления.ТоварыНаСкладах.Остатки`
  измерения: Склад, Номенклатура, Характеристика
  ресурсы: КоличествоОстаток, РезервОстаток

Ein zweites solches — und es wurde durch einen echten Fehlschlag vom 2026-08-18 gefunden. Der Agent gruppierte eine Abfrage nach einer Zeichenfolge ohne Längenbeschränkung; die Daten haben wir korrekt geliefert, aber der Unterschied war nur am Fehlen der Zahl in Klammern abzulesen:

> **Строки неограниченной длины** помечены `(неогр.)`. Платформа не даёт их
> сравнивать, группировать и упорядочивать и не пускает в РАЗЛИЧНЫЕ,
> ОБЪЕДИНИТЬ и агрегатные КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ. Ограничивайте
> длину — одинаково в списке выборки и в группировке:
>
>     ПОДСТРОКА(КодСкидки, 1, 100) КАК КодСкидки
>
> Длину подбирайте по смыслу поля: 100 — не универсальное число.

## Реквизиты

- `КодСкидки` — Строка (неогр. — только через ПОДСТРОКА) // Код скидки
- `КодМаркировки` — Строка(200) // Код маркировки

Der Rezepttext steht sowohl in der Fußnote als auch in der Feldzeile selbst, und das ist keine Redundanz. Die erste Fassung druckte die Fußnote als letzten Absatz der Karte. Ein Live-Agent 2026-08-18 rief get_object mit detail=fields auf, erhielt sie vollständig — und gruppierte trotzdem nach einem solchen Feld. Die Fußnote stand 721 Token später als die Feldzeile, und die Entscheidung wird dort getroffen, wo der Name kopiert wird. Dieselbe Lektion war bereits bei den Tool-Beschreibungen festgehalten: Eine Regel wirkt dort, wo man sie liest, nicht dort, wo man sie ordentlich ablegt.

Jedes Verbot ist geprüft: Aggregatfunktionen — Zitat aus der Hilfe, die übrigen fünf — Läufe auf der Live-Basis mit aufgezeichneten Fehlertexten. Die Hilfe kennt die Einschränkung nur bei drei der sechs Aggregatfunktionen und schweigt über Gruppierung, Sortierung, VERSCHIEDENE, VEREINIGEN und Vergleich — das heißt, ein Agent, der sie ehrlich gelesen hat, konnte davon nichts erfahren. Die Aufschlüsselung nach Herkunft steht in docs/data-sources.md, Abschnitt „Fußnoten in der Karte“.

Vor dem Aufruf einer Plattformfunktion auf alter Konfiguration — get_syntax. Nicht Verfügbares wird markiert, und dort liegt auch der Ersatzrezepttext, falls er aufgezeichnet ist.

Quellen sind unabhängig

Es sind fünf, und jede wird separat angeschlossen:

Quelle

Datei

Was sie liefert

Ohne sie

Konfigurationsmetadaten

СтруктураКонфигурации_*.zip

Objekte, Attribute, Verknüpfungen, Bewegungen

search_objects und get_object antworten nicht

Konfigurationscode

Archiv der Konfigurationsentladung in Dateien

Prozeduren der Hauptkonfiguration, Signaturen, Rümpfe, Kompilierungskontext, Aufrufstellen, Formularereignisse

ohne Konfigurationscode nennen search_procedures, get_procedure und get_callers die fehlende Quelle

Erweiterungscode

Archiv der Erweiterungsentladung in Dateien

eigene und geänderte Prozeduren der gewählten Erweiterung, ihre Rümpfe und Aufrufstellen

ohne Erweiterungscode ist die Hauptkonfiguration verfügbar, aber search_procedures, get_procedure und get_callers sehen den Code und die Überlagerungen dieser Erweiterung nicht

Plattformhilfe

shcntx_ru.hbk

Methoden, Eigenschaften, Signaturen, Verfügbarkeit, Versionen

search_syntax meldet „Quelle nicht angeschlossen“

Abfragesprache

shquery_ru.hbk

AUSWÄHLEN, LINKE VERBINDUNG, ERGEBNISSE NACH, DATENDIFFERENZ

Sprachkonstrukte der Abfragesprache werden nicht gefunden

Was geladen ist

Was funktioniert

Alle notwendigen Quellen

alles

Nur Konfiguration

Metadaten; Syntax antwortet „Quelle nicht angeschlossen“

Nur Hilfe

Syntax ohne Versionsfilterung, config wird nicht benötigt

Nichts

list_configurations erklärt, was zu laden ist

Abfragesprache — eine eigene Quelle

shquery_ru.hbk aus demselben Installationsverzeichnis der Plattform. 127 Seiten: 52 Funktionen, 67 Schlüsselwörter, 8 Artikel. Wird wie eine normale Quelle geladen und gelangt in denselben Suchindex wie die Plattformhilfe — mit einem separaten Werkzeug suchen muss man nicht, search_syntax findet beides.

Versionen gibt es in der Datei selbst nicht — geprüft auf allen 129 Seiten: null Erwähnungen von „8.3.x“ und „ab Version“. Aber die Abfragesprache ändert sich: Release 8.3.20 fügte 25 Funktionen hinzu, darunter СтрНайти, Лев, Прав, ВРег, НРег, СтрЗаменить, Окр, Цел und die gesamte Trigonometrie.

Die Version ist nirgends herzunehmen: Die Plattformhilfe beschreibt die Funktionen der Abfragesprache überhaupt nicht (ПОДСТРОКА — null Treffer bei 25 511 Elementen). Deshalb setzt die Versionen die kuratierte Tabelle query_versions.py — nach der 1C-Liste „Funktionen, die ab Release 8.3.20 zur Abfragesprache hinzugefügt wurden“. Den übrigen 27 Funktionen wird keine Version zugeschrieben: Sie gab es schon immer.

Danach greift der übliche Filter: Eine Konfiguration auf 8.3.5 sieht diese Funktionen nicht, auf 8.3.23 sieht sie sie.

Die Tabelle wird mit Daten geprüft — durch Vergleich zweier Hilfen verschiedener Plattformen. Was in der alten fehlt und in der neuen vorhanden ist, das ist dazwischen entstanden, und dafür muss eine Version stehen:

python3 tools/lab/compare_query_help.py <старая.hbk> <новая.hbk>

Lauf 2026-08-19, 8.3.5.1570 gegen die aktuelle: 29 neu erschienen, 29 abgedeckt, falsche Treffer 0. Ein falscher Treffer ist der schlimmste Fehler: Ein Element, das es in der alten Hilfe schon gab, aber mit einer Version markiert ist, versteckt sich vor einer Konfiguration, in der es vorhanden ist.

Eine Instanz pro Server: Ein erneutes Laden ersetzt die vorherige.

Seitentabellen werden angezeigt, aber nicht durchsucht. In dieser Hilfe sind die Tabellenzellen als Absätze innerhalb von <TD> ausgezeichnet, und ohne separate Auswertung druckte die Karte die Tabelle als Wertespalte: „Artikel / Menge / Nummer / Sanitär / 104 / …“ zwei Dutzend Zeilen hintereinander. Jetzt werden Tabellen in einem eigenen Feld ausgewertet — 51 Tabellen auf 31 von 127 Seiten — und an ihren Stellen im Text gedruckt: Eine Seite mit zwei Beispielen zeigt jedes Ergebnis unter seinem eigenen Beispiel. In den Suchindex gelangt der Inhalt der Tabellen nicht.

Die Tabellen in dieser Hilfe sind zweierlei Natur und werden unterschiedlich ausgewertet:

Was

Wie viele

Wie es in der Karte aussieht

Datentabelle — Ergebnis einer Beispielabfrage

51 auf 31 Seiten

als Markdown-Tabelle

gezeichnete Syntaxdiagramm — Grammatik des Konstrukts

21 auf 17 Seiten

als Treppe mit Einzug nach Verzweigungsebene

Sie unterscheiden sich nach Auszeichnung, nicht nach CSS-Klasse: class=SimplyTable steht nicht auf allen — 7 echte Tabellen kommen ohne sie. Das Merkmal ist die Geometrie: Bei einer Datentabelle haben alle Zeilen dieselbe Breite, bei einem Diagramm sind die Breiten unregelmäßig, und es gibt Zellen aus einer einzigen senkrechten Linie (das ist eine gezeichnete Linie, kein Wert).

Beschädigte Auszeichnung wird beim Namen genannt. Eine Seite mit ungeschlossenem <TABLE> wird ohne Tabellen ausgewertet, geht aber nicht verloren, und ihr Name gelangt in die Warnungen der Quelle: als Zeile in der Ladeausgabe (mcp1c.cli reg-add) und als eigene Zeile auf der Seite „Quellen“ des Dashboards. Eine stillschweigend ärmere Karte als üblich ist nicht erlaubt: Von einer Hilfe, in der das schlicht nicht vorhanden ist, ist das nicht zu unterscheiden.

Die Hälfte der Namen stimmt mit den Namen der Plattform überein (57 von 127) — ГОД, МЕСЯЦ, ПРЕДСТАВЛЕНИЕ gibt es dort wie hier. Damit eine Frage zur Abfrage nicht zur Plattformmethode führt, geben Wendungen wie „in der Abfrage“, „im Abfragetext“, „in der Auswahl“ den Elementen der Abfragesprache einen sanften Auftrieb. Bewusst sanft: Bei sicherem Abstand bleibt das Plattformelement an erster Stelle — „wie setze ich einen Parameter in der Abfrage“ kann auch Запрос.УстановитьПараметр meinen.

Der Parameter config ist Pflicht, wenn mehr als eine Konfiguration geladen ist. Standardmäßig wird nichts eingesetzt: Eine stille Auswahl führt dazu, dass der Agent Code nach einer fremden Konfiguration schreibt, und niemand bemerkt das.

Die Antwort hängt von der Plattformversion ab

Derselbe Aufruf, zwei Konfigurationen:

get_syntax("СтрШаблон", config="Розница")     → 8.3.23
# Метод: Глобальный контекст.СтрШаблон
с версии платформы 8.3.6
Доступность: ТонкийКлиент, ВебКлиент, Сервер, ТолстыйКлиент, …

get_syntax("СтрШаблон", config="Отраслевая")  → 8.3.5
# `Глобальный контекст.СтрШаблон` недоступен в этой конфигурации
Элемент существует, но появился в 8.3.6, а конфигурация работает на 8.3.5.1570.
Использовать нельзя — код не скомпилируется.

Für Plattform 8.3.5 wurden aus der Ausgabe 6 539 Elemente entfernt, für 8.3.23 — 874. Nicht als Warnung, sondern als Filterung: Eine Warnung überspringt der Agent, eine in der Ausgabe fehlende Methode nicht.

Das Feld Verfügbarkeit (Server / dünner Client / Web-Client / mobil) muss gelesen werden: Der Aufruf einer Servermethode aus dem Client-Kontext kompiliert nicht.

Hilfen mehrerer Versionen verschmelzen zu einem Index

Eine einzige frische Hilfe auf alter Konfiguration lügt. Gemessen auf 8.3.5: 199 Elemente würde der Server als nicht existent erklären, 117 mit fremder Signatur ausgeben (ЗаписьXML.ОткрытьФайл nimmt auf 8.3.5 zwei Parameter, auf 8.3.27 — drei), 410 — mit fremder Verfügbarkeit. Das sind alles Kompilierungsfehler, keine Ungenauigkeiten.

Deshalb werden Hilfen verschiedener Versionen nebeneinander gelegt und zu einem Index mit Grenzen since und until verschmolzen, und die Antwort wird unter der Version der konkreten Konfiguration zusammengestellt. Es braucht so viele Hilfen, wie es Plattformen bei den geladenen Konfigurationen gibt — zwei extreme Zwischenversionen ersetzen sie nicht.

Der Preis ist gemessen und gering: Die Verschmelzung dreier Versionen ergibt 25 691 Schlüssel gegen 24 777 bei einer, also weniger als ein Prozent. Ein eigener Container pro Version funktioniert ebenfalls und bleibt der Notfallweg, verliert aber als Hauptweg nach Zahlen — 300–450 MB und eine eigene Adresse für jede Version.

Der Server nennt selbst, welche Hilfen fehlen und welche überflüssig sind — in der Ausgabe von list_configurations.

Ersatz statt Verbot

Zu sagen „die Funktion gibt es nicht“ ist die halbe Antwort. Die zweite Hälfte ist, womit man sie ersetzt, und aus der Hilfe ist das nicht abzuleiten: Die Veraltungsmarkierung steht auf 15 von 25 000 Seiten.

Deshalb gibt es eine Ersatztabelle (replacements.py), derzeit 6 Einträge — Stringfunktionen, die in 8.3.6 erschienen sind. Statt eines Verbots liefert get_syntax einen Rezepttext:

get_syntax("СтрРазделить", config="Отраслевая")   → 8.3.5
# `СтрРазделить` недоступна: появилась в 8.3.6

Замена: РазложитьСтрокуВМассивПодстрок(<Строка>, <Разделитель>)
Оговорка: разделитель у `СтрРазделить` — набор символов, каждый из которых
самостоятельный разделитель; у замены это одна строка целиком.

Die Fußnote ist Pflicht. Der Ersatz ist fast nie äquivalent, und eine ähnliche Funktion still unterzuschieben ist schlimmer, als gar nichts zu empfehlen.

Die Tabelle wird nach lebenden Fällen ergänzt, nicht blind: Umgehungen für Funktionen zu erfinden, nach denen niemand gefragt hat, ergibt keinen Sinn.


4. Datenverwaltung

Quelle hinzufügen

# в 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 Выгрузка.zip

Einfacher: Eine Datei in data/bootstrap/ ablegen — sie wird beim nächsten Start aufgenommen.

Konfigurationsentladung in Dateien

Die zweite Quellenart — nicht Metadaten (СтруктураКонфигурации_*.zip), sondern die Konfigurationsentladung selbst in Dateien: Code der Module und Formulare. Der Server baut und cached interne Indizes von Prozeduren, Aufrufen und Formularen; search_procedures sucht im fertigen Bestand. Bei einem Cache-Fehlschlag werden die Indizes im Hintergrund aufgebaut: Werkzeuge, die nicht vom Code abhängen, antworten weiter, und die Code-Werkzeuge zeigen Phase X/4 und tatsächlich verarbeitete N von M Elementen der aktuellen Phase. Der fertige Bestand wird vollständig veröffentlicht, ohne Zwischenzustand aus verschiedenen Versionen. Der Hintergrundaufbau überschreibt registry.json nicht, solange der Startup noch die nächsten Quellen wiederherstellt. Wenn der Startup abgebrochen ist, bleibt der vorherige vollständige Schnappschuss auf der Platte vollständig; eine teilweise wiederhergestellte Quellenliste wird darüber nicht gespeichert.

Vier Verbrauchsdateien des Caches bewahren sichere Lokatoren, Abdeckungsaggregate und die ersten 20 anonymisierten Probleme mit der genauen Zahl der übrigen. Modulrümpfe, Prozedursignaturen und der Rohdatensatz des Formulars gelangen dort nicht hinein. Beim Warm-Start werden sha256 der Quelle, die Auswahlversion, die Lokatorgeneration, die internen Invarianten jedes Indexes und ihre Übereinstimmung mit einem Verzeichnis geprüft. Deshalb gilt ein strukturell oder semantisch beschädigter Bestand als vollständiger Fehlschlag, nicht als Quelle einer teilweise alten Antwort. Ein beschädigter oder schreibgeschützter Cache lässt die Quelle nicht fallen: Der Server führt einen Cold-Neuaufbau im Speicher aus und veröffentlicht die vollständige Diagnose, selbst wenn der neue Cache nicht geschrieben werden kann. Veröffentlichte Cold- und Warm-Antworten stimmen in allen Zählern und Ursachenkategorien überein. Lokale Ursachen jedes Formulars werden getrennt von der begrenzten Liste gespeichert: Dadurch zeigt get_object nach einem Neustart alle Formularprobleme des gewählten Objekts, ohne das allgemeine /sources in eine unbegrenzte Antwort zu verwandeln. Der Reader liest keine Cache-Datei größer als 256 MiB und entpackt keinen Payload größer als 512 MiB; das Überschreiten einer der Grenzen ist ein gewöhnlicher Cache-Miss bis marshal.loads, nicht der Versuch, den Speicher zu erschöpfen.

Die finale Live-Abnahme von selection v4 wurde am 2026-08-21 an vier anonymisierten Codequellen durchgeführt (drei Hauptauszüge und eine Erweiterung):

PYTHONPATH=src .venv/bin/python \
  tools/lab/measure_modules_acceptance.py --data data --timeout 120

Das Skript druckt ein einziges JSON ohne Namen und Pfade. Der Warm-Start dauerte 3,676 s, startup_problems_total = 0, Prozessspitze — 856,2 MiB. Der Katalog wies 8 650 hierarchische .bsl, 828 Module aus Form.bin, 1 523 flache .txt, 1 079 Module aus .Form und 7 kompilierte Module ohne Quelltext nach. Es wurden 6 150 Formulare gefunden: 3 331 vollständig, 1 330 teilweise und 1 489 nicht gelesen. Die genauen Einschränkungskategorien: descriptor_only=671, invalid_syntax=1598, known_marker_semantics_incomplete=659, form_structure_missing=561, compiled_without_source=7; unbekannte Marker, Budgetüberschreitungen, defekte Container und Konflikte gibt es in diesem Korpus nicht. Null ist hier das Ergebnis der Messung genau dieser Quellen und kein Versprechen der Unterstützung eines beliebigen künftigen Formats.

Die vorherige Messung der Hintergrund-Reaktionsfähigkeit vom 2026-08-21 bei kaltem Cache der drei Codequellen: in 72,12 s wurden 73 Sekundenaufrufe jedes Pfads gemacht, keine Ausfälle. Dieser Timer beginnt nach der Bereitschaft von /health, während die Container-Messung von 125 s weiter unten vom Containerstart bis ready aller Codequellen läuft. /health antwortete mit einem Median von 5,76 ms und der schlechtesten Zeit von 171,01 ms; echtes search_objects — 8,11 bzw. 172,49 ms. Der Container erreichte healthy, alle 12 Cache-Dateien wurden veröffentlicht. Zur Wiederholung mounten Sie in einen separaten Container eine Kopie von data/ ohne index/cache/*.modules-* und führen aus:

.venv/bin/python tools/lab/measure_background_responsiveness.py \
  http://127.0.0.1:5002 /путь/к/копии/data

Der Speicher des finalen Images wurde am 2026-08-21 nach selection v4 erneut gemessen: vier Codequellen und 16 Cache-Dateien der Modulindizes. Der Kaltstart nach dem Löschen nur des Verbrauchscaches dauerte 111,216 s, der Warm-Neustart desselben Containers mit unveränderten dev, ino, Größe und mtime_ns aller 16 Dateien — 11,495 s.

Zustand

memory.peak cgroup

memory.current nach ready

RSS PID 1

HWM PID 1

docker stats

kalte Neuerstellung

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

warmer Start

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

Beide Male erreichte der Container healthy; restart_count = 0, oom_killed = false. In jedem der beiden finalen Läufe gab es exakt 0 Zeilen mit jedem der Begriffe traceback, exception, critical und error. Die cgroup-Werte enthalten den Seitencache des Kernels, daher unterscheiden sie sich naturgemäß vom RSS des Prozesses und der Anzeige von docker stats. Dies ist ein Richtwert für die Größe genau dieses Korpus und keine Grundlage, einen mem_limit festzulegen.

Das Skript druckt ein einziges JSON nur mit Aggregaten: Dauer, Anzahl der Quellen und Caches, cgroup-Felder und PID 1, docker stats, Gesundheit, Neustarts, OOM und Zähler der Logbegriffe. Quellnamen, lokale Pfade und Logzeilen werden nicht gedruckt. Im Modus cold erstellt es das finale Image, stoppt vorher den Container und löscht nur die exakten Dateien modules-toc, modules-calls, modules-forms und modules-search, die von der arbeitenden Namensfunktion für die aktuellen Quellen berechnet wurden. Das Verzeichnis index/cache und die Ziele selbst dürfen keine symbolischen Links sein; ein überzähliger oder gemischter Namenssatz gilt nicht als bereit. Nach dem Stoppen wird das Verzeichnis mit O_NOFOLLOW geöffnet und seine dev/ino werden mit dem ursprünglich geprüften Verzeichnis abgeglichen. Die Ziele werden über dir_fd aufgelistet und geprüft, gelöscht werden nur exakte Basisnamen über denselben Deskriptor: Eine Vertauschung des Elternverzeichnisses durch einen symbolischen Link führt nicht nach außen, und ein harter Link verliert nur den internen Link. Danach führt das Skript --force-recreate aus. Der Messer selbst löscht und ersetzt keine Quellen, keinen entpackten Code und keine registry.json. Der laufende Server aktualisiert die Zustände der registry.json während des Starts und der Hintergrund-Erstellung regulär atomar; die Messung berücksichtigt diese Einträge im Generationsmarker. Bereitschaft erfordert nicht nur healthy, sondern auch unveränderte sha256, loaded_at und die Bindung der Codequelle selbst, denselben sha256 der Besitzer-Konfiguration, den Zustand ready und den exakten Satz der vier Caches pro Quelle. Bei einem normalen Neustart werden die Konfigurationsmetadaten erneut geparst und erhalten ein neues Runtime-loaded_at; der Messer erlaubt nur diesen Übergang und verlangt danach zwei identische Schnappschüsse der neuen Generation. Nach dem Lesen von Speicher, docker stats und Log liest die finale Prüfung das Register, dann den Cache und erneut das Register; beide Marker müssen mit der bereiten Generation übereinstimmen. Der Marker umfasst auch dev, ino, Größe und mtime_ns der registry.json selbst, daher gilt selbst das Schreiben derselben Bytes als neue Generation. Der Modus warm merkt sich vor dem Stoppen dev, ino, Größe und mtime_ns jeder exakten Cache-Datei. Sofort nach docker stop, noch vor docker start, öffnet er das Verzeichnis erneut mit O_NOFOLLOW, gleicht seine dev/ino und den gesamten Dateischnappschuss über den gehaltenen dir_fd ab; derselbe Schnappschuss wird bei Bereitschaft und in der finalen Prüfung verlangt. Eine Neuerstellung, Überschreibung oder Beschädigung einer Datei macht das gesamte Ergebnis zunichte. --timeout und --poll-interval sind endliche positive Sekunden; der einheitliche Rest von timeout begrenzt jeden Docker-Befehl.

.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.5

Der Erweiterungsauszug wird an denselben Ort gelegt, in data/incoming/, und mit derselben Schaltfläche verarbeitet. Die Art des Auszugs bestimmt der Server selbst, anhand von Configuration.xml im Archiv — der Mensch wählt weiterhin nur die Konfiguration, an die die Erweiterung angehängt wird, und keine separate Schaltfläche oder ein Feld „das ist eine Erweiterung“. Die Erweiterung wird als separate Quelle <NameDerKonfiguration>:ext:<NameDerErweiterung> (Art extension) angelegt, nicht als <NameDerKonfiguration>:modules: Der Name der Erweiterung stammt aus dem Tag Name ihres eigenen Auszugs und wird nicht vom Menschen erfunden. Der Code liegt in seinem eigenen Verzeichnis data/extensions/<NameDerKonfiguration>/<NameDerErweiterung>/ — neben data/modules/<NameDerKonfiguration>/, aber nicht darin, sodass der zweite Auszug den ersten nicht löscht. Eine Konfiguration kann beliebig viele Erweiterungen haben — der Konfigurationsmodule gibt es dabei weiterhin genau einen Auszug, wie bisher.

Die Identität der Erweiterung ist das Tag Name in ihrem Auszug, nicht der Dateiname und nicht der gesamte Inhalt. Der Mensch kann das Archiv beliebig umbenennen: Zwei Dateien mit unterschiedlichen Namen, aber gleichem Name, verarbeiten EIN und dieselbe Quelle erneut — der zweite Verarbeitungsdurchlauf aktualisiert nur den Code und origin (den Namen der zuletzt verarbeiteten Datei), Schlüssel und Verzeichnis ändern sich nicht. Die Kehrseite derselben Regel: Wenn der Name zweier UNTERSCHIEDLICHER Erweiterungen nach der Bereinigung um für Pfade unzulässige Zeichen übereinstimmt (z. B. ergeben Preis/Handel und Preis:Handel denselben Verzeichnisnamen), fallen auch sie zu einer Quelle zusammen — der zweite Verarbeitungsdurchlauf überschreibt den Code des ersten. Bei gewöhnlichen Namen (ohne Zeichen außer Buchstaben, Ziffern, Bindestrich, Unterstrich, Punkt und Leerzeichen) ändert die Bereinigung nichts und eine solche Übereinstimmung kommt nicht vor.

Die Erkennung ist eine positive Regel auf beiden Seiten, und die Prüfreihenfolge ist wichtig. Ein Fehler zugunsten der Konfiguration ist gefährlicher: Das bedeutet, in den Modulzweig zu gehen und den bereits verarbeiteten Konfigurationscode vollständig zu löschen. Deshalb werden zuerst die starken Erweiterungsmerkmale geprüft (ObjectBelonging, ConfigurationExtensionPurpose) — ist auch nur eines sichtbar, gibt es bei keinem CompatibilityMode mehr einen Weg in den Modulzweig: Danach entscheidet nur noch zwischen „Erweiterung“ (alle vier Bedingungen erfüllt: beide starken Merkmale, nichtleerer NamePrefix, kein CompatibilityMode) und Ablehnung. Und erst wenn gar kein starkes Erweiterungsmerkmal vorhanden ist, entscheidet CompatibilityMode: nichtleer — Konfiguration, leer oder Tag fehlt — Ablehnung. Alles andere — ebenfalls Ablehnung mit Erklärung, ohne etwas auf der Platte anzufassen: Configuration.xml wurde nicht gefunden (gesucht wird nicht nur im Archivstamm, sondern auch im einzigen Verzeichnis der obersten Ebene — so wird das Archiv mit dem Befehl zip -r archiv.zip ordner erstellt, und das Dienstverzeichnis __MACOSX/ mit .DS_Store des Finder-Archivs auf macOS stört dabei nicht), lässt sich nicht lesen (defekte CRC, abgebrochener Eintrag), lässt sich nicht als XML parsen, trägt keine erkennbare Struktur, oder die angegebene Dateigröße ist unplausibel groß.

Wohin legen. In data/incoming/, auf dem, und nicht über das Upload-Formular auf „Quellen“ — dieses hat dafür kein Feld. Das Verzeichnis erstellt der Server selbst beim Start, sodass es ab dem ersten Lauf vorhanden ist. Danach erscheint auf der Seite „Quellen“ (nur für unter ADMIN_TOKEN Angemeldete) der Block „Eingehende Auszüge“ mit der Schaltfläche „verarbeiten“.

Gescannt wird nur das Verzeichnis selbst, ohne verschachtelte Unterverzeichnisse. Ein Archiv, das in data/incoming/Handel/ gelegt wird, sieht der Server nicht — und sagt auch nichts dazu, weil er nichts anzuzeigen hätte.

Solange die Datei kopiert wird, gibt es keine Schaltfläche. cp von anderthalb Gigabyte dauert Minuten, und die Datei ist ab der ersten Sekunde im Verzeichnis sichtbar: Bei einem Archiv, das vor weniger als fünf Sekunden geändert wurde, wird der Zustand mit dem Vermerk „Datei wird noch kopiert“ angezeigt, sha256 wird gar nicht erst berechnet (er wäre ohnehin veraltet), und die Verarbeitung einer solchen Datei wird mit einer Erklärung abgelehnt. Warten Sie das Ende des Kopierens ab und aktualisieren Sie die Seite.

Ein erneuter Verarbeitungsdurchlauf überschreibt das Verzeichnis vollständig — aber nur nach Erfolg. Bei einem aktualisierten Auszug ist die Schaltfläche mit „erneut verarbeiten“ beschriftet: Der alte Inhalt von data/modules/<NameDerKonfiguration>/ (oder des Erweiterungsverzeichnisses) wird vollständig durch den neuen ersetzt, sonst blieben Dateien, die im neuen Auszug nicht vorhanden sind (ein gelöschtes Objekt, ein umbenanntes Modul), für immer dort und die beiden Auszüge würden sich vermischen. Das Entpacken erfolgt dabei in ein temporäres Verzeichnis daneben und berührt den bisherigen Verarbeitungsdurchlauf nicht: Wenn extract in der Mitte scheitert (defekte CRC bei einem Modul, kein Platz mehr, Rechte) oder null Dateien auswählt, kommt es gar nicht erst zum Schreiben in das Arbeitsverzeichnis — Register und Platte weichen nicht voneinander ab. Die Ersetzung ist kein Abriss des alten an Ort und Stelle, sondern eine Rochade („altes zur Seite umbenennen → neues an seine Stelle umbenennen → das Beiseitegestellte löschen“): Wenn der Umzug des neuen an die Stelle des alten fehlschlägt, versucht der Server, das alte dorthin zurückzubringen, wo es war. Wenn auch das fehlschlägt (die Natur des Fehlers ist bei beiden Umbenennungen meist dieselbe — Rechte, derselbe Bind-Mount), lehnt der Verarbeitungsdurchlauf explizit ab und nennt im Text beide Pfade: wo physisch der bisherige Verarbeitungsdurchlauf liegt und wo — der leere oder teilweise entpackte neue, damit man das Verzeichnis von Hand zurückholen kann; stillschweigend „verarbeitet“ für ein Verzeichnis, das es nicht gibt, zeigt der Server nicht an. Reste eines mitten im Prozess abgebrochenen Ablaufs (.tmp-*) werden vor dem nächsten Verarbeitungsdurchlauf derselben Konfiguration oder Erweiterung entfernt — die gespeicherte Kopie des bisherigen Verarbeitungsdurchlaufs (.old-*), falls es so weit kam, wird selbst nicht gelöscht: Die Entscheidung darüber liegt beim Menschen. Die Rechte des Verzeichnisses ändert der erneute Verarbeitungsdurchlauf nicht — das neue Verzeichnis erhält die Rechte des bisherigen (oder die üblichen, wenn es das Verzeichnis noch nicht gab), und nicht die eingeschränkten, mit denen das temporäre erstellt wird.

Gleichzeitige Verarbeitungsdurchläufe derselben Quelle werden sequenziell ausgeführt: Ein neuer Auftrag bricht sofort die bisherige Generation ab, wartet aber auf den Abschluss ihrer Arbeit mit dem temporären Verzeichnis. Daher kann ein Verarbeitungsdurchlauf kein fremdes aktives .tmp-* löschen, und das Arbeitsverzeichnis und den Cache erhält nur die letzte Generation. Ein abgebrochener Auftrag endet mit einem expliziten Fehler; ein wartender veralteter Auftrag beginnt gar nicht erst mit dem Entpacken. Verschiedene Konfigurationen und Erweiterungen mit verschiedenen Quellschlüsseln halten einander nicht auf.

«Отбор устарел» — Zustand für den Fall, dass sich nicht die Datei ändert, sondern die Regel. Jede verarbeitete Quelle merkt sich die Version der Auswahlregel (internes SELECTION_VERSION: was wir aus dem Archiv nehmen und wohin wir es legen). Wenn der Code auf der Platte mit einer alten Regelversion verarbeitet wurde, wird die Quelle als «Отбор устарел» angezeigt, nicht als «разобрано» — obwohl das Archiv auf incoming/ dieselbe Datei ist, mit demselben sha256. Der Button ist mit «переразобрать» beschriftet, wie bei einem aktualisierten Export: Der Code auf der Platte wird neu überschrieben, nun nach der aktuellen Regel. Die frühere Verarbeitung selbst wird nicht umgeschrieben — die Änderung der Auswahlregel sieht der Mensch erst nach dem Klick auf den Button. Eine Quelle, die vor dem Erscheinen dieses Feldes verarbeitet wurde (Eintrag ohne selection_version im alten registry.json), gilt ebenfalls als veraltet: Ihre Version ist unbekannt, nicht «mit Sicherheit frisch» — sonst würde der Mensch nie «переразобрать» für Code sehen, der nie durch die aktuelle Regel gelaufen ist. Die aktuelle Version 4 speichert XML-Deskriptoren der Formulare und hierarchische Ext/Form.bin; eine Quelle der Version 3 wird daher zwingend als veraltet angezeigt und erhält diese Dateien erst nach einem expliziten Neuverarbeiten. Die Auswahlversion geht in den Cache-Stempel ein: Ein alter Cache wird nicht akzeptiert, selbst für dasselbe unveränderte ZIP. Vor dem Ersetzen des Verzeichnisses schreibt der Server ein kurzes Rotationsjournal; nach einem Absturz schließt der nächste Start anhand von registry.json entweder die neue Generation ab oder stellt das vorherige Verzeichnis wieder her.

Der Müll des Finder-Archivierers auf macOS gelangt nicht in den Code. Ein Archiv, das mit dem Befehl «Сжать объекты» erstellt wurde, trägt ein Dienstverzeichnis __MACOSX/ mit Kopien der Ressourcen-Forks jeder Datei (._Имя, dasselbe Suffix wie beim Original) — die Auswahl überspringt sie, wie auch jeden Namen, der mit ._ beginnt, egal wo er liegt.

Der Archiv-Wrapper wird nicht im Pfad auf der Platte reproduziert. Ein Archiv, das mit dem Befehl zip -r архив.zip папка oder über den Finder («Сжать объекты») gepackt wurde — der gesamte Export liegt innerhalb eines einzigen Verzeichnisses der obersten Ebene —, wiederholt diese Ebene bei der Ablage auf der Platte nicht: Der Code liegt als data/modules/<ИмяКонфигурации>/Catalogs/…, nicht als data/modules/<ИмяКонфигурации>/папка/Catalogs/…. Die Erkennungsregel für den Wrapper ist dieselbe wie die Suche nach Configuration.xml darin (dieselbe Stelle im Absatz oben, «Распознавание»): Das Dienstverzeichnis __MACOSX/ und die .DS_Store im Wurzelverzeichnis zählen nicht, und mehrere Verzeichnisse der obersten Ebene gelten nicht als Wrapper — der Server wird nicht raten, welches davon «das richtige» ist. Die Pfadbereinigung (Ablehnung von Mitgliedern, die aus der Wurzel herausführen) wird erst nach dem Entfernen des Wrappers angewendet, nicht stattdessen.

Das Löschen einer Quelle nimmt auch den Code mit. Der Button «удалить» bei einer Quelle <ИмяКонфигурации>:modules entfernt data/modules/<ИмяКонфигурации>/, und bei einer Erweiterungsquelle <ИмяКонфигурации>:ext:<ИмяРасширения> nur deren eigenes Verzeichnis data/extensions/<ИмяКонфигурации>/<ИмяРасширения>/: Die Module der Konfiguration und andere Erweiterungen derselben Konfiguration werden nicht berührt. Sonst blieben Hunderte von Megabyte unsichtbar belegt: Im Abschnitt «Исходные файлы» werden sie nicht angezeigt, dort gibt es nur data/sources/.

Ein Archiv, in dem weder Module noch Formulare gefunden wurden, wird abgelehnt. Ein Export der Metadatenstruktur ist ebenfalls eine .zip-Datei, und ohne diese Prüfung würde sie eine Quelle mit null Dateien und dem Zustand «разобрано» anlegen. Sie wird über das Formular «Загрузить» auf derselben Seite eingereicht.

Warum nicht über den Browser. Das Archiv wiegt über ein Gigabyte — bei der typischen Einzelhandelskonfiguration 2.3.10.5 sind das 1 380 MB. Das Upload-Formular auf «Источники» ist für Metadaten im Bereich von einigen Megabyte ausgelegt und funktioniert bei einer solchen Datei aus drei Gründen nicht: Upload-Limit 500 MB; dreifaches Kopieren mit einem Spitzenwert von etwa 4 GB — Puffer für den Empfang des Request-Bodys, temporäre Kopie in mkdtemp() und Kopie auf das Volume selbst; und die Übertragung selbst von über einem Gigabyte über HTTP ohne die Möglichkeit, nach einem Abbruch fortzusetzen. Eine Datei auf dem Volume umgeht alle drei Einschränkungen: Sie wird mit einem gewöhnlichen cp kopiert, und der Server liest das Archiv Mitglied für Mitglied, ohne es jemals vollständig zu entpacken.

Was auf der Platte bleibt. Nicht das gesamte Archiv — nur Module (.bsl bei hierarchischem Export, .txt und kanonische kompilierte CommonModules/<Имя>.Module oder CommonModule.<Имя>.Module bei flachem) und Formulare: XML-Deskriptor, Form.xml und Form.bin bei hierarchischem, Container .Form vollständig bei flachem. Form.bin und .Form werden unverändert als Quelle für den Code-Provider gespeichert; ein abgeleitetes .bsl wird beim Empfang nicht erzeugt. Textuelle Layouts *.Template.txt werden nicht als Module akzeptiert. Der Container wird so gespeichert, wie er ist, zusammen mit dem binären Formulareintrag: Der Code eines gewöhnlichen Formulars liegt darin als Eintrag module, und das Parsen des Containers beim Empfang würde bedeuten, das 1C-Format hierher zu ziehen.

Nach dem Entpacken wird der physische Baum einmal in ein unveränderliches Verzeichnis kanonischer Adressen und sicherer Locators überführt. Inhaltsverzeichnis, Aufrufe, Formulare und Suche erhalten denselben Schnappschuss: Gewöhnliche .bsl/.txt werden als Dateien gelesen, Code aus Form.bin/.Form — als Eintrag module des ursprünglichen Containers, kompiliertes .Module bleibt eine Adresse ohne erfundenen Body. Identische Texte derselben Adresse werden nach gemeinsamer Normalisierung dedupliziert; unterschiedliche erhalten keine stillschweigende Priorität und werden als Konflikt ausgeschlossen.

Der Konfigurationscode liegt in data/modules/<ИмяКонфигурации>/, der Erweiterungscode in seinem eigenen Verzeichnis data/extensions/<ИмяКонфигурации>/<ИмяРасширения>/; aktuelle Abdeckungsjournale — in data/logs/. Alle drei Arten sind durch die Regeln **/modules/, **/extensions/ und **/logs/ in .gitignore geschützt. Messung python3 tools/lab/measure_intake.py <архив>..., Lauf vom 2026-08-19:

Was

Archiv

Entpackt

Ausgewählt

typische Einzelhandelskonfiguration 2.3.10.5

1 380 МБ

2 063 МБ, 33 188 Dateien

351,4 МБ, 11 072 Dateien

Erweiterung dazu

1 МБ

8 МБ, 453 Dateien

6,9 МБ, 155 Dateien

Ein echter Lauf des Empfangs selbst auf denselben Dateien — keine Schätzung anhand des Zip-Verzeichnisses, sondern ein realer Aufruf von intake.planned_size, intake.enough_space und intake.extract, Messung python3 tools/lab/measure_intake_run.py <каталог для распаковки> <архив>..., Lauf vom 2026-08-19: Schätzung des benötigten Platzes für ein Archiv von 1,4 ГБ — 0,15 с (nur das zentrale Zip-Verzeichnis wird gelesen, der Body wird gar nicht berührt), Entpacken — 3,1 с, RSS-Spitzenwert des Prozesses — 111 МБ. Dateien und Bytes, die extract() zurückgegeben hat, und das, was tatsächlich auf die Platte gelegt wurde, sind gleich — das prüft das Skript selbst.

Den Quellcode löscht der Server nicht. Das Verzeichnis data/incoming/ darf der Server nicht löschen — die Datei bleibt auch nach erfolgreicher Verarbeitung an Ort und Stelle; eine erneute Verarbeitung desselben Archivs berührt sie nicht, der Abgleich erfolgt über sha256 mit dem Cache auf der Seite (den Hash eines Gigabytes bei jeder Aktualisierung der Liste zu berechnen, geht nicht).

Die Quelle wird unter dem Schlüssel <ИмяКонфигурации>:modules angelegt, nicht unter dem Konfigurationsnamen: Derselbe Schlüssel wie bei den Metadaten würde diese beim Laden aus dem Register verdrängen. Welche Konfiguration die Besitzerin des Exports ist, entscheidet der Mensch. Wenn im Register genau eine geladen ist, ist keine Auswahl nötig: Es gibt kein Feld neben dem Button auf der Seite, die Verarbeitung nimmt die einzige selbst. Wenn zwei oder mehr geladen sind, erscheint neben dem Button eine Dropdown-Liste der geladenen Namen — welche gewählt wurde, an die wird der Code gebunden. Der Name aus dem Formular wird mit der Liste der geladenen abgeglichen: Ein unbekannter wird vor Beginn der Verarbeitung mit einer Erklärung abgelehnt. Eine automatische Zuordnung über das Export-Manifest (ohne menschliches Zutun) ist noch nicht umgesetzt. Die Plattform der Modulquelle wird von der Konfiguration übernommen, an die sie gebunden ist — der Export selbst enthält keine genauen Plattform-Builds in den Dateien, nur den Kompatibilitätsmodus, und das ist eine andere Zahl. Bei einer Erweiterung funktioniert die Konfigurationsauswahl genauso (siehe oben «Выгрузка расширения кладётся туда же»); die Art des Exports — Module oder Erweiterung — unterscheidet der Server selbst anhand von Configuration.xml, ein separates Feld oder einen Button dafür gibt es auf der Seite nicht.

Platzmangel — Ablehnung vor dem Beginn. Nach der Auswahl von Konfiguration und Quellenart prüft das Register den freien Platz auf dem Volume vor dem Entpacken. Erforderlich ist das Volumen der sicher ausgewählten Dateien plus die Indexreserve: 15 % aufgerundet, aber nicht weniger als 25 МБ. Die Formel ist dieselbe für die erste Verarbeitung und das Neuverarbeiten: Das vom alten Wurzelverzeichnis belegte Volumen ist bereits vom Wert des freien Platzes ausgeschlossen, es darf nicht erneut hinzugefügt werden. Reicht es nicht — die Verarbeitung beginnt nicht, und der Grund mit beiden Zahlen in Megabyte bleibt auf der Seite «Источники» und übersteht einen Neustart. Ein direkter Aufruf des Registers durchläuft dieselbe Prüfung; bei einem Fehler oder einem vollen Volume bleibt die frühere Verarbeitung an Ort und Stelle.

Kompiliertes *.Module ist in der Übersicht und in der Modulliste als ОбщийМодуль.<Имя> sichtbar, hat aber keine Prozeduren und keinen Body: search_procedures, get_procedure und get_callers sagen das direkt und geben keinen leeren Index als Beweis für das Fehlen einer Prozedur aus.

Der Button «разобрать» erfordert ADMIN_TOKEN — wie jeder andere Schreibvorgang: Ohne Token existiert diese Route nicht, nicht «sie ist gesperrt».

Änderungen ohne Neustart anwenden

Ein laufender Server hält das Register im Speicher, daher muss es nach reg-add angestoßen werden. Entweder ein Neustart (docker compose restart mcp1c, etwa 2 Sekunden) oder ein Admin-Endpunkt:

# включается переменной ADMIN_TOKEN; без неё маршрут отключён
ADMIN_TOKEN=секрет docker compose up -d
curl -X POST -H "x-admin-token: секрет" http://localhost:5001/admin/reload

Wörterbuch: wie man spricht gegen wie es heißt

Die Hauptschwierigkeit der Suche ist die Kluft zwischen den Wörtern des Menschen und den Namen in der Konfiguration. «Заказ клиента» — und das Objekt heißt ЗаказПокупателя. Das Wörterbuch liegt in data/dictionary.json, wird ohne Neuaufbau des Images bearbeitet.

Zwei Mechanismen, und sie sind verschieden.

Wortsynonyme — gelten für alle Konfigurationen:

python3 -m mcp1c.cli dict-synonyms клиент покупатель заказчик

Objekt-Aliasse — direkte Angabe «wenn ich so sage, meine ich diese Objekte», Gewicht höher als jede Textübereinstimmung. Zwei Dutzend typische Phrasen («файлы», «товары», «клиенты», «сотрудники», «задачи») sind eingebaut und funktionieren sofort; wenn es das Objekt in der Konfiguration nicht gibt, wird der Alias nicht angewendet. Eigene werden mit Bindung an eine Konfiguration hinzugefügt:

python3 -m mcp1c.cli dict-alias "справочник физлиц" \
    Справочник.ФизическиеЛица Справочник.Пользователи \
    --config РозницаДляКазахстана
«справочник физлиц»
    Справочник.ФизическиеЛица     псевдоним из словаря
    Справочник.Пользователи       псевдоним из словаря

Die Existenz der Objekte wird beim Hinzufügen geprüft — ein Alias gegen einen Tippfehler ist nutzlos. Inhalt ansehen: dict-show, löschen: dict-alias «фраза» --remove.

Änderungen werden durch einen Neustart des Containers oder POST /admin/reload angewendet — das Image muss nicht neu gebaut werden. Das Neuladen erfolgt außerhalb der Event-Loop, daher werden /health und MCP-Anfragen während der Wiederherstellung weiter bedient.

Suchschlüssel der Abfragesprache — der dritte Mechanismus, und er wird nur im Code (search_keys.py) mit der üblichen Änderungsprüfung bearbeitet. Die Kluft ist hier anderer Natur: Der Mensch nennt eine Konstruktion nicht mit einem fremden Wort, sondern beschreibt eine Aufgabe. «Количество дней между двумя датами» gegen РАЗНОСТЬДАТ, «убрать повторы» gegen РАЗЛИЧНЫЕ — gemeinsame Wörter gibt es null, und ein Synonym hilft nicht, es gibt nichts zu ersetzen.

Deshalb sind 116 von 127 Seiten Formulierungen zugeordnet, mit denen man sie fragt, und sie gelangen als separates Feld in den Suchindex. Zur Laufzeit wiegen sie nichts. Ergebnis auf einem echten Datensatz: 57,9 % → 94,7 % an erster Stelle, ohne Regression bei 61 000 automatischen Anfragen.

Die Schlüssel sind von uns erdacht, nicht exportiert, und daraus ergeben sich drei Einschränkungen:

  • leben als eigene Schicht in git, werden nicht einem verarbeiteten Element zugeschrieben;

  • gelangen nicht in die Antwort an den Agenten — die Antwort wird weiterhin nur aus der Hilfe zusammengestellt, die Schlüssel wirken ausschließlich auf das Auffinden des richtigen Artikels;

  • sind über die ID an Seiten gebunden, und wenn die Hilfe einen anderen Satz von Seiten liefert, wird die Abweichung beim Laden benannt, nicht stillschweigend durch eine gesunkene Suche sichtbar.

Die gesamte Regel steht in docs/data-sources.md, Abschnitt «Сгенерированные слои поверх источников».

Ansehen, was geladen ist

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 страниц

Konfigurationen können ganz fehlen — der Server arbeitet dann, wenn mindestens eine Hilfe geladen ist: search_syntax und get_syntax antworten, config muss nicht angegeben werden. reg-list listet in diesem Fall das Verbundene auf und gibt 0 zurück:

Конфигурации не загружены. Подключено:
  язык запросов, 127 страниц
Работают search_syntax и get_syntax, без фильтра по версии.

Bei einem völlig leeren Register – „Nichts geladen." und Rückgabecode 1. Jeder Befehl, der eine Konfiguration benötigt, sagt dort ebenfalls, was genau fehlt und womit es jeweils bezogen wird. reg-list wartet nicht auf einen kalten Build: Für die Hauptkonfiguration und jede Erweiterung zeigt es denselben atomaren Zustand wie /sources und list_configurations – fertige Zähler, Phase und Fortschritt, Fehler oder fehlenden Code.

Debugging ohne Agent – mcp1c.cli

Die CLI greift auf dasselbe Register und dieselben Funktionen zu wie die MCP-Werkzeuge. Wenn sie korrekt antwortet, liegt das Problem an der Client-Konfiguration, nicht am Server.

Die Befehle teilen sich in drei Gruppen. Nach Register – dasselbe, was der Agent sieht:

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 20

reg-search sucht ohne --syntax über Metadaten, mit --syntax über Hilfe und Abfragesprache. Drei Code-Befehle spiegeln die gleichnamigen MCP-Werkzeuge und geben dieselbe Antwort aus: reg-search-procedures QUERY akzeptiert --config, --extension, --scope, --limit (Standard 10); reg-get-procedure ADDRESS – --config, --extension, --start-line (0) und --lines (200); reg-get-callers ADDRESS – --config, --extension und --limit (20). Bei allen dreien ist --data standardmäßig gleich data. Bei einem kalten Einmalstart warten diese Befehle höchstens 90 Sekunden auf den Hintergrund-Build, damit der Prozess die Daemon-Threads nicht vor dem Ergebnis und dem Schreiben der vier Cache-Dateien beendet. Reicht das Zeitlimit nicht, gibt der Befehl einen expliziten Fehler zurück; der Server nutzt diese Wartezeit nicht und zeigt weiterhin den Fortschritt an.

Direkt über die Datei, ohne Register – die Ausgabe ansehen, bevor sie zum Server geht:

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 10

Der Pfad ist eine ZIP-Datei oder ein entpacktes Verzeichnis; das Format wird anhand des Manifests bestimmt.

Suchwörterbuch – Synonyme sind allgemein, Aliase sind an die Konfiguration gebunden:

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 "справочник физлиц" --remove

dict-show zeigt die Herkunft jeder Regel – hier beginnt die Analyse „warum sich die Suche so verhält".

Messung der Suchqualität – mcp1c.bench

Ein separater Prüfstand, denn „besser geworden" ohne Zahlen ist eine Meinung.

PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
    --data data --config РозницаДляКазахстана \
    --auto --sets query-language,roznica-metadata,modules-procedures \
    --check-notes

Schlüssel

Was es tut

--data Pfad

Datenverzeichnis des Servers, standardmäßig data

--sets Name,Name

manuelle Sätze Schema v1 aus tests/queries/*.json, ohne Erweiterung

--auto

automatische Sätze nach Hilfe: exakte Namen und gleichnamige

--config

Konfiguration; erforderlich, wenn mehrere geladen sind

--extension

separater Code-Korpus der Erweiterung für Prozedur-Sätze; ohne Schlüssel wird Basiscode gemessen

--limit

Ausgabetiefe, standardmäßig 10

--save Pfad

Lauf für Vergleich schreiben; vereinbarungsgemäß data/bench/JJJJ-MM-TT.json

--baseline Pfad

mit früherem Lauf vergleichen – nennt namentlich, wer den Platz gewechselt hat

--check-notes

Vermerke im Satz mit dem Platz abgleichen, den die Abfrage belegt hat

Jedes manuelle JSON enthält schema_version: 1, eine explizite domain – syntax, metadata oder procedures – und ein Array cases. Der Dateiname wählt keinen Index. In einem Procedure-Satz speichert expected bare BSL-Namen ohne Modulnamen; der Prüfstand expandiert den Namen ohne Beachtung der Groß-/Kleinschreibung auf alle exakten Adressen des gewählten Korpus. Das erlaubt, reproduzierbare Formulierungen zu veröffentlichen, ohne die Struktur einer konkreten Implementierung offenzulegen. Optionale expected_miss: true und zero-basierte expected_rank prüfen maschinell die festgehaltene Baseline bei --check-notes; das ist keine pytest-Schwelle. Ein altes Wurzel-JSON-Array und alte Baselines ohne Version werden explizit abgelehnt: Sie müssen neu erstellt werden. --save ersetzt zuerst atomar die Berichtsdatei und gibt erst dann die Ergebnisse aus: Ein Schreibfehler hinterlässt weder auf der Platte noch in stdout einen Teilbericht.

Gibt P@1/P@3/P@5/P@10, MRR, den Anteil „fremde Domäne zuerst" und den medianen Abstand des ersten Ergebnisses vom zweiten aus. Schwellen in assert gibt es bewusst nicht: Abfragesätze sind keine Tests, Prozente würden bei jeder Wörterbuchänderung brechen. Code 1 bedeutet eine Abweichung der Vermerke; Code 2 – dass die gesamte Messung vor dem Drucken und Speichern wegen eines unbrauchbaren Satzes, einer mehrdeutigen Auswahl oder eines nicht fertigen Index abgebrochen wurde. Bei einem Codewechsel während eines Prozedursatzes wird der gesamte Satz von Anfang an über eine Indexgeneration wiederholt.

Der Vergleich zweier Läufe sieht so aus (Verschlechterungen zuerst):

=== сравнение с прошлым прогоном ===
  - «как прибавить месяц к дате в запросе»: 1 -> промах
  - «как отсортировать результат запроса»: 1 -> 5
  + «в чем разница между внутренним и левым соединением»: 5 -> 4

Sätze gehören nicht ins Image (tests/ in .dockerignore) – aus der Arbeitskopie ausführen, nicht aus dem Container.

Server manuell – 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 5001

Andere Werte für --transport gibt es nicht. Veraltetes HTTP+SSE ist vollständig deaktiviert: Das Flag --transport sse wird vor dem Lesen der Daten und dem Start des Servers abgelehnt.

Woher die Quelldaten stammen

Struktur der Konfiguration – durch Verarbeitung aus exporter-1c/. Vier Modulvarianten für normale und verwaltete Form, XML und JSON; die XML-Varianten sind mit 8.3.5 kompatibel. Zwei Verarbeitungen liegen bereits gebaut vor und öffnen sich direkt: ВыгрузкаСтруктурыКонфигурации_ОбычнаяФорма_XML.epf (8.3.5 und höher) und ВыгрузкаСтруктурыКонфигурации_УправляемаяФорма_XML_JSON.epf (8.3.6 und höher, das Format wird im Formular gewählt).

Plattformhilfe – Datei shcntx_ru.hbk aus dem Installationsverzeichnis von 1C:

/opt/1cv8/<версия>/shcntx_ru.hbk
C:\Program Files\1cv8\<версия>\bin\shcntx_ru.hbk

Der Name muss vollständig übereinstimmen. Im selben Verzeichnis liegen Hunderte von .hbk-Dateien – 38 verschiedene Hilfen, jede in zwei Dutzend Sprachen. Ähnliche zur gewünschten:

Datei

Was es ist

Warum nicht geeignet

shcntx_root.hbk

dieselbe Hilfe, sprachunabhängiger Teil

25 508 Elemente, aber keine einzige Beschreibung: nur Seitenbaum und englische Identifikatoren, ohne Erscheinungsversionen

shlang_ru.hbk

Beschreibung der eingebauten Sprache

überhaupt kein 1C-Container

shquery_ru.hbk

Abfragesprache

dasselbe

config_ru.hbk

Hilfe des Konfigurators

Container, aber keine Syntaxassistent-Seiten darin

1cv8_ru.hbk

Benutzerhandbuch

kein Container

Nach Größe sind sie nicht zu unterscheiden: shcntx_root.hbk wiegt 33 MB gegenüber 39 MB der gewünschten. Das Suffix _ru ist die Sprache, _root der gemeinsame Teil ohne Texte.

Ist die Datei falsch, erklärt der Server, warum genau, und lässt die bisherige Hilfe an Ort und Stelle.

Eine einzige Hilfe von der neuesten verfügbaren Plattform genügt: Jedes Element trägt die Erscheinungsversion, und für alte Konfigurationen wird Überflüssiges herausgefiltert. Fehlt die Version im Pfad, wird sie aus den Daten selbst abgeleitet.

Hilfen von alten Plattformen werden ebenfalls akzeptiert – sie sind anders ausgezeichnet (Abschnitte auf div statt p), das ist berücksichtigt. Nützlich, wenn man einen separaten Server für alte Implementierungen aufsetzt: Die Hilfe von 8.3.5 ergibt 18 936 Elemente und enthält kein СтрНайти, СтрРазделить, ЗаписьJSON – die gab es in 8.3.5 auch nicht. Aber eine solche Hilfe meldet ihre Version nicht selbst: Es gibt keine Vermerke „ab Version", weil damals alles aktuell war. Deshalb wird die Version aus dem Datei- oder Verzeichnisnamen genommen – legen Sie sie als 8.3.5.1570.hbk oder in data/hbk/8.3.5.1570/ ab, sonst funktioniert die Zuordnung zur Konfiguration nicht.


5. Wie es aufgebaut ist

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           стенд замеров качества поиска

Ein Modell für zwei Formate. XML und JSON sind verschiedene Serialisierungen eines Schemas; der Lader führt beide auf dasselbe Wörterbuch zurück. Geprüft: Beide Ausgaben ergeben denselben Satz von 30 Schlüsseln.

Den Graphen baut der Lader, nicht 1C. Kanten werden aus Requisitentypen, Belegbewegungen, Eingabegrundlagen, Besitzern, Abonnement-Handlern und Methoden geplanter Aufgaben abgeleitet. Regeln lassen sich ohne Neuausgabe ändern.

Schwache Kanten. Requisiten wie ЗначениеДоступа listen Hunderte von Typen auf und verbinden fast alles mit allem. Solche Verbindungen werden als schwach markiert und standardmäßig ausgeblendet – sonst gehen die nützlichen darin unter.

Detaillierungsstufen. Die vollständige Beschreibung von Документ.ЧекККМ (50 Requisiten, 17 Tabellenteile) verbraucht den Kontext vollständig. brief – ein paar Zeilen, fields – Zusammensetzung, full – mit Verbindungen.

Ohne externe Datenbanken. Produktionsindizes bleiben in einem Prozess: Kompakte Code-Arrays antworten ohne separaten Netzwerkübergang, und die Suche dauert 0,18–1,5 ms. Elasticsearch, Vektor-Speicher und Graphdatenbank amortisieren einen separaten Prozess und die Wartung bei diesem Umfang nicht. Die Vektorsuche würde zusätzlich ein Encoder-Modell (+185–620 MB zum Image) und 16–32 ms nur für die Kodierung der Abfrage erfordern.

Gemessen an realen Daten – 2026-08-18

Was auf dem Arbeits-Server geladen ist:

Konfiguration

Plattform

Objekte

Kanten

Buchhaltung für Kasachstan

8.3.27.1936

3 492

84 426

Dokumentenfluss KORP

8.3.27.1936

4 596

50 554

Gehalt und Personalverwaltung

8.3.27.1936

5 181

100 136

Einzelhandel für Kasachstan

8.3.23.1997

5 637

58 345

Branchenkonfiguration

8.3.5.1570

1 616

29 288

Gesamt

20 522

322 749

Der Satz ist zufällig – das, was gerade zur Hand war. Wesentlich ist nicht die Konfiguration selbst, sondern die Streuung der Plattformen: 8.3.5, 8.3.23 und 8.3.27 in einem Register, und jede Konfiguration antwortet nach ihrer eigenen.

Dazu die Plattformhilfe – ein zusammengeführter Index von drei Versionen (8.3.5, 8.3.23, 8.3.27), 25 691 Elemente, und die Abfragesprache – 127 Seiten als separate Quelle.

Warmer Start des finalen Images mit 12 Cache-Dateien der Modulindizes – 19 s auf dem am 2026-08-21 gemessenen Arbeitskorpus. Bei kaltem Start werden die Quellen geparst, Indizes gebaut und in data/index/cache/ abgelegt, geparste Hilfen in data/index/syntax/. Danach werden sie von dort geladen.

Der Cache ist abgeleitet und verbrauchbar: gebunden an die Python-Version, den Fingerabdruck des Paketcodes und den Hash der Quelle. Stimmt etwas nicht, werden die Indizes neu gebaut. Das Verzeichnis kann jederzeit gelöscht werden, es stellt sich selbst wieder her. Ist das Cache-Volume nur lesbar, unterbricht die Unmöglichkeit, eine veraltete Datei zu löschen, nicht das Abmelden der Quelle.

Die Reihenfolge der Einträge in registry.json ist nicht wichtig: Code wird nur nach seiner eigenen Konfiguration wiederhergestellt. Fehlt ihr Eintrag, wurde sie während des Laufs gelöscht oder ersetzt, wird ein alter Modul- oder Erweiterungseintrag ohne Besitzer nicht veröffentlicht.

Die Postings der Suchindizes liegen in numpy-Arrays; die temporäre Wörterbuchbefüllung wird direkt nach dem Einfrieren freigegeben. Der gesamte RSS des Servers lässt sich nicht durch Addition isolierter Schichten ermitteln: Kalter Peak und aufgeheizter Containerzustand werden separat nach dem Anheben aller Quellen aufgenommen.

Modultexte – Code-Werkzeuge angeschlossen

Der Empfang der Konfigurationsausgabe in Dateien ist implementiert – Abschnitt „Konfigurationsausgabe in Dateien" oben: Code und Formulare werden auf die Platte gelegt, die Quelle ist im Register erfasst, vier interne Indizes werden gebaut und gecacht. search_procedures sucht exakte Namen und exportierte Prozeduren nach Wörtern, get_procedure liefert das Modulinhaltsverzeichnis oder eine Karte mit dem Körperfenster, und get_callers vereint bestätigte Aufrufstellen, Metadatenbindungen und Formularhandler ohne Lesen der Körper.

Der aktuelle Produktionsschnitt der Hauptkonfiguration am 2026-08-21: 137 116 Prozeduren, 619 029 Aufrufstellen, 3 194 Formulare, 89 528 Formularelemente und 24 202 Zeilen Ereignisbindungen.

Reproduzierbar auf der eigenen Ausgabe, ohne ihren Namen oder Pfad zu drucken:

MODULES_ROOT=/путь/к/выгрузке
.venv/bin/python tools/lab/measure_modules_cache.py "$MODULES_ROOT"

Der Messer druckt JSON-Aggregate mit den Schlüsseln procedures, calls, forms, elements und event_rows. Der letzte Zähler sind die rohen <Event>-Zeilen vor der Gruppierung und dem Entfernen von Duplikaten in den öffentlichen Bindungen.

Der historische Schnappschuss des Prototyps wurde am 2026-08-20 auf einer anonymisierten hierarchischen Ausgabe in Dateien aufgenommen: 7 878 Module, 137 115 Prozeduren und 260 MB Text. Unten sind genau seine Zahlen gespeichert, nicht die aktuellen Aggregate.

Ebene

Auf der Platte

Im Speicher

Inhaltsverzeichnis von 137 115 Prozeduren

14,9 MB

62 MB

619 030 aufgelöste und nicht aufgelöste Aufrufstellen

12,0 MB

51 MB

Suche über 49 181 exportierte Prozeduren

4,27 MB

173 MB

Formulare: 3 194 Dateien, 69 769 Elemente

5,8 MB

44 MB

Modultexte und Signaturen

260 MB

0

Die Suchlatenz beträgt 1,2–1,5 ms. Der vollständige Kaltaufbau der vier Indizes mit Cache-Schreiben dauert etwa 50 s.

Es gibt zwei verschiedene Ausgaben in Dateien, und die zweite wurde separat gemessen — eine Branchenkonfiguration 10.5.1.3 auf 8.3.5: flaches Layout, Module in .txt, Code normaler Formulare in binären .Form-Containern. 2 603 Module, 33 555 Prozeduren, Parsen 1,1 s, Suche über alle 94 MB bei einem Median von 0,2 ms. Die Formularstrukturen enthält dieses Format nicht, und ein Teil der gemeinsamen Module ist kompiliert geliefert — Quelltext ist darin gar nicht vorhanden. Solche Module sind unter der Adresse ОбщийМодуль.<Имя> sichtbar, aber Prozeduren und Aufrufe darin können nicht gelesen werden. Deshalb weisen Zusammenfassungen, Suche, Inhaltsverzeichnis eines normalen Moduls, Rückwärtssuche und Angaben zu Überlappungen über dem Ergebnis darauf hin, dass die Aggregate nur nach den verfügbaren Quelltexten angegeben sind und unvollständig sein können.

Die Messskripte liegen in tools/lab/; damit wird jede Zahl oben reproduziert:

.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.5

Suchqualität

Wird mit einem Prüfstand aufgenommen, mit einem einzigen Befehl reproduziert:

PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
    --data data --config РозницаДляКазахстана \
    --auto --sets query-language,roznica-metadata,modules-procedures \
    --check-notes

Satz

Abfragen

P@1

P@3

P@5

P@10

MRR

Abstand

Abfragesprache

21

85,7%

85,7%

90,5%

90,5%

0,869

35,0%

Metadaten Einzelhandel

21

81,0%

90,5%

90,5%

95,2%

0,862

93,2%

Modulprozeduren

3

0%

0%

0%

33,3%

0,047619

0%

Exakte Hilfenamen

50 926

97,1%

98,3%

98,7%

98,9%

0,978

91,7%

Gleichnamige

10 544

98,7%

99,8%

99,9%

100%

0,992

93,9%

Die gesamte Tabelle wurde am 2026-08-21 mit dem exakten Befehl oben im Read-only-Modus aufgenommen, ohne --save; der Befehl endete mit Code 0. Drei manuelle Sätze sind aus lebendigen Formulierungen und Fehlschlägen zusammengestellt, die letzten beiden werden aus den Daten selbst gebaut. Bei den Prozeduren sind die Ränge [Fehlschlag, Fehlschlag, 7]. Das ist die Baseline für Verbesserungen, nicht die Abnahmeschwelle.

Die Prozedurzeile wird separat schneller reproduziert:

PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
    --data data --config РозницаДляКазахстана \
    --sets modules-procedures

„Abstand" — wie weit das erste Ergebnis vom zweiten entfernt ist, als Median. Beantwortet die Frage „sicher getroffen oder durch Zufall": 35% bei der Abfragesprache gegenüber 91,7% bei der Hilfe bedeutet, dass diese Siege dreimal schwächer gehalten werden und eine Änderung des Rankings sie umdrehen kann, ohne ein einziges Prozent P@1 zu verschieben.

Die Suchlatenz beträgt 0,18–1,4 ms pro Abfrage, je nach Satz.

Die Abfragesätze sind nicht im Image enthalten (tests/ in .dockerignore): gemessen werden muss aus der Arbeitskopie, nicht aus dem Container.

Tests

.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest          # 1100 тестов (прогон 2026-08-21)

Sie hängen nicht vom Inhalt von data/ ab: Es gibt keine proprietären Ausgaben im Repository, alles Notwendige wird synthetisch in tests/conftest.py zusammengestellt.

Die Suchqualität wird durch Tests nicht geprüft — sie wird mit dem Prüfstand gemessen (mcp1c.bench, siehe „Gemessen"). Prozentschwellen würden bei jeder Änderung des Wörterbuchs brechen, deshalb druckt der Prüfstand Zahlen, und die Entscheidung trifft ein Mensch. pytest prüft das beobachtbare Verhalten: „Index wurde nicht neu aufgebaut", „Ausgabe stimmt überein", „Start ist nicht abgestürzt".


6. Sicherheit

Zwei Token, beide werden über Umgebungsvariablen gesetzt. Solange ein Token nicht gesetzt ist, ist der entsprechende Zugriff für alle offen, die die Adresse erreichen.

Variable

Was sie absichert

Nicht gesetzt

API_TOKEN

Lesen: MCP-Werkzeuge und Dashboard-Seiten

Konfigurationsstruktur ist für alle offen

ADMIN_TOKEN

Schreiben: Laden und Löschen von Quellen, Parsen der eingehenden Ausgabe (/sources/incoming/parse), Bearbeiten des Wörterbuchs, /admin/reload

Diese Routen sind deaktiviert, antworten mit 404

Der Unterschied zwischen „offen" und „deaktiviert" ist beabsichtigt. Lesen ohne Token funktioniert — auf dem eigenen Rechner ist das bequem und birgt keine Gefahr. Schreiben ohne Token funktioniert überhaupt nicht: Eine einzige fehlgeschlagene Wörterbuchbearbeitung zerstört still die Suche für alle, die mit dem gemeinsamen Server verbunden sind.

Das Token wird per Header übergeben — entweder X-Api-Token oder Authorization: Bearer <Token>. Das administrative Token taugt auch zum Lesen: Sonst müsste der Besitzer zwei Header im Client halten statt einem.

Das Token muss in lateinischen Buchstaben sein. HTTP-Header werden in latin-1 kodiert, und ein kyrillisches Token erreicht den Server physisch nicht: Über das Anmeldeformular im Browser funktioniert es, über den Client-Header nicht.

An der Prüfung vorbei werden zwei Pfade gelassen: /health (darüber läuft der Healthcheck des Containers, und er gibt keine Informationen über das Leserecht hinaus) und /login — sonst wäre das Anmeldeformular hinter genau der Autorisierung, die es ausgibt.

Noch zwei Regeln, die nichts mit Token zu tun haben:

  • Der MCP-Endpunkt gibt die Konfigurationsstruktur vollständig aus. Setzen Sie API_TOKEN bei jeder Verlagerung über die eigene Maschine hinaus; der Netzwerkzugriff reicht nicht.

  • Das Verzeichnis data/ ist vollständig in .gitignore — sowohl .hbk mit den Ausgaben als auch die geparsten Indizes. Der Hilfsindex ist derselbe Inhalt der Firma „1С", nur entpackt. Einmal ist er dorthin gelangt und lag 20 Commits lang; die Geschichte wurde mit git filter-repo umgeschrieben, und die Regel wurde nach Verzeichnis statt nach Erweiterungen neu formuliert: Geprüft werden muss nicht „ist das .hbk?", sondern „liegt das in data/?".


7. Dokumente

Datei

Worum es geht

CHANGELOG.md

was gemacht und was über 1С herausgefunden wurde

docs/schema-v1.md

Vertrag des Ausgabeformats

docs/data-sources.md

was wir aus welcher Quelle nehmen

docs/query-language-design.md

Aufbau der Quelle der Abfragesprache

docs/dashboard-design.md

Aufbau des Dashboards

docs/modules-intake-design.md

Annahme der Konfigurationsausgabe in Dateien — Aufgabenstellung

docs/modules-provider-design.md

Indizes und Werkzeuge des Code-Providers

exporter-1c/README.md

Verarbeitung der Ausgabe für 1С

CONTRIBUTING.md

wie man das Projekt bearbeitet: Sprache, Commits, Prüfungen

SECURITY.md

wie man eine Schwachstelle meldet

Veröffentlicht werden sechs eigenständige Vertragsdokumente: das Ausgabeformat, die Quellengrenze, der Aufbau der Abfragesprache und des Dashboards, die Annahme der Code-Ausgabe und der Code-Provider. Jeder Link aus einer öffentlichen Datei muss auf Material führen, das ebenfalls im Repository enthalten ist.

Externe DB, Vektoren, Graphdatenbank, SSE-Transport und Lazy Loading wurden durch Messungen des aktuellen Korpus abgelehnt. Zurückkehren kann man zu ihnen nur mit neuen Messungen, die die bisherigen Kosten widerlegen oder ein neues lebendiges Szenario zeigen.


8. Lizenz

Apache License 2.0. Separat sollte man NOTICE lesen — dort stehen zwei Dinge, die die Lizenz selbst nicht sagt:

  • das Projekt wurde unabhängig entwickelt und ist nicht mit der ООО «1С» verbunden; „1С" und „1С:Предприятие" sind Warenzeichen der ООО «1С», und die Lizenz gewährt keine Rechte daran (Apache 2.0, Abschnitt 6);

  • im Repository gibt es keine Plattformhilfe und keine Konfigurationsausgaben — weder im Originalzustand noch geparst. Das ist Inhalt der Firma „1С" und Daten konkreter Implementierungen; jeder nimmt sie aus seiner eigenen Lieferung und legt sie in data/ ab. Die Lizenz gilt für den Code, nicht für die Daten, die Sie hineingeladen haben.

Available Tools

11 tools
compare_configurationsA

Сравнить один и тот же объект в двух конфигурациях: чем различаются имена реквизитов. Типы и содержимое табличных частей не сравниваются. Дочитайте все страницы по готовому вызову продолжения.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoЧисло различий на странице суммарно для обеих сторон, от 1 до 100.
cursorNoНепрозрачный курсор из продолжения. Привязан к паре, объекту и содержимому сравнения.
configsNoРовно два разных имени из `list_configurations`. Не заданы — автоматический выбор только при ровно двух загруженных конфигурациях; иначе выберите пару явно.
full_nameYesПолное имя объекта, которое ищется в обеих конфигурациях.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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

Кто вызывает точную процедуру: подтверждённые места в коде с процедурой-владельцем, привязки подписок и регламентных заданий из метаданных, элементы и события формы. Одноимённые вызовы без разрешённого модуля показываются отдельно и не приписываются запрошенному адресу. Тела модулей не читаются.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoСколько мест вызова показать: целое число от 1 до 50. Оставшееся число подтверждённых мест и модулей указывается отдельно; одноимённые места без разрешённой цели тоже не выводятся без границы.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.
addressYesТочный адрес процедуры `Модуль::Имя`, полученный из `search_procedures` или оглавления `get_procedure`.
extensionNoИмя одного загруженного расширения. Не задано — места в коде ищутся только в основной конфигурации; чужой код не подмешивается.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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; после смены поколения чтение нужно начать заново.

ParametersJSON Schema
NameRequiredDescriptionDefault
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.
cursorNoНепрозрачный cursor из ответа get_object для продолжения HTTP-сервиса или подсистемы. Передавайте без изменений с теми же full_name, config и detail.
detailNoУровень детализации: `brief` — пара строк со счётчиками, `fields` — состав для написания кода, `full` — со свойствами и связями. Полное описание крупного документа занимает много контекста, поэтому `full` только когда связи действительно нужны.fields
full_nameYesПолное имя объекта: `Документ.ЧекККМ`, `Справочник.Номенклатура`. Получается из `search_objects`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 строк с готовым вызовом продолжения. Выбранное расширение читается отдельно от основной конфигурации; смысл его аннотации показывается явно.

ParametersJSON Schema
NameRequiredDescriptionDefault
linesNoРазмер окна тела: целое число от 1 до 200. Если тело длиннее, ответ содержит готовый вызов следующего окна без пропусков.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.
addressYesТочный адрес модуля (`ОбщийМодуль.ОбщегоНазначения`) или процедуры (`ОбщийМодуль.ОбщегоНазначения::Проверить`).
extensionNoИмя одного загруженного расширения. Не задано — читается код основной конфигурации; чужие расширения в тело не подмешиваются.
start_lineNoНомер первой строки окна тела, начиная с 0. Значение берётся из готового вызова продолжения в предыдущем ответе.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 нужен обход). Поле «Доступность» — тоже ошибка компиляции: серверный метод из клиентского контекста не соберётся. Режим совместимости проверяется отдельно: по одной версии платформы успешную компиляцию в старом режиме утверждать нельзя.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesИмя элемента платформы: `СтрНайти`, `ЗаписьJSON.ЗаписатьНачалоОбъекта`, `ValueTable.Columns`. Для членов объектов надёжнее указывать `Объект.Член`.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.
detailNoУровень карточки синтаксиса: `brief`, `fields` (по умолчанию), `full` (описание и первые 50 связей) или `links` (только связи, по 50 на страницу). Для следующей страницы `links` передайте `links_offset` из ответа. Связи показываются только по справке точного релиза конфигурации; без конфигурации доступность не проверена.fields
links_offsetNoСмещение страницы связей для `detail=links`, от нуля. В остальных режимах оставьте 0.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 обязателен во всех остальных инструментах, а имя для него берётся отсюда.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 не выдаётся за доказанный порядок исполнения модулей.

ParametersJSON Schema
NameRequiredDescriptionDefault
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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) приходят только оттуда. Запрос, написанный сразу после поиска, выглядит правильным и падает на «поле не найдено».

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoОграничить вид: Документ, Справочник, РегистрСведений, РегистрНакопления, Перечисление, ОбщийМодуль и т. п.
limitNoСколько результатов вернуть. По умолчанию 10, максимум 50 (большее молча урезается). Поднимать выше 10 стоит только когда нужного не оказалось в первой десятке: правильный ответ почти всегда в первой пятёрке, а длинная выдача тратит контекст.
queryYesФормулировка по-человечески («расходная накладная») или часть имени объекта.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 область не угадывается. Сигнатуры читаются из выгрузки в файлы только для показанных результатов.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoСколько результатов вернуть отдельно на каждом уровне поиска: по точному имени и по словам. Целое число от 1 до 50; значение вне диапазона отклоняется, чтобы не скрывать ошибку вызова.
queryYesТочное имя процедуры (`ПриЗаписи`) или слова из имени и комментария-шапки (`проверить остатки`), в том числе фраза о поддержанном типовом событии (`что выполняется при записи объекта`). Объект поиска из этого текста не угадывается — для него есть `scope`.
scopeNoНеобязательный явный scope: объект (`Документ.ЧекККМ`) или точный адрес (`ОбщийМодуль.ОбщегоНазначения`). В обычном поиске его модули поднимаются, а распознанное типовое событие разрешается только внутри scope. Из query область не выводится.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.
extensionNoИмя одного загруженного расширения. Не задано — поиск идёт только по коду основной конфигурации, без примеси расширений.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoОграничить вид: method, property, event, object, query_table, query_field.
limitNoСколько результатов вернуть. По умолчанию 10, максимум 50 (большее молча урезается). Поднимать выше 10 стоит только когда нужного не оказалось в первой десятке: правильный ответ почти всегда в первой пятёрке, а длинная выдача тратит контекст.
queryYesЧто ищем: «разделить строку», «ЗаписьJSON», «StrFind» по платформе. Русские и английские имена равнозначны.
configNoИмя конфигурации 1С, как его вернул `list_configurations` (например «ОтраслеваяКонфигурация»). Обязателен, если загружено больше одной конфигурации: по умолчанию ничего не подставляется, иначе ответ может относиться к чужой конфигурации.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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. 1 tool updatev4.2.0
    • Removedget_module_source_file
  2. 2 tool updatesv4.1.0
    • Addedget_module_source_file
    • Changedget_syntax2 fields changed
      • changedInput schema / properties / detail / description
        Previous value: -"Уровень детализации: `brief` — пара строк со счётчиками, `fields` — состав для написания кода, `full` — со свойствами и связями. Полное описание крупного документа занимает много контекста, поэтому `full` только когда связи действительно нужны."New value: +"Уровень карточки синтаксиса: `brief`, `fields` (по умолчанию), `full` (описание и первые 50 связей) или `links` (только связи, по 50 на страницу). Для следующей страницы `links` передайте `links_offset` из ответа. Связи показываются только по справке точного релиза конфигурации; без конфигурации доступность не проверена."
      • addedInput schema / properties / links_offset
        Added value: +{
        +  "default": 0,
        +  "description": "Смещение страницы связей для `detail=links`, от нуля. В остальных режимах оставьте 0.",
        +  "title": "Links Offset",
        +  "type": "integer"
        +}
  3. 1 tool updatev3.3.0
    • Changedget_object1 field changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Непрозрачный cursor из ответа get_object для продолжения HTTP-сервиса или подсистемы. Передавайте без изменений с теми же full_name, config и detail.",
        +  "title": "Cursor"
        +}
  4. 1 tool updatev3.0.0
    • Changedcompare_configurations3 fields changed
      • changedInput schema / properties / configs / description
        Previous value: -"Имена конфигураций из `list_configurations`. Не заданы — берутся все загруженные."New value: +"Ровно два разных имени из `list_configurations`. Не заданы — автоматический выбор только при ровно двух загруженных конфигурациях; иначе выберите пару явно."
      • addedInput schema / properties / cursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 2048,
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Непрозрачный курсор из продолжения. Привязан к паре, объекту и содержимому сравнения.",
        +  "title": "Cursor"
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 40,
        +  "description": "Число различий на странице суммарно для обеих сторон, от 1 до 100.",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "title": "Limit",
        +  "type": "integer"
        +}
  5. 11 tool updatesv2.0.0
    • First observedcompare_configurations
    • First observedget_callers
    • First observedget_object
    • First observedget_procedure
    • First observedget_related
    • First observedget_syntax
    • First observedlist_configurations
    • First observedlist_extensions
    • First observedsearch_objects
    • First observedsearch_procedures
    • First observedsearch_syntax

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Provides 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.
    23
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP 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
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides 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