# MCP DB Client

> MCP layer for 1C

- **Type:** MCP server
- **Install:** `agentstack add mcp-ditrixnew-mcp-db-client`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [DitriXNew](https://agentstack.voostack.com/s/ditrixnew)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [DitriXNew](https://github.com/DitriXNew)
- **Source:** https://github.com/DitriXNew/MCP-DB-Client

## Install

```sh
agentstack add mcp-ditrixnew-mcp-db-client
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# http1c — MCP Server Framework for 1C:Enterprise

**http1c** is a framework for building [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers from 1C:Enterprise. It provides a native component (DLL) that handles the MCP transport layer and a reference 1C data processor that demonstrates how to implement tools, resources, and prompts.

Use it as a template to expose any 1C business logic — catalogs, documents, reports, calculations — to AI applications like VS Code Copilot, Claude Desktop, and other MCP-compatible clients.

## Core Concept

The project is intentionally split into two layers with different responsibilities.

### Native component responsibilities

The DLL is the MCP engine. It handles protocol and transport details that should not be reimplemented in 1C business code:

- HTTP/SSE transport
- JSON-RPC request/response lifecycle
- MCP session management
- authentication, origin validation, and rate limiting
- pagination, notifications, and progress streaming
- converting 1C responses into valid MCP replies

### 1C responsibilities

The 1C side owns business logic. A 1C developer should work at the level of tools, resources, and prompts, not at the level of MCP internals:

- describe a tool/resource/prompt in BSL
- register it in the component
- handle the incoming call in 1C
- run any required client-side or server-side 1C logic
- return the result or send progress updates

### Why the project is designed this way

The goal is to let a 1C developer publish almost any 1C functionality through MCP without having to understand HTTP, JSON-RPC, SSE, session handling, or MCP message formatting.

In other words:

- the component knows how to be an MCP server
- 1C knows what the tool actually does

This keeps the integration point simple. To add new functionality, a 1C developer does not need to change the native transport layer. They only add or update 1C definitions and handlers.

### Mental model for a 1C developer

From the 1C side, the workflow is intentionally simple:

1. Define the MCP object in BSL.
2. Register it in the component.
3. Receive the request through `ExternalEvent`.
4. Execute arbitrary 1C logic.
5. Return the final result, and optionally send progress while the operation is running.

This means the project is not a fixed set of built-in utilities. It is an MCP transport and protocol layer for 1C, with the actual application behavior defined in 1C code.

## Key Features

- **Full MCP protocol support** — tools, resources, prompts with `listChanged` notifications
- **Streamable HTTP transport** — `POST /mcp` for requests, `GET /mcp` for SSE notification stream
- **Session management** — `Mcp-Session-Id` header, UUID v4 sessions per spec
- **Security** — Origin validation (DNS rebinding protection), Bearer token auth, rate limiting
- **Progress streaming** — SSE-based progress notifications for long-running operations
- **Pagination** — cursor-based pagination for `tools/list`, `resources/list`, `prompts/list`
- **Tool annotations** — `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`
- **Output schemas** — typed response contracts for tool results
- **Dynamic registration** — register/update tools, resources, prompts at runtime from 1C
- **Built-in semantic search (RAG)** — optional `search` / `grep` / `get_segment` / `list_collections` tools backed by a Rust search core (`rcore`) with dense/keyword/hybrid retrieval (see [Search Subsystem](#search-subsystem-rag))

## Architecture

```
┌─────────────────┐     HTTP/SSE      ┌──────────────────┐    ExternalEvent   ┌──────────────────┐
│   MCP Client    │◄─────────────────►│   Native DLL     │◄──────────────────►│  1C:Enterprise   │
│  (VS Code, etc) │   POST/GET /mcp   │  (HttpServer)    │   ToolCall, etc.   │  (BSL Module)    │
└─────────────────┘                   └──────────────────┘                    └──────────────────┘
```

1. A 1C form loads the native add-in and starts the HTTP server.
2. An MCP client connects to `http://localhost:PORT/mcp`.
3. The native component handles protocol-level messages (initialize, tools/list, etc.).
4. Business logic requests (tools/call, resources/read, prompts/get) are forwarded to 1C via `ExternalEvent`.
5. The 1C module processes the request and sends results back through `SendResponse`.
6. The DLL wraps the result in a JSON-RPC response and returns it to the client.

## Quick Start

### 1. Build the DLL

```bash
build/build-http1c-dll-release.sh
```

Requires Visual Studio Build Tools 2019+ with C++ support.

### 2. Package the add-in

Packaging is done automatically at the end of the build script. To run it standalone:

```bash
build/package-http1c-addin.sh
```

### 3. Compile the EPF (requires OneScript)

```bash
build/compile-http1c-epf.sh
```

### 4. Open in 1C

1. Open the `http1c.epf` data processor in your 1C infobase. The MCP server
   **starts automatically on open** (attaches the component, registers the tool /
   resource / prompt catalogs, and begins listening on port `8888` by default).
2. To restart it on a different port, set the port field and click **Connect**.
   (The `Connect` button remains available for manual control.)
3. Configure your MCP client to connect to `http://localhost:PORT/mcp`.

### 5. VS Code configuration

Add to your `.vscode/mcp.json`:

**Without authentication:**

```json
{
  "servers": {
    "1c-mcp-server": {
      "type": "sse",
      "url": "http://localhost:8888/mcp"
    }
  }
}
```

**With Bearer token authentication:**

```json
{
  "servers": {
    "1c-mcp-server": {
      "type": "sse",
      "url": "http://localhost:8888/mcp",
      "headers": {
        "Authorization": "Bearer ${input:mcpToken}"
      }
    }
  },
  "inputs": [
    {
      "id": "mcpToken",
      "type": "promptString",
      "description": "Bearer token for the 1C MCP server",
      "password": true
    }
  ]
}
```

When using the `${input:...}` syntax, VS Code will prompt for the token each time the MCP server connection starts. The entered value is masked as a password.

> **Important:** The token in VS Code must match the value set on the 1C side. If the server has no token configured (empty string), authentication is disabled and no `headers` are needed. If a token is set on the server but VS Code sends no `Authorization` header, the server responds with HTTP 401 and VS Code may try to start an OAuth flow — this is not supported; use the `headers` approach above instead.

## How to Build Your Own MCP Server from 1C

The reference data processor (`http-1c-dp`) is a working example. Use it as a starting point:

### Registering Tools

Tools are executable functions that AI clients can invoke. Define them as JSON structures and register with the component:

```bsl
// Create a tool definition
Tool = NewTool("myTool", "Description of what this tool does");
AddToolParam(Tool, "paramName", "string", "Parameter description");
AddToolAnnotations(Tool, True);  // readOnly, safe

// Define output schema (optional, helps clients validate responses)
Schema = NewOutputSchema();
AddOutputProperty(Schema, "result", "string", "Result description");
SetToolOutputSchema(Tool, Schema);

// Register all tools
Tools = New Array;
Tools.Add(Tool);
Await Component.RegisterToolsAsync(SerializeToJson(Tools));
```

Handle the tool call in the `ExternalEvent` handler:

```bsl
&AtClient
Async Procedure ExternalEvent(Source, Event, Data)
    If Source <> "HttpServer" Then Return; EndIf;
    If Event = "ToolCall" Then ProcessToolCall(Data); EndIf;
EndProcedure
```

### Registering Resources

Resources provide contextual data to AI clients (metadata, file contents, etc.):

```bsl
Resource = New Structure;
Resource.Insert("uri", "1c://metadata/catalogs");
Resource.Insert("name", "1C Catalogs");
Resource.Insert("description", "List of all catalog metadata objects");
Resource.Insert("mimeType", "application/json");

Resources = New Array;
Resources.Add(Resource);
Await Component.RegisterResourcesAsync(SerializeToJson(Resources));
```

Handle resource reads via `"ResourceRead"` events.

### Registering Prompts

Prompts are reusable interaction templates:

```bsl
Prompt = New Structure;
Prompt.Insert("name", "analyzeData");
Prompt.Insert("description", "Prompt for analyzing 1C data");

PromptArgs = New Array;
Arg = New Structure("name,description,required", "topic", "Analysis topic", False);
PromptArgs.Add(Arg);
Prompt.Insert("arguments", PromptArgs);

Prompts = New Array;
Prompts.Add(Prompt);
Await Component.RegisterPromptsAsync(SerializeToJson(Prompts));
```

Handle prompt gets via `"PromptGet"` events.

### Dynamic Updates

Call `RegisterToolsAsync()` / `RegisterResourcesAsync()` / `RegisterPromptsAsync()` again at any time with an updated list. The component will automatically send `notifications/tools/list_changed` (or equivalent) to all connected MCP clients.

### Security Configuration

The component supports optional Bearer token authentication. When a token is set, every HTTP request must include the `Authorization: Bearer ` header or it will be rejected with HTTP 401.

```bsl
// Enable authentication — all requests must include Authorization: Bearer my-secret-token
Component.AuthToken = "my-secret-token";

// Disable authentication — any request is accepted
Component.AuthToken = "";
```

**How it works:**

| Server token | Client header | Result |
|---|---|---|
| Empty (default) | None needed | All requests accepted |
| `"my-secret"` | `Authorization: Bearer my-secret` | Request accepted |
| `"my-secret"` | Missing or wrong token | HTTP 401 Unauthorized |

**Changing the token at runtime:** You can set or clear `AuthToken` while the server is running. The change takes effect immediately for all new requests — no restart needed.

**VS Code note:** If the server returns 401, VS Code may attempt an OAuth 2.0 PKCE authorization flow (redirecting to `/authorize`). This is **not supported** by the component. Always configure the token in `.vscode/mcp.json` via the `headers` field (see [VS Code configuration](#5-vs-code-configuration) above).

The component also enforces:
- **Origin validation** — only requests from `localhost` / `127.0.0.1` / VS Code origins are accepted
- **Rate limiting** — token-bucket algorithm (60 burst, 20/sec)
- **Session management** — `Mcp-Session-Id` assigned on initialize, validated on subsequent requests. A request presenting an **unknown** session id is not rejected with 404 — the session is transparently **resurrected** under the presented id, so a server restart does not strand connected MCP clients that never re-initialize (logged as `MCP: unknown session ... resurrected (server restart?)`)

## Native Component API

Methods exposed to 1C (English / Russian names). All of these are callable
asynchronously from BSL via the platform-generated `BeginCalling` wrappers
(`BeginCallingStartListen`, …):

| Method | Description |
|--------|-------------|
| `StartListen(port)` / `НачатьПрослушивание` | Start the HTTP server on the given port |
| `StopListen()` / `ОстановитьПрослушивание` | Stop the server and unblock all pending requests |
| `SendResponse(json)` / `ОтправитьОтвет` | Send the final response for a pending request |
| `SendProgress(id, progress, total, message)` / `ОтправитьПрогресс` | Send a progress notification for a pending request |
| `ApplyConfig(json)` / `ПрименитьНастройки` | **Async-safe config sink** (see below). Applies any subset of `logging_enabled`, `log_path`, `timeout`, `tools_json`, `resources_json`, `prompts_json`, `auth_token` in one call |
| `GetStatus()` / `ПолучитьСтатус` | **Async-safe** read of the status JSON (same payload as the `Status` property) |
| `RagDispatch(method, payload)` / `RagВыполнить` | Drive the Rust search core (`rcore`) — see [Search Subsystem](#search-subsystem-rag) |
| `TakeScreenshot(pid, format, quality, grayscale)` / `СделатьСкриншот` | Capture windows of a process as base64 images |
| `GetProcessId()` / `ПолучитьИдентификаторПроцесса` | Return the current 1C process id |

### Configuration: async methods vs. synchronous properties

The component also exposes its configuration as **properties** (`LoggingEnabled`,
`LogPath`, `Timeout`, `Tools`, `Resources`, `Prompts`, `AuthToken`, `Status`,
`Version`). These still exist, but reading or writing an AddIn property is a
**synchronous** platform call.

> In an **async-only infobase** — i.e. one where *"synchronous extension and
> add-in calls"* are disabled (the modern 1C default) — every `Component.Prop = …`
> assignment and every `… = Component.Prop` read throws
> **`Cannot call synchronous methods on the client!`**. 1C provides **no async
> property accessors** (there is no `BeginSetProperty`), so configuration cannot
> go through properties at all in that mode.

That is why all configuration is funneled through the **async `ApplyConfig`
method** and all status reads through the **async `GetStatus` function**. The
reference form (`Module.bsl`) uses only these — it never touches a property on
the client. The properties are retained for backward compatibility and for
infobases that still allow synchronous calls.

| Config field (in `ApplyConfig` JSON) | Equivalent property | Notes |
|--------------------------------------|---------------------|-------|
| `logging_enabled` (bool) | `LoggingEnabled` | runtime logging on/off |
| `log_path` (string) | `LogPath` | log file path (empty → default) |
| `timeout` (int) | `Timeout` | response timeout, seconds |
| `tools_json` (string) | `Tools` | pre-serialized tool-list JSON array |
| `resources_json` (string) | `Resources` | pre-serialized resource-list JSON array |
| `prompts_json` (string) | `Prompts` | pre-serialized prompt-list JSON array |
| `auth_token` (string) | `AuthToken` | Bearer token (empty = no auth) |
| *(read via `GetStatus`)* | `Status` / `Version` | status JSON includes `version` |

Every field is optional — `ApplyConfig` only touches the keys you send, so it
doubles as a "set just the logging flag" call or a full one-shot configuration.

## ExternalEvent Types

Events sent from the native component to 1C:

| Event | Description | Data |
|-------|-------------|------|
| `ToolCall` | MCP `tools/call` request | `{id, type, tool, arguments, progressToken}` |
| `ResourceRead` | MCP `resources/read` request | `{id, type, uri}` |
| `PromptGet` | MCP `prompts/get` request | `{id, type, name, arguments}` |
| `Request` | Legacy HTTP request (non-MCP) | `{id, method, path, body, params}` |

## MCP Protocol Support

### Implemented Methods

| Method | Handler |
|--------|---------|
| `initialize` | Native — returns capabilities, creates session |
| `notifications/initialized` | Native — accepted silently |
| `ping` | Native — returns empty result |
| `tools/list` | Native — paginated, from cache |
| `tools/call` | `search` / `grep` / `get_segment` / `list_collections` handled natively by the search core; all other tools delegated to 1C via ExternalEvent |
| `resources/list` | Native — paginated, from cache |
| `resources/read` | Delegated to 1C via ExternalEvent |
| `prompts/list` | Native — paginated, from cache |
| `prompts/get` | Delegated to 1C via ExternalEvent |

### Capabilities Advertised

```json
{
  "tools": { "listChanged": true },
  "resources": { "listChanged": true },
  "prompts": { "listChanged": true }
}
```

### HTTP Endpoints

| Endpoint | Description |
|----------|-------------|
| `POST /mcp` | MCP JSON-RPC messages |
| `GET /mcp` | SSE notification stream (list_changed events) |
| `DELETE /mcp` | Session termination |
| `GET /health` | Health check |
| `OPTIONS *` | CORS preflight |

## Reference Tools (in the demo processor)

| Tool | Purpose | Annotations |
|------|---------|-------------|
| `getStatus` | Component + runtime status | readOnly |
| `openForm` | Open a 1C form by path | idempotent |
| `execute` | Execute arbitrary 1C code on the server **or** the thin client (`location` param) | destructive |
| `evaluate` | Evaluate a 1C expression | readOnly

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [DitriXNew](https://github.com/DitriXNew)
- **Source:** [DitriXNew/MCP-DB-Client](https://github.com/DitriXNew/MCP-DB-Client)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-ditrixnew-mcp-db-client
- Seller: https://agentstack.voostack.com/s/ditrixnew
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
