mcp-marl-pursuit
MARL Cop & Thief — два ИИ-агента на базе MCP
Децентрализованная частично наблюдаемая игра в догонялки между двумя автономными ИИ-агентами — Cop (полицейским) и Thief (вором), — которые общаются на свободном естественном языке через MCP-серверы, выбирают ходы с помощью теоретико-игрового движка minimax + self-play RL, отображаются в реальном времени в веб-панели управления и отправляют по електронной почте согласованный обеими сторонами JSON-отчёт о матче через Gmail API.
Университет Хайфы · Orchestration of AI Agents (ex06) · д-р Йорам Сегал. Одна команда запускает всё; одна вкладка браузера проводит целый матч.
Ключевые особенности
Запуск одной командой —
python -m cop_thief.appзапускает оба MCP-сервера, публичные туннели Cloudflare и браузерную панель управления вместе (никаких осиротевших туннелей, никакой возни с портами).Веб-панель управления — статус узла в реальном времени, публичные URL/токены с копированием, форма вызова оппонента, зеркальный самотест в один клик и живое табло игры 5×5 — всё по адресу
http://127.0.0.1:8800.Настоящая стратегия — движок minimax «Ангел–Дьявол» (антагонистическая марковская игра, альфа-бета) с блокирующей игрой Конвея (Cop = стены Дьявола, §4.3) и обучением весов через self-play RL, далеко за пределами базовой табличной Q из задания. См.
docs/STRATEGY.md.Децентрализованность и защита от читерства — нет судьи; обе стороны хэшируют результат (SHA-256), и любое расхождение даёт счёт 0/0. Входящий текст считается враждебным: prompt-инъекции и принуждение отсеиваются, фиксируются как улики и не могут изменить исход (действия «сдаться» не существует).
Единая граница SDK + API Gatekeeper — вся логика за
CopThiefSDK; каждый внешний вызов (LLM, Gmail) проходит через шлюз с FIFO и обратным давлением, с фейловером DeepSeek→Anthropic.Контроль качества —
pytest≥ 85 % покрытия,ruffбез нарушений, ≤ 150 строк/файл, только uv.
Related MCP server: Police MCP Server
Быстрый старт
uv sync # install (uv is the ONLY package manager)
cp .env-example .env # fill in real values (see "Secrets")
uv run ruff check . # zero-violation lint gate
uv run pytest # full suite (>=85% coverage gate)
uv run python -m cop_thief.app # launch the control panel + servers + tunnelsЗатем откройте http://127.0.0.1:8800.
Проведение матча (панель управления)
uv run python -m cop_thief.app→ открывается панель; дождитесь зелёных индикаторов Серверы ● и Туннели ●.Карточка статуса показывает два ваших публичных URL
…/mcp/+ токены по ролям (кнопки копирования). Отправьте их оппоненту вместе сdocs/INTER_GROUP_TREATY_SPEC.md. Используйте формы для заполнения изmatch_setup/(RULES.txt,OUR_DETAILS,OPPONENT_DETAILS).Вставьте два URL
…/mcp/оппонента (и токены, если есть) в форму вызова, затем нажмите START CHALLENGE — 6 под-игр разыгрываются между хостами на табло, а отчёт отправляется по электронной почте.Партнёра пока нет? Нажмите MIRROR SELF-TEST ⟳ — он подставляет ваши собственные localhost-эндпоинты + токены и играет вас против вас самих (идеально для тестирования стратегии).
Игра = 6 под-игр (по §4.1): мы играем Cop в 3 (домашняя нога) и Thief в 3 (гостевая нога), Thief ходит первым, ≤ 25 ходов в каждой. Система очков неизменна: поимка Cop → 20 / 5; выживание Thief → 5 / 10.
Скриншоты
Панель управления — статус узла (серверы/туннели/игра), наши доступные для передачи URL …/mcp/ + токены с кнопками копирования, форма вызова оппонента и живая игра. Здесь запущен зеркальный самотест; обратите внимание на строку [INTENT: BARRIER] (Cop ставит стену на соседней клетке и остаётся на месте, §4.3), зелёный барьер B и поимку !.

Живая доска — сетка 5×5 с Cop C (синий) и Thief T (красный), рядом лента перехвата сообщений, показывающая передачи на естественном языке [INTENT: MOVE] и разделители HOME LEG / Sub-game.

Переход между ногами — бегун переходит в AWAY LEG (мы играем за Thief) на под-игре 4/6, при этом на доске всё ещё есть барьер B и поимка !.

Запуск узла выводит доступные для передачи эндпоинты в терминал (один процесс: серверы + туннели + панель):
Control panel > http://127.0.0.1:8800 (open in a browser)
╔══════════════════════════════════════════════════════════════════╗
║ LIVE PUBLIC MATRIX (Team Alpha) ║
╠══════════════════════════════════════════════════════════════════╣
║ COP (:8001) https://acting-tomorrow-yard-raid.trycloudflare.com/mcp/ ║
║ THIEF (:8002) https://dial-mean-courses-tramadol.trycloudflare.com/mcp/ ║
╚══════════════════════════════════════════════════════════════════╝
Tunnels live and written to config/setup.json. Share these /mcp/ URLs. Ctrl+C to stop.Архитектура
Слой | Модуль | Обязанность |
Домен |
| Иммутабельные |
Стратегия |
|
|
SDK |
| Единая точка входа |
Gatekeeper |
| FIFO-шлюз для всех вызовов LLM/Gmail; фейловер DeepSeek→Anthropic; телеметрия токенов. |
Серверы |
| FastMCP-серверы Cop и Thief; авторизация по токенам; инструмент |
Транспорт |
| streamable-HTTP хост |
Оркестрация |
|
|
UI |
| Бэкенд панели управления ( |
Отчётность |
| Gmail OAuth-репортер (имя группы в теме и теле), append-only журнал аудита, предохранитель. |
Точки входа
Команда | Что делает |
| Панель управления: серверы + туннели + веб-UI (основная). |
| Интерактивный терминальный вызов между хостами (запрашивает URL оппонента). |
| Только серверы + туннели (без UI). |
| Только два MCP-сервера ( |
| Офлайн-зонд погони нулевой стоимости (мок-LLM). |
Стратегия в одном абзаце
Каждый request_move обрабатывается ограниченным по глубине alpha-beta minimax над антагонистической марковской игрой (Cop максимизирует, Thief минимизирует, предположение об оптимальном противнике). Терминальные оценки, формируемые прогрессом (±WIN ∓ turns), заставляют политику стремиться к поимке/выживанию, поэтому ничьи структурно исключены. Множество действий Cop включает установку стены на соседней клетке (ход «Дьявола» Конвея, §4.3); фича containment в оценке — это залитая (flood-filled) область побега Thief, поэтому планировщик сам находит легальные линии загона в ловушку. Линейные веса оценки настраиваются через self-play TD (selfplay.train_weights). Три варианта профилей (агрессивный / сбалансированный / оборонительный) формируют требуемый состав из 3 агентов. Полное описание: docs/STRATEGY.md.
Формальная модель — Dec-POMDP
Погоня моделируется как децентрализованный частично наблюдаемый марковский процесс принятия решений — кортеж ⟨ n, S, {Aᵢ}, P, R, {Ωᵢ}, O, γ ⟩ (ex06 §11):
Символ | Значение | В этом проекте |
n | агенты | 2 — Cop и Thief (независимы, без общей памяти). |
S | пространство состояний |
|
Aᵢ | действия агента | Cop: 8 ходов короля (Чебышев ≤ 1) ∪ поставить барьер на соседнюю свободную клетку (остаться на месте) ∪ HOLD. Thief: 8 ходов короля ∪ HOLD. «Остаться» — вырожденный ход. |
P | переход | Детерминированный конечный автомат доски ( |
R | награда | Иммутабельная таблица 1: поимка → Cop +20 / Thief +5; уклонение → Cop +5 / Thief +10. Планировщик использует терминальные значения, формируемые прогрессом ( |
Ωᵢ | пространство наблюдений | Субъективный обзор для каждого агента: точные координаты оппонента тогда и только тогда, когда он в радиусе обзора, иначе качественный сектор заслонения (например, |
O | функция наблюдения |
|
γ | дисконт |
|
Частичная наблюдаемость реальна: каждый агент принимает решение на основе своего представления о доске (последнее наблюдение + разобранная проза оппонента), а не на основе глобальной истинной картины.
Проблемы оркестрации (трудная часть)
Согласно ex06 §14, ценность задания — в оркестрации, а не в победе. Трудные проблемы и способы их решения:
Свободный естественный язык, без предопределённого протокола. Агенты общаются прозой. Мы добавляем тонкий детерминированный контракт — каждое сообщение начинается ровно с одного маркера
[INTENT: MOVE|BARRIER|HOLD], за которым следует слово-компас, — так что ход машинно разрешим, а тело остаётся свободным естественным языком. Это удерживает два независимо построенных движка в синхронизации без общей кодовой базы.Языковая неоднозначность и недоверенный ввод. Входящая проза разбирается детерминированно (слово направления по самому длинному совпадению, намерение только в квадратных скобках, чтобы декоративный текст не мог его подделать) с опциональным LLM-разбором для неструктурированного текста противника; низкая уверенность → безопасный исследовательский запасной вариант (никогда не падает, никогда не подделывает взятие). Каждое поле рассматривается как враждебное — например, нечисловой
variantприводится, а не принимается на веру.Обеспечение взаимопонимания. Обе стороны используют общий детерминированный язык ходов (кодирование/разбор без необходимости в LLM), поэтому партия воспроизводима побайтово. В конце обе стороны хешируют каноническое значение
sub_games(SHA-256, K3); любое несовпадение ⇒ 0/0 для обеих — согласованность обеспечивается принудительно, а не предполагается.Живучесть в ненадёжной сети. Межхостовые ходы повторяются с переподключением; длительный сбой или зависший участник (таймаут 20 с на ход) означает поражение в этой под-игре, так что серия всегда завершает все 6 партий, а отчёт всё равно отправляется по почте — недоступный противник никогда не сможет остановить матч.
Визуализация и неопровержимые доказательства (§11)
GUI — Скриншоты выше показывают живую доску 5×5, ленту перехвата коммуникаций
[INTENT: …], барьеры (B), взятия (!) и переходы между этапами.Облачная MCP-коммуникация — загрузочный блок выше выводит актуальные публичные Cloudflare-URL
/mcp/, а лента коммуникаций панели транслирует реальные передачи[INTENT:], которыми обмениваются с облачными серверами; каждый ход также добавляется вdata/game_audit.jsonlи запечатывается в архив каждой партии с защитой от подделки (data/archive/, SHA-256 набора в отчёте).Обучение — веса стратегии настраиваются методом самоигры TD (
selfplay.train_weights); для сравнения сохранена базовая табличная модель Q-learning. Дизайн и кривые:docs/STRATEGY.md.
Безопасность и честная игра
Токены — каждый вызов инструмента MCP требует отдельного отзываемого bearer-токена для каждой роли; токены передаются внеполосно и могут ротироваться для отзыва доступа. Серверы закрыты по умолчанию (fail-closed).
Защита от инъекций — входящие передачи считаются недоверенными; инъекции/принуждение/имитация/подделка проверяются, помечаются
hostile:trueвdata/game_audit.jsonl, учитываются в отчёте и не влияют на результат, определяемый движком. Для противников это зафиксировано в договоре (§F).Взаимное согласие — обе стороны хешируют каноническое значение
sub_games; любое несовпадение ⇒ 0/0 (both_lose).Отчётность — Gmail API через OAuth2 Desktop (scope
gmail.modify, без паролей); название группы указывается и в теме письма, и в JSON-теле; предохранитель по умолчанию использует одноразовый почтовый ящик.
Бюджет токенов и стоимость
Каждый внешний вызов учитывается через API Gatekeeper → TokenTracker, который в реальном времени передаёт данные об использовании в data/token_usage.json (атомарная запись; эти данные исключены из хеша соглашения K3, поэтому стоимость никогда не влияет на результат). Все цифры задаются конфигурацией (config/setup.json → token_budget / economics).
Провайдер (роль) | Вход, $/M | Выход, $/M |
DeepSeek | 0.15 | 0.60 |
Anthropic | 3.00 | 15.00 |
Статья бюджета | Значение |
Фактические расходы на сегодня (суммарно по всем запускам) | ≈ $0.01 |
Бюджет жизненного цикла | 200 000 входных + 50 000 выходных токенов |
→ прогнозируемая стоимость жизненного цикла (основной) | ~$0.06 |
Оценка на один ход (120 входных / 40 выходных) | ~$0.00004 |
Жёсткий предел (предупреждение при 80 %) | $0.50 (предупреждение $0.40) |
Контроль соблюдения | gatekeeper возвращает |
На практике весь проект обошёлся примерно в $0.01 на LLM. Ходы генерирует локальный движок минимакса, а язык ходов — детерминированный
[INTENT: …]encode/parse: для игры и отправки отчёта LLM не нужен (Gmail API, а не LLM). Крошечный бюджет + фолбэк с приоритетом DeepSeek — это предохранители для опционального LLM-ассистированного разбора естественного языка; предел установлен на $0.50 с большим запасом.
Секреты и конфигурация
Скопируйте
.env-example→.envи заполните:DEEPSEEK_API_KEY,ANTHROPIC_API_KEY,COP_MCP_TOKEN,THIEF_MCP_TOKEN,GMAIL_CREDENTIALS_PATH. Автозагрузчик без зависимостей внедряет.envпри запуске —export/sourceне нужны; уже существующие экспортированные переменные окружения всегда имеют приоритет.Все настраиваемые параметры находятся в версионируемых
config/*.json(без хардкода). Секреты (.env,credentials.json,token.json) игнорируются git и никогда не попадают в систему контроля версий.
Документация
PRD · PLAN · TODO · STRATEGY · RULES_AND_AGREEMENTS · INTER_GROUP_TREATY_SPEC
Лицензия
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
Games for AI agents: negotiation, social deduction, racing and puzzles, vs bots and agents.
Agent City Wars: a persistent strategy game played by AI agents on Oids. One turn a day, over MCP.
Agent City Wars: a persistent strategy game played by AI agents on Oids. One turn a day, over MCP.
A persistent multi-agent world any AI agent can join over MCP, with a public record of every match.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server allowing two agents to play chess or Connect Four against each other, with a live rendered board and emotion signaling.-
- FlicenseNot gradedqualityCmaintenanceEnables a police agent to autonomously chase a thief in a peer-to-peer grid game using FastMCP for turn-based communication and decentralized orchestration.-
- FlicenseNot gradedqualityBmaintenanceImplements a distributed cops-and-robbers game agent as a FastMCP server, enabling peer-to-peer play with no central server. It manages turn-based moves, belief tracking, strategy selection, and secure protocol via SHA-256 commit-reveal.-
- FlicenseNot gradedqualityBmaintenanceRuns a decentralized thief agent for a peer-to-peer cops-and-robbers game, using FastMCP to exchange moves and messages with a police agent while employing Bayesian belief and credibility-based bluffing strategies.-