Skip to main content

kwork-mcp

CI PyPI Python License: MIT

kwork-mcp 1.0 — production-grade stdio MCP-шлюз к Kwork для Claude Code, Claude Desktop, Codex, Cursor и других MCP-клиентов. Он даёт типизированные read-результаты, проверяет фактический аккаунт, координирует лимиты между процессами и проводит все записи через durable prepare → commit → reconcile.

Это breaking redesign. Для миграции с 0.2.x см. руководство по миграции.

Что гарантирует шлюз

  • structuredContent соответствует объявленному outputSchema; текстовый content сохраняет краткое резюме и JSON-копию результата.
  • Read-операции различают known_data, known_empty и unknown_error; ошибки возвращаются с isError=true и стабильным кодом.
  • Перед каждым write заново проверяются KWORK_EXPECTED_USER_ID и фактический аккаунт. Без KWORK_ENABLE_WRITES=true запись невозможна.
  • Точный payload, его SHA-256, TTL, confirmation token и idempotency key связаны в общем SQLite ledger. Одну операцию выполняет только один процесс.
  • Неоднозначный результат записи не повторяется автоматически: состояние submission_unknown требует reconcile_write. Пропавший объект или неизвестный статус не считаются доказательством; если сверка не сходится, оператор фиксирует исход вручную через kwork-mcp-bootstrap resolve-write.
  • Лимиты account/route, защита от burst и circuit breaker общие для всех процессов, использующих один KWORK_STATE_DIR; fingerprint общей policy не позволяет процессу с другими лимитами ослабить координацию.
  • kwork==0.2.0 закреплён; сигнатуры и generic routes проверяются fail-loud при старте и contract-тестами.
  • Token и optional proxy сохраняются в account-scoped файлах с 0700/0600, flock, проверкой всей ancestor chain, O_NOFOLLOW/FD-anchored traversal и atomic replace. Runtime-discovered credentials динамически редактируются в логах и внешних данных.
  • Тексты проектов, профилей, сообщений и уведомлений помечаются external_untrusted и не являются инструкциями для агента.

Установка

Требуются Python 3.12–3.14 и uv.

uvx --from kwork-mcp==1.0.0 kwork-mcp-bootstrap --help

Из исходников:

git clone https://github.com/simonether/kwork-mcp.git
cd kwork-mcp
uv sync --locked --dev
uv run kwork-mcp-bootstrap --help

kwork-mcp использует только stdio. Все его логи идут в stderr; stdout зарезервирован для MCP JSON-RPC. kwork-mcp-bootstrap — отдельная human CLI и не является MCP transport.

Безопасная конфигурация

Обычный сервер работает без login/password/token/proxy в конфигурации host. Единственный поддерживаемый production flow:

  1. Узнайте стабильный numeric user_id своего аккаунта из настроек/профиля Kwork.
  2. Один раз запустите bootstrap из настоящего terminal TTY:
KWORK_EXPECTED_USER_ID=123456 \
  uvx --from kwork-mcp==1.0.0 kwork-mcp-bootstrap

CLI скрыто запросит login/password, optional phone digits и optional proxy URL, вызовет только auth + get_me, сверит точный user_id и атомарно запишет account-bound credential record. Если существует legacy ~/.kwork_token, CLI предложит явный validated import: только regular file текущего владельца с mode 0600, без symlink. Legacy-файл после успешного импорта намеренно остаётся на месте, чтобы удаление было отдельным осознанным действием.

  1. Запускайте normal MCP только с безопасными steady-state ключами:
export KWORK_EXPECTED_USER_ID='123456'
export KWORK_PERSIST_TOKEN='true'
export KWORK_ENABLE_WRITES='false'
uvx --from kwork-mcp==1.0.0 kwork-mcp

Normal entrypoint fail-closed отклоняет KWORK_LOGIN, KWORK_PASSWORD, KWORK_TOKEN, KWORK_PHONE_LAST и KWORK_PROXY_URL, даже если они пришли через environment. Не помещайте эти значения в Codex/Claude MCP config: некоторые hosts встраивают env map в собственный process argv. .env из cwd никогда не загружается. Secret values не принимаются через argv.

После запуска вызовите account_status и сверьте user_id. Только затем включайте KWORK_ENABLE_WRITES=true. KWORK_EXPECTED_USERNAME — дополнительная, более хрупкая проверка: username может быть переименован, primary identity — numeric ID.

По умолчанию состояние хранится в $XDG_STATE_HOME/kwork-mcp либо ~/.local/state/kwork-mcp. Это каталог с токенами и coordination.sqlite3; все процессы одного аккаунта должны использовать один локальный KWORK_STATE_DIR и одинаковые shared rate/circuit/write settings. Несовместимый fingerprint отклоняется fail-loud. Файлы содержат чувствительные данные и не зашифрованы самим приложением — используйте защищённую учётную запись ОС и шифрование диска. Вся физическая ancestor chain должна принадлежать текущему user либо root и не быть group/other-writable. Разрешён один стандартный sticky temp boundary (например, /tmp), после которого gateway создаёт private 0700 каталог; обычный 0777 parent, чужой owner, final symlink или подмена компонента отклоняются. Версия 1.0 использует POSIX fcntl/flock и поддерживает Linux/macOS, но не Windows.

Optional proxy вводится только bootstrap-команде и сохраняется рядом с token в защищённом account record; normal server не принимает KWORK_PROXY_URL. Legacy record без proxy означает прямое подключение. Чтобы добавить, заменить или удалить proxy либо обновить истёкшую сессию, остановите процессы этого account/state, повторите bootstrap и перезапустите MCP. Файл защищён правами ОС, но не шифруется на уровне приложения.

Полный справочник: docs/configuration.md.

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

Сначала выполните bootstrap в обычном терминале, как показано выше. В конфигурацию клиента передаются только безопасные значения: KWORK_EXPECTED_USER_ID, KWORK_PERSIST_TOKEN и KWORK_ENABLE_WRITES. Замените 123456 на свой user_id. После изменения конфигурации перезапустите клиент и вызовите account_status.

Claude Code

claude mcp add kwork --scope user \
  -e KWORK_EXPECTED_USER_ID=123456 \
  -e KWORK_PERSIST_TOKEN=true \
  -e KWORK_ENABLE_WRITES=false \
  -- uvx --from kwork-mcp==1.0.0 kwork-mcp

Проверка: claude mcp list должен показать kwork в состоянии connected.

Claude Desktop

Добавьте сервер в claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "kwork": {
      "command": "uvx",
      "args": ["--from", "kwork-mcp==1.0.0", "kwork-mcp"],
      "env": {
        "KWORK_EXPECTED_USER_ID": "123456",
        "KWORK_PERSIST_TOKEN": "true",
        "KWORK_ENABLE_WRITES": "false"
      }
    }
  }
}

Если Claude Desktop не находит uvx, укажите абсолютный путь из which uvx.

Cursor

Тот же блок mcpServers добавляется в ~/.cursor/mcp.json (глобально) или в .cursor/mcp.json проекта.

Codex

Добавьте в ~/.codex/config.toml:

[mcp_servers.kwork]
command = "uvx"
args = ["--from", "kwork-mcp==1.0.0", "kwork-mcp"]

[mcp_servers.kwork.env]
KWORK_EXPECTED_USER_ID = "123456"
KWORK_PERSIST_TOKEN = "true"
KWORK_ENABLE_WRITES = "false"

Для локальной checkout-версии:

[mcp_servers.kwork]
command = "uv"
args = ["--directory", "/absolute/path/to/kwork-mcp", "run", "kwork-mcp"]

[mcp_servers.kwork.env]
KWORK_EXPECTED_USER_ID = "123456"
KWORK_PERSIST_TOKEN = "true"
KWORK_ENABLE_WRITES = "false"

Codex CLI, IDE extension и desktop app используют общую MCP-конфигурацию host.

Ни в одном клиенте не добавляйте token/login/password/phone/proxy — ни как env, ни как env_vars, ни как arguments: сервер откажется запускаться.

MCP tools

Read-only

Tool Результат
account_status Фактический account ID, binding, готовность writes и unresolved_write_ids
get_connects Активные и общие коннекты
get_user_info, search_users Профиль/поиск пользователей
discover_projects favorites, all или category_ids, фильтры и opaque cursor
get_project, get_exchange_info Проект и полная exchange-информация
list_my_offers, get_offer Офферы с обязательными offer_id и project_id
list_worker_orders, get_order_details Заказы продавца и полные details
list_dialogs, get_dialog Диалоги и сообщения
list_my_kworks, get_kwork_details Собственные кворки
list_categories, list_favorite_categories Категории
list_notifications Полные группы уведомлений

discover_projects не смешивает режимы:

  • favorites — избранные категории аккаунта;
  • all — вся биржа;
  • category_ids — обязательный непустой список ID.

Возвращаемый PageInfo содержит next_cursor, query_fingerprint и high_watermark. Cursor подписан и привязан к подтверждённому аккаунту и точным фильтрам. Watermark позволяет клиенту вести локальную точку наблюдения для будущего delta polling, но 1.0 не обещает отдельный delta endpoint.

Safe write-flow

Поддерживаемые request.action: submit_offer, delete_offer, send_message, edit_message, delete_message, mark_dialog_read, submit_order_approval, set_kwork_state.

  1. Вызовите prepare_write с точным request и собственным стабильным idempotency_key.
  2. Проверьте возвращённые payload, payload_hash, account ID и expires_at.
  3. Передайте неизменённые write_id, payload_hash и confirmation_token в commit_write.
  4. Если state равен submission_unknown, не вызывайте commit повторно. После visibility window вызовите reconcile_write(write_id). Пока такая запись не сверена, новые commit для аккаунта отклоняются с ambiguous_write, а error.related_write_id называет запись, которую нужно сверить.
  5. get_write_status читает durable ledger без remote write.

Пример payload для подготовки оффера:

{
  "request": {
    "action": "submit_offer",
    "project_id": 123,
    "title": "Точное название предложения",
    "description": "Описание длиной не менее 150 символов, соответствующее проекту и не содержащее секретов.",
    "price": 10000,
    "duration_days": 5
  },
  "idempotency_key": "project-123-offer-v1"
}

Remote write никогда не retry автоматически. Повторный prepare_write с тем же idempotency key и другим request возвращает idempotency_conflict; пока исходная запись остаётся prepared, точный replay того же request возвращает ту же запись и тот же HMAC-derived confirmation token. Это позволяет безопасно восстановиться после потери ответа prepare, не создавая второй intent. После claim/terminal state confirmation token больше не выдаётся; состояние читается через get_write_status.

Если reconcile_write долго остаётся неоднозначным (например, кворк ушёл на модерацию или сообщение удалено), проверьте операцию на kwork.ru и зафиксируйте исход вручную. Команды запускаются с теми же KWORK_* настройками, что и сервер, а resolve-write требует TTY и явного подтверждения:

kwork-mcp-bootstrap pending-writes
kwork-mcp-bootstrap resolve-write <write_id> succeeded
kwork-mcp-bootstrap resolve-write <write_id> absent

Модель результата и ошибок

Каждый tool возвращает envelope версии 1.0:

{
  "schema_version": "1.0",
  "knowledge_state": "known_data",
  "summary": "…",
  "data": {},
  "error": null,
  "meta": {
    "source": "kwork",
    "content_trust": "external_untrusted",
    "observed_at": "…",
    "correlation_id": "…",
    "upstream_contract": "kwork==0.2.0"
  }
}

Коды ошибок и retry/reconciliation semantics описаны в docs/security.md. Неизвестное имя tool является protocol-level JSON-RPC -32602, а не обычным isError business-result; имя из недоверенного запроса намеренно не отражается в сообщении.

Архитектура и границы

Шлюз отвечает за MCP transport, авторизацию Kwork, account binding, корректность upstream-контракта, типизацию данных и безопасную доставку write-запроса. Он намеренно не содержит скоринг проектов, Notion, Telegram, email, CRM и другую pipeline/business logic.

MCP Tasks отключены. Стабильная спецификация считает их экспериментальными, а MCP-клиенту для коротких Kwork API-вызовов durable task lifecycle не даёт пользы. Durability write-flow реализована внутри ledger и доступна обычными tools без нестабильного protocol surface.

Подробнее: архитектура и security model.

Разработка

uv sync --locked --dev
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest tests/ -v --cov=kwork_mcp --cov-report=term-missing
uv build
uv run twine check dist/*
uv run check-wheel-contents dist/*.whl

Coverage gate — 92% branch-aware покрытия. CI дополнительно проверяет Python 3.12–3.14, зависимости, секреты, pinned MCP Registry schema, wheel install smoke и согласованность версий.

Лицензия

MIT

Release files for kwork-mcp 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kwork-mcp 1.0.0
File Size Uploaded
kwork_mcp-1.0.0.tar.gz 348.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kwork-mcp 1.0.0
File Interpreter ABI Platform
kwork_mcp-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 445.9 kB

Release files / kwork_mcp-1.0.0.tar.gz

Download URL kwork_mcp-1.0.0.tar.gz
Size 348.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f27e365477bbfd898a6bd08a992010536edcc9e3f25737851f1b9e886573d125
BLAKE2b-256 checksum
How to use checksums
4dff197e80fb7e0e48637ccf7325b1ad8dc1b3a0388fcf883a48203dd099afd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / kwork_mcp-1.0.0-py3-none-any.whl

Download URL kwork_mcp-1.0.0-py3-none-any.whl
Size 97.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2fa9cecb2a111113ec65ca65907c2c2af7f1ca73c914edbf756a35d5d6d5d020
BLAKE2b-256 checksum
How to use checksums
740355a42533930ad0d45158413b2f9c344a88945866fe8d53bb1fa09e464cf7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.0

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page