mcp-1c
MCP-Server für 1C-Konfigurationsstrukturen
Nachschlagewerk zu den Metadaten mehrerer 1C-Konfigurationen, zur Syntax der Plattform und zur Abfragesprache – für Agenten, die Code in BSL schreiben. Liefert einen minimal ausreichenden Ausschnitt: die Auflösung einer menschlichen Formulierung in den genauen Objektnamen, die Objektstruktur auf der gewünschten Detailebene, deren Beziehungen, die Beschreibung der Plattformmethoden unter Berücksichtigung der Version der jeweiligen Konfiguration sowie die Konstrukte der Abfragesprache.
Ersetzt kein grep über die Projektquellen: Der Code lebt in Dateien, der Server ist für das sich langsam ändernde Wissen über die Konfiguration zuständig. Die Grenze ist in docs/data-sources.md festgehalten.
Stand – 2026-08-18
Phase | Status |
Verarbeitung des Exports für 1C | ✅ 20 Metadatenarten, 8.3.5 und 8.3.23, XML und JSON |
Exportformat | |
Lader, Modell, Beziehungsgraph, Rendering | ✅ 5 Konfigurationen, 20 522 Objekte, 322 Tsd. Kanten |
Plattformdokumentation | ✅ zusammengeführter Index von drei Versionen, 25 691 Einträge, Grenzen |
Abfragesprache | ✅ |
Suche | ✅ 97,1 % Doku, 94,7 % Abfragesprache, 90,5 % Metadaten – siehe „Gemessen“ |
Virtuelle Registertabellen | ✅ vorgefertigte Abfragefeldnamen ( |
Ersetzungstabelle für alte Plattformen | ✅ Nicht verfügbar ist nicht nur verboten, sondern durch ein Rezept ersetzt |
Quellenverzeichnis, Versionsabgleich | ✅ |
MCP-Server, 7 Werkzeuge | ✅ streamable-http und stdio |
Docker | ✅ ein Container, 354 MB |
Suchindex-Cache | ✅ 12 MB, wird anstelle einer erneuten Analyse geladen |
Messstand | ✅ |
Tests | ✅ |
Dashboard | ✅ Verzeichnis, Quellen, Abfragelauf, Beziehungsgraph, Karten, Wörterbuch |
Autorisierung | ✅ |
Modulindex aus | ⬜ |
Inhalt
Start — Docker, Dashboard, Beziehungsgraph, ohne Docker
Agent verbinden — wie MCP funktioniert, falls keine Verbindung zustande kommt, Token, Client-Konfigurationen: Claude Code, Codex CLI, Cursor, VS Code, Qwen Code, stdio
Werkzeuge — Reihenfolge der Aufrufe, Quellen, Abfragesprache, Plattformversionen, Zusammenführen der Dokumentationen, Ersetzungen
Datenverwaltung — Quellen, Wörterbuch und Suchschlüssel, CLI, Messstand, Server manuell, Woher die Daten stammen
Sicherheit — Token, was ohne diese offen ist
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 Plattformdokumentation und die Abfragesprache sind getrennte Quellen und getrennte Felder:
syntax_loaded bezieht sich nur auf Ersteres, syntax listet die Versionen der
geladenen Dokumentationen auf. Die Namen der Konfigurationen und die Versionen der
Dokumentationen werden nur einer Anfrage mit Leserecht zurückgegeben; ohne Token
bleiben status, der Zähler und zwei Flags übrig.
Alles, was in data/bootstrap/ liegt, wird beim Start indiziert: *.zip – Exporte
der Konfigurationen, *.hbk – Plattformdokumentation. Eine erneute Verarbeitung
derselben Datei erfolgt nicht: Der Abgleich läuft über den Hash.
Das Verzeichnis ./data wird in den Container als /data eingehängt. Darin
verwaltet der Server Quellen, Indizes, Cache und registry.json; die Pfade im
Verzeichnis sind relativ, daher kann das Verzeichnis zwischen dem
Entwicklerrechner und dem Container verschoben werden.
data/ liegt vollständig außerhalb von git – es ist ein Volume, kein Teil des
Repositorys. Es wird durch Kopieren des Verzeichnisses übertragen. Nach dem Klonen
muss die Dokumentation also selbst abgelegt werden: Das Repository enthält sie
nicht und kann sie nicht enthalten, es handelt sich um Inhalte der Firma „1C“.
Nach einer Codeänderung muss der Container neu erstellt und nicht neu gestartet werden:
docker compose up -d --build --force-recreaterestart startet den bisherigen Container mit dem bisherigen Image, und die
Änderungen werden nicht übernommen.
Zum Port. Nach außen ist der Server auf 5001 gelegt, innerhalb des
Containers lauscht er auf 8000 – die Weiterleitung 5001:8000 steht in
docker-compose.yml. Alle Adressen in dieser Datei sind extern, also 5001.
Falls belegt – ändern Sie die linke Seite der Weiterleitung, die rechte lassen Sie
unangetastet: Daran hängen EXPOSE und der Healthcheck des Images.
Dashboard
http://localhost:5001/ – sechs Seiten:
Seite | Was es dort gibt |
Übersicht | was geladen ist: Objekte, Beziehungen, Plattformversion, Warnungen aus Manifesten |
Quellen | Liste des Geladenen, Hochladen von |
Abfragen | Ausführen einer Liste von Formulierungen mit Bewertung und Grund des Rankings |
Beziehungen | 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 Synonyngruppe anlegen |
Beziehungen – Graph des Objekts
/graph zeichnet die Umgebung eines Objekts: Farbe nach Art, Pfeil in
Bezugsrichtung, Kantenbeschriftung beim Überfahren. Ein Klick auf einen Knoten
erstellt den Graphen um diesen herum, Ziehen verschiebt, das Mausrad zoomt. Das
Limit der Nachbarn wird auf der Seite gewählt (15…400), die Beschneidung wird mit
einer Zahl benannt – „30 von 102 angezeigt“.
Beantwortet die Frage „Was bricht, wenn ich etwas anfasse“: Ein Register, umgeben von orangefarbenen Belegen, zeigt sofort, wer es bewegt.
Die Tiefe beträgt immer einen Schritt. Bei zwei Schritten werden aus einem
häufig genutzten Nachschlagewerk tausend Objekte, bei dreien ein Drittel der
Konfiguration; darüber hinaus führt die Beziehung über gemeinsame Mechanismen wie
zusätzliche Attribute, die fast alles mit allem verbinden. Man kann sie nicht über
einen Schwellenwert bei der Anzahl der Beziehungen abschneiden: Ein solcher Knoten
hat 34, der sinnvolle Справочник.Пользователи dagegen 323. Deshalb werden die
Knoten von einem Menschen aufgedeckt, nicht von einer Heuristik – er sieht, wohin
man nicht gehen sollte.
Der Agent hat ein solches Werkzeug bewusst nicht. Analyse und Rückgabebedingungen stehen in docs/TASKBOARD.md, Abschnitt „Aufgeschoben“.
Ein Fehlgriff wird direkt im Browser behoben: Auf der Abfrageseite hat jede Phrase einen Link „falsch – Alias anlegen“, der zum 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, der die Adresse erreicht, lesen –
einschließlich der Struktur der Konfigurationen und der Anpassungen. Für localhost
ist das akzeptabel, für einen Server im Netz nicht.
Die Token sind getrennt, weil das Lesetoken in der Konfiguration jedes MCP-Clients liegt und mit dieser mitläuft; der Agent sollte keine Rechte zum Löschen von Quellen haben. Das Admin-Token gilt auch als Lesetoken – man muss nicht zwei Header führen.
// .mcp.json — как клиент передаёт токен
{"mcpServers": {"1c": {"type": "http", "url": "http://localhost:5001/mcp",
"headers": {"X-Api-Token": "..."}}}}Nur ASCII: HTTP-Header werden in latin-1 kodiert, kyrillische Zeichen kommen dort
nicht an. /health bleibt für den Healthcheck offen, aber die Namen der
Konfigurationen werden nur mit Token zurückgegeben.
Hochladen, Löschen und Bearbeiten des Wörterbuchs erfordern ADMIN_TOKEN –
dasselbe wie bei /admin/reload; ohne dieses existieren diese Endpunkte nicht,
sie sind nicht „gesperrt“. Der Token wird einmal im Formular eingegeben, an den
Browser geht nicht er, sondern eine Sitzungskennung.
Wird über .env neben docker-compose.yml gesetzt – die 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-recreateDer Name im Ergebnis ist ein Link zur Karte: Bei einem Objekt sind das Attribute
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. Ein Attribut hat keine eigene
Karte – der Link führt zum Besitzerobjekt.
Die Seite „Abfragen“ beantwortet die Frage „Warum hat der Server genau das
geliefert“: Neben jedem Treffer steht der Grund – exakte Übereinstimmung,
Alias aus dem Wörterbuch, alle Wörter der Anfrage. Daran erkennt man, womit
man einen Fehlgriff behandelt – mit Synonym, Alias oder Gewicht.
Die Analyse der Dokumentation dauert einige Sekunden: Die Seite antwortet danach, aber MCP-Clients werden dadurch nicht aufgehalten – die Indizierung läuft in einem eigenen Thread.
Ohne Docker
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 50012. Agent verbinden
Der Server implementiert das MCP-Protokoll über die Standardtransporte des offiziellen SDKs und passt daher zu jedem MCP-Client. Es sind keine Wrapper um HTTP erforderlich.
Transport | Wann | Adresse |
streamable-http | Server in Docker oder auf einem anderen Rechner |
|
stdio | Client startet den Prozess selbst lokal | — |
| nur für alte Clients |
|
Beide Haupttransporte wurden mit dem offiziellen MCP-Client getestet:
initialize-Handshake, tools/list, tools/call, Protokoll 2025-11-25.
Wie es funktioniert
Es ist nützlich, das zu verstehen, bevor etwas keine Verbindung aufbaut. Die
Adresse ist eine – /mcp, es gibt keinen Endpunkt pro Werkzeug; welches
Werkzeug aufgerufen wird, steht im Anfragetext, nicht im Pfad.
Dann gibt es zwei verschiedene Mechanismen, die man nicht verwechseln sollte:
Werkzeugbeschreibungen | Daten | |
Wann | einmalig, beim Verbinden | bei jedem Aufruf |
Wer beginnt | Client, selbst, ohne Beteiligung des Modells | Modell, nach Entscheidung |
Methode |
|
|
Wohin | Systemprompt des Modells | Gesprächsinhalt |
Preis | einmalig, liegt die ganze Sitzung | 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 Werkzeuge auf einmal: Name, Beschreibung,
JSON-Schema der Parameter. Das alles wird in den Kontext des Modells gelegt,
bevor der Mensch das erste Wort getippt hat. Das Modell holt sich die
Beschreibung nicht, wenn es sie braucht – sie ist bereits da.
Daraus folgt eine wichtige Konsequenz bei der Bearbeitung von Beschreibungen: Sie belegen die ganze Sitzung Platz im Fenster, unabhängig davon, ob das Modell überhaupt ein Werkzeug aufruft oder keins.
Es sind immer sieben Werkzeuge, unabhängig davon, was geladen ist. Der Satz ist ein Vertrag, keine Variable: Die Werkzeuge hängen miteinander zusammen, und auf dem Arbeitsserver sind alle drei Quellen geladen – Konfiguration, Plattform-Hilfe, Abfragesprache. Der Vertrag tools/list plus instructions – etwa 3.900 Token, und diese Zahl hängt nicht vom Zustand des Registers ab.
Daraus folgt direkt, was man im Voraus wissen sollte: Wenn eine Quelle nicht geladen ist, zahlt man trotzdem für ihre Werkzeuge. Ohne Plattform-Hilfe liegen search_syntax und get_syntax im Kontext und kosten 1.185 Token, antworten aber mit „Hilfe nicht verbunden“; compare_configurations bei einer Konfiguration – 262 Token für die Antwort „mindestens zwei nötig“. Behoben wird das durch Laden der Quelle, nicht durch Auswahl der Werkzeuge: Die Auswahl wurde am 2026-08-19 ausprobiert und wieder verworfen – Details und Zahlen in „Aufgeschoben“.
Beschreibungen werden daher dicht geschrieben, Details wandern in die Ausgabe des Werkzeugs selbst: Dafür zahlt man nur, wenn sie gebraucht wird.
GET /mcp ist kein „falsches POST“, sondern die 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 sich nicht verbindet
Der Antwortcode im Log (docker logs -f mcp1c) nennt die Ursache:
Code | Was nicht stimmt |
| Client sendet kein |
| Client hat den Header |
| Client begann den Handshake mit |
| dasselbe: Der alte Transport ist nicht nach außen geführt |
|
|
Log ist leer | Client hat gar keine Anfrage gesendet – es liegt an seiner Konfiguration, bis zum Server ist nichts durchgedrungen |
Lebender Fall: Qwen Code konnte sich nicht verbinden, weil in seiner Konfiguration der Schlüssel url stand – in der Gemini-CLI-Familie (Qwen erbt das Format) bedeutet das 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
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 Werkzeuge einfach nicht.
Einer der beiden Header ist geeignet – der Server akzeptiert beide:
X-Api-Token: <токен>
Authorization: Bearer <токен>Drei Dinge, über die man stolpert:
Nur ASCII. HTTP-Header werden in latin-1 kodiert, ein kyrillisches Token kommt darüber nicht an. So generieren:
python3 -c "import secrets; print(secrets.token_urlsafe(32))".In den Client kommt
API_TOKEN, nichtADMIN_TOKEN. Der Admin-Token wird auch akzeptiert, aber die Client-Konfiguration wandert in Git und in Backups: Ein ausgelaufener Lese-Token erlaubt das Ansehen, ein ausgelaufener Admin-Token das Löschen von Quellen.stdiobenötigt keinen 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 den 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/mcp200 – Token akzeptiert. 401 – falscher Token oder Header nicht angekommen.
Wie man ein Geheimnis nicht eincheckt
.mcp.json und ähnliche Dateien liegen normalerweise im Repository. Optionen:
Variablenersetzung – wenn der Client das kann (Claude Code kann es):
"X-Api-Token": "${MCP1C_API_TOKEN}", die Variable selbst in~/.zshrc. In Git wandert der Variablenname, nicht der Wert.Datei aus Git nehmen:
git rm --cached .mcp.json && echo ".mcp.json" >> .gitignore.Einstellung nicht im Projekt, sondern in der Benutzerkonfiguration des Clients halten – dann hat das Repository damit 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 liegen kann:
echo 'export MCP1C_API_TOKEN=ваш_токен' >> ~/.zshrc && source ~/.zshrcOder 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 in diesem Format bedeutet den alten SSE-Transport: Der Client beginnt den Handshake mit GET /mcp, erhält 400 Missing session ID und verbindet sich nicht.
Andere Clients
Windsurf, Antigravity, Cline, Roo Code, Konsolen-Agenten – die Schreibweise ist dieselbe: Transporttyp, URL und, falls API_TOKEN gesetzt ist, ein Header-Block. Unterschiede nur im Dateinamen und im Schlüssel der obersten Ebene (mcpServers oder servers) – siehe Dokumentation des jeweiligen Clients.
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 starten 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 zu schützen.
{
"mcpServers": {
"1c": {
"command": "python3",
"args": ["-m", "mcp1c.server", "--transport", "stdio", "--data", "/путь/к/data"],
"env": { "PYTHONPATH": "/путь/к/проекту/src" }
}
}
}3. Werkzeuge
Der Satz ist fest und bewusst klein: Jedes Werkzeug hängt ständig im Kontext des Agenten. Eine neue Datenquelle bereichert die Antworten der vorhandenen, nicht fügt sie eigene hinzu.
Werkzeug | Zweck |
| was geladen ist, welche Anbieter pro Konfiguration verfügbar sind |
| menschliche Formulierung → exakter Objektname |
| Objektzusammensetzung; |
| Bewegungen, Verweise, Abhängigkeiten – nur direkte |
| ein Objekt in zwei Konfigurationen |
| Suche in der Plattform-Hilfe und in der Abfragesprache |
| Signatur, Parameter, Verfügbarkeit, Version, Ersatz für alte Plattform |
config ist Pflicht, wenn mehr als eine Konfiguration geladen ist: Der Server setzt sie bewusst nicht stillschweigend ein – sonst schreibt der Agent Code gegen eine fremde Basis, und niemand erfährt davon.
Ein Name kann in zwei Domänen gleichzeitig leben: СтрНайти gibt es sowohl in der Plattform (seit 8.3.6) als auch in der Abfragesprache. Dann listet get_syntax gleichnamige mit fertiger Adresse für jede auf, und der Aufruf kann mit einer Zeile aus der Ausgabe wiederholt werden:
get_syntax("СтрНайти") → Одноимённых элементов: 2
- `Глобальный контекст.СтрНайти` — Метод, с 8.3.6
- `Запрос.СтрНайти` — Функция запроса
get_syntax("Запрос.СтрНайти") → карточка функции языка запросовDer Qualifikator Запрос. ist nötig, weil ein Element der Abfragesprache keinen Besitzer hat: Es kann nicht wie ein Plattform-Element über Объект.Член benannt werden.
Reihenfolge der Aufrufe – und was verloren geht, wenn man sie bricht
list_configurations → search_objects → get_object → search_syntax → get_syntaxDer Schritt get_object darf nicht übersprungen werden. Die Suche liefert nur Namen und Zähler; alles, wovon der Code abhängt, lebt in der Objektkarte:
Art und Periodizität des Registers.
СрезПоследнихgibt es nur bei periodischen Informationsregistern, nicht bei nichtperiodischen – 566 von 603;fertige Feldnamen virtueller Tabellen. In der Abfrage heißt die Ressource
КоличествоКоличествоОстаток,КоличествоОборот,КоличествоПриход– im Konfigurator sind solche Namen nirgends sichtbar, sie werden von der Plattform erzeugt;Subconto-Grenze, Korrespondenz, Diagrammressourcen – ohne sie sind Felder wie
СубконтоДт1nicht zu benennen;Zeichenfolgen unbegrenzter Länge. Direkt im Typ markiert:
Строка (неогр. — только через ПОДСТРОКА)gegenüberСтрока(200). Ein solches Feld darf nicht unverändert in eine Abfrage – die Plattform lässt es weder vergleichen, noch gruppieren, noch sortieren. Solche Felder machen 23% bis 38% der Zeichenfolgen in lebenden 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“. Beispiel für etwas, das nur aus get_object kommt:
## Таблицы запроса
- `РегистрНакопления.ТоварыНаСкладах.Остатки`
измерения: Склад, Номенклатура, Характеристика
ресурсы: КоличествоОстаток, РезервОстатокEin zweites solches – und es wurde durch einen lebenden Fehlgriff am 2026-08-18 gefunden. Der Agent gruppierte eine Abfrage nach einer Zeichenfolge ohne Längenbegrenzung; die Daten haben wir korrekt geliefert, aber der Unterschied war nur am Fehlen der Zahl in Klammern abzulesen:
> **Строки неограниченной длины** помечены `(неогр.)`. Платформа не даёт их
> сравнивать, группировать и упорядочивать и не пускает в РАЗЛИЧНЫЕ,
> ОБЪЕДИНИТЬ и агрегатные КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ. Ограничивайте
> длину — одинаково в списке выборки и в группировке:
>
> ПОДСТРОКА(КодСкидки, 1, 100) КАК КодСкидки
>
> Длину подбирайте по смыслу поля: 100 — не универсальное число.
## Реквизиты
- `КодСкидки` — Строка (неогр. — только через ПОДСТРОКА) // Код скидки
- `КодМаркировки` — Строка(200) // Код маркировкиDas Rezept steht sowohl im Hinweis als auch in der Feldzeile selbst, und das ist keine Redundanz. Die erste Fassung druckte den Hinweis als letzten Absatz der Karte. Ein lebender Agent rief am 2026-08-18 get_object mit detail=fields auf, erhielt sie vollständig – und gruppierte trotzdem nach einem solchen Feld. Der Hinweis stand 721 Token nach der Feldzeile, und die Entscheidung wird dort getroffen, wo der Name kopiert wird. Dieselbe Lektion war bereits in den Werkzeugbeschreibungen festgehalten: Die Regel wirkt dort, wo man sie liest, nicht dort, wo man sie ordentlicher ablegt.
Jedes Verbot ist geprüft: Aggregatfunktionen – Zitat aus der Hilfe, die übrigen fünf – Läufe auf einer lebenden Basis mit aufgezeichneten Fehlertexten. Die Hilfe kennt die Einschränkung nur bei drei der sechs Aggregatfunktionen und schweigt über Gruppierung, Sortierung, РАЗЛИЧНЫЕ, ОБЪЕДИНИТЬ und Vergleich – das heißt, ein Agent, der sie ehrlich gelesen hat, konnte davon nichts wissen. Aufschlüsselung nach Herkunft – in docs/data-sources.md, Abschnitt „Hinweise in der Karte“.
Vor dem Aufruf einer Plattformfunktion auf einer alten Konfiguration – get_syntax.
Nicht Verfügbares wird markiert, und dort liegt auch das Ersatzrezept, falls es aufgezeichnet ist.
Quellen sind unabhängig
Es gibt drei, und jede wird separat angeschlossen:
Quelle | Datei | Was sie liefert | Ohne sie |
Konfigurationsmetadaten |
| Objekte, Attribute, Verweise, Bewegungen |
|
Plattform-Hilfe |
| Methoden, Eigenschaften, Signaturen, Verfügbarkeit, Versionen |
|
Abfragesprache |
|
| Sprachkonstrukte werden nicht gefunden |
Was geladen ist | Was funktioniert |
Alle drei | alles |
Nur Konfiguration | Metadaten; Syntax antwortet „Quelle nicht verbunden“ |
Nur Hilfe | Syntax ohne Filterung nach Version, |
Nichts |
|
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 landet im selben Suchindex wie die Plattform-Hilfe – separat 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.
Eine Version gibt es nicht von irgendwoher: Die Plattformhilfe der Abfragesprachenfunktionen beschreibt sie überhaupt nicht (ПОДСТРОКА — null Treffer bei 25 511 Elementen). Deshalb vergibt die kuratierte Tabelle query_versions.py die Versionen — anhand 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 funktioniert 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 es in der alten nicht gibt und in der neuen schon, das ist dazwischen erschienen, und dafür muss eine Version stehen:
python3 tools/lab/compare_query_help.py <старая.hbk> <новая.hbk>Lauf vom 2026-08-19, 8.3.5.1570 gegen die aktuelle: erschienen 29, abgedeckt 29, Fehlalarme 0. Ein Fehlalarm 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 Tabellenzellen als Absätze innerhalb von <TD> ausgezeichnet, und ohne separate Verarbeitung druckte die Karte die Tabelle als Wertespalte: «Товар / Количество / Номер / Сантехника / 104 / …» zwei Dutzend Zeilen hintereinander. Jetzt werden Tabellen in einem eigenen Feld verarbeitet — 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 verarbeitet:
Was | Wie viele | Wie es in der Karte aussieht |
Datentabelle — Ergebnis eines Beispielabfrage | 51 auf 31 Seiten | als Markdown-Tabelle |
gezeichnete Syntaxdiagramm — Grammatik der Konstruktion | 21 auf 17 Seiten | als Treppe mit Einzug nach Verzweigungsebene |
Sie unterscheiden sich in der Auszeichnung, nicht in der 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 einem einzigen senkrechten Strich (das ist eine gezeichnete Linie, kein Wert).
Beschädigte Auszeichnung wird beim Namen genannt. Eine Seite mit ungeschlossenem <TABLE> wird ohne Tabellen verarbeitet, geht aber nicht verloren, und ihr Name landet in den Warnungen der Quelle: als Zeile in der Ladeausgabe (mcp1c.cli reg-add) und als eigene Zeile auf der Seite «Quellen» des Dashboards. Eine Karte stillschweigend ärmer als üblich auszuliefern geht nicht: Von einer Hilfe, in der es das einfach nicht gibt, 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 einem sicheren Abstand bleibt das Plattformelement an erster Stelle — «wie man einen Parameter in einer Abfrage setzt» kann auch Запрос.УстановитьПараметр meinen.
Der Parameter config ist Pflicht, wenn mehr als eine Konfiguration geladen ist.
Standardmäßig wird nichts eingesetzt: Eine stillschweigende Auswahl führt dazu, dass der Agent Code nach einer fremden Konfiguration schreibt, und niemand merkt es.
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 6 539 Elemente aus der Ausgabe entfernt, für 8.3.23 — 874. Nicht als Warnung, sondern durch Filterung: Eine Warnung übersieht der Agent, eine in der Ausgabe fehlende Methode nicht.
Das Feld Verfügbarkeit (Server / dünner Client / Web-Client / mobil) muss man unbedingt lesen: Ein Aufruf einer Servermethode aus einem Client-Kontext kompiliert nicht.
Hilfen mehrerer Versionen verschmelzen zu einem Index
Eine einzige frische Hilfe auf einer alten Konfiguration lügt. Gemessen auf 8.3.5: 199 Elemente würde der Server als nicht existent erklären, 117 würde er mit fremder Signatur liefern (Запись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 den Grenzen since und until verschmolzen, und die Antwort wird unter der Version der jeweiligen Konfiguration zusammengestellt. Es braucht so viele Hilfen, wie es Plattformen bei den geladenen Konfigurationen gibt — zwei extreme ersetzen die Zwischenstufen nicht.
Der Preis ist gemessen und klein: Die Verschmelzung von drei 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 das lässt sich aus der Hilfe nicht ableiten: Die Veraltet-Markierung steht auf 15 von 25 000 Seiten.
Deshalb gibt es eine Ersatztabelle (replacements.py), derzeit 6 Einträge — Zeichenfolgenfunktionen, die in 8.3.6 erschienen sind. Statt eines Verbots liefert get_syntax ein Rezept:
get_syntax("СтрРазделить", config="Ювелирный") → 8.3.5
# `СтрРазделить` недоступна: появилась в 8.3.6
Замена: РазложитьСтрокуВМассивПодстрок(<Строка>, <Разделитель>)
Оговорка: разделитель у `СтрРазделить` — набор символов, каждый из которых
самостоятельный разделитель; у замены это одна строка целиком.Der Vorbehalt ist Pflicht. Ein Ersatz ist fast nie äquivalent, und eine ähnliche Funktion stillschweigend 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 Выгрузка.zipEinfacher: Eine Datei in data/bootstrap/ legen — sie wird beim nächsten Start aufgenommen.
Änderungen ohne Neustart anwenden
Ein laufender Server hält das Register im Speicher, daher muss man es nach reg-add anstoßen. Entweder Neustart (docker compose restart mcp1c, etwa 2 Sekunden) oder der Admin-Endpunkt:
# включается переменной ADMIN_TOKEN; без неё маршрут отключён
ADMIN_TOKEN=секрет docker compose up -d
curl -X POST -H "x-admin-token: секрет" http://localhost:5001/admin/reloadWö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, lässt sich ohne Neuaufbau des Images bearbeiten.
Zwei Mechanismen, und sie sind verschieden.
Wortsynonyme — für alle Konfigurationen gemeinsam:
python3 -m mcp1c.cli dict-synonyms клиент покупатель заказчикObjektaliase — die direkte Angabe «wenn ich so sage, meine ich diese Objekte», Gewicht höher als jede Textübereinstimmung. Zwei Dutzend typische Wendungen («файлы», «товары», «клиенты», «сотрудники», «задачи») sind eingebaut und funktionieren sofort; wenn es das Objekt in der Konfiguration nicht gibt, wird der Alias nicht angewendet. Eigene werden mit Bindung an die Konfiguration hinzugefügt:
python3 -m mcp1c.cli dict-alias "справочник физлиц" \
Справочник.ФизическиеЛица Справочник.Пользователи \
--config РозницаДляКазахстана«справочник физлиц»
Справочник.ФизическиеЛица псевдоним из словаря
Справочник.Пользователи псевдоним из словаряDie Existenz der Objekte wird beim Hinzufügen geprüft — ein Alias für einen Tippfehler ist nutzlos. Inhalt ansehen: dict-show, löschen: dict-alias «фраза» --remove.
Änderungen werden durch Neustart des Containers oder POST /admin/reload angewendet — das Image muss nicht neu gebaut werden.
Suchschlüssel der Abfragesprache — der dritte Mechanismus, und er wird nur im Code gepflegt (search_keys.py, in git mit Review). Die Kluft ist hier anderer Natur: Der Mensch nennt die Konstruktion nicht mit einem fremden Wort, sondern beschreibt die Aufgabe. «Количество дней между двумя датами» gegen РАЗНОСТЬДАТ, «убрать повторы» gegen РАЗЛИЧНЫЕ — gemeinsame Wörter null, und ein Synonym hilft nicht, es gibt nichts zu ersetzen.
Deshalb sind 116 von 127 Seiten Formulierungen zugeordnet, mit denen man danach fragt, und sie gelangen als eigenes Feld in den Suchindex. Zur Laufzeit wiegen sie nichts. Ergebnis auf einem lebenden Satz: 57,9 % → 94,7 % auf dem ersten Platz, ohne Regression bei 61 000 automatischen Anfragen.
Die Schlüssel sind von uns erdacht, nicht exportiert, und daraus ergeben sich drei Einschränkungen:
sie leben als eigene Schicht in git, nicht als Zuschreibung an das verarbeitete Element;
sie 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 Treffen des richtigen Artikels;
sie sind über die ID an Seiten gebunden, und wenn die Hilfe einen anderen Seitensatz liefert, wird die Abweichung beim Laden genannt, nicht stillschweigend durch eine gesunkene Suche sichtbar.
Die ganze 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 kann es gar nicht geben — der Server arbeitet dabei, wenn mindestens eine Hilfe geladen ist: search_syntax und get_syntax antworten, config muss nicht angegeben werden. reg-list zählt in diesem Fall das Angeschlossene auf und liefert 0:
Конфигурации не загружены. Подключено:
язык запросов, 127 страниц
Работают search_syntax и get_syntax, без фильтра по версии.Bei einem völlig leeren Register — «Ничего не загружено.» und Rückgabecode 1. Jeder Befehl, der eine Konfiguration braucht, sagt dort auch, was genau fehlt und womit jedes beschafft wird.
Debugging ohne Agenten — mcp1c.cli
Die CLI geht in dasselbe Register und dieselben Funktionen wie die MCP-Werkzeuge. Wenn sie richtig antwortet, liegt es an der Client-Einrichtung, nicht am Server.
Die Befehle teilen sich in drei Gruppen. Zum 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 5reg-search ohne --syntax sucht in den Metadaten, mit ihm — in der Hilfe und der Abfragesprache.
Direkt über die Datei, ohne Register — den Export ansehen, bevor er zum Server fährt:
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 10Der Pfad ist eine ZIP oder ein entpacktes Verzeichnis, das Format wird über das Manifest bestimmt.
Suchwörterbuch — Synonyme allgemein, Aliase 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 "справочник физлиц" --removedict-show zeigt die Herkunft jeder Regel — damit beginnt die Analyse «warum sich die Suche so verhält».
Messung der Suchqualität — mcp1c.bench
Ein eigener Prüfstand, weil «besser geworden» ohne Zahlen eine Meinung ist.
PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
--data data --config РозницаДляКазахстана \
--auto --sets query-language,roznica-metadata --check-notesSchlüssel | Was es tut |
| manuelle Sätze aus |
| automatische Sätze nach der Hilfe: exakte Namen und gleichnamige |
| Konfiguration; Pflicht, wenn mehrere geladen sind |
| Tiefe der Ausgabe, standardmäßig 10 |
| Lauf für den Vergleich aufzeichnen; nach Vereinbarung |
| mit dem früheren Lauf vergleichen — nennt namentlich, wer den Platz gewechselt hat |
| die Notizen im Satz mit dem Platz abgleichen, den die Anfrage belegt hat |
Druckt P@1/P@3/P@5/P@10, MRR, den Anteil «fremde Domäne zuerst» und den medianen Abstand des ersten Ergebnisses vom zweiten. Schwellen in assert gibt es bewusst nicht: Anfragesätze sind keine Tests, Prozente würden bei jeder Wörterbuchänderung brechen. Ein von null verschiedener Rückgabecode kommt nur bei einer Abweichung der Notizen vor — das ist keine Suchqualität, sondern eine Lüge in der Datei.
Der Vergleich zweier Läufe sieht so aus (Verschlechterungen zuerst):
=== сравнение с прошлым прогоном ===
- «как прибавить месяц к дате в запросе»: 1 -> промах
- «как отсортировать результат запроса»: 1 -> 5
+ «в чем разница между внутренним и левым соединением»: 5 -> 4Die Sätze gehören nicht ins Image (tests/ in .dockerignore) — aus der Arbeitskopie ausführen, nicht aus dem Container.
Server von Hand — 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--transport sse gibt es im Code und funktioniert, ist aber nicht nach außen geführt: Das SDK hebt einen Transport pro Prozess an, und der ganze Zustand liegt bei uns im Speicher — ein zweiter Transport würde ungefähr so viel kosten wie der erste. SSE selbst ist in MCP zugunsten von streamable-http für veraltet erklärt.
Woher die Quelldaten kommen
Struktur der Konfiguration — durch eine Verarbeitung aus exporter-1c/. Vier Modulvarianten für die normale und die verwaltete Form, XML und JSON; die XML-Varianten sind mit 8.3.5 kompatibel. Zwei Verarbeitungen liegen bereits gebaut vor und öffnen sich wie sie sind: ВыгрузкаСтруктурыКонфигурации_ОбычнаяФорма_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 — die Datei shcntx_ru.hbk aus dem Installationsverzeichnis von 1C:
/opt/1cv8/<версия>/shcntx_ru.hbk
C:\Program Files\1cv8\<версия>\bin\shcntx_ru.hbkDer Name muss vollständig übereinstimmen. Im selben Verzeichnis liegen Hunderte von .hbk-Dateien — 38 verschiedene Hilfen, jede in zwei Dutzend Sprachen. Ähnliche zum gewünschten:
Datei | Was das ist | Warum nicht geeignet |
| dieselbe Hilfe, sprachunabhängiger Teil | 25 508 Elemente, aber keinerlei Beschreibung: nur Seitenbaum und englische Bezeichner, ohne Einführungsversionen |
| Beschreibung der eingebauten Sprache | überhaupt kein 1С-Container |
| Abfragesprache | dasselbe |
| Konfigurator-Hilfe | Container, aber keine Syntaxassistent-Seiten darin |
| Benutzerhandbuch | kein Container |
Anhand der Größe sind sie nicht zu unterscheiden: shcntx_root.hbk wiegt 33 MB gegenüber 39 MB beim richtigen. Das Suffix _ru ist die Sprache, _root der gemeinsame Teil ohne Texte.
Ist die Datei falsch, erklärt der Server genau, warum, und lässt die bisherige Hilfe an ihrer Stelle.
Es genügt eine Hilfe von der neuesten verfügbaren Plattform: Jedes Element trägt die Einführungsversion, und für alte Konfigurationen wird Überflüssiges herausgefiltert. Wenn die Version nicht im Pfad steht, wird sie aus den Daten selbst abgeleitet.
Hilfen von alten Plattformen werden ebenfalls akzeptiert – sie sind anders ausgezeichnet (Abschnitte in div statt p), das ist berücksichtigt. Das ist nützlich, wenn man einen separaten Server für alte Installationen aufsetzt: Die Hilfe von 8.3.5 liefert 18 936 Elemente und enthält kein СтрНайти, СтрРазделить, ЗаписьJSON – die gab es in 8.3.5 auch nicht. Aber eine solche Hilfe gibt ihre Version nicht preis: Es gibt darin keine Vermerke „ab Version“, weil damals alles aktuell war. Deshalb wird die Version aus dem Datei- oder Verzeichnisnamen übernommen – 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 кэш поисковых индексов, расходный
store.py чтение и запись разобранных справок
render.py markdown-карточки объектов и элементов
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 desselben Schemas; der Lader führt beide auf dasselbe Wörterbuch zurück. Verifiziert: Beide Exporte ergeben denselben Satz von 30 Schlüsseln.
Den Graphen baut der Lader, nicht 1С. Kanten werden aus Attributtypen, Dokumentbewegungen, Eingabegrundlagen, Besitzern, Abonnement-Handlern und Methoden geplanter Aufgaben abgeleitet. Die Regeln lassen sich ändern, ohne neu zu laden.
Schwache Kanten. Attribute 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.
Detaillierungsgrade. Die vollständige Beschreibung von Документ.ЧекККМ (50 Attribute, 17 Tabellenteile) frisst den gesamten Kontext. brief – ein paar Zeilen, fields – die Zusammensetzung, full – mit Beziehungen.
Ohne externe Datenbanken. Fünf Konfigurationen samt Hilfe werden im Speicher eines einzigen Prozesses gehalten – 628 MB, Laden von der Platte 9,4 s. Elasticsearch, Vektorspeicher und Graphdatenbank wurden geprüft und mit Zahlen abgelehnt: die Analyse steht in docs/TASKBOARD.md, Abschnitt „Zurückgestellt“. Kurz: Eine halbe Million Dokumente ist für ES zu wenig, und der ganze Preis des Vektors liegt nicht im Speicher, sondern im Encoder-Modell zur Laufzeit (+185–620 MB zum Image wegen torch, Anfragekodierung 16–32 ms gegenüber aktuellen 0,18–1,4 ms für die gesamte Suche).
Gemessen an realen Daten – 2026-08-18
Was auf dem Arbeitsserver geladen ist:
Konfiguration | Plattform | Objekte | Kanten |
Бухгалтерия для Казахстана | 8.3.27.1936 | 3 492 | 84 426 |
Документооборот КОРП | 8.3.27.1936 | 4 596 | 50 554 |
Зарплата и управление персоналом | 8.3.27.1936 | 5 181 | 100 136 |
Розница для Казахстана | 8.3.23.1997 | 5 637 | 58 345 |
Ювелирный торговый дом | 8.3.5.1570 | 1 616 | 29 288 |
Gesamt | 20 522 | 322 749 |
Dazu die Plattform-Hilfe – ein zusammengeführter Index von drei Versionen (8.3.5, 8.3.23, 8.3.27), 25 691 Element, und die Abfragesprache – 127 Seiten als separate Quelle.
Start aus dem Cache – 9,4 s bei all dem. Der erste Start dauert länger: Die Quellen werden geparst, Indizes werden aufgebaut und in data/index/cache/ (12 MB) abgelegt, die geparsten Hilfen in data/index/syntax/ (11 MB). Danach werden sie von dort geladen.
Der Cache ist abgeleitet und entbehrlich: Er ist an die Python-Version, den Code-Fingerabdruck des Pakets und den Hash der Quelle gebunden. Wenn etwas nicht übereinstimmt, werden die Indizes neu aufgebaut. Das Verzeichnis kann jederzeit gelöscht werden; es wird von selbst wiederhergestellt.
Der Speicher des laufenden Containers beträgt 628 MB. Die Index-Postings liegen als numpy-Arrays vor; die Befüllung bleibt wörterbuchbasiert und wird sofort nach dem Einfrieren freigegeben. Das Image ist 354 MB.
Modultexte – Erkundung, Provider gibt es noch nicht
Der Provider modules ist nicht umgesetzt, der Server liefert keine Code-Werkzeuge. Die Kosten wurden vorab gemessen, am Datei-Export von „Розница“ 2.3.10.5 (2 063 MB, 33 188 Dateien, 7 878 Module, 136 909 Prozeduren):
Ebene | Auf der Platte | Im Speicher |
Signaturen und Adressen der Prozeduren | 18,1 MB | 65 MB |
Suche über alle Prozeduren | — | 473 MB |
Suche nur über exportierte (49 068) | — | 156 MB |
Formulare: 3 194 Dateien, 69 769 Elemente | 5,8 MB | 44 MB |
Die Suchlatenz beträgt 0,4–1,2 ms. Das Parsen des Korpus dauert 7–10 s.
Es gibt zwei verschiedene Datei-Exporte, und der zweite wurde separat gemessen – „Ювелирный торговый дом“ 10.5.1.3 auf 8.3.5: flache Ablage, 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. Dieses Format enthält keine Formularstrukturen, und ein Teil der allgemeinen Module ist kompiliert mitgeliefert – Quelltext ist darin gar nicht vorhanden.
Die Messskripte liegen in tools/lab/, sie sind explorativ und werden weggeworfen, sobald der echte Provider erscheint. Bis dahin wird mit ihnen jede der obigen Zahlen reproduziert:
python3 tools/lab/measure_modules.py <каталог выгрузки в файлы>
python3 tools/lab/measure_resident.py <каталог> <файл индекса> собрать
python3 tools/lab/measure_search.py <файл индекса> [экспортные]
python3 tools/lab/measure_forms.py <каталог>
python3 tools/lab/measure_flat.py <каталог плоской выгрузки>Die vollständige Analyse – einschließlich des Aufbaus von Konfigurationserweiterungen – docs/modules-and-extensions-2026-08-18.md.
Suchqualität
Wird auf dem Benchmark gemessen und mit einem einzigen Befehl reproduziert:
PYTHONPATH=src .venv/bin/python -m mcp1c.bench \
--data data --config РозницаДляКазахстана \
--auto --sets query-language,roznica-metadata --check-notesDatensatz | Anfragen | P@1 | P@3 | P@5 | MRR | Abstand |
Abfragesprache | 19 | 94,7% | 94,7% | 100% | 0,958 | 35,0% |
Metadaten von Розница | 21 | 90,5% | 95,2% | 95,2% | 0,934 | 94,0% |
Exakte Hilfenamen | 50 926 | 97,1% | 98,3% | 98,7% | 0,978 | 91,7% |
Gleichnamige | 10 544 | 98,8% | 99,8% | 99,9% | 0,993 | 93,8% |
Die ersten beiden Datensätze sind manuell erstellt, aus echten Fehltreffern. Die letzten beiden werden aus den Daten selbst erzeugt: der Name eines Elements als Anfrage, derselbe Name als erwartete Antwort.
„Abstand“ – wie weit das erste Ergebnis vom zweiten entfernt ist, im Median. Er beantwortet die Frage „sicher getroffen oder durch Zufall“: 35 % bei der Abfragesprache gegenüber 91,7 % bei der Hilfe bedeutet, dass diese Erfolge dreimal schwächer stehen und eine Änderung des Rankings sie umdrehen kann, ohne auch nur ein Prozent P@1 zu verschieben.
Die Suchlatenz beträgt 0,18–1,4 ms pro Anfrage, je nach Datensatz.
Die Anfragesä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 # 371 тест, ~2 сSie hängen nicht vom Inhalt von data/ ab: Es gibt keine proprietären Exporte im Repository, alles Nötige wird synthetisch in tests/conftest.py erzeugt.
Die Suchqualität wird durch Tests nicht geprüft – sie wird mit dem Benchmark gemessen (mcp1c.bench, siehe „Gemessen“). Prozentuale Schwellen würden bei jeder Wörterbuchänderung brechen, deshalb druckt der Benchmark Zahlen aus, 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 Zugang für alle offen, die die Adresse erreichen.
Variable | Was abgesichert wird | Nicht gesetzt |
| Lesen: MCP-Werkzeuge und Dashboard-Seiten | Struktur der Konfigurationen ist für alle offen |
| Schreiben: Laden und Entfernen von Quellen, Bearbeiten des Wörterbuchs, | diese Routen sind deaktiviert und antworten mit 404 |
Der Unterschied zwischen „offen“ und „deaktiviert“ ist beabsichtigt. Lesen ohne Token funktioniert – auf dem eigenen Rechner ist das bequem und ungefährlich. Schreiben ohne Token funktioniert überhaupt nicht: Eine einzige fehlgeschlagene Wörterbuchänderung zerstört still die Suche für alle, die mit dem gemeinsamen Server verbunden sind.
Das Token wird per Header übertragen – entweder X-Api-Token oder Authorization: Bearer <токен>. Der Admin-Token taugt auch zum Lesen: Sonst müsste der Besitzer zwei Header im Client halten statt einem.
Das Token muss lateinische Zeichen enthalten. 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 (dort läuft der Healthcheck des Containers, und er gibt keine Informationen über das Leserecht hinaus) und /login – sonst stünde das Anmeldeformular hinter genau der Autorisierung, die es ausstellt.
Zwei weitere Regeln, die nichts mit Tokens zu tun haben:
Der MCP-Endpunkt gibt die Struktur der Konfigurationen vollständig heraus. Setzen Sie
API_TOKEN, sobald Sie über die eigene Maschine hinausgehen; Netzwerkzugriff allein reicht nicht.Das Verzeichnis
data/steht vollständig in.gitignore– sowohl.hbk-Dateien mit Exporten als auch die geparsten Indizes. Der Hilfeindex ist derselbe Inhalt der Firma „1С“, nur entpackt. Einmal ist er dort gelandet und blieb 20 Commits liegen; die Geschichte wurde mitgit filter-repoumgeschrieben, und die Regel wurde nach Verzeichnis statt nach Erweiterungen formuliert: Man muss nicht prüfen „ist das eine.hbk?“, sondern „liegt das indata/?“.
7. Dokumente
Datei | Inhalt |
Regeln für die Arbeit am Projekt | |
Was gemacht wurde und was über 1С herausgefunden wurde | |
Pläne, Prioritäten und abgelehnte Vorschläge mit Gründen | |
Vertrag für das Exportformat | |
Was wir aus welcher Quelle beziehen | |
Aufbau der Quelle der Abfragesprache | |
Aufbau des Dashboards | |
Überblick über Alternativen und was daraus übernommen wurde | |
Exportverarbeitung für 1С |
Der Abschnitt „Zurückgestellt“ im Aufgabenboard – abgelehnte Vorschläge mit Zahlen: externe Datenbank, Vektoren, Graphdatenbank, SSE nach außen, Lazy Loading. Bevor man so etwas erneut vorschlägt, sollte man das lesen: Solche Entscheidungen werden durch neue Messungen aufgehoben, nicht durch neue Überlegungen.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Get up-to-date, version-specific documentation and code examples from official sources directly in…
RU INN/OGRN, banks, geo, WHOIS. Agent self-registers via register_agent. 20 free/day.
RedM / RDR3 docs MCP server: native lookups, semantic search, VORP, RSGCore, oxmysql.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/AzeevAN/mcp-1c'
If you have feedback or need assistance with the MCP directory API, please join our Discord server