1c-mcp
by skiddgoddamn
README.md
<div align="center">
# 1c-mcp
**Give an AI agent eyes into your [1C:Enterprise](https://1c.ru) 8.3 base — read metadata & data, run queries, and diagnose why a document won't post — over one extension HTTP service.**





</div>
## Why
Most 1C automation tooling either reads metadata **or** reads data. The thing an analyst actually gets stuck on — *"this document won't post, why?"* — needs both, plus the ability to run the posting logic and capture the error. `1c-mcp` does exactly that.
It exposes your base as [MCP](https://modelcontextprotocol.io) tools through a thin HTTP service in a **configuration extension**. The MCP server stays a small, strict TypeScript client; the reasoning about *how to fix* a broken document is left to the agent (Claude) — no LLM baked into the server, no API keys to manage.
- 🔎 **Metadata introspection** — objects, attributes, tabular sections, register records
- 📄 **Data & queries** — read objects by ref, run 1C query-language, list documents, read register movements
- 🩺 **Document diagnosis** — test-post a document *inside a rolled-back transaction*, capture the fill errors, the exception text, the failing attribute, and the movements it tried to make — the whole context an agent needs to explain and fix it
- 🔒 **Read-only by default** — write tools (`object_update`, `document_post`) exist but only register when `ONEC_ALLOW_WRITE=1`
- 🪶 **TypeScript, ESM, MIT** — 2 runtime deps (`@modelcontextprotocol/sdk`, `zod`), no 1C secrets in the repo
## How document diagnosis works
`document_diagnose(ref)` is the headline. The extension runs, inside a transaction it always **rolls back**:
1. `ПроверитьЗаполнение()` — collects required-field / validation problems
2. `Записать(…Проведение)` in a `Попытка/Исключение` — captures the posting exception and every `Сообщить()`
3. reads back the register movements it *would* have made
…then returns one structured object. The agent gets the error text, the exact attribute/row that failed, the document data, the object's metadata, and the attempted movements — and works out the fix:
```
document_diagnose # ref → { filled, fillErrors, posts, errorText, messages, wouldMove, data, metadata }
# agent reads it, explains the cause, proposes the change
object_update # (if ONEC_ALLOW_WRITE=1) apply the fix
document_post # (if ONEC_ALLOW_WRITE=1) post for real
```
Because the transaction is always rolled back, diagnosis has **zero side effects** on the base.
## Requirements
1. **1C:Enterprise 8.3** base published on a web server with HTTP services enabled.
2. A **configuration extension** exposing the HTTP service `mcp` (see [The 1C side](#the-1c-side) — this is the part you build, against a fixed contract).
3. A 1C user for the MCP to authenticate as (Basic Auth).
4. Node ≥ 18.
## Setup
```bash
npm install
cp .env.example .env # set ONEC_URL / ONEC_USER / ONEC_PASSWORD
npm run build
```
Register it with your MCP client:
```json
{
"mcpServers": {
"1c": {
"command": "node",
"args": ["D:/projects/1c-mcp/dist/index.js"],
"env": {
"ONEC_URL": "http://localhost/mybase/hs/mcp",
"ONEC_USER": "mcp",
"ONEC_PASSWORD": "secret",
"ONEC_ALLOW_WRITE": "0"
}
}
}
}
```
| Env | Meaning |
|-----|---------|
| `ONEC_URL` | HTTP-service root: `http://<host>/<base>/hs/<rootURL>` |
| `ONEC_USER` / `ONEC_PASSWORD` | 1C user for Basic Auth |
| `ONEC_ALLOW_WRITE` | `1` registers the write tools; anything else = read-only |
> The env prefix is `ONEC_` (not `1C_`) on purpose — a var name starting with a digit breaks in POSIX shells.
## Tools
| Tool | Purpose |
|------|---------|
| `metadata_list` | List metadata objects (Catalogs / Documents / Registers …) with a filter. |
| `metadata_get` | Full structure of one object: attributes, tabular sections, register records. |
| `metadata_search` | Search objects by name/synonym across all kinds. |
| `object_get` | Read an object by GUID ref — attributes + tabular sections. |
| `query_run` | Run a 1C query-language query and return rows. |
| `document_list` | List documents by type / period / filter. |
| `register_records` | Register movements / balances by document or filter. |
| `document_diagnose` | Test-post in a rolled-back transaction → fill errors, exception text, failing attribute, movements, data, metadata. |
| `document_check_fill` | Fill check only (no test-post). |
| `object_update` ⚑ | Write an object's attributes / tabular sections. |
| `document_post` ⚑ | Post a document for real. |
⚑ — registered only when `ONEC_ALLOW_WRITE=1`.
## The 1C side
The MCP talks to one HTTP service. **You implement it** in a configuration extension, against this contract.
Root: `http://<host>/<base>/hs/mcp`. Every method: `POST`, JSON body, Basic Auth. Errors: non-2xx with body `{ "error": { "code": string, "message": string } }` (the client turns this into a tool error).
| Method | Request | Response (key fields) |
|--------|---------|-----------------------|
| `/metadata/list` | `{ kind?, filter? }` | `{ objects: [{ fullName, name, synonym, kind }] }` |
| `/metadata/get` | `{ fullName }` | `{ fullName, synonym, attributes[], tabularSections[], registerRecords[] }` |
| `/query/run` | `{ text, params?, limit? }` | `{ columns[], rows[][] }` |
| `/object/get` | `{ ref }` | `{ ref, presentation, fields{}, tabularSections{} }` |
| `/document/list` | `{ type, period?, filter?, limit? }` | `{ documents: [{ ref, number, date, presentation, posted }] }` |
| `/register/records` | `{ register, filter?, ref? }` | `{ records[] }` |
| `/document/diagnose` | `{ ref }` | see below |
| `/document/checkfill` | `{ ref }` | `{ filled, fillErrors[] }` |
| `/object/update` ⚑ | `{ ref, fields{}, tabularSections? }` | `{ ok, ref }` |
| `/document/post` ⚑ | `{ ref }` | `{ ok, posts, errorText? }` |
### `/document/diagnose` response
```json
{
"ref": "guid",
"presentation": "Реализация 0001 от 01.01.2026",
"filled": false,
"fillErrors": [{ "field": "Организация", "message": "Поле не заполнено" }],
"posts": false,
"errorText": "Недостаточно 5 шт номенклатуры X на складе Y",
"messages": [{ "text": "...", "field": "Товары", "dataPath": "Товары[2].Количество" }],
"wouldMove": [{ "register": "ТоварыНаСкладах", "records": [{ "...": "..." }] }],
"data": { "Организация": null, "Товары": [{ "...": "..." }] },
"metadata": { "attributes": [], "tabularSections": [], "registerRecords": [] }
}
```
### Extension setup checklist
1. Create a **configuration extension**, add an **HTTP service** with root URL `mcp`.
2. Implement the URL templates from the contract (method POST, JSON in/out).
3. The key handler `/document/diagnose` — a side-effect-free test-post:
```bsl
Объект = Ссылка.ПолучитьОбъект();
Результат = Новый Структура("filled, fillErrors, posts, errorText, messages, wouldMove, data, metadata");
НачатьТранзакцию();
Попытка
Результат.filled = Объект.ПроверитьЗаполнение(); // messages collected below
Попытка
Объект.Записать(РежимЗаписиДокумента.Проведение);
Результат.posts = Истина;
Исключение
Результат.posts = Ложь;
Результат.errorText = ОписаниеОшибки();
КонецПопытки;
Результат.messages = ПолучитьСообщенияПользователю(Истина);
Исключение
Результат.errorText = ОписаниеОшибки();
КонецПопытки;
ОтменитьТранзакцию(); // always roll back — the base is never changed
```
Fill `data` / `metadata` / `wouldMove` and return the JSON above.
4. Publish the base on a web server, enable HTTP services, create the `ONEC_USER` user.
5. Smoke test: `curl -u user:pass -X POST http://host/base/hs/mcp/metadata/list -d "{}"`.
## Development
```bash
npm test # vitest — config, HTTP client, write-tool gating (no live 1C needed)
npm run build # tsc → dist/
npx tsc --noEmit # typecheck
```
The design spec and implementation plan live in `docs/superpowers/`.
## Security
- `document_diagnose` always runs inside a rolled-back transaction — zero side effects.
- Write tools register only when `ONEC_ALLOW_WRITE=1`.
- 1C credentials come from the environment only; `.env` is git-ignored and never committed.
## Contributing
PRs welcome. Good first ideas:
- a bundled reference extension (`.xml` sources of the HTTP-service module)
- OData transport as a read-only fallback (no extension required)
- richer `wouldMove` shaping / typed diagnose result
- Russian README
1. Fork and branch: `git checkout -b feature/my-change`
2. `npm install`; `npm run build` and `npx tsc --noEmit` must pass; `npm test` green
3. **Never commit secrets** (`.env`, passwords) or real base data
4. Open a PR describing what and why
## License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues