Metadata-Version: 2.5
Name: i2crm-mcp
Version: 0.1.2
Summary: MCP-сервер для публичного API i2crm: отправка и приём сообщений в мессенджерах из ИИ-агента
Project-URL: Homepage, https://i2crm.ru
Project-URL: Documentation, https://app.i2crm.ru/api_v1/for-ai
License-Expression: MIT
License-File: LICENSE
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: ruff==0.16.3; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: lint
Requires-Dist: ruff==0.16.3; extra == 'lint'
Description-Content-Type: text/markdown

# i2crm-mcp

MCP-сервер для публичного API i2crm: отправка и приём сообщений в мессенджерах из
ИИ-агента — Claude Code, Cursor, VS Code и других совместимых. Разработчик ставит пакет,
задаёт адрес и токен, подключает сервер к агенту — и собирает интеграцию, спрашивая
контракт словами, а не вычитывая спеку целиком.

| | |
|---|---|
| Версия | 0.1.2 |
| Требуется | Python 3.11+ |
| Зависимости | **нет ни одной**, только стандартная библиотека |
| Транспорт | stdio, сервер работает локально у разработчика |
| Инструментов | 12 — контракт API и действия в аккаунте |

---

## Состояние

Путь интеграции проходится целиком: агент спрашивает порядок шагов и контракт, смотрит
каналы, заводит исходящий канал с callback-URL, отправляет текстовое сообщение — и
`i2crm-mcp listen` показывает, что пришло обратно.

---

## Установка

Пакет лежит в реестре пакетов проекта. Своё окружение — чтобы путь к интерпретатору был
известен: он понадобится агенту.

```bash
python -m venv ~/.venvs/i2crm-mcp
source ~/.venvs/i2crm-mcp/bin/activate      # Windows: %USERPROFILE%\.venvs\i2crm-mcp\Scripts\activate
pip install i2crm-mcp
```

`--index-url` подменяет PyPI целиком, и это безопасно ровно потому, что зависимостей у
пакета нет: резолвить в чужом индексе нечего.

Дальше — адрес и токен i2crm:

```bash
i2crm-mcp setup     # спросит адрес и токен, сохранит в профиль пользователя
i2crm-mcp check     # проверит связь: спека читается, токен принят, каналы видны
i2crm-mcp where     # покажет, откуда взяты настройки, и маску токена
i2crm-mcp listen    # примет вебхуки и напечатает входящие и статусы доставки
```

---

## Подключение к агенту

Пример для Claude Code; у Cursor, Windsurf и VS Code свои файлы конфигурации, но поле
команды в них то же:

```bash
claude mcp add --scope user i2crm -- ~/.venvs/i2crm-mcp/bin/python -m i2crm_mcp.server
```

Интерпретатор указывается полным путём — тем, куда поставлен пакет. Агент запускает сервер
не из вашего шелла: ни `PATH`, ни активированное окружение до него не доходят, и короткое
`python` найдёт не то.

Настройки сервер берёт из профиля, созданного командой `setup`. Без профиля адрес и токен
задаются блоком `env` в конфиге агента — `I2CRM_BASE_URL` и `I2CRM_TOKEN`.

---

## Инструменты

**Знание о контракте.** Токен не нужен: спека публична. Нужен только адрес — контракт
берётся у той установки i2crm, к которой подключён разработчик, и не копируется в пакет.

| Инструмент | Назначение |
|---|---|
| `i2crm_playbook` | Порядок интеграции: что делает человек, что агент, чем проверяется |
| `i2crm_endpoints` | Вся поверхность API за пару килобайт: метод, путь, нужный токен, назначение |
| `i2crm_endpoint_get` | Контракт одного метода: параметры, тело с раскрытыми схемами, ответы, примеры |
| `i2crm_schema_get` | Схема по имени — по ней пишется тело запроса и приёмник вебхуков |

**Действия в аккаунте.** Токенов у API два, но агент держит только номер канала: ключ
исходящего канала инструменты подставляют сами, а при единственном канале берут его молча.

| Инструмент | Назначение |
|---|---|
| `i2crm_diagnose` | Проверка подключения: адрес, токен маской, спека, оба списка каналов |
| `i2crm_sources` | Входящие каналы: какие мессенджеры подключены и от какого аккаунта отвечать |
| `i2crm_targets` | Исходящие каналы: номер, тип, активность, ключ |
| `i2crm_target_create` | Создать исходящий канал с callback-URL и получить его ключ |
| `i2crm_target_update` | Переставить callback-URL, переименовать, включить или выключить |
| `i2crm_target_validate` | Канал жив и ключ принимается |
| `i2crm_reply_sources` | Через что этот канал может отвечать: `domain`, `type`, `source`, шаблоны |
| `i2crm_send` | Отправить текстовое сообщение клиенту |

Спросите агента обычными словами:

> проверь подключение к i2crm и покажи, через какие каналы можно ответить

Ответ, который не влезает в потолок, не урезается молча: вложенные схемы сворачиваются до
имён, и агенту сказано, чем их раскрыть.

---

## Приём вебхуков

Отправку видно по ответу инструмента, а дошло ли сообщение — только по вебхуку. Принять
его локально можно, не написав обработчика:

```bash
i2crm-mcp listen --port 3000     # --raw печатает payload целиком, --once ждёт одно событие
```

Приёмник слушает только этот компьютер, поэтому наружу его выводит туннель:

```bash
cloudflared tunnel --url http://localhost:3000
```

Полученный адрес ставится каналу с путём — `https://ваш-туннель/i2crm` — иначе i2crm его
не примет: требуется https и непустой путь. Дальше в терминале видно входящие сообщения,
правки и статусы доставки, а по подписи вебхука названо, какому каналу он адресован.

Два требования i2crm, которые приёмник закрывает сам и о которых стоит знать, когда
обработчик пишется в своём коде: **ответ обязан быть JSON**, а не просто 200, — тело
ответа разбирается, и на не-JSON доставка считается неудачной и повторяется; правка ранее
отправленного сообщения приходит методом `PATCH` на тот же адрес.

Приёмник отладочный: он никого не проверяет, ничего не хранит и не годится на роль
рабочего обработчика.

---

## Границы

- **Разрушающих операций нет вообще** — ни удаления канала, ни удаления сообщений. Агент
  не может снести рабочий канал, даже если его попросить.
- **Подключение мессенджеров не автоматизируется**: QR и вход по коду интерактивны, это
  делает человек в личном кабинете. Инструменты только показывают состояние.
- **Переписка не читается**: клиентская спека скрывает эту часть API, набор инструментов
  повторяет её границу, а не расширяет.
- **Запросы разрежаются на нашей стороне**: своего лимита у API нет, и агент в цикле —
  единственное, что может выжечь аккаунт отправками.
- **Токен не светится**: в профиле с правами только владельцу, в выводе — маской, в
  stdout — ничего кроме протокола. Ключи каналов инструменты агенту показывают: без них
  он не напишет код, который ходит в API сам. В терминале (`check`) они маской.

---

## Настройки

Адрес и токен берутся из двух мест, окружение перебивает профиль:

| Что | Переменная | Профиль |
|---|---|---|
| Адрес i2crm | `I2CRM_BASE_URL` | пишется командой `setup` |
| Токен пользователя | `I2CRM_TOKEN` | там же |

Профиль лежит по соглашению ОС — `%APPDATA%\i2crm-mcp\config.json` на Windows,
`~/.config/i2crm-mcp/config.json` на macOS и Linux — и читается только владельцем.
Переопределяется переменной `I2CRM_MCP_CONFIG`.

Адреса по умолчанию нет намеренно: каждая установка i2crm отвечает на своём хосте, и
угаданный адрес — это токен, отправленный туда, куда сегодня резолвится это имя. Адрес и
токен показаны в личном кабинете, на странице настройки API.

---

## Разработка

Свой протокол MCP на стандартной библиотеке (`protocol.py`), 249 тестов без обращений к
сети, ruff и сборка пакета — на каждый коммит.

Разработка ведётся в приватном репозитории i2crm; порядок правки и выпуска описан там же,
в `CONTRIBUTING.md`.
