PatchFirst / Разработчикам
API и MCP
Получайте находки платных серверов, составляйте очередь обновлений и запускайте пересчёт из своих инструментов.
Отдельный токен для каждой интеграции
Создайте персональный API-токен в разделе «API-токены» кабинета. Укажите имя до 64 символов, права read или write (чтение и запись), срок от 1 до 365 дней. Для выпуска повторно введите текущий пароль аккаунта. При смене или восстановлении пароля все API-токены аккаунта отзываются. Обычный выход из кабинета сохраняет доступ CI и MCP. Чтобы отозвать все токены, нажмите отдельную кнопку «Отозвать все токены» в кабинете. Причина отзыва видна в кабинете. Одновременно доступно до 50 действующих токенов. Скопируйте секрет сразу: он показывается один раз. Сервис хранит только проверочный хэш. В кабинете можно посмотреть список токенов, отозвать токен и открыть журнал его использования.
Используйте HTTPS и передавайте токен только в заголовке Authorization: Bearer …. Токены в URL отклоняются. В примерах токен находится в переменной окружения PATCHFIRST_API_TOKEN; не сохраняйте секрет в репозитории, скриншотах и логах. Существующие ключи чтения/записи парка и токены агентов — отдельные учётные данные.
curl --fail-with-body "https://patchfirst.dev/v1/me/fleets" \
-H "Authorization: Bearer $PATCHFIRST_API_TOKEN"Токен открывает только парки своего владельца. Чужой парк возвращает 404, как и несуществующий. Токен read не может запускать пересчёт. Доступ браузера с другого источника закрыт (CORS).
API и MCP доступны для платного мониторинга. Без подходящей оплаты запросы возвращают 402. После истечения мониторинга доступны только сохранённые снимки отчётов уже оплаченного периода по правилам биллинга, без новых данных. Детали CVE требуют активной оплаты: без неё API возвращает 402, а инструмент cve_details — ошибку оплаты в результате MCP; свежие KEV, EPSS, эксплойты, sightings и упоминания в архиве недоступны. Новые расчёты требуют действующего права на мониторинг, включая предусмотренный биллингом льготный период; бесплатные места сами по себе доступа к API не дают.
Эндпоинты API v1
Базовый адрес: https://patchfirst.dev. Подставляйте вместо {fleet} и {server} UUID из списков парков и серверов. Все эндпоинты этой таблицы используют персональный Bearer-токен.
| Метод и путь | Результат |
|---|---|
GET /v1/me/fleets | Парки владельца: {"fleets":[{"id":"…","created_at":1792713600}]}. |
GET /v1/me/fleets/{fleet}/servers | Доступные платные серверы: {"servers":[{"id":"…","name":"web-1","name_kind":"alias","updated_at":1792713600}]}. |
GET /v1/me/fleets/{fleet}/report | Рейтинг парка, счётчики P0–P3 и отчёты серверов в assets. |
GET /v1/me/fleets/{fleet}/servers/{server}/report | Рейтинг сервера, находки, CVE, версии исправления и рекомендации. |
GET /v1/me/fleets/{fleet}/servers/{server}/history | {"history":[…]}: сохранённые снимки рейтинга. |
GET /v1/me/cves/{cve} | Запись CVE, KEV, EPSS, эксплойты и упоминания в источниках. Пример ID: CVE-2026-12345. |
POST /v1/me/fleets/{fleet}/refresh | 202: пересчёт принят. Нужны write и право на мониторинг. Получите результат повторным чтением отчёта. |
curl --fail-with-body "https://patchfirst.dev/v1/me/fleets/11111111-1111-4111-8111-111111111111/report" \
-H "Authorization: Bearer $PATCHFIRST_API_TOKEN"
curl --fail-with-body -X POST "https://patchfirst.dev/v1/me/fleets/11111111-1111-4111-8111-111111111111/refresh" \
-H "Authorization: Bearer $PATCHFIRST_API_TOKEN"Управление токенами в кабинете использует сессию вошедшего пользователя отдельно от Bearer-доступа: GET/POST /v1/account/api-tokens, DELETE /v1/account/api-tokens/{token_id}, GET /v1/account/api-tokens/{token_id}/usage. Создание принимает {"name":"acme integration","scope":"read","expires_in_days":30,"password":"CURRENT_PASSWORD"} и возвращает 201 с метаданными и одноразовым секретом token. Запись с сессией требует проверки того же источника запроса.
Формат ответов и имена
Документ OpenAPI задаёт JSON-схемы v1. Значение и тип существующих полей сохраняются; клиенты должны допускать новые поля. Успешный ответ — JSON-объект. Списки лежат в массивах fleets, servers или history. Время в метаданных токена, создание парка, обновление сервера и recorded_at истории — секунды Unix (UTC); computed_at отчёта — строка даты и времени UTC либо null.
Отчёт сервера содержит id, name, name_kind, score, grade, counts, findings. В находке: priority (P0–P3), component, установленная version, исправленная версия fix, рекомендация action и CVE в top. Если исправления нет, fix может быть пустым или null; проверяйте unfixed, pro_only, action.
score и grade — основной рейтинг по проверенным компонентам. global_score и global_grade — глобальный рейтинг с учётом неизвестного риска непроверенной доли. Объект coverage содержит целые числа checked (проверено) и total (всего обнаружено). Эти поля возвращаются в отчётах сервера и парка, списках серверов и сохранённых снимках истории. В отчёте парка охват суммируется по серверам, а глобальный рейтинг взвешивается так же, как основной. Грейд ? означает, что соответствующий рейтинг недоступен: показывайте ?, даже если для совместимости сохранено числовое значение. У старого снимка до появления двух рейтингов глобальных данных может не быть: числовое значение — null, клиенту следует допускать null.
Поля complete, rating_complete, reasons и blind сохраняются для совместимости и описывают охват. Они не заменяют основной рейтинг и не задают вердикт. Методика глобального рейтинга и охвата →
Открытое условное имя, например web-1, приходит с name_kind: "alias". Для зашифрованных и незаданных имён name_kind: "opaque" означает непрозрачную метку. Удалённый сервис не знает зашифрованных имён серверов и не может их расшифровать. Не используйте домены, IP, названия компании или клиента как открытые условные имена.
Ошибки, лимиты и журнал
Стабильный формат ошибки: {"error":"Понятное описание","code":"machine_code"}. В программной логике используйте HTTP-статус и code; текст описания может меняться.
| Статус | Значение |
|---|---|
| 400 | Неверные данные, неподдерживаемые параметры или токен в URL. |
| 401 | Токен отсутствует, неверен, истёк или отозван. |
| 402 | Нужен платный мониторинг либо доступный снимок оплаченного периода. |
| 403 | Недостаточно прав или неверный источник запроса; для пересчёта нужен write-токен. |
| 404 | Ресурс не существует или принадлежит другому владельцу. |
| 405 | Метод не поддерживается; MCP принимает POST. |
| 409 | Достигнут лимит 50 действующих персональных API-токенов. |
| 429 | Слишком много запросов. Подождите число секунд из Retry-After. |
Разрешено 120 запросов в минуту на аккаунт суммарно для API и MCP: все токены аккаунта делят один лимит. Для пересчёта парка действует отдельный лимит 10 запросов в минуту на аккаунт, общий для API и MCP. Журнал показывает до 100 последних сохранённых обращений. Одинаковые обращения (токен, метод, путь, статус) сохраняются не чаще раза в минуту; ответы 429 не записываются. Записи хранятся до 30 дней и до 1000 на токен; ежечасная чистка удаляет превышения. История рейтинга возвращает до 1000 последних записей. Журнал содержит время, метод, путь и HTTP-статус; тела запросов и ответов, а также секрет токена в него не попадают.
Подключение удалённого MCP
Адрес: https://patchfirst.dev/v1/mcp. Транспорт: Streamable HTTP, протокол 2025-06-18, тот же Bearer-токен, проверка владельца и оплаты. Начните с токена чтения. Удалённые инструменты: list_servers, server_report, fleet_report, cve_details, patch_first (что обновить первым). Для пересчёта доступен инструмент refresh_fleet: требуются write, UUID fleet и активная оплата; действует отдельный лимит пересчёта на аккаунт.
server_report принимает UUID fleet и server; fleet_report — fleet; cve_details — cve. list_servers возвращает UUID парка в поле fleet. Для list_servers и patch_first параметр fleet необязателен: по умолчанию используется ваш парк. Схемы аргументов возвращает tools/list. Ошибки протокола приходят в формате JSON-RPC; ошибки выполнения инструмента, включая оплату и лимит пересчёта, — с HTTP 200 и isError: true.
Поддерживается только статический Bearer: токен вручную выпускается в кабинете и задаётся в конфигурации клиента. OAuth-сервер авторизации не предоставляется; автоматическое получение токена через OAuth не поддерживается. Это ограниченный режим статического токена; полный поток авторизации OAuth из спецификации MCP не реализован. Открытый эндпоинт /.well-known/oauth-protected-resource публикует адрес MCP, документацию и ссылку на выпуск токена в кабинете (token_issuance_uri). При 401 заголовок WWW-Authenticate: Bearer resource_metadata="…" указывает на эти метаданные. Используйте клиент с поддержкой вручную заданного Bearer-токена.
Claude Code
Задайте токен в окружении, затем добавьте HTTP-сервер:
claude mcp add --transport http patchfirst "https://patchfirst.dev/v1/mcp" \
--header "Authorization: Bearer $PATCHFIRST_API_TOKEN"Codex
Добавьте в ~/.codex/config.toml и запускайте Codex с заданной переменной PATCHFIRST_API_TOKEN:
[mcp_servers.patchfirst]
url = "https://patchfirst.dev/v1/mcp"
bearer_token_env_var = "PATCHFIRST_API_TOKEN"Официальная документация OpenAI о настройке MCP в Codex.
Cursor
Добавьте сервер в настройках MCP или в локальном ~/.cursor/mcp.json. Вместо заглушки укажите свой токен и храните этот файл как секрет:
{
"mcpServers": {
"patchfirst": {
"url": "https://patchfirst.dev/v1/mcp",
"headers": {"Authorization": "Bearer YOUR_API_TOKEN"}
}
}
}Пример протокола
Сервер не хранит сессии. Отправляйте Accept: application/json, text/event-stream и Content-Type: application/json. Сначала initialize, затем notifications/initialized, после — tools/list или tools/call с MCP-Protocol-Version: 2025-06-18. Уведомления возвращают 202 без тела; идентификатор серверной сессии не нужен. GET /v1/mcp возвращает 405 с заголовком Allow: POST.
curl --fail-with-body "https://patchfirst.dev/v1/mcp" \
-H "Authorization: Bearer $PATCHFIRST_API_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"acme","version":"1.0"}}}'Пересчёт через MCP
Пример tools/call с write-токеном; замените UUID парка:
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"refresh_fleet","arguments":{"fleet":"11111111-1111-4111-8111-111111111111"}}}Локальный MCP с расшифровкой имён
Существующий core/mcp_server.py продолжает работать через stdio. Запускайте python3 /path/to/patchfirst/core/mcp_server.py локально с настроенным CLI владельца и локальными файлами парков (PSR_FLEETS, PSR_INVENTORY). Он умеет восстанавливать имена из локального зашифрованного словаря. Удалённый MCP оставляет зашифрованные имена непрозрачными.