Skip to main content
Glama

approval-gate-mcp

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

Создан на основе FastMCP. Работает с любым MCP-клиентом.

Проблема

Процесс, который действует сам по себе, полезен ровно до тех пор, пока одно из его действий не становится значимым. Обычные ответы одинаково плохи. Выключите его — и вы потеряете всё, что он делал хорошо. Оставьте работать — и узнаете об этом потом.

Шлюз — это третий вариант. Процесс продолжает работать без присмотра, но когда он хочет выполнить действие, которое вы пометили как значимое, он записывает предложение и движется дальше, вместо того чтобы действовать. Вы просматриваете предложения, когда до них доходят руки, в любом уже открытом MCP-клиенте, и одобряете или отклоняете. Процесс подхватывает ваше решение на следующем цикле.

Ни одна из сторон не блокирует другую. Между ними нет никакого сервиса. Контракт — это два JSON-файла.

  process                            you
     |                                |
     |-- writes proposal ----> pending.json
     |                                |
     |                          list_pending_approvals
     |                          approve(0) / reject(1)
     |                                |
     |<-- reads on next cycle -- approved.json
     |
     |-- acts, appends to records.json

Инструменты

Шлюз одобрения

Инструмент

Что делает

list_pending_approvals

Каждое предложение, ожидающее решения, со всеми его полями

approve(index)

Переместить одно предложение в файл одобренных

reject(index)

Отклонить одно предложение

Управление процессом

Инструмент

Что делает

process_status

Запущен или нет, PID, время работы, ЦП, память, диск, последняя строка журнала

process_logs(lines)

Хвост файла журнала

restart_process

Перезапуск через ваш стартовый скрипт, в отвязанном режиме, чтобы пережить SSH-сессию

run_command(cmd)

Запасной выход для разовых проверок

Записи

Инструмент

Что делает

record_summary(n)

Итоги, решённые и открытые, разбивка по типам, последние записи

record_dashboard

Более широкая таблица, а также открытые записи и их экспозиция

Параметры — регистрируются только если PARAMS_SCHEMA указывает на ваш манифест

Инструмент

Что делает

list_params

Что данное развертывание объявляет настраиваемым и что переопределено прямо сейчас

set_param(name, value)

Записать одно переопределение с проверкой по вашему манифесту

clear_param(name)

Удалить одно переопределение или все сразу

Цепочка — регистрируется только если заданы EVM_RPC_URL, WALLET_ADDRESS и TOKEN_CONTRACT

Инструмент

Что делает

wallet_balance

Баланс ERC-20 и нативный баланс для отслеживаемого адреса только для чтения. Ничего не подписывается

Установка

git clone https://github.com/WillyV347/approval-gate-mcp
cd approval-gate-mcp
pip install -r requirements.txt
cp .env.example .env      # then edit it

Попробуйте в инспекторе, прежде чем подключать к клиенту:

fastmcp dev server.py

Затем зарегистрируйте его. Для клиента, который читает JSON-конфигурацию:

{
  "mcpServers": {
    "approval-gate": {
      "command": "python3",
      "args": ["/absolute/path/to/approval-gate-mcp/server.py"],
      "env": {
        "VPS_HOST": "your.host.or.ip",
        "VPS_USER": "your-ssh-user",
        "PROCESS_DIR": "/srv/my-process",
        "PROCESS_MATCH": "my_process.py",
        "PARAMS_SCHEMA": "/absolute/path/to/params.schema.json"
      }
    }
  }
}

Для VPS_HOST, VPS_USER и PROCESS_DIR нет значений по умолчанию. Сервер завершает работу с понятным сообщением, если они отсутствуют. Инструмент мониторинга, который молча откатывается к хосту, зашитому его автором, — это баг, поэтому этот отказывается угадывать.

Аутентификация — это ваша существующая настройка SSH. Сервер вызывает системный бинарник ssh, поэтому агенты, аппаратные ключи и менеджеры паролей, поддерживающие агента, работают без изменений. Сам он никогда не читает закрытый ключ.

Контракт, который реализует ваш процесс

На стороне процесса нужны три вещи. Ни одна из них не требует библиотеки.

1. Записи. Добавляйте в JSON-массив. Четыре ключа интерпретируются, если присутствуют, а всё остальное переносится без изменений:

[
  {
    "id": "job-1041",
    "record_type": "reindex",
    "resolved": true,
    "outcome": "win",
    "cost": 4.25,
    "result": 11.80,
    "label": "nightly reindex, shard 3"
  }
]

2. Предложения. В режиме одобрения записывайте сюда вместо действия:

{
  "proposals": [
    {
      "id": "job-1042",
      "label": "reindex shard 7",
      "action": "reindex",
      "cost": 6.00,
      "created_at": "2026-08-18T22:14:07Z"
    }
  ]
}

Каждое включенное поле отображается. У сервера нет схемы для предложений, и она ему не нужна.

3. Опросите файл одобренных. На каждом цикле читайте approved.json, выполняйте то, что там есть, и очищайте его. Примерно:

approved = read_json(APPROVED_FILE) or {"proposals": []}
for proposal in approved["proposals"]:
    execute(proposal)
write_json(APPROVED_FILE, {"proposals": []})

Порядок на стороне сервера продуман. Решение удаляет предложение из pending.json до записи в approved.json, поэтому сбой при незавершенном решении приводит к потере предложения, но никогда к дублированию действия.

Параметры и почему их нет в этом репозитории

Горячая перезагрузка полезна только если сервер знает, что можно настраивать, а зашивание параметров одного развертывания в общий инструмент делает его узкоспециализированным. Поэтому вы объявляете свои параметры в манифесте и указываете на него через PARAMS_SCHEMA:

{
  "poll_interval_seconds": { "type": "int",  "description": "Seconds between work cycles" },
  "max_concurrent_jobs":   { "type": "int",  "description": "Jobs in flight at once" },
  "dry_run":               { "type": "bool", "description": "Plan work but do not execute" },
  "approval_mode":         { "type": "bool", "description": "Queue proposals instead of acting" }
}

Поддерживаемые типы: int, float, bool, str, dict и list. set_param приводит и проверяет по ним и отклоняет всё, что не конвертируется. Без манифеста инструменты параметров просто не регистрируются, что лучше, чем открывать путь записи без проверки.

params.schema.json находится в .gitignore, потому что ваша настройка — ваша. params.schema.example.json поставляется в качестве отправной точки.

Пусть ваш процесс читает файл переопределений при запуске и на каждом цикле, если вы хотите, чтобы изменения применялись без перезапуска:

overrides = read_json(PARAMS_FILE) or {}
poll_interval = overrides.get("poll_interval_seconds", POLL_INTERVAL_DEFAULT)

Пример сеанса

> is it running?

  Process RUNNING

  PID:      31882
  Uptime:   14h 22m (51720s)
  CPU:      0.6%
  Memory:   84.3 MB
  Disk:     212M

  Last log: 2026-08-18 22:03:11 cycle complete, 2 proposals queued

> anything waiting on me?

  2 proposal(s) awaiting approval

  --- Proposal #0 ------------------------------
    id:           job-1042
    label:        reindex shard 7
    action:       reindex
    cost:         6.00
    created_at:   2026-08-18T22:14:07Z

  --- Proposal #1 ------------------------------
    id:           job-1043
    label:        reindex shard 12
    action:       reindex
    cost:         6.00
    created_at:   2026-08-18T22:14:07Z

  Use approve(index) or reject(index) to decide.

> approve 0, reject 1

  Approved and queued for execution: reindex shard 7
  Rejected and removed: reindex shard 12

Вывод выше носит иллюстративный характер.

Заметки о безопасности

  • run_command выполняет произвольный shell на удаленном хосте. Он существует, потому что альтернатива — всё равно открывать терминал, но это самый опасный инструмент здесь. Ограничьте SSH-пользователя тем, что ему действительно нужно, а не запускайте всё от root.

  • wallet_balance доступен только для чтения и никогда не касается ключа. Если вы его не настроили, его не существует.

  • Ничто в этом репозитории не хранит учетные данные. RPC-URL несут ключи провайдера в пути, поэтому держите EVM_RPC_URL в переменных окружения, а не в конфигурационных файлах.

  • StrictHostKeyChecking установлен в accept-new: неизвестные хосты доверяются при первом подключении, измененные ключи хоста по-прежнему приводят к ошибке. Установите yes и заранее заполните known_hosts, если хотите более строгое поведение.

Лицензия

MIT

-
license - not tested
-
quality - not tested
C
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 Connectors

  • Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.

  • A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready

  • A paid remote MCP for hosted MCP server, built to return verdicts, receipts, usage logs, and audit-r

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/WillyV347/approval-gate-mcp'

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