Skip to main content
Glama

iikocloud-mcp

MCP-сервер поверх Iikocloud-manager (IikoCloudApiClientManager): интроспекцией менеджера сервер отдаёт 236 методов iikoCloud в 22 доменах как MCP-тулы, но запускается с вариативно задаваемым подмножеством, а не целиком. Мультиарендный: учётные данные iikoCloud передаёт клиент через канал транспорта (HTTP-заголовки под TLS или переменные окружения для stdio) — секреты никогда не попадают в аргументы тулов, а значит и в контекст модели или логи.

Прямой аналог iikoserver-mcp: тот же принцип, та же модель безопасности, отличия — только там, где различаются сами API (auth v2 вместо логина/пароля, асинхронные команды с опросом, кэш справочников).

  • Транспорты: stdio и streamable-HTTP.

  • Отбор тулов: по домену, по типу операции (read/write), по именам/glob, из разных источников (CLI / env / YAML).

  • Безопасность по умолчанию: read-only; запись — явным опт-ином, под подтверждением.

Зачем подмножество, а не все 236 тулов

В контекст модели при каждом подключении идут и JSON-схемы тулов, и их описания — считать надо обе части (здесь и далее вес в символах: у схем это практически байты, у русских описаний в UTF-8 байт вдвое больше).

Подмножество

Тулов

Схемы

Описания

Итого в контекст

все

236

~356 КБ

~83 КБ

~439 КБ

только read

106

~95 КБ

~29 КБ

~124 КБ

домен invoice_processing

93

~114 КБ

~23 КБ

~137 КБ

Сервер сам вырезает из схем служебные поля, которые ничего не дают модели (pydantic-title, дублирующий имя свойства, и описания вида «Latitude.», буквально повторяющие имя поля): без обрезки схемы весили бы ~433 КБ вместо ~356 КБ, то есть экономия около 18% (на описания обрезка не влияет). Самый тяжёлый отдельный тул — discounts__calculate_loyalty_checkin, 18.9 КБ схемы. Из 236 методов 106 — read, 130 — write; ошибок схематизации при интроспекции — 0, регистрируются все.

Отсюда практический совет: выбирайте --domains под конкретную задачу клиента, а не поднимайте сервер со всем каталогом — это и экономит контекст модели, и сокращает поверхность записи.

Related MCP server: OpenAPI MCP Server

Установка

# как пакет в активированное окружение: даёт команду iikocloud-mcp на PATH
uv pip install "iikocloud-mcp @ git+https://github.com/UserVanya/Iikocloud-mcp.git"

# или для разработки: команда доступна только как `uv run iikocloud-mcp`,
# на PATH сама по себе она не появляется
git clone https://github.com/UserVanya/Iikocloud-mcp.git && cd Iikocloud-mcp && uv sync

Требуется Python 3.12+ и креды iikoCloud auth v2 (api_key, app_id, client_secret).

Примеры ниже написаны для второго (dev) пути, поэтому идут с префиксом uv run. Если пакет установлен первым способом и его окружение активировано, префикс не нужен.

Быстрый старт

# stdio: клиент запускает сервер как подпроцесс, креды — через env
IIKOCLOUD_API_KEY=key IIKOCLOUD_APP_ID=app IIKOCLOUD_CLIENT_SECRET=secret \
  uv run iikocloud-mcp --transport stdio --domains organizations,menu

# HTTP: сервер на VPS, только чтение по организациям и меню.
# Слушаем 127.0.0.1 — TLS терминирует reverse-proxy на этом же хосте.
uv run iikocloud-mcp --transport http --host 127.0.0.1 --port 8000 \
  --domains organizations,menu,dictionaries,addresses

--host 0.0.0.0 оправдан только если TLS-прокси работает на другом хосте: сам сервер говорит по HTTP без шифрования, а в каждом запросе едут X-Iikocloud-Api-Key, X-Iikocloud-App-Id и X-Iikocloud-Client-Secret. Открытый в интернет порт — это те же креды открытым текстом (см. Безопасность).

Тот же результат — через конфиг-файл (см. server.example.yml):

cp server.example.yml server.yml   # server.yml в .gitignore
uv run iikocloud-mcp --config server.yml

Отбор тулов

Тул включается, если: домен разрешён И тип операции разрешён И (нет allow ИЛИ имя совпало с allow) И имя не совпало с deny. deny всегда побеждает allow.

Имена тулов — <домен>__<метод> (например menu__get_nomenclature, deliveries__create_delivery_order). 22 домена: addresses, banquets, customer_categories, customers, deliveries, deliveries_retrieve, delivery_restrictions, dictionaries, discounts, drafts, employees, invoice_processing, marketing_sources, menu, messages, notifications, operations, orders, organizations, report, terminal_groups, webhooks.

Способ

CLI

env

YAML

Домены

--domains a,b

IIKOCLOUD_MCP_DOMAINS=a,b

domains: [a, b]

Разрешить запись

--allow-write

IIKOCLOUD_MCP_ALLOW_WRITE=1

operations: [read, write]

Allowlist имён/glob

--allow 'get_*' --allow '*_report'

IIKOCLOUD_MCP_ALLOW=get_*,*_report

allow: ["get_*"]

Denylist имён/glob

--deny 'delete_*'

IIKOCLOUD_MCP_DENY=delete_*

deny: ["delete_*"]

Выключить подтверждение записи

--no-confirm-writes

IIKOCLOUD_MCP_CONFIRM_WRITES=0

confirm_writes: false

Фолбэк без elicitation

--write-fallback open

IIKOCLOUD_MCP_WRITE_FALLBACK=open

write_fallback: open

Лимит JSON-ответа (символы)

--max-output-chars N

IIKOCLOUD_MCP_MAX_OUTPUT_CHARS=N

max_output_chars: N

Таймаут вызова, с

--call-timeout N

IIKOCLOUD_MCP_CALL_TIMEOUT=N

call_timeout: N

Потолок окна лимитера, с

--max-rate-window N

IIKOCLOUD_MCP_MAX_RATE_WINDOW=N

max_rate_window: N

TTL кэша справочников, с

--cache-ttl N

IIKOCLOUD_MCP_CACHE_TTL=N

cache_ttl: N

Потолок записей кэша

--cache-max-entries N

IIKOCLOUD_MCP_CACHE_MAX_ENTRIES=N

cache_max_entries: N

Хост / порт

--host / --port

IIKOCLOUD_MCP_HOST / IIKOCLOUD_MCP_PORT

host: / port:

Транспорт

--transport {stdio,http}

IIKOCLOUD_MCP_TRANSPORT

transport:

Приоритет источников: CLI > env > YAML-файл. Источник, задавший поле, заменяет его целиком (списки не мержаются). Путь к YAML — --config server.yml или IIKOCLOUD_MCP_CONFIG. См. server.example.yml.

--allow-write — это только включение записи со стороны CLI: чтобы выключить её обратно, просто не передавайте флаг. У env-переменной IIKOCLOUD_MCP_ALLOW_WRITE есть и включающее, и выключающее значение (1/0, true/false и т. п.).

Примеры:

# всё чтение по доставкам, но без карт лояльности
uv run iikocloud-mcp --transport http --domains deliveries,deliveries_retrieve \
  --deny '*loyalty*'

# запись включена, но без операций очистки
uv run iikocloud-mcp --transport http --allow-write --deny '*__clear_*'

Пустое значение — это осознанный ноль, а не «без ограничения»: --domains ''domains: [] в YAML) даёт сервер без единого тула, а не со всеми 236. Так значение из файла можно очистить из CLI. Про непонятое имя домена и про нулевую регистрацию сервер пишет в лог предупреждение.

Передача учётных данных

Секреты идут только по каналу транспорта, не как аргументы тулов — модель их не видит.

HTTP-заголовок

env для stdio

API-ключ

X-Iikocloud-Api-Key

IIKOCLOUD_API_KEY

App ID

X-Iikocloud-App-Id

IIKOCLOUD_APP_ID

Client secret

X-Iikocloud-Client-Secret

IIKOCLOUD_CLIENT_SECRET

Фолбэка на Authorization: Basic нет: он вмещает два секрета, а iikoCloud требует три.

Для HTTP-транспорта обязателен TLS — терминируйте HTTPS на reverse-proxy перед сервером, заголовки с кредами передавайте только под ним. Отсюда и дефолт --host 127.0.0.1: сам сервер шифрования не делает, поэтому наружу он должен смотреть только через прокси. stdio — переменные окружения подпроцесса (см. выше), сервер как локальный процесс отдельного TLS не требует.

Один сервер обслуживает несколько аккаунтов iikoCloud: экземпляр менеджера кэшируется по отпечатку sha1(api_key:app_id:client_secret) (ApiCredentials.key_id). Все три секрета обязательны в отпечатке: если бы он строился только по api_key и app_id, вызывающий с верным ключом и app_id, но чужим или неверным client_secret, получил бы доступ к кэшу и уже авторизованной сессии другого арендатора.

Подключение MCP-клиента

stdio (например, конфиг Claude Desktop):

{
  "mcpServers": {
    "iikocloud": {
      "command": "iikocloud-mcp",
      "args": ["--transport", "stdio", "--domains", "organizations,menu,dictionaries"],
      "env": {
        "IIKOCLOUD_API_KEY": "key",
        "IIKOCLOUD_APP_ID": "app",
        "IIKOCLOUD_CLIENT_SECRET": "secret"
      }
    }
  }
}

command должен быть исполняемым файлом: голое iikocloud-mcp работает, только если пакет установлен через uv pip install в окружение, видимое клиенту. Для dev-установки укажите "command": "uv" и "args": ["run", "--directory", "/путь/к/Iikocloud-mcp", "iikocloud-mcp", "--transport", "stdio", ...].

Удалённый HTTP:

{
  "mcpServers": {
    "iikocloud": {
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "X-Iikocloud-Api-Key": "key",
        "X-Iikocloud-App-Id": "app",
        "X-Iikocloud-Client-Secret": "secret"
      }
    }
  }
}

Программный API

from iikocloud_mcp import ServerConfig, ToolFilter, create_server

cfg = ServerConfig(
    # host="0.0.0.0" — только если TLS терминирует прокси на другом хосте
    transport="http", host="127.0.0.1", port=8000,
    tool_filter=ToolFilter(domains={"menu", "dictionaries"}, operations=frozenset({"read"})),
)
server = create_server(cfg)        # FastMCP с зарегистрированными тулами
server.run(transport="streamable-http")

Подтверждение операций записи

Write-тулы по умолчанию требуют подтверждения пользователя перед мутацией — сервер вызывает MCP-elicitation и выполняет метод только при явном accept. Это серверный гейт, а не просто хинт клиенту (destructiveHint): даже клиент с авто-подтверждением тулов не выполнит запись без ответа пользователя. Политику задаёт оператор при запуске (не LLM):

  • по умолчанию — подтверждение включено, фолбэк closed;

  • --write-fallback open — если клиент не умеет elicitation, выполнять запись без подтверждения (оператор берёт риск на себя); по умолчанию (closed) такая запись блокируется;

  • --no-confirm-writes — полностью отключить гейт (для доверенной автоматизации).

Встроенные подсказки

Сервер обогащает описание и результат каждого тула, не полагаясь на память модели.

Асинхронные команды. 42 тула из 236 возвращают только correlationId — это квитанция о принятой команде, самого результата в ответе нет. Описание такого тула получает пометку:

⏳ Асинхронная команда: ответ содержит только correlationId, результата в нём нет. Чтобы узнать исход, вызовите operations__wait_command с этим correlationId и organizationId.

Ещё у 8 write-тулов ответ содержательный, и сервер ищет в нём поле creationStatus: если оно равно InProgress, к JSON-результату добавляется ключ _iikocloudMcpHint с той же инструкцией — опросить operations__wait_command. Реально сработать подсказка может у 4 из них — тех, что возвращают OrderInfo-подобную структуру: deliveries__create_delivery_order, drafts__commit_delivery_draft, orders__create_table_order, banquets__create_reserve. У остальных четырёх поля creationStatus в ответе нет вовсе: drafts__create_delivery_draft и drafts__save_delivery_draft возвращают CreateOrSaveDraftResponse (correlationId, orderId), employees__open_personal_session и employees__close_personal_sessioncorrelationId и error. Проверка идёт по значению в ответе, а не по типу, поэтому лишнего она не добавляет.

«Где взять ID». Схема параметров каждого тула сверяется с курируемой картой полей вида organizationId → organizations__get_organizations, terminalGroupId → terminal_groups__get_terminal_groups, productId → menu__get_nomenclature и т. д. Совпавшие поля попадают в описание тула строкой «Где взять ID: …», так что модель не пытается угадывать идентификаторы.

Как часто можно звать. Если у метода есть запись в лимитере менеджера, описание получает приписку вида «Троттлинг MCP-сервера (не лимит iikoCloud): не чаще N запрос(ов) за M с — кэшируйте результат в диалоге». Приписка намеренно говорит о клиентском троттлинге этого сервера (значения лимитера менеджера, уже с потолком --max-rate-window), а не о лимите самого API: настоящие лимиты iikoCloud бывают жёстче и описаны в докстрингах SDK, которые сервер не трогает (например, webhooks__update_webhook_settings — примерно 1 обновление в час).

У 17 тулов записи в лимитере нет: это тулы-обёртки вроде customers__get_customer_by_phone, который под капотом зовёт лимитируемый customers__get_customer_info. Молчание модель прочла бы как «ограничений нет», поэтому такие тулы получают общую приписку: своего троттлинга нет, но вызов расходует квоту нижележащего метода. Ручной карты «обёртка → метод» нет намеренно — она протухала бы при каждом изменении менеджера.

Версии внешнего меню. У menu__get_external_menu_by_id результат — объединение ExternalMenuV2 | ExternalMenuV3 | ExternalMenuV4: форма ответа зависит от параметра version. Описание тула вручную перечисляет все переименования полей между версиями и рекомендует явно указывать version=4.

Адрес доставки. У deliveries__create_delivery_order описание отдельно поясняет: формат адреса задаёт сама организация (addressFormatType, значение — из organizations__get_organization_settings), улицу можно передать и id (addresses__get_streets_by_city), и просто name вместе с city, а город указывать нужно всегда — он определяет разбор остального адреса.

Кэш справочников

15 из 22 тулов-источников идентификаторов (тех самых, куда отправляют подсказки «где взять ID») допускают не чаще одного запроса в 60 секунд — а диалог с моделью легко делает несколько похожих запросов подряд. Поэтому ответы примерно 27 справочных read-тулов (организации, домены справочников, адреса, меню, курьеры и т. п.) кэшируются в памяти процесса с TTL.

  • --cache-ttl — время жизни записи в секундах, по умолчанию 300; 0 полностью выключает кэш.

  • --cache-max-entries — потолок числа записей (LRU-вытеснение), по умолчанию 256; обязателен, потому что ответ menu__get_nomenclature может весить мегабайты.

Ключ кэша учитывает аккаунт (по хэшу кредов, не сами секреты) и аргументы вызова — на HTTP-транспорте один процесс безопасно обслуживает разных арендаторов. Инвалидация — только по TTL.

Лимит размера ответа и таймаут вызова

По умолчанию лимита на размер ответа нет. Если установить положительный --max-output-chars, слишком длинный результат вернётся не оборванным текстом, а корректным JSON-объектом:

{
  "truncated": true,
  "totalChars": 250000,
  "limitChars": 100000,
  "contentPrefix": "..."
}

contentPrefix — начало полного JSON-результата, так модель может распознать усечение и сузить запрос вместо того, чтобы принять обрезанный ответ за полный.

--call-timeout (по умолчанию 120 с) ограничивает время одного вызова тула — лимитер менеджера иначе просто блокирует запрос без таймаута. При превышении сервер тоже возвращает корректный JSON, а не обрыв соединения:

{
  "timeout": true,
  "tool": "menu__get_nomenclature",
  "timeoutSeconds": 120,
  "reason": "Вызов не уложился в лимит времени. Обычная причина — rate limit метода: лимитер ждёт освобождения окна. Повторите позже или сузьте запрос."
}

Текст reason у write-тулов другой, и это принципиально: asyncio.wait_for отменяет только ожидание внутри сервера, а запрос в iikoCloud уже ушёл и мог там выполниться — вместе с настоящим correlationId, который при таймауте теряется. Поэтому write-тул на таймауте сообщает, что операция могла пройти, что повтор создаст дубль (второй заказ, вторую бронь, второе пополнение) и что проверять надо чтением — для доставок семейством deliveries_retrieve__*.

--max-rate-window (по умолчанию 120 с) отдельно зажимает окна лимитера методов сверху: у методов с окном шире потолка (например 1 запрос/1800 с) окно укорачивается до потолка при сохранении числа запросов — иначе --call-timeout по умолчанию не успел бы дождаться собственного окна лимитера.

Тесты

uv run pytest -m unit -v          # 196 тестов, быстро, без сети и кредов
uv run pytest -m integration -v   # 4 read-only теста; без креда IIKOCLOUD_TEST_CONFIG — skip, не fail

Интеграционный набор (tests/integration/) гоняет реальные тулы через _make_tool против живого iikoCloud: получение организаций, camelCase-алиасы в ответе, попадание в кэш при повторном вызове, усечение по max_output_chars. Он только читающий — write-тестов против живого API нет и не будет: мутационный путь проверяется моками в tests/test_server.py.

Креды берёт из YAML по пути IIKOCLOUD_TEST_CONFIG (секция read) — см. config.test.example.yml и .env.example. Скопируйте оба в config.test.yml и .env: оба файла в .gitignore, секреты в репозиторий не попадают. Без IIKOCLOUD_TEST_CONFIG в окружении фикстура read_creds делает pytest.skip, а не падение, — так что набор безопасно запускать и на машине без кредов.

Безопасность

  • Секреты не попадают в аргументы тулов (модель их не видит), не логируются, живут только в памяти на время сессии.

  • Для HTTP обязателен TLS (reverse-proxy). Заголовки с кредами — только под HTTPS.

  • Дефолт и все примеры — host: 127.0.0.1. 0.0.0.0 открывает нешифрованный порт с кредами в заголовках; он оправдан только когда TLS-прокси стоит на другом хосте.

  • Своих гейтов по организациям или app_id сервер не вводит — доступ ограничивают настройки самого iikoCloud-аккаунта.

  • Дефолт read-only: мутации требуют явного --allow-write.

  • Дефолт: write-тулы требуют подтверждения пользователя (elicitation, см. выше).

Документация дизайна

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • 350+ production-ready APIs through one MCP server — weather, geocoding, validation, financial data.

  • 34 production API tools over one hosted MCP endpoint.

  • A paid remote MCP for AI SDK MCP gateway registry, built to return verdicts, receipts, usage logs, a

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/UserVanya/Iikocloud-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server