Локальный HTTP API
Через этот API работает MCP-сервер, и к нему же можно обращаться напрямую — из Python, Node, n8n, Postman или любой программы, которая умеет HTTP.
Адрес и токен
Заголовок раздела «Адрес и токен»После Automation → Enable API / MCP access Accovod запускает сервер на 127.0.0.1 и записывает параметры в файл:
~/Library/Application Support/Accovod/control.json{ "app": "Accovod", "platform": "macos", "apiVersion": "1.0", "port": 25252, "token": "8f3c…", "baseUrl": "http://127.0.0.1:25252"}- Порт — 25252, если он свободен. Надёжнее читать
baseUrlиз файла, чем хардкодить адрес. - Файл удаляется, когда Accovod закрывается. Нет файла — приложение не запущено или API выключен.
- Токен меняется через Automation → Regenerate token.
Как вызывать
Заголовок раздела «Как вызывать»Одна точка входа — POST /v1/rpc, в теле указывается метод и параметры:
CONTROL=~/Library/Application\ Support/Accovod/control.jsonBASE=$(jq -r .baseUrl "$CONTROL")TOKEN=$(jq -r .token "$CONTROL")
curl -s "$BASE/v1/rpc" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"method":"profiles.list","params":{}}'import json, pathlib, urllib.request
control = json.loads(pathlib.Path( "~/Library/Application Support/Accovod/control.json").expanduser().read_text())
def call(method, **params): req = urllib.request.Request( control["baseUrl"] + "/v1/rpc", data=json.dumps({"method": method, "params": params}).encode(), headers={"Authorization": f"Bearer {control['token']}", "Content-Type": "application/json"}) reply = json.load(urllib.request.urlopen(req)) if not reply["ok"]: raise RuntimeError(reply["error"]) return reply["result"]
for p in call("profiles.list")["profiles"]: print(p["name"], p["url"])GET /v1/health отвечает без токена — так можно проверить, запущено ли приложение.
Формат ответа
Заголовок раздела «Формат ответа»Все ответы в одном конверте:
{ "ok": true, "result": { … } }{ "ok": false, "error": { "code": "PROFILE_NOT_FOUND", "message": "…", "hint": "…" } }hint подсказывает, что поправить в запросе. Необязательное поле id из запроса возвращается в ответе.
Главные правила
Заголовок раздела «Главные правила»profileId— единственный надёжный идентификатор профиля. Берите его изprofiles.listи передавайте во все методыpage.*. Полеindexменяется при сортировке.- Сначала
app.status. Он показывает режим загрузки профилей (allилиactiveOnly), активную группу и остановлен ли агент. - Элементы — через
page.snapshot. Он возвращает список интерактивных элементов с готовым объектомtarget. Передавайте его вpage.clickиpage.fillцеликом. После перехода на другую страницу сделайте новый снимок. - Повторы безопасны.
profiles.create,profiles.createMany,profiles.importManyтребуютidempotencyKey: повтор с тем же ключом вернёт уже созданное, а не создаст дубль. - Удаление — только с
confirm: true. Без негоprofiles.deleteиsessions.deleteничего не удаляют и отвечают, что именно было бы удалено. - Долгие операции можно запускать через
operations.startи спрашивать результат черезoperations.get— это спасает при таймаутах клиента.
Частые ошибки
Заголовок раздела «Частые ошибки»| Код | HTTP | Что значит |
|---|---|---|
UNAUTHORIZED |
401 | Нет токена или токен неверный. |
BROWSER_ORIGIN_BLOCKED |
403 | Запрос пришёл со страницы в браузере — такие отклоняются. |
AGENT_STOPPED |
409 | Пользователь нажал Stop. Всё, кроме app.status, отклоняется до Resume. |
PROFILE_NOT_FOUND |
404 | Такого profileId нет в открытой группе. |
PROFILE_NOT_LIVE |
409 | У профиля нет открытой вкладки — в режиме activeOnly сначала вызовите profiles.open. |
REVISION_MISMATCH |
409 | Профиль изменили, пока вы его читали. Ничего не записано — перечитайте и повторите. |
PROFILE_LIMIT_REACHED |
409 | В облачной группе закончился лимит тарифа. |
TARGET_NOT_FOUND / AMBIGUOUS_TARGET |
404 / 409 | Элемент не найден или подходят несколько — ничего не нажато. |
ELEMENT_OCCLUDED |
409 | Элемент перекрыт баннером или окном — в сообщении указано, чем именно. |
CONFIRMATION_REQUIRED |
400 | Удаление без confirm: true. |
Все методы и их основные параметры — в справочнике инструментов. Имя MCP-инструмента и метода API связаны просто: profiles_list ↔ profiles.list, page_wait_for ↔ page.waitFor.
