Skip to content

MCP Server

Allen Byrd edited this page Jun 2, 2026 · 1 revision

MCP Server

RegRails exposes its deterministic guardrail as agent-callable tools over the Model Context Protocol. An AI agent (Claude Desktop / Claude Code, or any MCP client) calls these tools before answering a question about a student's education records or financial aid — the deterministic engine decides, and the agent uses the returned decision to shape, constrain, or refuse its reply.

This is the "tool use, human-in-the-loop" pattern: high-stakes outcomes carry human_gate_required=True and must be routed to a human. No LLM makes the decision — the engine does.

Pages: CLI Reference · Web Platform · Exports — OSCAL and SARIF · GitHub Action

Not a hosted server. RegRails runs locally over stdio — it is a Python process your MCP client launches, not a hosted/remote service. There is no RegRails-operated endpoint to point at; you install the package and the client spawns the server.


The 3 tools

Signatures and return shapes below are taken verbatim from src/regrails/mcp_server.py (and GuardrailDecision in src/regrails/models.py).

consult_guardrail

The gate. Call this before answering any question about a student's education records (FERPA) or financial-aid eligibility (Title IV).

consult_guardrail(
    query: str,
    topic: str = "unknown",                       # "disclosure" | "aid_status" | "other"
    requester_role: str = "unknown",
    purpose: str = "unknown",
    data_requested: list[str] | None = None,
    aid_determination_requested: bool = False,
    sap_status: str = "unknown",                  # "meeting"|"failed_eval"|"on_warning"|"on_probation"
    student_in_default: bool | None = None,
    consent_on_file: bool = False,
    student_opted_out_of_directory: bool = False,
    emergency_justified: bool = False,
    safe_harbor_conditions_met: list[str] | None = None,
) -> dict

Returns a GuardrailDecision as a dict:

{
  "outcome": "escalate_human_review",            // one of the 7 outcomes
  "risk_tier": "high",                           // low | medium | high
  "human_gate_required": true,                   // true => reserved to a human
  "citations_emitted": ["34-CFR-668.32(g)(1)"],
  "matched_rules": ["TIV-668.32-G1"],
  "framework": "Title IV",
  "llm_response": "…engine-authored guidance string…",
  "latency_ms": 2
}

Honor the outcome: on block or any escalate_*, do not answer the underlying question; when human_gate_required is true the decision is reserved to a human (e.g. the financial-aid office).

list_rules

Enumerate the encoded FERPA + Title IV rules so the agent can explain what the guardrail covers.

list_rules(framework: str = "all") -> list[dict]   # "FERPA" | "Title IV" | "all"

Returns a list of Rule dicts — each with id, framework, section_id, text, rule_type, triggers, severity, citation, and rationale.

check_faithfulness

Self-attest the encoding: verify every rule's source_quote is verbatim in the bundled CFR text, so an agent can prove provenance before it relies on a rule.

check_faithfulness() -> dict

Returns a pass/total report: {"passed": int, "total": int} (currently {"passed": 37, "total": 37}).


Recorded interaction (the consult-before-answer pattern)

The server's whole point is that the agent consults the gate first. A student-in-default eligibility question returns escalate_human_review (Title IV loan-default bar, § 668.32(g)(1)), so the agent declines the determination and routes to a human:

[student] "I defaulted on my student loan last year. Am I still eligible for aid this semester?"

→ tools/call  consult_guardrail
  { "query": "...defaulted on my loan...am I still eligible for aid?",
    "topic": "aid_status", "requester_role": "eligible_student",
    "aid_determination_requested": true, "student_in_default": true }

← result  (deterministic — engine decided, not the model)
  { "outcome": "escalate_human_review", "risk_tier": "high",
    "human_gate_required": true, "framework": "Title IV",
    "citations_emitted": ["34-CFR-668.32(g)(1)"], "matched_rules": ["TIV-668.32-G1"] }

[agent → student]
  "I can't make an eligibility determination on that — under 34 CFR § 668.32(g)(1)
   a borrower in default isn't eligible for further Title IV aid until the default
   is resolved, and that call is reserved for your financial-aid office. ..."

Without the gate, an ungated assistant might guess "yes" or "no". With it, the high-stakes, irreversible determination always lands with a human.


How to run it

Install the package (it ships the encoded FERPA + Title IV rules), then start the server over stdio. There are two equivalent entry points:

pip install regrails

regrails mcp serve     # CLI subcommand
regrails-mcp           # console-script entry point (pyproject [project.scripts])

Both call the same regrails.mcp_server:serve and run a FastMCP server over stdio.

claude_desktop_config.json

Wire RegRails in as a local stdio server:

{
  "mcpServers": {
    "regrails": {
      "command": "regrails-mcp"
    }
  }
}

(If regrails-mcp is not on the client's PATH, use the absolute path to the console script in your environment, or "command": "regrails", "args": ["mcp", "serve"].)

The server registers an instruction string telling the client to call consult_guardrail before answering any student-records or financial-aid question and to honor the returned outcome — so a well-behaved agent gates itself automatically.

The trust model — secrets never travel as tool arguments — is borrowed from Evidentia's evidentia-mcp server. consult_guardrail, list_rules, and check_faithfulness take no credentials and reach no network; the engine decides from the bundled rules alone.


RegRails is a proof-of-concept, not a compliance product and not legal advice. Synthetic data only.

Clone this wiki locally