Skip to main content
Glama

1C 구성 구조 MCP 서버

여러 1C 구성의 메타데이터, 플랫폼 구문 및 쿼리 언어에 대한 참조 — BSL로 코드를 작성하는 에이전트용. 최소한으로 충분한 정보를 제공: 사람의 표현을 정확한 객체 이름으로 해석, 필요한 세부 수준에서의 객체 구조, 객체의 연결 관계, 특정 구성 버전을 고려한 플랫폼 메서드 설명 및 쿼리 언어 구문.

프로젝트 소스에 대한 grep을 대체하지 않음: 코드는 파일에 존재하며, 서버는 구성에 대한 느리게 변화하는 지식을 담당. 경계는 docs/data-sources.md에 명시됨.

상태 — 2026-08-18 기준

단계

상태

1C 언로드 처리

✅ 20종 메타데이터, 8.3.5 및 8.3.23, XML 및 JSON

언로드 형식

schema v1

로더, 모델, 연결 그래프, 렌더

✅ 5개 구성, 20 522개 객체, 322천 개 엣지

플랫폼 도움말

✅ 세 버전 병합 인덱스, 25 691개 요소, since/until 경계

쿼리 언어

shquery_ru.hbk, 127페이지, 버전 없는 별도 소스

검색

✅ 97.1% 도움말, 94.7% 쿼리 언어, 90.5% 메타데이터 — «측정 결과» 참조

레지스터 가상 테이블

✅ 준비된 쿼리 필드 이름 (КоличествоОстаток)

구형 플랫폼 대체 테이블

✅ 사용 불가능한 것을 단순히 금지하는 것이 아니라 레시피로 대체

소스 레지스트리, 버전 매핑

MCP 서버, 7개 도구

✅ streamable-http 및 stdio

Docker

✅ 단일 컨테이너, 354MB

검색 인덱스 캐시

✅ 12MB, 재파싱 대신 로드

측정 스탠드

python -m mcp1c.bench, P@k, MRR, 격차, 표시 검증

테스트

pytest, 371

대시보드

✅ 레지스트리, 소스, 쿼리 실행, 연결 그래프, 카드, 사전

인증

✅ 읽기용 API_TOKEN, 쓰기용 ADMIN_TOKEN

.cf 모듈 인덱스

목차

  1. 실행 — Docker, 대시보드, 연결 그래프, Docker 없이

  2. 에이전트 연결MCP 작동 방식, 연결되지 않는 경우, 토큰, 클라이언트 구성: Claude Code, Codex CLI, Cursor, VS Code, Qwen Code, stdio

  3. 도구호출 순서, 소스, 쿼리 언어, 플랫폼 버전, 도움말 병합, 대체

  4. 데이터 관리 — 소스, 사전 및 검색 키, CLI, 측정 스탠드, 수동 서버, 데이터 출처

  5. 구조 — 모듈, 측정, 테스트

  6. 보안 — 토큰, 토큰 없이 공개되는 것

  7. 문서


1. 실행

Docker (기본 방법)

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

플랫폼 도움말과 쿼리 언어는 서로 다른 소스이자 서로 다른 필드: syntax_loaded는 전자에만 해당하고, syntax는 로드된 도움말 버전을 나열. 구성 이름과 도움말 버전은 읽기 검증을 통과한 요청에만 제공되며, 토큰 없이는 status, 카운터 및 두 플래그만 남음.

data/bootstrap/에 있는 모든 것은 시작 시 인덱싱됨: *.zip — 구성 언로드, *.hbk — 플랫폼 도움말. 동일한 파일은 다시 파싱되지 않음: 해시로 검증.

./data 디렉토리는 컨테이너에 /data로 마운트됨. 그 안에서 서버는 소스, 인덱스, 캐시 및 registry.json을 유지하며, 레지스트리의 경로는 상대적이므로 디렉토리를 개발자 머신과 컨테이너 사이에서 이동할 수 있음.

data/는 완전히 git 밖 — 볼륨이지 저장소의 일부가 아님. 디렉토리 복사로 이동. 따라서 클론 후 도움말을 직접 넣어야 함: 저장소는 이를 포함하지 않으며 포함할 수도 없음 — 1C 회사의 콘텐츠이기 때문.

코드 변경 후 컨테이너는 재시작이 아니라 재생성해야 함:

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

restart는 이전 이미지로 이전 컨테이너를 올리므로 수정 사항이 적용되지 않음.

포트에 대해. 외부로는 5001로 노출되고, 컨테이너 내부에서는 8000을 수신 — docker-compose.yml5001:8000 포트 포워딩. 이 파일의 모든 주소는 외부 주소, 즉 5001. 다른 서비스가 사용 중이면 포워딩의 왼쪽 부분을 변경하고 오른쪽은 건드리지 말 것: EXPOSE와 이미지의 healthcheck가 오른쪽에 연결되어 있음.

대시보드

http://localhost:5001/ — 여섯 페이지:

페이지

내용

개요

로드된 것: 객체, 연결, 플랫폼 버전, 매니페스트의 경고

소스

로드된 목록, .zip.hk 로드, 삭제

쿼리

평가 및 순위 이유가 포함된 표현 목록 실행

연결

객체 주변 그래프를 그림으로

카드

객체 구성 또는 플랫폼 요소 설명 — 에이전트가 보는 것과 동일

사전

출처가 있는 규칙; 별칭 또는 동의어 그룹 생성

연결 — 객체 그래프

/graph는 객체 주변을 그림: 종류별 색상, 링크 방향별 화살표, 호버 시 엣지 레이블. 노드 클릭 시 그 주변 그래프를 그리고, 드래그로 이동, 휠로 확대/축소. 이웃 한도는 페이지에서 선택(15…400), 잘림은 숫자로 표시 — «102개 중 30개 표시».

«건드리면 무엇이 깨지는가»에 답: 주황색 문서들로 둘러싸인 레지스터는 누가 그것을 움직이는지 즉시 알려줌.

깊이는 항상 한 단계. 자주 쓰이는 참고서에서 두 단계면 천 개 객체, 세 단계면 구성의 1/3; 그 이상은 추가 속성 같은 공통 메커니즘을 통해 연결되는데, 이는 거의 모든 것을 모든 것과 연결함. 연결 수 임계값으로 잘라낼 수 없음: 그런 노드는 34개인 반면, 의미 있는 Справочник.Пользователи는 323개. 따라서 노드를 펼치는 것은 휴리스틱이 아니라 사람 — 어디로 가지 말아야 할지 볼 수 있음.

에이전트에게는 의도적으로 그러한 도구가 없음. 분석 및 반환 조건은 docs/TASKBOARD.md의 «연기됨» 섹션에 있음.

빗나감은 브라우저를 벗어나지 않고 해결: 쿼리 페이지의 각 문구에 «아님 — 별칭 만들기» 링크가 있으며, 이미 문구가 채워진 사전으로 연결. 수정은 즉시 적용 — 인덱스를 다시 빌드하거나 재시작할 필요 없음.

읽기는 API_TOKEN으로, 쓰기는 ADMIN_TOKEN으로 보호. API_TOKEN이 설정되지 않은 동안에는 주소에 접근할 수 있는 사람은 누구나 읽을 수 있음 — 구성 구조와 수정 사항 포함. localhost에서는 허용 가능하지만, 네트워크의 서버에서는 그렇지 않음.

토큰이 분리된 이유는 읽기 토큰이 각 MCP 클라이언트의 구성에 있어 함께 유출되기 때문; 에이전트에게 소스를 삭제할 권한이 있어서는 안 됨. 관리자 토큰은 읽기 토큰으로도 사용 가능 — 두 개의 헤더를 유지할 필요 없음.

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

ASCII만: HTTP 헤더는 latin-1로 인코딩되므로 키릴 문자는 전달되지 않음. /health는 healthcheck를 위해 열려 있지만, 구성 이름은 토큰이 있을 때만 제공.

로드, 삭제 및 사전 편집은 ADMIN_TOKEN 필요/admin/reload와 동일한 것; 그것 없이는 해당 핸들이 «닫혀 있는» 것이 아니라 존재하지 않음. 토큰은 폼에 한 번 입력되며, 브라우저로 전송되는 것은 토큰이 아니라 세션 식별자.

.env를 통해 docker-compose.yml 옆에 설정 — 모든 변수가 있는 템플릿은 .env.example에 있음:

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

결과의 이름은 카드 링크: 객체는 유형이 있는 속성, 테이블 부분 및 이동, 플랫폼 요소는 시그니처, 매개변수, 가용성 및 등장 버전. 에이전트가 받는 동일한 텍스트에 brief / fields / full 토글 포함. 속성에는 자체 카드가 없음 — 링크는 소유 객체로 연결.

«쿼리» 페이지는 «서버가 왜 이것을 반환했는가»에 답: 각 적중 옆에 이유가 있음 — 정확한 일치, 사전의 별칭, 쿼리의 모든 단어. 이를 통해 빗나감을 무엇으로 치료할지 알 수 있음 — 동의어, 별칭 또는 가중치.

도움말 파싱은 몇 초 걸림: 페이지는 파싱 후 응답하지만 MCP 클라이언트는 지연되지 않음 — 인덱싱은 별도 스레드로 진행.

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 5001

2. 에이전트 연결

서버는 공식 SDK의 표준 전송으로 MCP 프로토콜을 구현하므로 모든 MCP 클라이언트에 적합. HTTP 주변의 래퍼는 필요 없음.

전송

시기

주소

streamable-http

Docker 또는 별도 머신의 서버

http://주소:5001/mcp

stdio

클라이언트가 로컬에서 프로세스를 직접 실행

sse

구형 클라이언트 전용

--transport sse

두 주요 전송 모두 공식 MCP 클라이언트로 검증됨: 핸드셰이크 initialize, tools/list, tools/call, 프로토콜 2025-11-25.

작동 방식

무언가 연결되지 않기 전에 이해하는 것이 유용함. 주소는 하나 — /mcp, 도구별 핸들은 없음; 어떤 도구가 호출되는지는 경로가 아니라 요청 본문에 기록됨.

그 다음은 두 가지 다른 메커니즘이며 혼동해서는 안 됨:

도구 설명

데이터

시기

연결 시 한 번

호출마다

시작 주체

클라이언트, 모델 없이 직접

모델, 결정에 따라

메서드

POST initialize, 그 다음 POST tools/list

POST tools/call

전달 대상

모델의 시스템 프롬프트

대화 본문

비용

일회성, 전체 세션 동안 유지

호출마다

연결 시 클라이언트는 POST initialize를 수행 — 서버는 이름, 버전 및 instructions 텍스트로 응답하고, 헤더에 mcp-session-id를 반환. 그 다음 POST tools/list는 도구를 한 번에 제공: 이름, 설명, 매개변수 JSON 스키마. 이 모든 것은 사람이 첫 단어를 입력하기 전에 모델 컨텍스트에 들어감. 모델은 필요할 때 설명을 가져오지 않음 — 이미 가지고 있음.

따라서 설명을 수정할 때 중요한 결과: 설명은 모델이 도구를 하나도 호출하지 않더라도 전체 세션 동안 창 공간을 차지함.

도구는 무엇이 로드되었든 항상 일곱 개입니다. 세트는 변수가 아니라 계약입니다. 도구들은 서로 연결되어 있고, 작업 서버에는 세 가지 소스(구성, 플랫폼 도움말, 쿼리 언어)가 모두 로드되어 있습니다. tools/list 계약에 instructions를 더하면 약 3,900 토큰이며, 이 숫자는 레지스트리 상태와 무관합니다.

여기서 미리 알아야 할 직접적인 결과가 나옵니다: 소스가 로드되지 않아도 해당 도구에 대한 비용은 지불합니다. 플랫폼 도움말이 없으면 search_syntaxget_syntax가 컨텍스트에 남아 1,185 토큰을 소모하며 "도움말이 연결되지 않았습니다"라고 응답합니다. 구성이 하나뿐일 때 compare_configurations는 "최소 두 개가 필요합니다"라는 응답을 위해 262 토큰을 소모합니다. 이는 도구를 선별하는 것이 아니라 소스를 로드하여 해결합니다. 선별은 2026-08-19에 시도했다가 취소되었습니다. 자세한 내용과 수치는 「보류됨」에 있습니다.

따라서 설명은 밀도 있게 작성되고, 세부 사항은 도구 자체의 출력으로 이동합니다. 출력에 대한 비용은 필요할 때만 지불되기 때문입니다.

GET /mcp는 "잘못된 POST"가 아니라 같은 주소의 세 번째 메서드입니다. 서버에서 클라이언트로의 메시지 스트림을 열며, 이미 받은 mcp-session-id가 필요합니다. DELETE /mcp는 세션을 닫습니다.

클라이언트가 연결되지 않는 경우

로그(docker logs -f mcp1c)의 응답 코드가 원인을 알려줍니다:

코드

문제

406

클라이언트가 Accept: application/json, text/event-stream을 보내지 않음 — 두 유형 모두 필요

400 Missing session ID

클라이언트가 initialize에서 받은 mcp-session-id 헤더를 반환하지 않음

GET /mcp에서 400

클라이언트가 GET으로 핸드셰이크를 시작함 — 이전 HTTP+SSE 전송을 사용하며, 이 주소는 streamable-http임

/sse에서 404

동일한 문제: 이전 전송은 외부로 노출되지 않음

401

API_TOKEN이 설정된 경우 X-Api-Token이 전달되지 않음

로그가 비어 있음

클라이언트가 요청을 전혀 보내지 않음 — 서버에 도달하기 전에 클라이언트 구성 문제

실제 사례: Qwen Code는 구성에 url 키가 있어서 연결되지 않았습니다. Gemini CLI 계열(Qwen은 형식을 상속)에서 이는 이전 SSE 전송을 의미하며, 클라이언트는 GET으로 시작하여 400을 받았습니다. httpUrl — 즉 streamable-http — 을 사용하면 연결이 즉시 성공합니다.

토큰: 클라이언트 설정에 추가할 내용

서버에 API_TOKEN이 설정된 경우, 각 클라이언트는 헤더로 이를 보내야 합니다. 헤더가 없으면 /mcp401로 응답하고, 에이전트는 도구를 볼 수 없습니다.

두 헤더 중 아무거나 사용 가능합니다 — 서버는 둘 다 수락합니다:

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

자주 걸려 넘어지는 세 가지:

  • ASCII만. HTTP 헤더는 latin-1로 인코딩되며, 키릴 문자 토큰은 통과할 수 없습니다. 생성 방법: python3 -c "import secrets; print(secrets.token_urlsafe(32))".

  • 클라이언트에는 API_TOKEN을 넣고, ADMIN_TOKEN이 아닙니다. 관리자 토큰도 수락되지만, 클라이언트 구성은 git과 백업에 들어갑니다: 유출된 읽기 토큰은 조회 권한을 주고, 유출된 관리자 토큰은 소스 삭제 권한을 줍니다.

  • stdio는 토큰이 전혀 필요 없습니다. 클라이언트가 프로세스를 직접 실행하므로 네트워크가 관여하지 않아 확인할 것이 없습니다. 클라이언트가 헤더를 설정할 수 없다면 이것이 실용적인 해결 방법입니다.

클라이언트를 설정하기 전에 서버가 토큰을 인식하는지 확인:

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 — 토큰이 수락됨. 401 — 토큰이 틀리거나 헤더가 도달하지 않음.

비밀을 커밋하지 않는 방법

.mcp.json 및 유사한 파일은 일반적으로 저장소에 있습니다. 옵션:

  1. 변수 대체 — 클라이언트가 지원하는 경우(Claude Code는 지원): "X-Api-Token": "${MCP1C_API_TOKEN}", 변수 자체는 ~/.zshrc에. git에는 변수 이름만 들어가고 값은 들어가지 않습니다.

  2. 파일을 git 관리에서 제외: git rm --cached .mcp.json && echo ".mcp.json" >> .gitignore.

  3. 설정을 프로젝트가 아닌 클라이언트의 사용자 구성에 유지 — 그러면 저장소와 전혀 무관합니다.

Claude Code

프로젝트 루트의 .mcp.json 파일:

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

headers 블록은 서버에 API_TOKEN이 설정된 경우에만 필요합니다. 값은 환경 변수에서 가져오므로 파일을 저장소에 유지할 수 있습니다:

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

또는 명령으로:

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

Codex CLI

~/.codex/config.toml 또는 프로젝트의 .codex/config.toml:

[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 — 여기서 키 이름은 servers입니다:

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

Qwen Code

Gemini CLI 형식이며, 키가 전송 방식을 선택합니다 — 이것이 유일한 주의 사항입니다:

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

httpUrl — streamable-http, 우리의 경우입니다. 이 형식의 url은 이전 SSE 전송을 의미합니다: 클라이언트는 GET /mcp로 핸드셰이크를 시작하고 400 Missing session ID를 받아 연결되지 않습니다.

기타 클라이언트

Windsurf, Antigravity, Cline, Roo Code, 콘솔 에이전트 — 기록 형식은 동일합니다: 전송 유형, URL, 그리고 API_TOKEN이 설정된 경우 헤더 블록. 차이는 파일 이름과 최상위 키(mcpServers 또는 servers)뿐입니다 — 특정 클라이언트의 문서를 확인하세요.

클라이언트가 헤더를 설정할 수 없다면 막다른 길이 아닙니다: stdio로 연결하세요. 네트워크가 없으므로 토큰이 필요 없습니다.

stdio를 통한 로컬 실행

클라이언트가 서버를 직접 시작해야 하는 경우. 여기서 토큰은 필요 없습니다: 프로세스는 클라이언트가 시작하고, 통신은 네트워크가 아닌 프로세스 채널을 통해 이루어지므로 확인할 것도, 보호할 대상도 없습니다.

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

3. 도구

세트는 고정되어 있으며 의도적으로 작습니다: 각 도구는 에이전트의 컨텍스트에 항상 존재합니다. 새 데이터 소스는 자체 도구를 추가하는 대신 기존 도구의 응답을 풍부하게 만듭니다.

도구

용도

list_configurations

무엇이 로드되었는지, 각 구성에서 사용 가능한 공급자

search_objects(query, config, kind, limit)

인간의 표현 → 정확한 객체 이름

get_object(full_name, config, detail)

객체 구성; detail: brief / fields / full

get_related(full_name, config)

이동, 참조, 종속성 — 직접적인 것만

compare_configurations(full_name, configs)

두 구성에서의 하나의 객체

search_syntax(query, config, kind, limit)

플랫폼 도움말 및 쿼리 언어 검색

get_syntax(name, config, detail)

시그니처, 매개변수, 가용성, 버전, 이전 플랫폼용 대체

config는 둘 이상의 구성이 로드된 경우 필수입니다: 서버는 의도적으로 조용히 대체하지 않습니다 — 그렇지 않으면 에이전트가 다른 데이터베이스를 기반으로 코드를 작성하고 아무도 알 수 없기 때문입니다.

하나의 이름이 두 도메인에 동시에 존재할 수 있습니다: СтрНайти는 플랫폼(8.3.6부터)과 쿼리 언어 모두에 있습니다. 이 경우 get_syntax는 각각의 준비된 주소와 함께 동일한 이름을 나열하며, 출력의 문자열로 호출을 반복할 수 있습니다:

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

Запрос. 한정자가 필요한 이유는 쿼리 언어 요소에 소유자가 없기 때문입니다: 플랫폼 요소처럼 Объект.Член으로 지정할 수 없습니다.

호출 순서 — 그리고 위반 시 잃는 것

list_configurations → search_objects → get_object → search_syntax → get_syntax

get_object 단계는 건너뛸 수 없습니다. 검색은 이름과 카운터만 반환합니다. 코드가 의존하는 모든 것은 객체 카드에 있습니다:

  • 레지스터 유형 및 주기성. СрезПоследних는 주기적 정보 레지스터에만 있으며, 비주기적 레지스터는 603개 중 566개입니다;

  • 가상 테이블 필드의 준비된 이름. 쿼리에서 리소스 КоличествоКоличествоОстаток, КоличествоОборот, КоличествоПриход라고 합니다 — 구성 도구에서는 이러한 이름을 어디에서도 볼 수 없으며, 플랫폼이 생성합니다;

  • 하위 콘토 한도, 대응, 일정 리소스 — 이것 없이는 СубконтоДт1 유형의 필드를 지정할 수 없습니다;

  • 무제한 길이 문자열. 유형에 직접 표시됩니다: Строка (неогр. — только через ПОДСТРОКА)Строка(200). 이러한 필드는 쿼리에 그대로 넣을 수 없습니다 — 플랫폼은 비교, 그룹화, 정렬을 허용하지 않습니다. 실제 구성에서 문자열 필드의 23%~38%가 이러한 필드이므로, 이러한 필드가 있는 카드(20,522개 중 2,474개)에서는 필드 목록 앞에 해결 방법이 포함된 주의 문구가 인쇄됩니다.

search_objects 직후에 작성된 쿼리는 올바르게 보이지만 "필드를 찾을 수 없음" 오류로 실패합니다. get_object에서만 얻을 수 있는 것의 예:

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

두 번째도 동일하며, 2026-08-18의 실제 실수에서 발견되었습니다. 에이전트는 길이 제한이 없는 문자열로 쿼리를 그룹화했습니다. 데이터는 정확하게 제공했지만, 차이는 괄호 안의 숫자 부재로만 읽을 수 있었습니다:

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

## Реквизиты

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

해결 방법은 주의 문구와 필드 문자열 자체 모두에 있으며, 이는 중복이 아닙니다. 첫 번째 버전은 주의 문구를 카드의 마지막 단락으로 인쇄했습니다. 2026-08-18의 실제 에이전트는 detail=fieldsget_object를 호출하여 전체를 받았지만 — 여전히 해당 필드로 그룹화했습니다. 주의 문구는 필드 문자열보다 721 토큰 뒤에 있었고, 결정은 이름을 복사하는 지점에서 이루어집니다. 동일한 교훈이 이미 도구 설명에 기록되어 있습니다: 규칙은 정확하게 배치된 곳이 아니라 읽히는 곳에서 작동합니다.

각 금지 사항은 검증되었습니다: 집계 함수는 도움말의 인용문, 나머지 다섯 개는 오류 텍스트가 기록된 실제 데이터베이스 실행입니다. 도움말은 여섯 개의 집계 함수 중 세 개에서만 제한을 알고 있으며, 그룹화, 정렬, РАЗЛИЧНЫЕ, ОБЪЕДИНИТЬ 및 비교에 대해서는 침묵합니다 — 즉, 도움말을 성실히 읽은 에이전트는 이를 알 수 없었습니다. 출처별 분류는 docs/data-sources.md의 "카드의 주의 문구" 섹션에 있습니다.

이전 구성에서 플랫폼 함수를 호출하기 전에 — get_syntax. 사용할 수 없는 것은 표시되며, 대체 방법이 기록된 경우 그곳에 있습니다.

소스는 독립적입니다

세 가지가 있으며, 각각 별도로 연결됩니다:

소스

파일

제공 내용

없을 때

구성 메타데이터

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

객체, 속성, 연결, 이동

search_objectsget_object가 응답하지 않음

플랫폼 도움말

shcntx_ru.hbk

메서드, 속성, 시그니처, 가용성, 버전

search_syntax가 "소스가 연결되지 않음"이라고 말함

쿼리 언어

shquery_ru.hbk

ВЫБРАТЬ, ЛЕВОЕ СОЕДИНЕНИЕ, ИТОГИ ПО, РАЗНОСТЬДАТ

쿼리 언어 구문을 찾을 수 없음

로드된 것

작동하는 것

세 가지 모두

모두

구성만

메타데이터; 구문은 "소스가 연결되지 않음"이라고 응답

도움말만

버전 필터링 없는 구문, config 불필요

없음

list_configurations가 무엇을 로드할지 설명

쿼리 언어 — 별도의 소스

플랫폼 설치 디렉터리의 동일한 shquery_ru.hbk. 127페이지: 함수 52개, 키워드 67개, 기사 8개. 일반 소스로 로드되어 플랫폼 도움말과 동일한 검색 인덱스에 들어갑니다 — 별도 도구로 검색할 필요 없이 search_syntax가 둘 다 찾습니다.

파일 자체에는 버전이 없습니다 — 129페이지 모두에서 확인: "8.3.x" 및 "버전부터" 언급이 0개. 그러나 쿼리 언어는 변경됩니다: 8.3.20 릴리스는 25개의 함수를 추가했으며, 그중 СтрНайти, Лев, Прав, ВРег, НРег, СтрЗаменить, Окр, Цел 및 모든 삼각 함수가 있습니다.

버전을 가져올 곳이 없다: 쿼리 언어 함수 플랫폼 도움말은 전혀 설명하지 않는다 (ПОДСТРОКА — 25,511개 요소에서 0건 일치). 따라서 버전은 큐레이팅된 테이블 query_versions.py가 지정한다 — 1C 목록 «8.3.20 릴리스부터 쿼리 언어에 추가된 함수» 기준. 나머지 27개 함수에는 버전이 부여되지 않는다: 항상 존재했기 때문이다.

그 다음에는 일반 필터가 작동한다: 8.3.5 구성은 이 함수들을 볼 수 없고, 8.3.23 구성은 볼 수 있다.

테이블은 데이터로 검증된다 — 서로 다른 두 플랫폼의 도움말을 비교해서. 이전 도움말에 없고 새 도움말에 있는 것은 그 사이에 나타난 것이며, 여기에는 반드시 버전이 있어야 한다:

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

2026-08-19 실행, 8.3.5.1570 대 현재 버전: 29개 발견, 29개 커버, 오탐 0건. 오탐은 최악의 오류다: 이미 이전 도움말에 있던 요소가 버전으로 표시되면, 그 요소가 존재하는 구성에서 숨겨지기 때문이다.

인스턴스는 서버당 하나: 재로드 시 이전 것을 대체한다.

페이지 테이블은 표시되지만 검색되지는 않는다. 이 도움말에서 테이블 셀은 <TD> 내부의 단락으로 마크업되어 있으며, 별도 파싱 없이는 카드가 테이블을 값 열로 출력했다: «Товар / Количество / Номер / Сантехника / 104 / …» 이렇게 수십 줄이 연속으로. 이제 테이블은 별도 필드로 파싱된다 — 127개 페이지 중 31개 페이지에 51개 테이블 — 그리고 텍스트의 해당 위치에 출력된다: 두 개의 예제가 있는 페이지는 각 결과를 해당 예제 아래에 표시한다. 검색 인덱스에는 테이블 내용이 포함되지 않는다.

이 도움말의 테이블은 두 가지 서로 다른 성격이며, 다르게 파싱된다:

무엇

개수

카드에서의 모습

데이터 테이블 — 예제 쿼리의 결과

31개 페이지에 51개

markdown 테이블로

그려진 구문 다이어그램 — 구문의 문법

17개 페이지에 21개

분기 수준에 따라 들여쓰기된 계단식

CSS 클래스가 아니라 마크업으로 구분된다: class=SimplyTable가 모든 테이블에 있는 것은 아니다 — 실제 테이블 7개는 그것 없이 간다. 기준은 기하학이다: 데이터 테이블은 모든 행의 너비가 같고, 다이어그램은 너비가 들쭉날쭉하며 단일 세로선으로 된 셀이 있다 (그것은 그려진 선이지 값이 아니다).

손상된 마크업은 공개적으로 언급된다. 닫히지 않은 <TABLE>이 있는 페이지는 테이블 없이 파싱되지만 손실되지 않으며, 그 이름은 소스 경고에 들어간다: 로드 출력의 한 줄 (mcp1c.cli reg-add)과 대시보드의 «Источники» 페이지의 별도 줄로. 평소보다 빈약한 카드를 조용히 넘길 수는 없다: 그냥 없는 도움말과 구별할 수 없기 때문이다.

이름의 절반이 플랫폼 이름과 일치한다 (127개 중 57개) — ГОД, МЕСЯЦ, ПРЕДСТАВЛЕНИЕ는 양쪽 모두에 있다. 쿼리에 대한 질문이 플랫폼 메서드로 이어지지 않도록, «в запросе», «в тексте запроса», «в выборке» 같은 표현은 쿼리 언어 요소에 약한 상승을 준다. 의도적으로 약하게: 확실한 분리가 있을 때 플랫폼 요소가 첫 번째로 유지된다 — «как задать параметр в запросе»는 Запрос.УстановитьПараметр에 관한 것일 수도 있다.

config 매개변수는 둘 이상의 구성이 로드된 경우 필수다. 기본적으로 아무것도 대체되지 않는다: 조용한 선택은 에이전트가 다른 구성에 대한 코드를 작성하게 하며, 아무도 이를 알아차리지 못한다.

응답은 플랫폼 버전에 따라 달라진다

동일한 호출, 두 가지 구성:

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

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

플랫폼 8.3.5의 경우 결과에서 6,539개 요소가 제거되었고, 8.3.23의 경우 874개가 제거되었다. 경고가 아니라 필터링으로: 경고는 에이전트가 무시할 수 있지만, 결과에 없는 메서드는 무시할 수 없다.

Доступность 필드 (서버 / 씬 클라이언트 / 웹 클라이언트 / 모바일)는 반드시 읽어야 한다: 클라이언트 컨텍스트에서 서버 메서드를 호출하면 컴파일되지 않는다.

여러 버전의 도움말이 하나의 인덱스로 병합된다

오래된 구성에 대한 하나의 최신 도움말은 거짓말을 한다. 8.3.5에서 측정됨: 서버가 199개 요소를 존재하지 않는 것으로 선언하고, 117개를 잘못된 시그니처로 반환하며 (ЗаписьXML.ОткрытьФайл은 8.3.5에서 두 개의 매개변수를 받고, 8.3.27에서는 세 개), 410개를 잘못된 가용성으로 반환한다. 이 모든 것은 컴파일 오류이지 부정확함이 아니다.

따라서 서로 다른 버전의 도움말이 나란히 놓이고 sinceuntil 경계가 있는 하나의 인덱스로 병합되며, 응답은 특정 구성의 버전에 맞춰 조합된다. 도움말은 로드된 구성의 플랫폼 수만큼 필요하다 — 두 개의 극단적인 중간 버전은 대체하지 못한다.

비용은 측정되었고 작다: 세 버전의 병합은 단일 버전의 24,777개 키 대비 25,691개 키를 제공하며, 즉 1% 미만이다. 버전별 별도 컨테이너도 작동하며 비상 경로로 남아 있지만, 기본 경로로는 숫자에서 패배했다 — 버전당 300–450MB와 자체 주소가 필요하다.

서버는 어떤 도움말이 부족하고 어떤 것이 불필요한지 스스로 말한다 — list_configurations 출력에서.

금지 대신 대체

«함수가 없다»고 말하는 것은 답의 절반이다. 나머지 절반은 무엇으로 대체할지이며, 도움말에서 도출되지 않는다: 폐기 표시는 25,000개 페이지 중 15개에만 있다.

따라서 대체 테이블(replacements.py)이 있으며, 현재 6개 항목 — 8.3.6에 나타난 문자열 함수들. get_syntax는 금지 대신 레시피를 반환한다:

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

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

고지가 필수다. 대체는 거의 항상 동등하지 않으며, 비슷한 함수를 조용히 제안하는 것은 아무것도 제안하지 않는 것보다 나쁘다.

테이블은 맹목적으로가 아니라 실제 사례를 통해 채워진다: 아무도 요청하지 않은 함수에 대한 우회 방법을 만들어 내는 것은 의미가 없다.


4. 데이터 관리

소스 추가

# в 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

더 간단하게: 파일을 data/bootstrap/에 넣으면 다음 시작 시 자동으로 인식된다.

재시작 없이 변경 사항 적용

실행 중인 서버는 레지스트리를 메모리에 보관하므로 reg-add 후에는 서버를 밀어줘야 한다. 재시작(docker compose restart mcp1c, 약 2초) 또는 관리자 핸들:

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

사전: 말하는 방식 대 명명된 방식

검색의 주요 어려움은 사람의 단어와 구성의 이름 사이의 간극이다. «Заказ клиента» — 객체는 ЗаказПокупателя라고 불린다. 사전은 data/dictionary.json에 있으며, 이미지 재빌드 없이 수정할 수 있다.

두 가지 메커니즘이 있으며 서로 다르다.

단어 동의어 — 모든 구성에 공통:

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

객체 별칭 — «내가 이렇게 말하면 이 객체들을 의미한다»는 직접적인 지시로, 가중치는 모든 텍스트 일치보다 높다. 약 20개의 전형적인 문구 («файлы», «товары», «клиенты», «сотрудники», «задачи»)가 내장되어 즉시 작동한다; 구성에 객체가 없으면 별칭은 적용되지 않는다. 자체 별칭은 구성에 바인딩되어 추가된다:

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

객체 존재는 추가 시 확인된다 — 오타에 대한 별칭은 쓸모없다. 내용 보기: dict-show, 삭제: dict-alias «фраза» --remove.

변경 사항은 컨테이너 재시작 또는 POST /admin/reload로 적용된다 — 이미지를 재빌드할 필요는 없다.

쿼리 언어 검색 키 — 세 번째 메커니즘으로, 코드에서만 수정된다 (search_keys.py, git에서 리뷰 포함). 간극은 다른 성격이다: 사람은 구조를 다른 단어로 부르는 것이 아니라 작업을 설명한다. «Количество дней между двумя датами» 대 РАЗНОСТЬДАТ, «убрать повторы» 대 РАЗЛИЧНЫЕ — 공통 단어가 전혀 없고, 동의어도 도움이 되지 않으며, 대체할 것도 없다.

따라서 127개 페이지 중 116개에 사람들이 묻는 방식의 표현이 지정되어 검색 인덱스에 별도 필드로 들어간다. 런타임에는 아무것도 무게를 차지하지 않는다. 실제 데이터셋 결과: 57,9% → 94,7% 첫 번째 자리, 61,000개의 자동 쿼리에서 회귀 없음.

키는 우리가 만든 것이지 내보낸 것이 아니며, 여기서 세 가지 제약이 따른다:

  • git에서 별도 레이어로 존재하며, 파싱된 요소에 첨부되지 않는다;

  • 에이전트 응답에 포함되지 않는다 — 응답은 여전히 도움말에서만 조합되며, 키는 올바른 문서에 도달하는 데만 작동한다;

  • 식별자로 페이지에 바인딩되며, 도움말이 다른 페이지 세트를 제공하면 불일치는 로드 시 언급되고, 조용히 검색 저하로 나타나지 않는다.

전체 규칙은 docs/data-sources.md의 «Сгенерированные слои поверх источников» 섹션에 있다.

로드된 내용 보기

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

구성이 전혀 없을 수도 있다 — 이 경우 서버는 도움말이 하나라도 로드되어 있으면 작동한다: search_syntaxget_syntax가 응답하고, config를 지정할 필요가 없다. reg-list는 이 경우 연결된 것을 나열하고 0을 반환한다:

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

완전히 빈 레지스트리에서는 — «Ничего не загружено.» 및 반환 코드 1. 구성이 필요한 모든 명령은 같은 위치에서 정확히 무엇이 부족하고 각각 어떻게 해결되는지 말한다.

에이전트 없이 디버깅 — mcp1c.cli

CLI는 MCP 도구와 동일한 레지스트리와 동일한 함수에 접근한다. CLI가 올바르게 응답하면 문제는 클라이언트 설정에 있는 것이지 서버에 있는 것이 아니다.

명령은 세 그룹으로 나뉜다. 레지스트리 기준 — 에이전트가 보는 것과 동일:

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

reg-search--syntax 없이 메타데이터를 검색하고, --syntax와 함께 — 도움말과 쿼리 언어를 검색한다.

레지스트리 없이 파일 직접 — 서버로 보내기 전에 내보내기를 확인:

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

경로는 ZIP 또는 압축 해제된 디렉토리이며, 형식은 매니페스트로 결정된다.

검색 사전 — 동의어는 공통, 별칭은 구성에 바인딩:

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는 각 규칙의 출처를 보여준다 — «검색이 왜 이렇게 동작하는지» 분석의 시작점이다.

검색 품질 측정 — mcp1c.bench

별도 스탠드, «더 좋아졌다»는 숫자 없이는 의견이기 때문이다.

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

기능

--sets имя,имя

tests/queries/*.json의 수동 세트, 확장자 없이

--auto

도움말 기반 자동 세트: 정확한 이름 및 동음이의어

--config

구성; 여러 개가 로드된 경우 필수

--limit

결과 깊이, 기본값 10

--save путь

비교를 위한 실행 기록; 관례상 data/bench/ГГГГ-ММ-ДД.json

--baseline путь

이전 실행과 비교 — 누가 순위를 바꿨는지 이름을 지정

--check-notes

세트의 메모를 쿼리가 차지한 순위와 대조

P@1/P@3/P@5/P@10, MRR, «다른 도메인이 첫 번째» 비율 및 첫 번째 결과와 두 번째 결과의 중앙 간격을 출력한다. assert의 임계값은 의도적으로 없다: 쿼리 세트는 테스트가 아니며, 사전의 각 수정마다 백분율이 깨질 것이다. 0이 아닌 반환 코드는 메모 불일치에서만 발생한다 — 이것은 검색 품질이 아니라 파일의 거짓말이다.

두 실행의 비교는 다음과 같다 (악화가 먼저):

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

세트는 이미지에 포함되지 않는다 (tests/.dockerignore에 있음) — 컨테이너가 아닌 작업 복사본에서 실행해야 한다.

수동 서버 — 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는 코드에 존재하고 작동하지만 외부로 노출되지 않았다: SDK는 프로세스당 하나의 트랜스포트를 올리며, 모든 상태는 메모리에 있다 — 두 번째 트랜스포트는 첫 번째와 거의 같은 비용이 들 것이다. MCP에서 SSE 자체는 streamable-http를 위해 폐기되었다.

원본 데이터의 출처

구성 구조exporter-1c/의 처리로. 일반 및 관리형 폼, XML 및 JSON용 모듈의 네 가지 변형; XML 변형은 8.3.5와 호환된다. 두 개의 처리는 이미 빌드되어 그대로 열린다: ВыгрузкаСтруктурыКонфигурации_ОбычнаяФорма_XML.epf (8.3.5 이상) 및 ВыгрузкаСтруктурыКонфигурации_УправляемаяФорма_XML_JSON.epf (8.3.6 이상, 형식은 폼에서 선택).

플랫폼 도움말 — 1C 설치 디렉토리의 shcntx_ru.hbk 파일:

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

이름은 전체가 일치해야 한다. 같은 디렉토리에는 수백 개의 .hbk 파일이 있다 — 각각 약 20개 언어로 된 38개의 서로 다른 도움말. 원하는 것과 유사한 것:

파일

무엇인가

왜 부적합한가

shcntx_root.hbk

동일한 도움말, 언어 비의존 부분

25,508개 요소이지만 설명이 하나도 없음: 페이지 트리와 영어 식별자만 있고, 등장 버전이 없음

shlang_ru.hbk

내장 언어 설명

1C 컨테이너가 전혀 아님

shquery_ru.hbk

쿼리 언어

동일함

config_ru.hbk

구성기 도움말

컨테이너이지만 내부에 구문 도우미 페이지가 없음

1cv8_ru.hbk

사용자 가이드

컨테이너가 아님

크기로는 구분할 수 없다: shcntx_root.hbk는 33MB인 반면, 필요한 파일은 39MB다. 접미사 _ru는 언어, _root는 텍스트가 없는 공통 부분이다.

파일이 틀리면 — 서버가 그 이유를 설명하고 기존 도움말을 그대로 둔다.

가장 최신 사용 가능한 플랫폼의 도움말 하나면 충분하다: 각 요소는 등장 버전을 담고 있고, 오래된 구성의 경우 불필요한 것은 필터링된다. 버전이 경로에 없으면 데이터 자체에서 추론한다.

이전 플랫폼의 도움말도 허용된다 — 마크업이 다르고(p 대신 div로 구분), 이는 반영되어 있다. 오래된 구현을 위한 별도 서버를 구축할 때 유용하다: 8.3.5의 도움말은 18,936개 요소를 제공하며 СтрНайти, СтрРазделить, ЗаписьJSON을 포함하지 않는다 — 8.3.5에는 실제로 없었기 때문이다. 하지만 이러한 도움말은 자신의 버전을 알려주지 않는다: "버전부터" 표시가 없는데, 당시에는 모든 것이 현재형이었기 때문이다. 따라서 버전은 파일 이름이나 디렉터리에서 가져온다8.3.5.1570.hbk 또는 data/hbk/8.3.5.1570/에 넣어라. 그렇지 않으면 구성과의 매칭이 작동하지 않는다.


5. 구조

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

두 형식에 하나의 모델. XML과 JSON은 동일한 스키마의 서로 다른 직렬화이며, 로더는 둘 다 동일한 사전으로 변환한다. 검증됨: 두 내보내기 모두 동일한 30개 키 집합을 제공한다.

그래프는 1C가 아니라 로더가 구축한다. 엣지는 속성 유형, 문서 이동, 입력 근거, 소유자, 구독 핸들러, 예약 작업 메서드에서 도출된다. 규칙은 재내보내기 없이 변경할 수 있다.

약한 엣지. ЗначениеДоступа 같은 속성은 수백 가지 유형을 나열하고 거의 모든 것을 서로 연결한다. 이러한 연결은 약한 것으로 표시되고 기본적으로 숨겨진다 — 그렇지 않으면 유용한 연결이 묻혀버린다.

세부 수준. Документ.ЧекККМ의 전체 설명(속성 50개, 표 부분 17개)은 컨텍스트를 완전히 소모한다. brief는 두 줄, fields는 구성, full은 연결 포함.

외부 데이터베이스 없음. 도움말이 있는 5개 구성이 단일 프로세스 메모리에 유지된다 — 628MB, 디스크에서 로드 9.4초. Elasticsearch, 벡터 저장소, 그래프 DB가 검토되었고 수치와 함께 기각되었다 — 분석은 docs/TASKBOARD.md의 "보류" 섹션에 있다. 요약: ES에 50만 문서는 너무 적고, 벡터의 전체 비용은 저장소가 아니라 런타임의 인코더 모델에 있다(torch로 이미지에 +185–620MB, 쿼리 인코딩 16–32ms 대 현재 전체 검색 0.18–1.4ms).

실제 데이터로 측정 — 2026-08-18

작업 서버에 로드된 내용:

구성

플랫폼

객체

엣지

카자흐스탄 회계

8.3.27.1936

3,492

84,426

문서관리 KORP

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

합계

20,522

322,749

플러스 플랫폼 도움말 — 세 버전(8.3.5, 8.3.23, 8.3.27)의 병합된 인덱스, 25,691개 요소, 그리고 쿼리 언어 — 별도 소스로 127페이지.

캐시에서 시작 — 이 모든 것에 9.4초. 첫 시작은 더 오래 걸린다: 소스를 파싱하고, 인덱스를 구축하여 data/index/cache/(12MB)에 저장하고, 파싱된 도움말은 data/index/syntax/(11MB)에 저장한다. 이후에는 거기서 로드된다.

캐시는 파생적이고 소모적이다: Python 버전, 패키지 코드 지문, 소스 해시에 바인딩된다. 하나라도 일치하지 않으면 인덱스가 다시 구축된다. 디렉터리는 언제든 삭제할 수 있으며 자동으로 재생성된다.

라이브 컨테이너 메모리 — 628MB. 인덱스 포스팅은 numpy 배열로 저장되고, 채움은 사전 형태로 유지되다가 동결 직후 해제된다. 이미지 — 354MB.

모듈 텍스트 — 탐색만, 프로바이더는 아직 없음

modules 프로바이더는 만들어지지 않았고, 코드 관련 도구는 서버가 제공하지 않는다. 비용은 미리 측정되었다 — "소매" 2.3.10.5 내보내기 기준(2,063MB, 33,188개 파일, 7,878개 모듈, 136,909개 프로시저):

계층

디스크

메모리

프로시저 시그니처 및 주소

18.1MB

65MB

전체 프로시저 검색

473MB

내보낸 프로시저만 검색(49,068개)

156MB

폼: 3,194개 파일, 69,769개 요소

5.8MB

44MB

검색 지연 시간 — 0.4–1.2ms. 코퍼스 파싱 — 7–10초.

파일 내보내기는 두 가지 다른 종류가 있고, 두 번째는 별도로 측정되었다 — "보석 무역 회사" 10.5.1.3 on 8.3.5: 평면 레이아웃, 모듈은 .txt, 일반 폼 코드는 이진 .Form 컨테이너 내부. 2,603개 모듈, 33,555개 프로시저, 파싱 1.1초, 전체 검색 94MB, 중앙값 0.2ms. 이 형식은 폼 구조를 포함하지 않으며, 일부 공통 모듈은 컴파일된 상태로 제공되어 소스가 전혀 없다.

측정 스크립트는 tools/lab/에 있으며 탐색용이므로 실제 프로바이더가 생기면 제거될 것이다. 지금은 위의 모든 수치를 재현한다:

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 <каталог плоской выгрузки>

구성 확장 구조를 포함한 전체 분석 — docs/modules-and-extensions-2026-08-18.md.

검색 품질

벤치로 측정하고 단일 명령으로 재현한다:

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

세트

쿼리 수

P@1

P@3

P@5

MRR

격차

쿼리 언어

19

94.7%

94.7%

100%

0.958

35.0%

소매 메타데이터

21

90.5%

95.2%

95.2%

0.934

94.0%

도움말 정확한 이름

50,926

97.1%

98.3%

98.7%

0.978

91.7%

동음이의어

10,544

98.8%

99.8%

99.9%

0.993

93.8%

처음 두 세트는 수동으로, 실제 실패 사례에서 수집했다. 나머지 두 세트는 데이터 자체에서 구축된다: 요소 이름을 쿼리로, 동일한 이름을 기대 응답으로.

"격차" — 첫 번째 결과가 두 번째 결과에서 얼마나 떨어져 있는지, 중앙값. "확실히 맞았는지 우연인지"에 대한 답: 쿼리 언어 35% 대 도움말 91.7%는 이러한 승리가 3배 약하게 유지되며 순위 조정이 P@1의 1%도 움직이지 않고 뒤집을 수 있음을 의미한다.

검색 지연 시간 — 세트에 따라 쿼리당 0.18–1.4ms.

쿼리 세트는 이미지에 포함되지 않는다(.dockerignoretests/): 컨테이너가 아닌 작업 복사본에서 측정해야 한다.

테스트

.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest          # 371 тест, ~2 с

data/ 내용과 무관하다: 저장소에 독점 내보내기가 없고, 필요한 모든 것은 tests/conftest.py에서 합성적으로 생성된다.

검색 품질은 테스트로 확인되지 않는다 — 벤치로 측정된다(mcp1c.bench, "측정" 참조). 백분율 임계값은 사전을 수정할 때마다 깨지므로 벤치는 숫자를 출력하고 결정은 사람이 내린다. pytest는 관찰 가능한 동작을 확인한다: "인덱스가 재구축되지 않음", "결과가 일치함", "시작이 실패하지 않음".


6. 보안

두 개의 토큰, 둘 다 환경 변수로 설정된다. 토큰이 설정되지 않는 한, 해당 접근은 주소에 도달할 수 있는 모든 사람에게 열려 있다.

변수

보호 대상

설정되지 않음

API_TOKEN

읽기: MCP 도구 및 대시보드 페이지

구성 구조가 모든 사람에게 공개됨

ADMIN_TOKEN

쓰기: 소스 업로드 및 삭제, 사전 편집, /admin/reload

해당 라우트가 비활성화되고 404 응답

"열림"과 "비활성화"의 차이는 의도적이다. 토큰 없는 읽기는 작동한다 — 자신의 머신에서는 편리하고 위협이 없다. 토큰 없는 쓰기는 전혀 작동하지 않는다: 사전 편집 한 번 실패하면 공유 서버에 연결된 모든 사람의 검색이 조용히 깨진다.

토큰은 헤더로 전달된다 — X-Api-Token 또는 Authorization: Bearer <토큰>. 관리 토큰은 읽기에도 유효하다: 그렇지 않으면 소유자가 클라이언트에 두 개의 헤더 대신 하나를 유지해야 한다.

토큰은 라틴 문자여야 한다. HTTP 헤더는 latin-1로 인코딩되며 키릴 토큰은 물리적으로 서버에 도달하지 않는다: 브라우저의 로그인 폼을 통해서는 작동하지만 클라이언트 헤더를 통해서는 작동하지 않는다.

검사에서 제외되는 두 경로: /health(컨테이너 healthcheck가 사용하며 읽기 권한 이상의 정보를 제공하지 않음)와 /login — 그렇지 않으면 로그인 폼이 발급하는 바로 그 인증 뒤에 갇히게 된다.

토큰과 무관한 두 가지 규칙:

  • MCP 엔드포인트는 구성 구조를 전체적으로 제공한다. 자신의 머신 밖으로 내보낼 때는 API_TOKEN을 설정하라. 네트워크 접근만으로는 충분하지 않다.

  • data/ 디렉터리는 전체가 .gitignore에 있다.hbk와 내보내기, 파싱된 인덱스 모두. 도움말 인덱스는 1C사의 동일한 콘텐츠를 압축 해제한 것이다. 한 번 커밋되어 20개 커밋 동안 남아 있었다. 히스토리는 git filter-repo로 다시 작성했고, 규칙은 확장자가 아닌 디렉터리 기준으로 재정의했다: 확인할 것은 "이게 .hbk인가?"가 아니라 "이게 data/에 있는가?"다.


7. 문서

파일

내용

AGENTS.md

프로젝트 작업 규칙

CHANGELOG.md

1C에 대해 수행된 작업과 확인된 사항

docs/TASKBOARD.md

계획, 우선순위, 이유가 있는 기각된 제안

docs/schema-v1.md

내보내기 형식 계약

docs/data-sources.md

어떤 소스에서 무엇을 가져오는지

docs/query-language-design.md

쿼리 언어 소스 구조

docs/dashboard-design.md

대시보드 구조

docs/market-review-2026-08-17.md

유사 제품 검토 및 채택된 내용

exporter-1c/README.md

1C 내보내기 처리

작업 보드의 "보류" 섹션 — 수치가 있는 기각된 제안: 외부 DB, 벡터, 그래프 DB, 외부 SSE, 지연 로딩. 이 중 무엇을 다시 제안하기 전에 읽어야 한다: 이러한 결정을 뒤집는 것은 새로운 측정이지 새로운 고려 사항이 아니다.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

View all MCP Connectors

Latest Blog Posts

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