---
author: OOMOL
author_url: https://oomol.com/ru/about/
title: Руководство по самостоятельному размещению OOMOL OpenConnector
description: Разместите open-source connector service самостоятельно, защитите
  локальные credentials, настройте provider connections и предоставьте actions
  агентам через MCP или HTTP.
lang: ru
canonical_url: https://oomol.com/ru/docs/openconnector-self-hosting/
markdown_url: https://oomol.com/ru/docs/openconnector-self-hosting.md
---

# Руководство по самостоятельному размещению OOMOL OpenConnector

[OOMOL OpenConnector](https://github.com/oomol-lab/open-connector) — это open-source connector service, который можно self-host. Используйте его, когда агентам или внутренним инструментам нужно вызывать реальные внешние сервисы, а provider credentials, permissions и execution history должны оставаться в вашей среде. Он предоставляет типизированные actions для сервисов GitHub, Gmail, Notion, Hacker News, Ably, Abstract, A-Leads и других через MCP или HTTP.

Агенты видят schemas, scopes, execution status и безопасные account labels; raw provider tokens, action permissions и execution history остаются внутри вашей deployment boundary.

## Что это даёт

- Runtime, который предоставляет provider actions через MCP, HTTP, OpenAPI и web console.
- Credential storage для API keys, custom credentials, OAuth2 connections и no-auth providers.
- Typed action schemas, чтобы агенты могли понять, что они могут вызвать, до вызова.
- Connection identity и scopes, чтобы users и agents видели, от имени какого account будет выполняться action.
- Temporary file transit для actions, которым нужны file URLs.
- Recent run logs с редактированными summaries входа и provider errors.
- Provider catalog с local executors, которые загружаются только при использовании action.

Начните с выбора места запуска runtime, затем настройте storage, access control, provider connections и agent-facing MCP или HTTP entry point.

## Выберите deployment target

| Target | Когда использовать | Storage |
| --- | --- | --- |
| Docker Compose | Нужен самый быстрый local или single-server deployment. | Docker volume, смонтированный в `/app/data`, с SQLite в `/app/data/connect.sqlite`. |
| Source runtime | Вы разрабатываете OOMOL OpenConnector или provider executors. | Local `./data/connect.sqlite`, если не задан `OOMOL_CONNECT_DATA_DIR`. |
| Cloudflare Workers | Нужен Cloudflare-hosted deployment runtime state и metadata. | D1 для runtime records и R2 для temporary transit files. |

## Подготовьте runtime

Перед deployment определите эти значения:

| Значение | Почему это важно |
| --- | --- |
| `OOMOL_CONNECT_ADMIN_TOKEN` | Защищает web console, `/api` и local API reference, когда они доступны за пределами вашего shell. |
| `OOMOL_CONNECT_ENCRYPTION_KEY` | Шифрует сохранённые provider credentials и OAuth client secrets. Храните его в secret manager. |
| `OOMOL_CONNECT_ORIGIN` | Задаёт public origin для OAuth callback URLs. Требуется, когда browser достигает runtime через tunnel, domain или Worker URL. |
| Runtime tokens | Аутентифицируют вызовы agents и clients к `/v1` и `/mcp`. Создавайте их на вкладке Access web console или через admin API. |
| Action policy | Ограничивает actions, которые можно выполнять через `/v1` и MCP. Используйте `OOMOL_CONNECT_ALLOWED_ACTIONS` и `OOMOL_CONNECT_BLOCKED_ACTIONS`. |

Считайте runtime database чувствительной. Без `OOMOL_CONNECT_ENCRYPTION_KEY` OOMOL OpenConnector всё равно работает, но provider secrets хранятся в чувствительном local SQLite file.

## Запуск с Docker Compose

Клонируйте репозиторий OOMOL OpenConnector, перейдите в каталог проекта и запустите runtime:

```bash
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
docker compose up --build
```

Откройте web console:

```text
http://localhost:3000
```

Откройте сгенерированную API reference:

```text
http://localhost:3000/docs
```

Проверьте runtime no-auth action:

```bash
curl -s -X POST http://localhost:3000/v1/actions/hackernews.get_top_stories \
  -H 'content-type: application/json' \
  -d '{"input":{}}'
```

Docker Compose хранит runtime state в volume `connector-data`. Container хранит SQLite здесь:

```text
/app/data/connect.sqlite
```

Для private server deployment задайте как минимум admin token и encryption key перед запуском:

Выполняйте эти примеры в Bash. Вводите реальные учётные данные только в скрытых приглашениях; не вставляйте их в команды оболочки или журналы команд.

```bash
(
  set -eu
  read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
  echo
  test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
  export OOMOL_CONNECT_ADMIN_TOKEN
  read -r -s -p "OOMOL_CONNECT_ENCRYPTION_KEY: " OOMOL_CONNECT_ENCRYPTION_KEY
  echo
  test -n "$OOMOL_CONNECT_ENCRYPTION_KEY"
  export OOMOL_CONNECT_ENCRYPTION_KEY
  docker compose up --build
)
```

Когда runtime доступен через public domain или tunnel, задайте также public origin:

```bash
(
  set -eu
  export OOMOL_CONNECT_ORIGIN="https://connect.example.com"
  read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
  echo
  test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
  export OOMOL_CONNECT_ADMIN_TOKEN
  read -r -s -p "OOMOL_CONNECT_ENCRYPTION_KEY: " OOMOL_CONNECT_ENCRYPTION_KEY
  echo
  test -n "$OOMOL_CONNECT_ENCRYPTION_KEY"
  export OOMOL_CONNECT_ENCRYPTION_KEY
  read -r -s -p "OOMOL_CONNECT_RUNTIME_TOKEN: " OOMOL_CONNECT_RUNTIME_TOKEN
  echo
  test -n "$OOMOL_CONNECT_RUNTIME_TOKEN"
  export OOMOL_CONNECT_RUNTIME_TOKEN
  docker compose up --build
)
```

Docker image внутри container привязывается к `0.0.0.0`. Контролируйте внешний доступ через host firewall, reverse proxy или container platform.

## Защитите admin и runtime access

Admin HTTP clients вызывают `/api`, `/docs` или web console с:

```text
Authorization: Bearer replace-with-an-admin-token
```

Создавайте runtime tokens для agents и SDK-style clients на вкладке Access web console. Token показывается один раз; хранится только hash.

Его также можно создать через admin API:

Для примеров запросов с аутентификацией нужны Python 3 и [curl версии 7.76.0 или новее](https://curl.se/docs/manpage.html#--fail-with-body), поддерживающий параметр --fail-with-body, используемый во всех этих примерах. Секреты вводятся скрыто и передаются curl через стандартный ввод, не попадая в аргументы командной строки или историю оболочки.

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
payload = {'name': 'Claude Desktop'}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/api/runtime-tokens', '--header', 'content-type: application/json'],
    input=config, text=True, check=True,
)
PY
```

Runtime clients затем вызывают `/v1` или `/mcp` с:

```text
Authorization: Bearer oct_...
```

Для bootstrap scripts и backward compatibility `OOMOL_CONNECT_RUNTIME_TOKEN` всё ещё принимается:

```bash
(
  set -eu
  read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
  echo
  test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
  export OOMOL_CONNECT_ADMIN_TOKEN
  read -r -s -p "OOMOL_CONNECT_RUNTIME_TOKEN: " OOMOL_CONNECT_RUNTIME_TOKEN
  echo
  test -n "$OOMOL_CONNECT_RUNTIME_TOKEN"
  export OOMOL_CONNECT_RUNTIME_TOKEN
  docker compose up --build
)
```

Ограничьте actions, которые агенты могут выполнять:

```bash
OOMOL_CONNECT_ALLOWED_ACTIONS="hackernews.*,github.get_current_user" docker compose up --build
```

Блокируйте конкретные actions, даже если более широкая allowlist включает их:

```bash
OOMOL_CONNECT_ALLOWED_ACTIONS="github.*" \
OOMOL_CONNECT_BLOCKED_ACTIONS="github.delete_repository" \
docker compose up --build
```

## Подключите API-key provider

GitHub — компактный пример API key, потому что он может использовать personal access token.

Проверьте provider contract:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/providers/github'],
    input=config, text=True, check=True,
)
PY
```

Сохраните default GitHub connection:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
payload = {'authType': 'api_key', 'values': {'apiKey': None}}
payload["values"]["apiKey"] = getpass.getpass("GitHub API key: ")
if not payload["values"]["apiKey"]:
    raise SystemExit("An API key is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'PUT', 'http://localhost:3000/api/connections/github', '--header', 'content-type: application/json'],
    input=config, text=True, check=True,
)
PY
```

Вызовите GitHub через runtime:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
    raise SystemExit("A token is required")
payload = {'input': {}}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/v1/actions/github.get_current_user', '--header', 'content-type: application/json'],
    input=config, text=True, check=True,
)
PY
```

Проверьте настроенные connections и safe account identity, видимую агентам:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/connections'],
    input=config, text=True, check=True,
)
PY
```

### Именованные подключения

Добавьте `connectionName`, когда одному provider нужно несколько accounts:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
payload = {'authType': 'api_key', 'connectionName': 'work', 'values': {'apiKey': None}}
payload["values"]["apiKey"] = getpass.getpass("GitHub API key: ")
if not payload["values"]["apiKey"]:
    raise SystemExit("An API key is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'PUT', 'http://localhost:3000/api/connections/github', '--header', 'content-type: application/json'],
    input=config, text=True, check=True,
)
PY
```

Выберите этот account при execution:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
    raise SystemExit("A token is required")
payload = {'input': {}}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/v1/actions/github.get_current_user', '--header', 'x-oo-connector-alias: work', '--header', 'content-type: application/json'],
    input=config, text=True, check=True,
)
PY
```

Query parameter `alias` также принимается.

## Подключите OAuth provider

OAuth providers используют ваше собственное provider OAuth app. Сначала перечислите providers с поддержкой OAuth и скопируйте `expectedRedirectUri` для service:

```bash
curl -s http://localhost:3000/api/oauth/configs \
  -H 'authorization: Bearer replace-with-an-admin-token'
```

С портом по умолчанию GitHub использует этот callback URL:

```text
http://localhost:3000/oauth/callback
```

Вставьте точный callback URL, возвращённый `/api/oauth/configs`, в provider OAuth app. Если вы меняете `PORT`, `HOST` или открываете runtime через другой origin, задайте `OOMOL_CONNECT_ORIGIN` перед запуском runtime и снова прочитайте callback URL.

Сохраните OAuth client локально:

```bash
curl -s -X PUT http://localhost:3000/api/oauth/configs/github \
  -H 'authorization: Bearer replace-with-an-admin-token' \
  -H 'content-type: application/json' \
  -d '{"clientId":"...","clientSecret":"..."}'
```

Запустите authorization:

```bash
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
  -H 'authorization: Bearer replace-with-an-admin-token' \
  -H 'content-type: application/json' \
  -d '{"service":"github"}'
```

Откройте возвращённый `authorizationUrl` в браузере. После redirect provider на callback URL OOMOL OpenConnector сохранит OAuth credential как default connection.

Чтобы сохранить OAuth result как named connection, включите `connectionName`:

```bash
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
  -H 'authorization: Bearer replace-with-an-admin-token' \
  -H 'content-type: application/json' \
  -d '{"service":"github","connectionName":"work"}'
```

## Передайте tools агенту

Для MCP-capable clients укажите client:

```text
http://localhost:3000/mcp
```

MCP server предоставляет discovery-oriented tools:

- `list_apps`
- `search_actions`
- `get_action_guide`
- `execute_action`

Просмотрите MCP tool metadata:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
    raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/mcp/tools'],
    input=config, text=True, check=True,
)
PY
```

Для HTTP clients используйте `/v1` runtime API:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
    raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/v1/actions'],
    input=config, text=True, check=True,
)
PY
```

У каждого action есть локальное Markdown-руководство с input schema, scopes, provider permissions, current connection identity и request examples:

```bash
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings

warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
    raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
    ['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/actions/github.get_current_user/agent.md'],
    input=config, text=True, check=True,
)
PY
```

Web console также может копировать примеры cURL, TypeScript и agent prompt для каждого action.

## Запуск из source

Используйте source workflow, когда разрабатываете OOMOL OpenConnector или provider executors. Используйте Node.js 22 или новее.

```bash
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
npm install
npm run build:web
npm run dev
```

`npm install` и `npm run dev` создают локальные generated files, когда они отсутствуют или устарели.

При запуске из source runtime state хранится в:

```text
./data/connect.sqlite
```

Используйте другой data directory с:

```bash
OOMOL_CONNECT_DATA_DIR=/path/to/data npm run dev
```

Задайте те же environment variables admin, encryption, origin, runtime token и action policy, которые описаны выше.

## Deploy в Cloudflare Workers

Cloudflare Workers поддерживается как deployment target для metadata и runtime-state.

Клонируйте repository, создайте ресурсы Cloudflare и deploy:

```bash
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
cp wrangler.example.jsonc wrangler.local.jsonc
npm install
npm run generate:catalog
npm run build:web
npx wrangler d1 create oomol-connect
npx wrangler r2 bucket create oomol-connect-transit-files
```

Перед deploy обновите игнорируемый файл `wrangler.local.jsonc`, указав D1 `database_id`, возвращённый Cloudflare.

Во время первоначальной настройки Worker должен оставаться закрытым: в локальной конфигурации Wrangler задайте workers_dev и preview_urls как false и не настраивайте публичные маршруты или собственные домены. Не открывайте публичный доступ, пока не заданы все три секрета ниже.

```bash
npx wrangler d1 migrations apply oomol-connect --remote --config wrangler.local.jsonc
npm run deploy:cloudflare
```

Задайте secrets через Wrangler:

```bash
npx wrangler secret put OOMOL_CONNECT_ADMIN_TOKEN --config wrangler.local.jsonc
npx wrangler secret put OOMOL_CONNECT_RUNTIME_TOKEN --config wrangler.local.jsonc
npx wrangler secret put OOMOL_CONNECT_ENCRYPTION_KEY --config wrangler.local.jsonc
```

После настройки всех трёх секретов включите нужный публичный маршрут в локальной конфигурации и выполните повторное развёртывание.

Cloudflare использует те же имена environment variables для origin, auth tokens, action policy, transit file limits и credential encryption. `PORT`, `HOST` и `OOMOL_CONNECT_DATA_DIR` применяются только к local Node.

Worker runtime обслуживает catalog metadata, metadata endpoints `/api` и `/v1`, connections, runtime tokens, OAuth config и state, transit files на R2 и generated provider action executor registry. Настройте R2 lifecycle rule для transit bucket, если хотите автоматически очищать непрочитанные expired transit files.

## Эксплуатация deployment

Держите эти records доступными для support и recovery:

| Record | Где найти |
| --- | --- |
| Runtime database | Docker volume, local `OOMOL_CONNECT_DATA_DIR` или Cloudflare D1. |
| Temporary transit files | `OOMOL_CONNECT_DATA_DIR/files` для local runtime или Cloudflare R2. |
| Admin token and encryption key | Ваш secret manager. OOMOL OpenConnector не хранит encryption key за вас. |
| Runtime token prefix | Вкладка Access web console или `/api/runtime-tokens`. Полные runtime tokens показываются только один раз. |
| Execution history | Recent runs в web console или `GET /api/runs`. |

Для file-upload actions local transit files хранятся в `OOMOL_CONNECT_DATA_DIR/files` и очищаются по age. Настройте lifetime и upload size через `OOMOL_CONNECT_TRANSIT_FILE_TTL_SECONDS` и `OOMOL_CONNECT_TRANSIT_FILE_MAX_BYTES`.

## Устранение неполадок

| Симптом | Что проверить |
| --- | --- |
| Web console или `/api` возвращает unauthorized. | Отправьте `Authorization: Bearer <admin-token>` и подтвердите, что `OOMOL_CONNECT_ADMIN_TOKEN` соответствует running environment. |
| `/v1` или `/mcp` возвращает unauthorized. | Используйте runtime token, созданный на вкладке Access или через `POST /api/runtime-tokens`. Admin tokens предназначены для admin surfaces, а не runtime clients. |
| OAuth redirect уходит на неправильный host. | Задайте `OOMOL_CONNECT_ORIGIN` как origin, который users открывают в browser, перезапустите runtime, затем скопируйте свежий `expectedRedirectUri` из `/api/oauth/configs`. |
| Action не находит credentials. | Проверьте `/api/connections`, выбранный `x-oo-connector-alias` и доступность connection. |
| Action заблокирован. | Проверьте `OOMOL_CONNECT_ALLOWED_ACTIONS` и `OOMOL_CONNECT_BLOCKED_ACTIONS`. Blocked actions имеют приоритет над более широкими allowlists. |
| Provider credentials перестали работать. | Переподключите provider, если token истёк и refresh token недоступен, или проверьте, что encryption key всё ещё соответствует сохранённым records. |
