ClinGate
ClinGate is an MCP-native human-in-the-loop gateway that sits between AI agents and clinical tools, classifying every action by risk and forcing human approval before irreversible actions reach patient records.
README
ClinGate
MCP Gateway for Clinical AI Agent Oversight
Why this exists
ClinGate is an open-source MCP (Model Context Protocol) gateway that sits between any AI agent framework and the clinical tools it calls. It classifies every action by risk in real time, and forces a human decision before anything irreversible reaches a patient record. Clinical AI agents are moving from answering questions to taking actions, but most multi-agent frameworks lack the built-in capability to enforce who is allowed to approve what, and how it gets logged. This is an infrastructure and dev-tool project, not a medical device. It acts as a governance layer any agent framework can sit behind, with clinical policy rules as the first shipped example.
Architecture Pipeline
graph TD
Agent[Agent Orchestrator] -->|MCP Tool Calls| Gateway[ClinGate MCP Gateway Server]
Gateway --> RuleEngine{Deterministic Rule Engine}
RuleEngine -->|No match| LLM{LLM Risk Classifier}
RuleEngine -->|Match| DecisionBranch
LLM --> DecisionBranch
DecisionBranch{Decision State} -->|AUTO_CLEAR| RealTool[Real Downstream Tool API]
DecisionBranch -->|ESCALATE| Queue[Escalation Queue & Dashboard]
DecisionBranch -->|BLOCK| Blocked[Blocked Action]
Queue -->|Human Approves| RealTool
Queue -->|Human Rejects| Blocked
Queue -.->|Logs to| Ledger[(SQLite Audit Ledger)]
DecisionBranch -.->|Logs to| Ledger
Request Lifecycle (order_medication)
sequenceDiagram
participant A as Agent
participant G as ClinGate Gateway
participant F as openFDA API
participant R as Rule Engine
participant L as Audit Log
A->>G: order_medication(drug="Adderall")
G->>F: GET api.fda.gov/drug/label.json
F-->>G: DEA Schedule II
G->>R: Evaluate Policies (clinical-default.yaml)
R-->>G: Match: block_controlled_substances -> BLOCK
G->>L: Append row (BLOCK, reason: "Controlled substance")
G-->>A: Call intercepted and held for review. Status: BLOCK.
Regulatory Grounding
This gateway directly addresses the human-oversight patterns expected by modern regulatory frameworks:
| Requirement | Article / Guidance | How ClinGate addresses it |
|---|---|---|
| Human oversight capability | EU AI Act Art. 14 | Escalation queue with hard stop before execution |
| Record-keeping / logging | EU AI Act Art. 12 | Structured, exportable audit ledger per action |
| Deployer oversight assignment | EU AI Act Art. 26 | Reviewer role explicitly modeled, not implicit |
| Risk management system | EU AI Act Art. 9 | Configurable risk taxonomy + policy rules as first-class artifact |
| AI as Medical Device oversight | UK MHRA guidance | Same interception pattern maps directly to SaMD change-control expectations |
| Vendor oversight evidence | NHS DTAC | Dashboard + audit export is the artifact a DTAC assessor asks for |
Real Data Sources
The single biggest thing that separates this from a toy demo is that the risk classification pipeline reasons over real, live, public data rather than a hard-coded drug list. Four public sources are wired in:
| Source | What it provides | Endpoint (public, no key required for demo volume) | Used for |
|---|---|---|---|
| openFDA Drug Label API | Structured drug labeling including DEA schedule where present | GET https://api.fda.gov/drug/label.json?search=openfda.generic_name:"{drug}"&limit=1 |
Real-time controlled-substance detection — replaces a static keyword list with an actual regulatory field lookup |
| RxNorm (NLM RxNav) | Normalized drug names, RxCUI identifiers, ingredient relationships | GET https://rxnav.nlm.nih.gov/REST/rxcui.json?name={drug} |
Normalizes whatever string the agent used ("tylenol" → acetaminophen RxCUI) before the rule engine matches it, so policy rules match on the real ingredient, not on string luck |
| ClinicalTrials.gov API v2 | Live registry of recruiting trials by condition | GET https://clinicaltrials.gov/api/v2/studies?query.term={condition}&pageSize=3 |
Grounds the create_referral action type with real, currently-recruiting trials instead of a fictional referral target |
| HAPI FHIR public R4 sandbox | Real FHIR R4 Patient resources (synthetic patients, real schema and server) |
GET https://hapi.fhir.org/baseR4/Patient?_count=3&_format=json |
Populates the demo's patient context with genuine FHIR-shaped records, not a hand-typed JSON blob |
Quickstart
- Clone the repository
git clone https://github.com/vilsee/clingate.git
cd clingate
- Setup Environment Variables
cp .env.example .env
(Note: CLASSIFIER_MODE=mock is the safe default requiring no Anthropic API key. If you have an Anthropic API key, set CLASSIFIER_MODE=live and supply your key).
- Run the application (While a Docker Compose configuration is provided, it has not yet been verified end-to-end. We recommend running locally with Uvicorn for development and testing.)
pip install -r requirements.txt
uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reload
The FastAPI MCP server and the static Next.js/HTML dashboard will be available at http://localhost:8000.
Screenshots
- TODO:
(The Reviewer Queue showing an ESCALATE item pending with a Classifier Disagreement badge) - TODO:
(The raw JSON audit ledger showing the final_status and classifier_disagreement flags) - TODO:
(The demo.html page showing live API degradation)
Implemented vs Roadmap
As per the Product Requirements Document (PRD), the MVP milestone requires two differentiating features to be fully implemented, with the remaining four explicitly stubbed for the roadmap.
Implemented Features
1. Classifier Disagreement Signal
- Status: Implemented
- Description: Logs when the deterministic rule engine and the fallback LLM risk classifier would have made different decisions.
- Implementation Details: Evaluated inside the interception loop (
main.py). If the rule engine falls through, the LLM is queried. If the LLM returns an escalation or block (disagreeing with the implicit rule engine fall-through of AUTO_CLEAR), theclassifier_disagreementboolean flag in the SQLite audit table is set toTrue.
2. SLA Breach Failsafe
- Status: Implemented
- Description: A background daemon that automatically transitions unreviewed
ESCALATEitems intoBLOCK(or a specific SLA breach state) if human reviewers fail to act within a defined timeframe. - Implementation Details: Implemented as an asynchronous background task
sla_breach_monitorinmain.py. It loops every 60 seconds and updates anyPENDINGintercept call older than 5 minutes toSLA_BREACH_BLOCKin the database.
Roadmap Stubs (To Be Implemented)
These features have been explicitly documented as stubs in the backend/main.py source code to facilitate future roadmap development.
3. Clinical Trials Context Matching
- Status: Stubbed (
stub_feature_1_clinical_trials_matching) - Description: Would automatically query ClinicalTrials.gov and attach currently recruiting, localized trials to any blocked medication order to provide alternatives to the reviewer. (Note: ClinicalTrials.gov data is currently retrieved and attached for referrals as a baseline integration, but this advanced matching/suggestion algorithm is deferred).
4. FHIR Resource Validation
- Status: Stubbed (
stub_feature_2_fhir_resource_validation) - Description: Would validate outgoing tool arguments against active FHIR R4 profiles to ensure payload schema compliance before the call ever reaches the real system.
5. Reviewer Delegation Rules
- Status: Stubbed (
stub_feature_3_reviewer_delegation_rules) - Description: Would route specific
ESCALATEitems to specific specialist queues (e.g., Oncology-related referrals route only to boarded oncologists) rather than a global reviewer pool.
6. Agent Feedback Loop
- Status: Stubbed (
stub_feature_4_agent_feedback_loop) - Description: Would send natural language explanations of a
BLOCKdecision back to the autonomous agent, giving it the opportunity to self-correct and try a different tool call without human intervention.
Tech Stack
- Gateway server: Python, FastAPI, MCP Python SDK
- Rule engine: custom YAML DSL +
pydanticvalidation - LLM classification: Anthropic API (Claude) via structured JSON output
- Audit store: SQLite (migratable to PostgreSQL)
- Dashboard: HTML/CSS/JS (vanilla stack matching a Next.js aesthetic)
- External APIs: openFDA, RxNorm, ClinicalTrials.gov, HAPI FHIR
License & Contributing
Licensed under the Apache 2.0 License. Want to add your own YAML policy pack? See CONTRIBUTING.md.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.