debary-mcp-compliance
Officialdebary-mcp-compliance
MCP-сервер, который даёт языковой модели доступ к движку правил fair housing и рекламных требований для текстов объявлений о недвижимости в США — но не передаёт ей само решение.
Движок детерминирован: 81 фразовое правило, 35 обязательных элементов, шесть штатов и ни одной модели по пути принятия решения. Этот сервер принимает вопрос на входе и отдаёт вердикт на выходе. Модель на другом конце получает каждое выявленное нарушение, закон, стоящий за ним, и формулировку, которую база правил предлагает взамен. Чего она не получает — так это права не согласиться.
Именно поэтому это MCP-сервер, а не REST-эндпоинт с красивым описанием. Модели нужен инструмент, с которым она не может спорить, и MCP — это протокол, который кладёт такой инструмент в пределы её досягаемости, не отдавая его в её суждение.
Создано DE BARY LLC. Движок, который сервер оборачивает, работает на gate.debary.us.
Попробовать
Никакой конфигурации, никакой базы правил, никакой сети:
pip install -e .
python demo.pyДемонстрация запускает сервер как подпроцесс, общается с ним по протоколу MCP и пошагово разбирает: объявление, которое не проходит проверку; закон, стоящий за каждым нарушением; исправление; и повторную проверку, которая вылавливает то, что исправление всё ещё упустило.
⚠️ Если ничего не настроено, сервер работает на демонстрационной базе правил — шести правилах и четырёх обязательных элементах, написанных для этого репозитория, чтобы его мог запустить и проверить любой желающий. Она себя маркирует: каждый результат содержит backend: "sample" и rules_version: "sample-1". Это иллюстрация и не инструмент комплаенса. Направьте GATE_APP_DIR или GATE_URL на настоящую базу, чтобы получить настоящие ответы.
Related MCP server: projectpermit-mcp
Что он предоставляет
У MCP есть три примитива. Этот сервер использует все три, и каждый присутствует здесь потому, что это правильная форма для того, что он передаёт.
Tools — то, что модель просит движок выполнить
Tool | Какую задачу решает |
| Прогоняет текст объявления через движок. Возвращает найденные нарушения, отсутствующие обязательные элементы и вердикт |
| Полностью правило, стоящее за нарушением, включая нормативный акт. Модель цитирует источник, а не вспоминает его по памяти. |
| Символьные смещения каждого проблемного фрагмента плюс одобренная заменяющая формулировка. Сознательно не переписывает — сочинение текста — задача модели, а проверка — движка. |
| Сохранённая проверка: что именно было исследовано, относительно какой версии правил и каков SHA-256 точного текста. |
Resources — материалы, которые модель может читать напрямую
URI | Содержимое |
| Индекс базы правил: все нарушающие элементы и обязательные элементы по идентификатору, уровню серьёзности и категории |
| Одно правило в полном виде, с авторитетным источником и документом-первоисточником |
| Элементы раскрытия, которые обязана содержать реклама в этом штате |
| Прошлая проверка с её опорным блоком |
Prompts — готовые сценарии, чтобы каждый клиент не изобретал их заново
Prompt | Что он предписывает |
| проверка → цитата → переписывание → снова проверка переписанного текста. Последний шаг — ровно то, что пропустит, когда модель импровизирует. |
| Превращает квитанцию в результат, на который лицензированный агент может реально опереться, включая то, что движок не смог проверить автоматически. |
Заметки по разработке
Вердикт не является предметом обсуждения. blocking равно true, когда срабатывает любое правило высокого уровня серьёзности или отсутствует любой обязательный элемент. Описание инструмента говорит об этом, серверные инструкции говорят об этом, и промпт review_listing предписывает модели честно сообщать о неудачном переписывании, а не подавать его как исправленное.
blocking: false — ещё не допуск. Это означает лишь, что ни одно правило не сработало. элементы_ручные содержит список того, что движок не может проверить механически, — а это всё равно требует — требуется. Инструмент, который молча докладывает об успехе по тому, чего не проверил, хуже, чем инструмент вообще.
Каждое нарушения несёт свой источник. Нарушение без ссылки на него — просто мнение; движок правил, у которого есть мнения, — это языковая модель с лишними шагами. Это обеспечено в тестовом контуре, а не просто заявлено.
Три бэкенда — один интерфейс. LocalBackend подключает движок и проводит оценку в том же процессе — без сети, и текст объявления никогда не покидает машину. RemoteBackend вызывает запущенный сборочный узел по HTTP. SampleBackend несёт в себе небольшую базу правил, чтобы сервер поднимался в свежем клоне. Все три возвращают одну и ту же форму, поэтому слой MCP никогда не узнает, кто именно ответил.
Запасной план сам объявляет о себе. Образцовая база, которая тихо прикидывается настоящей, была бы ловушкой. Эта же ставит sample в каждый результат и sample-1 в поле версии, а также есть тест, который падает, если одна из меток пропадёт.
Два транспорта. stdio — для десктопного клиента, streamable-http — для контейнера. sse ещё принимается для старых клиента, но он объявлен устаревшим в протоколе, и для нового кода его выбирать не стоит.
Требуется SDK 2.x. Python SDK в 2.0 переименовал FastMCP в MCPServer и перенёс его из mcp.server.fastmcp в mcp.server.mcpserver; поля результата переехали с structuredContent на structured_content. Этот сервier предназначен только для 2.x. Поддержку обеих мажорных версий за прослойкой рассматривали и отодвинули: это добавило бы слой совместимости в проект, главный аргумент которого — в том, что путь принятия решения остаётся простым.
Запуск
С локальной базой правил
pip install -e .
GATE_APP_DIR=/path/to/compliance-gate/app debary-mcp-complianceЗапуск с работающим шлюзом
GATE_URL=https://gate.debary.us GATE_TOKEN=… debary-mcp-complianceЕсли заданы обе переменные, побеждает GATE_APP_DIR: оценка в рамках процесса быстрее и не гоняет текст объявления по сети сили.
В Docker
docker compose up -dКонтейнер слушает :8765/mcp (streamdle-streamable HTTP) и публикуется на хосте порту8766`, привязан к loopback. Ставьте перед ним туннель, а не открывайте порт наружу. База правил смонтирована в режиме только на чтение — из контейнера можно применять правила, но не изменять их.
Claude Desktop
{
"mcpServers": {
"debary-compliance": {
"command": "debary-mcp-compliance",
"env": { "GATE_APP_DIR": "/path/to/compliance-gate/app" }
}
}
}Claude Code
claude mcp add debary-compliance \
--env GATE_APP_DIR=/path/to/compliance-gate/app \
-- debary-mcp-complianceКонфигурация
Переменная | Значение |
| Каталог с |
| Базовый URL работающего шлюза. Выбирает удалённый бэкенд. |
(ни одно не задано) | Запасной вариант на встроенных демонстрационных правилах. |
| Bearer-токен для шлюза, если его API закрыт. |
|
|
| Адрес привязки для HTTP-транспортов. По умолчанию |
Тесты
pip install -e ".[dev]"
pytest -q # 21 protocol tests, no setup
GATE_APP_DIR=/path/to/compliance-gate/app pytest -q # + 3 production testsТесты не импортируют товар инструмент функции и не вызывают их сами. Они запускают сервер подпроцессом, проходят рукопожатие по stdio и водят его, как клиент. Потому что инструмент, работающий внутри процесса и ломающийся по сети, — это инструмент, который не работает.
Что они проверяют (помимо свертки с путёвкой):
каждый инструмент объявляет output schema, поэтому вызывающая сторона ветвится по полям, а не по прозе;
каждое нарушение несёт источник и заменяющие формулировки;
нарушения никогда не перекрываются, поэтому ничего не учитывается дважды и ни один перепис не искажается;
смещения переписывания действительно индексируют текст, с которыми они заявляют совпадение;
дайджест получается именно из отправленного текста, а не из нормализованной копии;
неизвестный идентификатор правила — ошибка, а не пустой ответ;
элемент, который движок не может проверить, возвращается как
manual, никогда как пропуск;демонстрационный бэкенд навешивает на себя ярлык демонстрационного бэкенда.
Три боевых теста пропускаются, если не установлена GATE_APP_DIR. Они проверяют версию правил и те количественные показатели, которые этот проект заявляет публично, а также то, что вердикты различаются по штатам, — то, чего никакая демонстрация заменить не может.
Область применения и ограничения
⚠️ Не юридическая консультация. Правила составлены из публичных законодательных актов, разъяснений органов и отраслевых политик; у каждого указан источник и дата его изучения. Соответствие правилам определяется регуляторами и судами, а не этим сервером.
⚠️ Шесть штатов: TX, CA, NY, FL, IL, WA. Проверка, проведённая для ошибочного штата, незаметно подставит предположительно не те обязательные элементы — аргумент state не декоративный.
⚠️ Демонстрационная база правил — это не результат продукта. Шесть правил по публичным источникам составлены так, чтобы репозиторий можно было запускать любому. База за gate.debary.us больше, собрана по первоисточникам с датами прочтения и поддерживается отдельно.
⚠️ Предупреждения имеют привязку к штату. С выработанной обязательностью в одном штате, в другом она может вернуться как advisory. Движок таким образом проявляет точность, а не неуверенность.
Apache-2.0 · DE BARY LLC, Austin TX
Available Tools
4 toolscheck_listingCheck listing textARead-only
Run listing text through the compliance rule engine.
Returns every rule that fired, the statute behind it, and the required elements the text is missing for that state and channel. Supplying brokerage, licensee and license_id lets the engine verify disclosure elements instead of deferring them to manual review.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | The listing copy exactly as it will be published | |
| state | No | Two-letter state: TX, CA, FL, AZ, NY or NC. | TX |
| channel | No | Where it will run: website, social, email, print or mls. | website |
| licensee | No | Licensed agent's name, if known | |
| brokerage | No | Sponsoring brokerage's legal name, if known | |
| license_id | No | License number, if known |
Output Schema
| Name | Required | Description |
|---|---|---|
| low | Yes | |
| high | Yes | |
| state | Yes | |
| medium | Yes | |
| backend | Yes | local = evaluated in process, remote = called a gate |
| channel | Yes | |
| summary | Yes | |
| advisory | Yes | Informational findings; never blocking on their own |
| blocking | Yes | True if any high-severity finding or any missing required element. This is the field to branch on. It is a judgement, not a clearance. |
| distinct | Yes | Distinct rules triggered |
| findings | Yes | |
| occurrences | Yes | Total findings including repeats |
| receipt_url | No | Set when the gate stored a receipt |
| text_sha256 | Yes | SHA-256 of the exact text checked |
| rules_version | Yes | |
| elements_manual | Yes | Elements the engine cannot verify mechanically. Not failures -- they need a human to confirm. |
| elements_missing | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, so the safety profile is known. The description adds meaningful behavioral detail beyond that: it documents the return contents and explains that supplying optional identifiers triggers disclosure verification instead of deferring to manual review. This gives an agent a good sense of what will happen when it invokes the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core action, the second explains the output, and the third clarifies the optional-parameter behavior. No sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the high schema coverage, the presence of an output schema, and read-only annotations, the description covers the essential invocation context well. It explains what results look like and how optional context improves the check, though it could additionally mention how this tool relates to get_receipt or when a previously generated receipt should be used instead.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all six parameters are already documented. The description adds value by explaining the functional impact of the optional identifiers—brokerage, licensee, and license_id—enabling verification of disclosure elements rather than deferring them. This goes beyond the schema's individual parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource—'Run listing text through the compliance rule engine'—and then distinguishes the tool by explaining it returns fired rules, the statute behind each, and missing required elements. This clearly differentiates it from siblings like explain_rule and suggest_rewrite.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: use this when you need to check listing text against the compliance rule engine before publication. It also explains how adding brokerage, licensee, and license_id affects the check, though it does not explicitly contrast with sibling tools or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_ruleExplain a ruleARead-only
Return the full rule behind a finding, including the statute it rests on.
Use this before telling anyone why their text was flagged. The authority field
is the citation; do not substitute a remembered one.
| Name | Required | Description | Default |
|---|---|---|---|
| rule_id | Yes | Rule id from a finding, e.g. fh-fam-001 |
Output Schema
| Name | Required | Description |
|---|---|---|
| why | Yes | |
| match | Yes | phrase or regex |
| source | Yes | Document and section the rule was compiled from |
| pattern | Yes | The literal phrase or regular expression that matches |
| rule_id | Yes | |
| suggest | Yes | |
| category | Yes | |
| severity | Yes | |
| authority | Yes | |
| scope_note | No | |
| source_date | No | |
| authority_type | Yes | binding_law, agency_guidance or industry_policy |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and closed-world. The description adds value by specifying that it returns the full rule and the statute, and importantly warns to use the `authority` field as the citation rather than substituting a remembered one. This gives behavioral guidance beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences, front-loaded with the main purpose and followed by a use case and a caveat. Every sentence carries necessary information; no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only tool with an output schema, the description covers the purpose, the trigger for use, and the critical caveat about the authority field. The runtime context (finding IDs, rule IDs) is referenced in the schema. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter `rule_id` is fully documented in the schema (100% coverage) with a clear description and example. The tool description does not add anything about the parameter, so the schema baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and object: 'Return the full rule behind a finding, including the statute it rests on.' This clearly states the tool's function and scope, and the second sentence adds the use context (before explaining why text was flagged). It does not explicitly name or contrast sibling tools, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs when to use the tool: 'Use this before telling anyone why their text was flagged.' This is clear contextual guidance. No exclusions or alternative routing is provided, but the context is enough to avoid misuse among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_receiptFetch a stored receiptARead-only
Retrieve a stored check receipt, including its anchoring block if one exists.
A receipt records what was checked, against which rule version, and the SHA-256 of the exact text. Where an anchor is present, that digest was written to a public ledger by a signer that does not run on the gate -- so the record can be shown to a third party without asking them to trust the server that produced it.
| Name | Required | Description | Default |
|---|---|---|---|
| receipt_id | Yes | Receipt id, e.g. c32520ab8cd8 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and openWorldHint annotations, the description explains what a receipt records, the SHA-256 digest, and the anchoring ledger property. It also discloses conditional behavior ('if one exists') and the trust rationale, which are meaningful details not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main action is front-loaded in the first sentence, and the following sentences add relevant context about receipt contents and anchoring without fluff. Every sentence earns its place, and the length is appropriate for the conceptual complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with an output schema, the description covers the tool's semantics, return contents, and an important edge case (anchor absent). There is no obvious invocation gap, and the description is complete enough for an agent to select and call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully documents the only parameter, receipt_id, including an example value, so schema coverage is 100%. The description adds no additional meaning about the parameter itself, keeping it at the 3 baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb ('Retrieve') and resource ('stored check receipt'), and adds the key conditional 'including its anchoring block if one exists.' This clearly differentiates the tool from siblings like check_listing, which suggests enumeration, and explain_rule/suggest_rewrite, which are rule-focused.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for fetching a single receipt by ID, but it never explicitly states when to prefer it over check_listing or mentions alternatives. An agent must infer usage from the name, title, and schema rather than receiving direct when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_rewritePrepare a rewrite briefARead-only
Collect what must change in a text, with character offsets and the engine's own replacement wording.
This tool deliberately does not rewrite anything. It hands back the spans and the
approved substitutions; composing the new text is the calling model's job, and
the result must be checked again with check_listing before it is published.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | The listing copy to be repaired | |
| state | No | TX | |
| channel | No | website |
Output Schema
| Name | Required | Description |
|---|---|---|
| hints | Yes | |
| blocking | Yes | |
| guidance | Yes | |
| text_sha256 | Yes | |
| missing_elements | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description strengthens this by explaining the tool 'does not rewrite anything' and that composing new text is the caller's job. It also reveals the postcondition: the final result must be re-checked with check_listing, which is valuable behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core function, and the following sentences add essential behavioral constraints. Every sentence earns its place, with no filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's contract, return nature (spans and substitutions), and required follow-up check. An output schema exists, so the return values do not need full explanation. The main gap is the unexplained state and channel parameters, which keeps this from being fully complete, but the overall context is strong.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%; the text parameter is documented in the schema, but state and channel are only given defaults with no explanation. The description does not compensate for these undocumented parameters or explain their role in the rewrite brief, so an agent has to infer their meaning from names and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: it 'collect[s] what must change in a text' via character offsets and replacement wording. It also distinguishes itself from siblings by explicitly saying it 'deliberately does not rewrite anything' and naming check_listing as the follow-up validation step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: this tool produces a rewrite brief, the calling model must compose the new text, and the result must be checked with check_listing before publishing. It does not explicitly catalog when to prefer this over explain_rule or get_receipt, but the sequencing and responsibility for composing the final text are clearly stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
check_listing - First observed
explain_rule - First observed
get_receipt - First observed
suggest_rewrite
TDQS
Scored across 4 tools
Each tool occupies a distinct role: running a compliance check, explaining a rule, suggesting rewrite spans, and retrieving an audit receipt. There is no meaningful overlap or ambiguity between them.
All four tools follow the same snake_case verb_noun pattern: check_listing, explain_rule, suggest_rewrite, get_receipt. The naming is predictable and makes the action and target of each tool immediately clear.
Four tools is a well-scoped size for a compliance-assistance server. Each tool supports a necessary step in the workflow without adding redundant or decorative surface area.
The tool set covers the full workflow: check a listing, understand why it was flagged, obtain safe replacement wording, and retrieve verifiable proof of a prior check. The deliberate absence of auto-rewriting is handled cleanly through the check-again instruction.
Maintenance
Related MCP Connectors
中文内容合规检查:广告法违禁词 + AI 标识规则,逐条给出法条依据。Chinese content compliance: ad-law banned terms + AI labeling.
Sentiment, toxicity, entity extraction, PII, translation, summary, QA, fraud scoring, safety audit.
Deterministic eligibility scoring for AI agents: CLEAR/HOLD/FAIL verdicts, published weights.
Pay-per-call US city property compliance and Base tx checks, paid in USDC on Base via x402.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI-powered real estate analysis with built-in EU AI Act compliance, providing a production-ready MCP server for property insights and governance.1MIT
- FlicenseNot gradedqualityFmaintenanceEnables municipal permit preflight checks for construction and renovation projects, returning evidence-linked, rule-version-aware results without using an LLM.-
- FlicenseNot gradedqualityBmaintenanceEnables scanning e-commerce advertising content to detect prohibited claims and trademark violations, returning deterministic compliance evaluations for autonomous agents.7-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to retrieve verbatim U.S. mortgage regulations with citations and effective dates, verify quotes, and run guided compliance playbooks without sending user documents to the server.MIT