groundtruth-mcp
groundtruth-mcp
Ваш агент кодирования может прочитать каждый файл в вашем репозитории и всё равно лишь гадает. Это превращает собственные проверки, повторы, симуляции и запросы вашего проекта в инструменты MCP, поэтому он наблюдает последствия своего изменения, а не предсказывает их.
Китайская документация · Руководство по внедрению · Архитектура · Почему фиксированные сиды
Проблема
Агент, редактирующий структурированную конфигурацию — граф рабочего процесса, файл правил, конечный автомат, определение пайплайна — работает с контекстом не того рода. Он может прочитать схему. Он не может прочитать, что происходит, когда эта штука запускается.
Поэтому он делает выводы. Он меняет лимит повторов и говорит вам, что изменение безопасно, потому что «безопасно» было наиболее правдоподобным следующим токеном при диффе, который выглядел разумным. Никто ничего не запускал. Нарушенное ограничение находится в инварианте тремя файлами дальше или в распределении, которое никто не сэмплировал с момента последней настройки политики.
Решение — не улучшенный промпт. Решение — дать агенту возможность что-то наблюдать.
Что это делает
flowchart LR
E[Agent edits a config] --> L[lint]
L -->|DANGLING_TRANSITION at states 1.transitions 0.to| E
E --> R[replay seed=7]
R -->|the 5 steps that actually ran| E
E --> S[simulate 2000 seeds]
S -->|88.3% success · p95 2566ms · PASS| E
S --> G["CI: groundtruth simulate --gate"]
G -->|same config, same thresholds| SПять инструментов, построенных на четырёх небольших функциях, которые вы пишете:
Инструмент | Отвечает | Свойство, которое делает его полезным |
| Является ли эта конфигурация самосогласованной? | Каждая проблема несёт точный путь для правки |
| Что произойдёт, если я запущу именно эту? | Чистая функция от |
| Стало ли моё изменение лучше или хуже в целом? | Сидированный батч, распределение, пороги, прохождение/непрохождение |
| Что на самом деле в данных? | Только чтение, обеспечиваемое базой данных, а не регулярным выражением |
| Какие таблицы существуют? | Чтобы никому не пришлось угадывать схему |
Те же возможности доступны через CLI, так что groundtruth simulate --gate — это шлюз слияния, читающий те же пороги, против которых агент оптимизирует. Они не могут разойтись, потому что существует только одна копия.
Шестьдесят секунд
pip install "groundtruth-mcp[mcp]"
git clone https://github.com/ZhenGtai123/groundtruth-mcp && cd groundtruth-mcp
groundtruth --config examples/checkout-flow/groundtruth.toml lint broken_checkoutВстроенный пример — это управляемый конфигом процесс оформления заказа: четыре страницы, нестабильный платёжный шлюз, политика повторов, уходящие клиенты. broken_checkout.json содержит ошибки, которые агент действительно совершает при редактировании конфига, который он не может запустить.
broken_checkout: BLOCKED errors=6 warnings=1 infos=0
source: flows\broken_checkout.json
-- ERRORS — these block (6) --
[DANGLING_TRANSITION] states[1].transitions[0].to 'payment_methd' does not name any states.id
fix: point it at an existing state id, or delete the transition
[DEAD_END] states[6] 'review_hold' has no outgoing edge and is not marked terminal — a run that arrives here stops with no result
fix: give it a transition, or mark it kind = "terminal" with an outcome
[DUPLICATE_STATE] states[2] duplicate id='shipping' (first declared at states[1])
fix: rename one of them; the engine silently uses the first and ignores the rest
[RATE_OUT_OF_RANGE] policy.gateway_failure_rate 1.4 is above the maximum 1.0
fix: this is a probability, not a percentage — 0.18, not 18
[RETRY_BUDGET_TOO_THIN] policy.max_retries 140% gateway failure with 1 retries leaves 196.0% of checkouts failing on payment alone (budget: 2.0%)
fix: raise max_retries, or lower gateway_failure_rate if the gateway improved
[UNKNOWN_STATE_KIND] states[3].kind 'stage' is not one of ['step', 'gateway', 'retry', 'terminal']
fix: the engine only knows these four kinds; anything else is treated as a plain step
-- WARNINGS (1) --
[UNREACHABLE_STATE] states[4] 'gift_wrap' cannot be reached from 'cart_review'
fix: no path from start reaches this state — delete it, or wire it inШесть из них берутся из файла правил. RETRY_BUDGET_TOO_THIN возникает из восьми строк Python, потому что «соответствует ли этот бюджет повторов целевому показателю отказов продукта» — это арифметика, а не схема.
Теперь посмотрите на один запуск:
groundtruth --config examples/checkout-flow/groundtruth.toml replay standard_checkout --seed 3standard_checkout seed=3 outcome=success steps=7 fingerprint=52b66a2024a61b5d
metrics: latency_ms=2506 payment_attempts=2 steps=7
-- TRACE --
0. cart_review --always-->
1. shipping --always-->
2. payment_method --always-->
3. authorize --failure--> # attempt 1 declined
4. retry_decision --retries_left--> # 0 retry(s) used of 2
5. authorize --success--> # attempt 2 authorized
6. confirmed # terminal: successСид 3 всегда порождает эти семь шагов — на вашей машине, в CI, в следующем году. Именно поэтому его стоит читать.
И две тысячи таких:
groundtruth --config examples/checkout-flow/groundtruth.toml \
simulate standard_checkout --runs 2000 --seed 0 --gate --check-determinismstandard_checkout: PASS runs=2000 base_seed=0 fingerprint=449e16b50c8184c0
-- OUTCOMES --
success: 1767 (88.3%)
abandoned: 227 (11.3%)
payment_failed: 6 (0.3%)
-- METRICS (mean / p50 / p95 / max) --
latency_ms: 1587.75 / 1553 / 2566 / 3626
payment_attempts: 1.06 / 1 / 2 / 3
steps: 5.12 / 5 / 7 / 10
-- THRESHOLDS --
PASS rate:success = 0.8835 expected >= 0.8 (below this, the flow is losing customers faster than the business case allows)
PASS rate:stuck = 0 expected <= 0 (a run with nowhere to go is always a config bug, never bad luck)
PASS p95:latency_ms = 2566 expected <= 4000 (95th-percentile checkout wall time, retries included)
PASS mean:payment_attempts = 1.0585 expected <= 1.6 (rising attempts mean the gateway is degrading or the retry policy is too eager)
note: determinism: 20 seeds re-ran identicallyЧасть, которая окупает себя
Поднимите одно число — shipping.abandon_chance с 0.05 до 0.28, правку такого рода, которая выглядит как продуктовое изменение и проходит ревью:
$ groundtruth lint standard_checkout
standard_checkout: OK errors=0 warnings=0 infos=0 # exit 0
$ groundtruth simulate standard_checkout --runs 2000 --seed 0 --gate
standard_checkout: FAIL runs=2000 base_seed=0 fingerprint=5a7c0d9feed5adca
-- OUTCOMES --
success: 1336 (66.8%)
abandoned: 660 (33.0%)
-- THRESHOLDS --
FAIL rate:success = 0.668 expected >= 0.8
PASS rate:stuck = 0 expected <= 0
PASS p95:latency_ms = 2549 expected <= 4000
PASS mean:payment_attempts = 0.795 expected <= 1.6
# exit 1Структурно безупречно. Двадцать один пункт конверсии потерян. Ни схема, ни система типов, ни ревью кода этого не ловят; сидированный батч с объявленным диапазоном ловит это за четыре секунды, в пулл-реквесте, до того как человек прочитает дифф.
Это работает и в обратную сторону. express_checkout показывает более высокий процент успеха, чем стандартный поток — 91.0% — и при этом является худшим конфигом: его платёжные сбои составляют 3.9% против 0.3%, скрываясь внутри заголовочного числа, которое выглядит нормально. Агрегат это упускает; написанный вручную валидатор говорит об этом прямо:
[RETRY_BUDGET_TOO_THIN] policy.max_retries 18% gateway failure with 1 retries
leaves 3.2% of checkouts failing on payment alone (budget: 2.0%)Ни один слой не поглощает другой. Вот почему их два.
Внедрение
Один модуль, один файл конфигурации. examples/checkout-flow/groundtruth_app.py — это весь шаблон, около сотни строк, включая комментарии.
from groundtruth_mcp import Context, Issue, Loaded, Toolkit, Trace
kit = Toolkit(name="my-project", subject_noun="pipeline")
@kit.loader
def load(name: str):
path = CONFIG_DIR / f"{name}.yaml"
if not path.is_file():
return None # → "no pipeline named X; available: ..."
return Loaded(subject=parse(path), source=str(path))
@kit.validator
def check(pipeline, ctx: Context) -> list[Issue]:
... # the checks a rule file can't express
@kit.runner
def run_once(pipeline, seed: int, ctx: Context) -> Trace:
... # one run, pure in (pipeline, seed)Один только @kit.runner даёт вам и replay, и simulate — библиотека запускает его по одному разу на каждый сид и сохраняет результат. Всё остальное (пакетирование сидов, агрегация, процентили, проверка порогов, бюджетирование вывода, формулировка ошибок, MCP-поверхность) поставляется пакетом.
# groundtruth.toml
[project]
toolkit = "groundtruth_app:kit"
[lint]
rules = "rules.toml"
[[thresholds]]
metric = "rate:success"
min = 0.80
note = "why this number, for whoever has to change it"Затем groundtruth doctor сообщает, что подключено, groundtruth serve передаёт инструменты агенту, а groundtruth simulate --gate блокирует слияние. Полное пошаговое руководство с примерами по каждой предметной области: docs/ADOPTION.md.
Правила, которые вы получаете бесплатно
Структурные проверки объявляются, а не пишутся вручную. Двенадцать типов, каждый из которых покрывает один из способов, которыми структурированные конфиги реально портятся:
Тип | Ловит | Ключевые поля |
| недописанные записи |
|
| дублирующиеся идентификаторы, которые движок молча затеняет |
|
| значение, которое ваш движок не обрабатывает |
|
| строка там, где должно быть число |
|
|
|
|
| идентификаторы, нарушающие контракт именования |
|
| пустой список там, где требуется одна запись |
|
| ссылка на то, что было переименовано |
|
| узел, до которого не ведёт ни один путь от начала |
|
| нетерминальный узел без выхода |
|
| узел, который переходит сам в себя |
|
| кольцо без выхода (со списком |
|
Селекторы — это намеренно небольшой язык путей — states[].transitions[].to — и каждое совпадение сообщает конкретный путь, по которому оно найдено, что делает возможным states[3].transitions[1].to вместо «переход недействителен».
Каждое правило принимает необязательные code, severity и hint. Подсказка (hint) — это предложение, на которое действует агент, поэтому пишите его в повелительном наклонении.
Только чтение означает только чтение
query выполняет один SELECT. Это обеспечивают два уровня, и они не равны.
Сканирование ключевых слов — это пользовательский опыт: оно отклоняет DELETE FROM … предложением с объяснением, вместо ошибки базы данных, которую модели приходится расшифровывать. Это не граница — чёрный список по тексту всегда в одном случае от ошибки, и каноническая демонстрация — SELECT * INTO audit_copy FROM users, который начинается с SELECT, не содержит запрещённых глаголов и создаёт таблицу.
Граница — это хранилище данных: mode=ro плюс PRAGMA query_only в SQLite, транзакция READ ONLY в PostgreSQL, таймаут запроса в обоих. Тесты полностью обходят защиту и подтверждают, что соединение по-прежнему отказывает.
Маскирование столбцов — это единственный контроль на текстовом уровне, который является принудительным: значения в deny_columns отбрасываются после выборки и до того, как создаётся результирующая строка, поэтому SELECT * не может их утечь. Всё возвращаемое оборачивается в теги <untrusted>, потому что столбец notes, содержащий нечто похожее на инструкцию, — это данные, и он должен прийти помеченным как данные.
CLI
groundtruth [--config PATH] <command>
doctor what is wired up, what is missing
targets the configs this project exposes
lint TARGET exit 1 on errors
replay TARGET --seed N one deterministic run, full trace
simulate TARGET --runs N --seed N --gate --check-determinism
query "SELECT ..." one read-only statement
schema readable tables and columns
serve the MCP server, over stdioКоды выхода: 0 — чисто, 1 — найдены проблемы (ошибки линтера, порог вне своего диапазона, недетерминизм), 2 — не удалось запустить (плохой конфиг, отсутствующая возможность, отклонённый запрос). Добавьте --json к lint, replay и simulate для машиночитаемого вывода.
Установка
pip install groundtruth-mcp # core: rules, simulation, gating, CLI
pip install "groundtruth-mcp[mcp]" # + the MCP server
pip install "groundtruth-mcp[postgres]" # + the PostgreSQL data sourcePython 3.11+. Ядро не имеет сторонних зависимостей — это сделано намеренно, чтобы CI-шлюз не зависел от стека агента. Голый раннер может обеспечивать соблюдение ваших порогов без установки SDK.
Проверка подключения
python scripts/mcp_smoke.py [path/to/groundtruth.toml]Запускает сервер как настоящий подпроцесс, инициализирует через stdio, перечисляет инструменты, вызывает два из них, печатает ответ — ту же последовательность, которую выполняет клиент. Запустите это, прежде чем винить агента в том, что он не видит ваши инструменты.
Что CI проверяет в каждом пулл-реквесте
Не значок, означающий «тесты прошли», — шесть вещей, каждая из которых однажды что-то заблокировала:
Проверка | Почему это шлюз, а не предложение |
| Включая |
| Пакет поставляется с |
| 69 тестов, нижняя граница покрытия 75% (сейчас 78% с покрытием ветвлений) |
| Настоящий подпроцесс, настоящий stdio, настоящие |
| Собственный аргумент проекта, применённый к самому себе |
| Линтер, который не может упасть, декоративен |
Ограничения, изложенные прямо
Белый список таблиц SQL является текстовым. Он сканирует идентификаторы после
FROMиJOIN. Настоящее обеспечение по таблицам — это грант базы данных; это защитное ограждение с хорошим сообщением об ошибке, а удерживает на самом деле транзакция только для чтения.Чёрный список ключевых слов срабатывает внутри строковых литералов. Запрос, фильтрующий по значению, содержащему
grant, будет отклонён. Исправление требует настоящего SQL-парсера, который не стоит строить, когда парсер не является границей.Авто-
LIMIT— это эвристика.LIMITвнутри подзапроса подавляет добавление на верхнем уровне.max_rowsпо-прежнему ограничивает то, что выводится.Селекторы не фильтруют.
states[].transitions[]обходит всё; нетstates[kind=terminal]. Язык предикатов был бы третьей функцией, которую никто не просил. Вместо этого напишите@kit.validator.Пороги действуют на весь проект, а не на каждую цель. Каждая цель в проекте оценивается по одним и тем же диапазонам. Проекты, чьи конфиги требуют действительно разных диапазонов, должны использовать отдельные файлы
groundtruth.toml.Источник PostgreSQL реализован, но слабо протестирован — набор тестов проверяет границу на SQLite, где он может работать везде без служебного контейнера.
Откуда это взялось
Извлечено из приватной кодовой базы, где этот паттерн заслужил своё место: конвейер создания контента, участники которого постоянно поставляли конфигурации, проходившие валидацию схемы и ломавшиеся во время выполнения. Домен-специфичные части остались в стороне. Обобщению подверглась форма — проверка, воспроизведение, симуляция, запрос — а также набор решений, которые оказались важнее, чем список функций:
Единый список пороговых значений, читаемый и агентом, и CI, потому что две копии рассинхронизировались, и инструмент какое-то время выдавал PASS для чисел, которые CI отверг бы.
Ошибки, которые прямо называют допустимые альтернативы, потому что агент, которому нужно сделать второй вызов, чтобы узнать, что ему можно передать, вместо этого будет угадывать.
Описания инструментов, формируемые из текущей конфигурации, потому что устаревшее описание — это инструмент, которым агент пользуется уверенно, но неправильно.
Ограничение объёма вывода на каждом пути, потому что один слишком активный запрос может вытеснить остальную часть разговора.
docs/ARCHITECTURE.md содержит карту модулей и полное обоснование.
Лицензия
MIT.
This server cannot be installed
Maintenance
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
A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage
Free public MCP for AI agents — 193 tools, 44 workflows. No API key.
Agent Replay Debugger MCP — record every agent step + deterministic replay. Step-debugger for
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/ZhenGtai123/groundtruth-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server