Skip to main content
Glama
DE-BARY-LLC

debary-mcp-compliance

Official
by DE-BARY-LLC

debary-mcp-compliance

tests

An MCP server that gives a language model access to a fair-housing and advertising rule engine for US real-estate listing text — without giving it the decision.

The engine is deterministic: 81 phrase rules, 35 required elements, six states, no model anywhere in the decision path. This server carries the question in and the verdict out. The model on the other end receives every finding, the statute behind it, and the wording the rule base proposes instead. What it does not receive is permission to disagree.

That is the reason this is an MCP server and not a REST endpoint with a nice description. A model needs a tool it cannot argue with, and MCP is the protocol that puts that tool inside its reach without putting it inside its judgement.

Built by DE BARY LLC. The engine it wraps runs at gate.debary.us.


Try it

No configuration, no rule base, no network:

pip install -e .
python demo.py

The demo starts the server as a subprocess, speaks MCP to it, and walks through a listing that fails, the statute behind each finding, a repair, and the re-check that catches what the repair still missed.

⚠️ With nothing configured the server runs on a sample rule base — six rules and four required elements, written for this repository so it can be run and tested by anyone. It labels itself: every result carries backend: "sample" and rules_version: "sample-1". It is illustrative and is not a compliance tool. Point GATE_APP_DIR or GATE_URL at the real base to get real answers.


Related MCP server: Claude Critical Rules MCP Server

What it exposes

MCP has three primitives. This server uses all three, and each one is here because it is the right shape for what it carries.

Tools — things the model asks the engine to do

Tool

Purpose

check_listing

Run listing copy through the engine. Returns findings, missing required elements, and a blocking verdict to branch on.

explain_rule

The full rule behind a finding, including the statute. So a model cites the authority instead of recalling one.

suggest_rewrite

Character offsets of every problem span plus the approved replacement wording. Deliberately does not rewrite — composing text is the model's job, verifying it is the engine's.

get_receipt

A stored check: what was examined, against which rule version, and the SHA-256 of the exact text.

Resources — material the model can read directly

URI

Contents

gate://rules

The rule base index: every rule and required element by id, severity and category

gate://rules/{rule_id}

One rule in full, with authority and source document

gate://elements/{state}

Disclosure elements an advertisement must carry in that state

gate://receipt/{receipt_id}

A past check with its anchoring block

Prompts — the workflows, so each client does not reinvent them

Prompt

What it enforces

review_listing

check → cite → rewrite → check the rewrite again. The last step is the one that gets skipped when a model improvises.

explain_verdict

Turn a receipt into something a licensed agent can act on, including what the engine could not verify mechanically.


Design notes

The verdict is not negotiable. blocking is true when any high-severity rule fires or any required element is missing. The tool description says so, the server instructions say so, and the review_listing prompt tells the model to report a failed rewrite plainly rather than presenting it as fixed.

blocking: false is not a clearance. It means no rule fired. elements_manual lists what the engine cannot check mechanically — those still need a person. A tool that quietly reports success for what it did not examine is worse than no tool.

Every finding carries its authority. A finding without a citation is an opinion, and a rule engine that has opinions is a language model with extra steps. This is enforced in the test suite, not just intended.

Three backends, one interface. LocalBackend imports the engine and evaluates in-process — no network, and the listing text never leaves the machine. RemoteBackend calls a running gate over HTTP. SampleBackend carries a small rule base of its own so the server runs on a fresh clone. All three return the same shape, so the MCP layer never learns which one answered.

The fallback announces itself. A sample that silently impersonates the real thing would be a trap. This one puts sample in every result and sample-1 in the version field, and there is a test that fails if either label goes missing.

Two transports. stdio for a desktop client, streamable-http for the container. sse is still accepted for older clients; it is deprecated in the protocol and should not be chosen for anything new.

Requires the 2.x SDK. The Python SDK renamed FastMCP to MCPServer in 2.0 and moved it from mcp.server.fastmcp to mcp.server.mcpserver; result fields went from structuredContent to structured_content. This server targets 2.x only. Supporting both majors behind a shim was considered and rejected — it would add a compatibility layer to a project whose whole argument is that the decision path stays simple.


Running it

Against a local rule base

pip install -e .
GATE_APP_DIR=/path/to/compliance-gate/app debary-mcp-compliance

Against a running gate

GATE_URL=https://gate.debary.us GATE_TOKEN=… debary-mcp-compliance

GATE_APP_DIR wins if both are set: evaluating in-process is faster and keeps the listing text off the wire.

In Docker

docker compose up -d

The container listens on :8765/mcp (streamable HTTP) and is published on host port 8766, bound to loopback. Put a tunnel in front of it rather than opening a port. The rule base is mounted read-only — the container can evaluate rules, not change them.

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

Configuration

Variable

Meaning

GATE_APP_DIR

Directory holding engine.py and rules.json. Selects the local backend.

GATE_URL

Base URL of a running gate. Selects the remote backend.

(neither set)

Falls back to the built-in sample rule base.

GATE_TOKEN

Bearer token for that gate, if its API is closed.

MCP_TRANSPORT

stdio (default), streamable-http, or sse.

MCP_HOST / MCP_PORT

Bind address for the HTTP transports. Default 0.0.0.0:8765.


Tests

pip install -e ".[dev]"
pytest -q                                            # 21 protocol tests, no setup
GATE_APP_DIR=/path/to/compliance-gate/app pytest -q  # + 3 production tests

The tests do not import the tool functions and call them. They launch the server as a subprocess, complete the handshake over stdio, and drive it as a client — because a tool that works in-process and fails over the wire is a tool that does not work.

What they check, beyond the happy path:

  • every tool declares an output schema, so callers branch on fields rather than prose

  • every finding carries an authority and a replacement wording

  • findings never overlap, so nothing is double-counted and no rewrite is corrupted

  • rewrite offsets actually index the text they claim to match

  • the digest is of the exact text submitted, not a normalised copy

  • an unknown rule id is an error, not an empty answer

  • an element the engine cannot verify comes back manual, never as a pass

  • the sample backend labels itself as one

The three production tests skip unless GATE_APP_DIR is set. They assert the rule version and the counts this project states in public, and that verdicts differ by state — claims no sample can stand in for.


Scope and limits

⚠️ Not legal advice. The rules were compiled from public statutes, agency guidance and industry policy; each carries its source and the date it was read. Compliance is decided by regulators and courts, not by this server.

⚠️ Six states: TX, CA, FL, AZ, NY, NC. A check run against the wrong state silently applies the wrong required elements — the state argument is not cosmetic. The server does not keep its own copy of this list: it asks the engine, because a hand-maintained copy drifted once and made two states unreachable.

⚠️ The sample rule base is not the product. Six rules against public statutes, written so this repository can be run by anyone. The base behind gate.debary.us is larger, is compiled from sourced documents with read dates, and is maintained separately.

⚠️ Advisory findings are state-scoped. A phrase that is binding in one state may come back as advisory in another. That is the engine being precise, not uncertain.


Apache-2.0 · DE BARY LLC, Austin TX

Available Tools

4 tools
check_listingCheck listing textA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe listing copy exactly as it will be published
stateNoTwo-letter state: TX, CA, FL, AZ, NY or NC.TX
channelNoWhere it will run: website, social, email, print or mls.website
licenseeNoLicensed agent's name, if known
brokerageNoSponsoring brokerage's legal name, if known
license_idNoLicense number, if known

Output Schema

ParametersJSON Schema
NameRequiredDescription
lowYes
highYes
stateYes
mediumYes
backendYeslocal = evaluated in process, remote = called a gate
channelYes
summaryYes
advisoryYesInformational findings; never blocking on their own
blockingYesTrue if any high-severity finding or any missing required element. This is the field to branch on. It is a judgement, not a clearance.
distinctYesDistinct rules triggered
findingsYes
occurrencesYesTotal findings including repeats
receipt_urlNoSet when the gate stored a receipt
text_sha256YesSHA-256 of the exact text checked
rules_versionYes
elements_manualYesElements the engine cannot verify mechanically. Not failures -- they need a human to confirm.
elements_missingYes

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ruleA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
rule_idYesRule id from a finding, e.g. fh-fam-001

Output Schema

ParametersJSON Schema
NameRequiredDescription
whyYes
matchYesphrase or regex
sourceYesDocument and section the rule was compiled from
patternYesThe literal phrase or regular expression that matches
rule_idYes
suggestYes
categoryYes
severityYes
authorityYes
scope_noteNo
source_dateNo
authority_typeYesbinding_law, agency_guidance or industry_policy

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 receiptA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
receipt_idYesReceipt id, e.g. c32520ab8cd8

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 briefA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe listing copy to be repaired
stateNoTX
channelNowebsite

Output Schema

ParametersJSON Schema
NameRequiredDescription
hintsYes
blockingYes
guidanceYes
text_sha256Yes
missing_elementsYes

TDQS

A4.3/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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. Dates show when Glama detected each change.

  1. 4 tool updatesv0.1.0
    • First observedcheck_listing
    • First observedexplain_rule
    • First observedget_receipt
    • First observedsuggest_rewrite

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivityMaintained
ResponsivenessNo issues

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Provides AI agents with instant access to jurisdiction-specific landlord-tenant law data and verified state statutes across five US states and major cities. It enables users to query legal rules for security deposits, eviction timelines, and habitability standards with sub-10ms local response times.
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI-powered real estate analysis with built-in EU AI Act compliance, providing a production-ready MCP server for property insights and governance.
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to parse and analyze mortgage documents (Loan Estimates & Closing Disclosures), converting them into structured MISMO-compliant JSON and checking for TRID compliance violations.
    2
    MIT

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/DE-BARY-LLC/debary-mcp-compliance'

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