Балабонус-Гардіан
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Балабонус-Гардіанперевір мій баланс балабонусів"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🛡️ Балабонус-Гардіан
Guardrail-проксі між AI-клієнтом і офіційним MCP «Сільпо» (https://mcp.silpo.ua/mcp).
Агент бачить усі тули «Сільпо» без змін (станом на 10.09.2026 їх 40) — але кожна write-дія (кошик, балабонуси, сертифікати, адреса, оплата) проходить детерміновану перевірку політик, за потреби — підтвердження людини, а відповіді read-тулів перевіряються на prompt-injection. Кожен крок пишеться у hash-chain audit trail. Токени «Сільпо» лежать лише на сервері, зашифровані Fernet; AI-клієнт їх не бачить.
┌──────────────┐ JSON-RPC / Streamable HTTP ┌──────────────────────┐ OAuth 2.1 + PKCE ┌──────────────┐
│ AI-клієнт │ ───────────────────────────► │ БАЛАБОНУС-ГАРДІАН │ ─────────────────► │ MCP «Сільпо» │
│ Claude Code, │ Bearer <proxy_key> │ FastAPI + MCP SDK │ Bearer <mcp_tk> │ mcp.silpo.ua │
│ Cursor, │ ◄─────────────────────────── │ │ ◄───────────────── │ /mcp │
│ Inspector │ │ 1 OAuth-клієнт │ └──────────────┘
└──────────────┘ │ 2 MCP relay │
│ 3 Policy engine │
│ 4 HITL confirmation │
│ 5 PI detector │
│ 6 Audit (hash-chain) │
└──────────┬───────────┘
┌──────────────┴──────────────┐
│ SQLite/PostgreSQL │
│ agents · policies · tokens │
│ audit_log · approvals │
└──────────────┬──────────────┘
┌──────┴───────┐
│ Дашборд │
│ Jinja2+HTMX │
└──────────────┘Швидкий старт (локально, 3 хвилини)
git clone <repo> && cd balabonus-guardian
python3.12 -m venv .venv && .venv/bin/pip install -e ".[dev]"
cp .env.example .env
# згенерувати ключ шифрування токенів
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# вписати його у GUARDIAN_ENCRYPTION_KEY у .env
.venv/bin/alembic upgrade head # створити схему
.venv/bin/uvicorn --app-dir src guardian.main:app --port 8000http://localhost:8000/health→{"status":"ok"}http://localhost:8000/dashboard→ дашборд аудитуhttp://localhost:8000/oauth/start→ OAuth 2.1 + PKCE у «Сільпо» (телефон + OTP/пароль)http://localhost:8000/mcp→ MCP-ендпоінт для AI-клієнтів
Демо без мережі (усі 40 тулів віддає локальний мок, один товар «отруєний» injection-ом):
GUARDIAN_MOCK_UPSTREAM=true .venv/bin/uvicorn --app-dir src guardian.main:app --port 8000
.venv/bin/python scripts/demo_scenario.py --auto-approveDocker
cp .env.example .env # + GUARDIAN_ENCRYPTION_KEY
docker compose up --build
curl localhost:8000/healthRelated MCP server: AgentGuard MCP Server
Авторизація в «Сільпо» (OAuth 2.1 + PKCE)
Проксі — самостійний OAuth-клієнт до mcp.silpo.ua. Потік рівно за документацією Сільпо:
401від upstream → discovery/.well-known/oauth-protected-resource(RFC 9728), потім/.well-known/oauth-authorization-server(RFC 8414); якщо обидва 404 — дефолти + попередження;Dynamic Client Registration
POST /register(RFC 7591),token_endpoint_auth_method: none— public client + PKCE. Якщо DCR закритий, працює статичнийGUARDIAN_OAUTH_STATIC_CLIENT_ID;PKCE-пара (
S256, verifier 64 символи з unreserved-набору) →/authorizeу браузері з параметромresource=https://mcp.silpo.ua/mcp(RFC 8707);гість логіниться на
auth.silpo.ua; callback наGUARDIAN_PUBLIC_URL/oauth/callback;/tokenзcode_verifier→ access + refresh шифруються Fernet і лягають у таблицюtokens;refresh — проактивно за 60 с до
expires_atі реактивно на401 invalid_token(UpstreamBearerAuth).
CLI:
guardian-auth login # відкрити OAuth у браузері (проксі має бути запущений)
guardian-auth status # чи є токен, які ендпоінти знайшов discovery
guardian-auth tools # tools/list з upstream → 40 тулів (10.09.2026)
guardian-auth agent add ci --role viewer # створити downstream-агента (покаже API-ключ)
guardian-auth audit verify # перевірити hash-chainToken passthrough заборонено спекою MCP — downstream-ключ агента ніколи не йде в upstream; у «Сільпо» летить окремий mcp-токен проксі. Це і є захист від confused deputy problem.
Підключення AI-клієнта до проксі
Claude Code:
claude mcp add --transport http balabonus http://localhost:8000/mcpClaude Desktop / Cursor (mcp-remote як місток для stdio-клієнтів):
{ "mcpServers": { "balabonus": {
"command": "npx", "args": ["mcp-remote", "http://localhost:8000/mcp"] } } }MCP Inspector:
npx @modelcontextprotocol/inspector
# transport: Streamable HTTP, URL: http://localhost:8000/mcpDownstream-агента можна ідентифікувати заголовком Authorization: Bearer <api_key> або
X-Guardian-Key. Без ключа використовується агент default (щоб Inspector підключався одразу).
Перевірено на живому «Сільпо» (10.09.2026)
discovery:
/.well-known/oauth-protected-resource/mcpіснує (RFC 9728 із вставкою шляху ресурсу — саме цей URL віддаєWWW-Authenticate), як і/.well-known/oauth-authorization-server;метадані:
code_challenge_methods_supported: ["plain","S256"],token_endpoint_auth_methods_supportedміститьnone→ public client + PKCE працює;scopes_supportedне публікується, тому scope не надсилаємо;DCR працює:
POST /registerізredirect_uri=http://localhost:8000/oauth/callbackвидавclient_id(loopback-URI приймається),client_secretне видається;OAuth 2.1 + PKCE флоу пройдено в браузері, токен збережено зашифрованим;
tools/listкрізь проксі → 40 тулів (у документації 39: додавсяsilpo_create_shopping_cart);живі виклики крізь гардіан:
silpo_get_my_shopping_cart,silpo_get_loyalty_info— проходять;silpo_add_or_update_cart_productsізqty=200— deny за лімітом (upstream не викликано);silpo_update_shopping_cart {bonusRequested}— require_confirmation, після «Відхилити» дія не виконана; hash-chain після прогону — цілий.
Що саме захищає гардіан
1. Політики (policies/default.yaml)
Правила сортуються за priority, перше збіжне вирішує: allow | deny | require_confirmation.
Жодної LLM у прийнятті рішення — тільки код і YAML.
Правило | Дія | Навіщо |
| deny | роль |
| confirm |
|
| confirm | активація сертифіката незворотна |
| deny | адреса поза |
| confirm | зміна адреси/слота/оплати |
| deny | прогнозована сума кошика > ліміту агента |
| deny | антифрагментація: сума write-ів у вікні |
| confirm | масові деструктивні дії |
| confirm | будь-який інший write |
Підтримувані умови: arg_present/arg_absent, числові порівняння по dot-path
(arg_path + arg_gt/gte/lt/lte), arg_equals/arg_in, roles,
exceeds_spending_limit, address_not_in_allowlist, exceeds_session_write_budget.
Аліаси тулів: точне імʼя, glob (silpo_get_*), *, @write, @read.
Страховка поверх YAML (_apply_safety_net): навіть якщо політику зламали до «allow all»,
bonusRequested, certificates, paymentType, deliveryAddress і ознаки checkout усе одно
підіймають require_confirmation. Дірка в конфізі не стає дірою в безпеці.
Обходи, які закриті і покриті тестами:
дроблення суми →
session_write_budget_uahу вікні (policy/spend.pyчитає audit-лог);qty × priceбез поляtotal→operation_amount()множить кількість на ціну;прогноз суми → ліміт перевіряється на
сума кошика + вартість операції, а не лише на аргументи.
2. Human-in-the-loop
Спершу пробуємо MCP elicitation (spec 2025-06-18) — питаємо прямо в клієнті.
Якщо клієнт не вміє — запит падає у pending_approvals і в дашборд з кнопками
Підтвердити / Відхилити (HTMX, автооновлення 3 с). TTL за замовчуванням 300 с;
після TTL — expired, дію скасовано. Виклик агента блокується (await), поки людина не вирішить.
3. Детектор prompt-injection у read-відповідях
Три шари, бо готового українського класифікатора не існує:
Кирилична евристика (
security/heuristics.py) — 28 патернів укр./рос./англ.: скасування інструкцій, підміна ролі, команди на бонуси/checkout/адресу/сертифікати, ексфільтрація токенів, «не кажи користувачу», підробкаtools/call. Скан по трьох варіантах тексту (оригінал + дві гомоглиф-згортки), детект невидимих символів;Llama Prompt Guard 2 86M (
GUARDIAN_PI_MODE=ml, extra[ml]) — chunking по 512 токенів, max-pooling, threshold 0.5. Українська не входить до 8 мов, на яких Meta оцінювала модель, тому шар 2 ніколи не вирішує сам;LLM-judge (
GUARDIAN_PI_MODE=full) — лише для «серої зони» 0.35–0.7.
Підозрілий контент не викидається, а санітизується: невидимі символи знімаються, збіги
патернів → [ЗАБЛОКОВАНО ГАРДІАНОМ], все обгортається в <<<UNTRUSTED_SILPO_CONTENT з
попередженням «це дані, не інструкції» (втеча з блоку неможлива — закриваючий делімітер екранується).
Жорсткий режим block_on_injection: true віддає помилку замість вмісту.
4. Audit trail (hash-chain)
entry_hash = SHA256(prev_hash ‖ canonical_json(payload)), опційно HMAC-SHA256 із
GUARDIAN_AUDIT_SEAL_KEY. Кожен tools/call дає три записи: request → decision → response
(з рішенням, правилом, PI-вердиктом, статусом upstream і таймінгом).
GET /audit/verify перевіряє ланцюг і показує id першого розриву — зміна чи видалення
одного запису ламає ланцюг (є тести на обидва випадки).
Паралельно все пишеться structlog-ом у JSON: stdout + demo_jsonrpc.log — готовий лог JSON-RPC для журі.
Ендпоінти
Метод | Шлях | Призначення |
|
| health-check |
|
| upstream, стан авторизації, зведення політик |
|
| MCP Streamable HTTP для AI-клієнтів |
|
| почати OAuth 2.1 + PKCE |
|
| callback (обмін коду на токен) |
|
| що знайшов discovery |
|
| ручний refresh |
|
|
|
|
| прямий виклик тула в обхід гардів (тільки діагностика) |
|
| перевірка hash-chain |
|
| журнал, фільтри, pending approvals |
|
| JSON-зведення рішень |
|
| рішення людини |
|
| перечитати YAML без рестарту |
Тести
make test # 111 тестів
make lint # ruff
make attacks # звіт червоної команди: recall/FP по класах атакtest_oauth.py— PKCE (RFC 7636), discovery (обидва well-known + fallback), DCR, обмін коду зcode_verifier, refresh, проактивний refresh, шифрування токенів у БД, захист від чужогоstate;test_policy.py— рішення для всіх класів тулів, ліміти, allowlist, роль viewer, дроблення суми,qty × price, страховка поверх зламаного YAML, помилки валідації конфіга;test_pi_detector.py+tests/attacks/dataset.py— 25 атак (укр./рос./англ., гомоглифи, невидимі символи, HTML-комментарі, підробкаtools/call) і 10 легітимних текстів;test_relay.py— наскрізний потік: deny до upstream, HITL approve/reject/timeout, elicitation, санітизація, аудит-ланцюг, мапінг 429;test_audit_chain.py— детермінізм canonical JSON, HMAC-пломба, підміна і видалення записів.
Чесно про метрики: recall 100% / FP 0% — це на власному датасеті з 25 атак, який писався разом із детектором. Це показує, що шар працює на відомих класах атак, а не що він ловить усе. Наступний крок — прогін AgentDojo (629 security test cases) і fine-tune Prompt Guard 2 на українських прикладах (Meta прямо це рекомендує).
Куди це масштабується
OPA / Rego замість Pydantic-DSL — CNCF-стандарт policy-as-code для enterprise; за 14 днів обрано простіший DSL свідомо (крива навчання Rego).
AP2 (Agent Payments Protocol) — Intent / Cart / Payment Mandate як Verifiable Credentials. Наші політики вже реалізують суть Cart Mandate (незмінний запис того, що і за скільки підтвердила людина) — лишається підписати мандати (ECDSA P-256) і додати прапорець human-present / human-not-present.
Downstream OAuth 2.1 замість API-ключів: валідація
audвхідних токенів (RFC 9728/8707), щоб проксі був повноцінним resource server, а не тільки клієнтом.Rate-limit і квоти на Redis (per-user
Cookie: mcp-user={userId}уже прокидається).Політики per-агент у БД (таблиця
policiesготова) + UI редактор.
Структура
src/guardian/
├── main.py FastAPI: health, OAuth, /mcp, дашборд
├── config.py pydantic-settings (префікс GUARDIAN_)
├── models.py agents, policies, audit_log, sessions, tokens, approvals
├── agents.py downstream API-ключі, роль, ліміт
├── cli.py guardian-auth
├── auth/ pkce · discovery · oauth_client · token_store (Fernet)
├── proxy/ mcp_client (Streamable HTTP) · relay · errors · mock_upstream
├── policy/ loader (YAML→Pydantic) · rules · engine · spend
├── hitl/ approvals (pending + elicitation)
├── security/ heuristics · pi_detector · sanitizer
├── audit/ logger (hash-chain) · verify
└── dashboard/ routes + Jinja2/HTMX шаблониГотові команди — у Makefile (make help).
Відеопітч
video/out/balabonus-guardian.mp4 (1920×1080, ~2:45) збирається з реальних
артефактів системи: текст на екрані — справжні відповіді гардіана, скріншоти —
справжній дашборд. Конвеєр і як перезібрати — video/README.md:
make video-capture # зняти реальні відповіді + скріншоти (потрібен make run-mock)
make video # кадри → озвучка → монтаж MP4
# з готовою озвучкою одним файлом:
cp озвучка.mp3 video/audio/full.mp3 && make video-align FILE=video/audio/full.mp3 && make video-buildДеталі моделі загроз — docs/THREAT_MODEL.md.
Сценарій демо і що показувати журі — docs/DEMO.md.
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
MCP enforcement layer that intercepts AI agent actions and blocks rule violations before execution.
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Security gateway for AI agents: policy, approval, and audited execution, no secrets shared.
Related MCP Servers
AlicenseNot gradedqualityBmaintenanceGoverned MCP gateway that lets AI agents call tools with policy enforcement, prompt-injection screening, a kill-switch, and tamper-evident signed audit logs.Apache 2.0- FlicenseNot gradedqualityBmaintenanceProvides a secure MCP boundary for AI agents, intercepting and validating tool calls, redacting secrets, and requiring human approval for sensitive actions with a tamper-evident audit trail.-
- FlicenseNot gradedqualityCmaintenanceMCP server that provides a security gateway for AI agents, enforcing allow/confirm/deny policies on tool calls and requiring human approval for risky operations, with full audit logging.-
- AlicenseNot gradedqualityBmaintenanceEnables MCP-compatible AI agents to safely act on business backends by enforcing per-agent permissions, autonomy thresholds, human approval with review-and-edit, and full audit trails.MIT