Metadata-Version: 2.4
Name: platform42-mcp-proxy
Version: 0.1.4
Summary: MCP proxy server for 1C HTTP services
Project-URL: Repository, https://gitlab.com/platform42/mcp-proxy
Author: Platform42
License: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: fastapi>=0.115.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp>=1.8.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: pydantic>=2.5.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: uvicorn[standard]>=0.30.0
Description-Content-Type: text/markdown

# Platform42 MCP Proxy for 1C

Python MCP-прокси между MCP-клиентами и HTTP-сервисом 1С. Репозиторий содержит только Python proxy-server, без 1С-расширения/конфигурации.

Основано на `src/py_server` проекта <https://github.com/vladimir-kharin/1c_mcp>.

## Режимы выбора базы

### 1. Fixed-base: `MCP_ONEC_URL` задан

Если `MCP_ONEC_URL` задан, прокси работает только с этой публикацией 1С:

```env
MCP_ONEC_URL=https://host/base
MCP_ONEC_USERNAME=Admin
MCP_ONEC_PASSWORD=secret
MCP_ONEC_SERVICE_ROOT=mcp
```

В этом режиме параметр `_base_url` запрещён. Если MCP-клиент передаст `_base_url` в `tools/call`, прокси вернёт ошибку.

### 2. Dynamic-base: `MCP_ONEC_URL` не задан

Если `MCP_ONEC_URL` не задан, прокси не привязан к конкретной базе. Тогда:

- `tools/list` берётся из отдельного catalog source;
- в schema каждого tool автоматически добавляется обязательный параметр `_base_url`;
- каждый `tools/call` обязан передать `_base_url`;
- `_base_url` используется только прокси и не передаётся в 1С;
- логин/пароль для фактического вызова берутся из `MCP_ONEC_USERNAME` / `MCP_ONEC_PASSWORD`.

Пример вызова tool в dynamic-base:

```json
{
  "_base_url": "https://host/base-or-data-area",
  "actualParameter": "value"
}
```

В 1С уйдёт только:

```json
{
  "actualParameter": "value"
}
```

## Catalog source для `tools/list` в dynamic-base

MCP `tools/list` не принимает arguments, поэтому адрес/логин/пароль для получения списка tools задаются в конфигурации прокси.

### Источник `onec`

Список tools берётся из обычной базы 1С:

```env
MCP_TOOLS_CATALOG_SOURCE=onec
MCP_TOOLS_CATALOG_URL=https://host/catalog-base
MCP_TOOLS_CATALOG_USERNAME=Admin
MCP_TOOLS_CATALOG_PASSWORD=secret
MCP_TOOLS_CATALOG_SERVICE_ROOT=mcp

MCP_ONEC_USERNAME=Admin
MCP_ONEC_PASSWORD=secret
MCP_ONEC_SERVICE_ROOT=mcp
```

Если `MCP_TOOLS_CATALOG_USERNAME/PASSWORD` не заданы, используются `MCP_ONEC_USERNAME/PASSWORD`.

### Источник `file`

```env
MCP_TOOLS_CATALOG_SOURCE=file
MCP_TOOLS_CATALOG_PATH=/opt/mcp-proxy/tools.json

MCP_ONEC_USERNAME=Admin
MCP_ONEC_PASSWORD=secret
```

Формат файла:

```json
{
  "tools": [
    {
      "name": "example_tool",
      "description": "Example tool",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {"type": "string"}
        },
        "required": ["name"]
      }
    }
  ]
}
```

Также поддерживается raw array tools.

### Источник `http`

```env
MCP_TOOLS_CATALOG_SOURCE=http
MCP_TOOLS_CATALOG_URL=https://example.com/tools.json
MCP_TOOLS_CATALOG_USERNAME=optional-basic-auth-user
MCP_TOOLS_CATALOG_PASSWORD=optional-basic-auth-password

MCP_ONEC_USERNAME=Admin
MCP_ONEC_PASSWORD=secret
```

## Безопасность `_base_url`

В dynamic-base режиме `_base_url` может превратить прокси в SSRF-примитив с Basic Auth кредами. Для production рекомендуется задавать allowlist:

```env
MCP_ONEC_ALLOWED_BASE_URLS=https://host/base1,https://host/base2
```

или JSON array:

```env
MCP_ONEC_ALLOWED_BASE_URLS=["https://host/base1", "https://host/base2"]
```

Если allowlist задан, `_base_url` обязан совпадать с одним из разрешённых URL после удаления trailing slash. Поддерживаются shell-style wildcard-шаблоны (`*`, `?`, `[seq]`), например:

```env
MCP_ONEC_ALLOWED_BASE_URLS=https://*.example.com/base/*,https://*.example.org/1c
```

## Установка

```bash
python -m pip install platform42-mcp-proxy
```

Из исходников:

```bash
python -m pip install -e .
```

## Запуск

### Stdio

```bash
python -m src.py_server stdio
# или после установки пакета
mcp-proxy-1c stdio
```

### HTTP

```bash
python -m src.py_server http --port 8000
# или
mcp-proxy-1c http --port 8000
```

Endpoints HTTP-режима:

- `/mcp/` — Streamable HTTP MCP transport;
- `/sse` — SSE transport;
- `/health` — health check;
- `/info` — server info.

## Stdio конфигурация для агентов

### Fixed-base

```json
{
  "mcpServers": {
    "1c-mcp-proxy": {
      "command": "mcp-proxy-1c",
      "args": ["stdio"],
      "env": {
        "MCP_ONEC_URL": "https://host/base",
        "MCP_ONEC_USERNAME": "Admin",
        "MCP_ONEC_PASSWORD": "password",
        "MCP_ONEC_SERVICE_ROOT": "mcp"
      }
    }
  }
}
```

### Dynamic-base

```json
{
  "mcpServers": {
    "1c-mcp-proxy": {
      "command": "mcp-proxy-1c",
      "args": ["stdio"],
      "env": {
        "MCP_ONEC_USERNAME": "Admin",
        "MCP_ONEC_PASSWORD": "password",
        "MCP_ONEC_SERVICE_ROOT": "mcp",
        "MCP_TOOLS_CATALOG_SOURCE": "onec",
        "MCP_TOOLS_CATALOG_URL": "https://host/catalog-base",
        "MCP_TOOLS_CATALOG_SERVICE_ROOT": "mcp",
        "MCP_ONEC_ALLOWED_BASE_URLS": "https://host/base1,https://host/base2"
      }
    }
  }
}
```

В dynamic-base каждый `tools/call` обязан передавать `_base_url`.

## Сборка пакета

```bash
python -m pip install -U build twine
python -m build
python -m twine check dist/*
```
