jev-norma-mcp
Triage regulatory documents (LatAm data-privacy policies / terms in Spanish) into a JSON report of clause obligations and risk flags using Jev as a fast System One gate, with fail-open human review.
Accepts a
.html/.pdffile path viasource, or inline text/HTML viatext;typeis inferred if omitted.Normalizes clauses with a deterministic 0-IA heuristic (no LLM words), stripping nav/boilerplate and handling CMS-agnostic HTML or text-layer/OCR PDFs.
Classifies each clause with Jev into
choice(obligacion|riesgo|sin_accion) plus a 0–2 severity score, both with calibrated confidence.Sends only the first
sampleclauses to the gate (default 12;0= all) to control cost/latency.Flags any clause with confidence < 0.8 as
gate_humano=true, routing it to a human review queue (never rejects on Jev alone).Supports normalization-only runs with
api: false(no Jev API call).Returns a JSON report with bucket, severity, confidences, and the human-review queue.
Documents generated by Drupal are likewise handled by the CMS-agnostic normalizer, letting privacy policies/terms from Drupal sites be converted into clauses and classified by the Jev gate.
The normalizer extracts policy content positionally from documents rendered by Webflow sites (and other CMSes), stripping nav/header/footer chrome and boilerplate so clauses can be fed to the Jev gate.
Policy and terms pages produced by WordPress are supported by the 0-AI normalizer, which isolates main content, merges paragraphs and list items, and discards boilerplate before triage.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jev-norma-mcp haz triaje de esta política y marca riesgos: politica.html"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
jev-norma
Triaje normativo LatAm con Jev (System One) como gate. Toma una política de
tratamiento de datos / términos en español (Ley 1581 de 2012, Colombia), normaliza las
cláusulas con heurística 0-IA (sin palabras, determinista), y clasifica cada cláusula
con Jev en choice [obligacion | riesgo | sin_accion] + score de severidad 0–2,
ambos con confidence, con una
cola de revisión humana fail-open (confianza < 0.8 → humano; nunca matar por Jev solo).
El núcleo es una decisión tipada de Jev (System 1), no generar texto. Jev corre
40-200x más rápido y es órdenes de magnitud más barato que un LLM frontier
($0.00002/cláusula medido).
¿Qué resuelve?
El buyer es pymes / legal-tech LatAm que deben auditar políticas de privacidad y términos
ante la SIC (Colombia) / AEPD (España). Hoy eso es revisión legal manual cara. jev-norma
convierte el documento crudo en un tablero de obligaciones + banderas de riesgo, y solo
enruta a humano lo genuinamente ambiguo.
Related MCP server: genpark-personal-communication-triage-sentinel-skill
Pipeline
documento (HTML/PDF) ──> cláusulas (heurística 0-IA) ──> gate Jev (choice+score+confidence)
│
confianza < 0.8 ─┴─> cola de revisión humanaNormalizador 0-IA (
jev_norma.normalizer): extracción posicional de contenido (<main>><article>><body>, sin chrome nav/header/footer),<h1..h6>y líneas cortas en mayúsculas como cabeceras de sección, merge de<p>+<li>, descarte de boilerplate (NIT/dirección/www/©/email). Funciona con cualquier CMS (Webflow, WordPress, Drupal…). PDF con capa de texto víapypdf; PDF escaneado vía--ocr(WU11).Gate Jev (
jev_norma.gate): cada cláusula se embebe en sus preguntas (self-contained) — regla de state engineering verificada empíricamente. Chunking para respetar el presupuesto de contexto (~32k) y el timeout. En una request mixta por cláusula,choiceclasifica el tipo yscoreubica la severidad en una escala ordenada de 0 a 2.Reporte fail-open (
jev_norma.pipeline): bucket, severidad y sus confianzas; confianza < 0.8 en cualquiera de las dos decisiones envía la cláusula a revisión humana.
Instalación
pip install jev-norma # CLI + MCP (stdlib puro, 0-deps)
pip install jev-norma[pdf] # + soporte PDF (pypdf)
pip install jev-norma[ocr] # + OCR PDFs escaneados (pymupdf + visión OpenRouter)Requiere TYPESAFE_API_KEY en ~/.hermes/.env o en el entorno (leída del proceso,
nunca impresa).
CLI
jev-norma --selftest # tests unitarios (sin API)
jev-norma politica.html --no-api # solo normalización (sin gate)
jev-norma politica.html [--sample 12] # normaliza + gate Jev real
jev-norma politica.pdf --output reporte.json
jev-norma politica_escaneada.pdf --ocr --sample 6 # PDF escaneado: OCR visión + gate
jev-norma escaneada.pdf --ocr --ocr-workers 8 # OCR paralelo (WU12) + gate
jev-norma --url https://…/politica.html # fetch resiliente a WAF + normaliza + gate--ocr detecta PDFs sin capa de texto (escaneados/imagen), los transcribe página a
página con un VLM barato vía OpenRouter (z-ai/glm-5.3-flash, visión) y vuelve a
alimentar el pipeline normal sin más cambios; requiere OPENROUTER_API_KEY en
~/.hermes/.env y pip install jev-norma[ocr] (WU11).
--ocr-workers N (default 4) transcribe las páginas de un escaneado en paralelo
(la llamada a la visión es I/O-bound: ~6–19 s/página), preservando siempre el orden
de página en el texto. Medido sobre un escaneado real de 5 páginas: 3.9× más rápido
(82.0 s → 21.2 s) con N=5 (WU12). --ocr-workers 1 reproduce el comportamiento serial.
--url descarga el documento con un fetcher resiliente (User-Agent de navegador real,
rotación de UA ante 403/5xx, reintento de fallos transitorios, declinación clara en 404)
— el patrón con el que se evita el bot-protection que responde 403/000 a urllib pelado
en bancos/SIC/superintendencias colombianas. Luego corre el mismo pipeline local.
MCP server
jev-norma-mcp expone el pipeline como la tool triage sobre stdio (MCP 2024-11-05,
JSON-RPC 2.0, stdlib puro), para que un agente (Hermes/Claude) lo consuma sin UI:
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"triage","arguments":{"source":"politica.html","sample":12,"api":true}}}Tests
pip install -e .[dev]
pytestEvaluación y calibración (gold set)
El gate no se declara preciso por anécdota: hay un arnés que corre el pipeline de producción contra un set etiquetado y mide accuracy, matriz de confusión, MAE de severidad, ECE (calibración) y cobertura del gate.
python tools/eval_gold.py wu20/gold.jsonl --out wu20/evidence-wu20.jsonResultado medido el 2026-11-11 (modelo jev-1.14.0, 26 cláusulas de una política real, 21,270 tokens in, 963 ms, $0.000893):
accuracy bucket 0.846;
obligacionP 0.93 / R 0.81 ·riesgoP 1.00 / R 0.75 ·sin_accionP 0.67 / R 1.00.severidad: exacta 0.615 · MAE 0.42 · dentro de 1 nivel 0.962.
calibración: ECE choice 0.023 (confianza fiable) vs ECE severidad 0.198 (no usar para automatizar prioridades).
gate a 0.8: 7/26 auto-resueltas (cobertura 0.27) con 0 errores; el resto a humano.
trade-off medido: si se ignora la confianza del eje severidad la cobertura sube a 0.73 con 1 error (obligación→sin_accion). La curva, no un umbral dogmático, es el producto: el comprador elige el punto de operación.
Limitación declarada: un solo anotador. No es ground truth legal; es una prueba de conformidad con la rúbrica. Tras WU22a el gold cubre dos políticas reales (52 cláusulas) y ya permite medir estabilidad cross-documento, pero para mover el umbral global sigue haciendo falta el segundo anotador independiente + κ de Cohen.
Curva cobertura↔accuracy (--sweep)
El umbral no se debate en abstracto: el arnés barre umbrales sobre la confianza de
choice y expone el precio de cada punto de operación. Funciona sobre una evidencia
guardada, sin volver a llamar a la API (reproducible por el comprador):
python tools/eval_gold.py --from-evidence wu21/evidence-wu21-sweep.json --sweepMedido sobre el gold set Nequi (26 cláusulas, jev-1.14.0):
umbral | auto | cobertura | accuracy_auto | errores_auto |
0.80 | 19/26 | 0.73 | 0.95 | 1 |
0.90 | 14/26 | 0.54 | 0.93 | 1 |
0.95 | 11/26 | 0.42 | 1.00 | 0 |
1.00 | 6/26 | 0.23 | 1.00 | 0 |
Dos lecturas de producto: (1) el gate de producción acopla la confianza del eje
severidad y por eso rinde 0.27 de cobertura; desacoplarlo (severidad solo prioriza, no
manda a humano) sube a 0.42 con cero errores; (2) el umbral 0.80 compra +0.31 de
cobertura pagando 1 error — ese intercambio lo decide el comprador, no el default.
recommended_point devuelve el punto de mayor cobertura con cero errores, y None
si ninguno lo logra (no se inventa recomendación sin evidencia).
Pinnea la versión cuando un umbral dependa de la calibración (el alias jev-latest
se movió a 1.14 el 14-oct-2026):
JEV_MODEL=jev-1.14.0 jev-norma politica.pdf --sample 12Estabilidad cross-documento (--by-source)
Una accuracy global esconde documentos buenos y documentos malos. --by-source
desagrega métricas, matriz de confusión y curva por documento, y adjunta el
source a cada fila de la evidencia:
cat wu20/gold.jsonl wu22/gold_logistral.jsonl > wu22/gold_multi.jsonl
python tools/eval_gold.py wu22/gold_multi.jsonl --out wu22/evidence-wu22-multi.json --sweep --by-sourceMedido el 2026-11-12 (jev-1.14.0, 52 cláusulas de dos políticas reales,
45,108 tokens in, 2,100 ms, $0.001895):
documento | n | accuracy | ECE bucket | gate@0.8 auto / errores | punto 0-errores |
Nequi (fintech, Webflow) | 26 | 0.846 | 0.013 | 8 / 0 | umbral 0.90 (12/26) |
Logistral (pyme, PDF) | 26 | 0.577 | 0.127 | 6 / 1 | umbral 0.85 (7/26) |
global | 52 | 0.712 | 0.068 | 14 / 1 | umbral 0.90 (17/52) |
Hallazgo de producto (el que manda): el gate todavía NO es estable cross-documento.
La caída se concentra en el recall de riesgo (0.29 en la pyme vs 0.75 en la fintech)
y en precisiones de sin_accion (0.44): el límite está en la semántica de la
rúbrica (¿una lista de finalidades es deber o información? ¿un aviso de
videovigilancia es riesgo?) más que en fallos absurdos del modelo. Las confianzas
acompañan: 9 de las 11 fallas de la pyme quedaron < 0.8; las dos fronterizas son
L009 (0.80, retenida igualmente por la confianza de severidad 0.34) y L035
(0.82, deslinde de responsabilidad sobre sitios de terceros), la única falla que
se auto-pasa en producción.
Consecuencia: el punto de operación con cero errores existe en las dos políticas (0.85 / 0.90) pero con coberturas distintas (0.27 / 0.46) — el comprador fija su riesgo, y el umbral por defecto no se mueve hasta tener el segundo anotador y κ.
Acuerdo inter-anotador (κ de Cohen, WU22b)
Un solo anotador no demuestra que la rúbrica sea reproducible. El paquete ciego separa el texto de la etiqueta para que una segunda persona etiquete las mismas 52 cláusulas sin ver el gold ni las predicciones del modelo:
python tools/annotate_packet.py wu22/gold_multi.jsonl \
--out wu22b/packet_blind.jsonl --guide wu22b/GUIA-ANOTACION.md
python tools/kappa_report.py wu22/gold_multi.jsonl wu22b/respuestas_anotador2.jsonl \
--out wu22b/evidence-wu22b-kappa.jsonEl paquete sale en dos formatos equivalentes: packet_blind.csv (para anotar en
Excel/Sheets, columnas bucket y severity vacías) y packet_blind.jsonl. Sólo lleva
id, source y text (lista blanca en jev_norma.packet); el reporte une por id,
lista los ids faltantes y calcula κ global y por documento, matriz de acuerdo y, si
ambos lados traen severity, acuerdo de severidad. κ es None cuando es indefinido
(sin ids comunes o acuerdo esperado = 1): no se inventa un número. Criterio
pre-registrado: κ >= 0.6 para considerar la rúbrica reproducible; por debajo, el
umbral de producción no se mueve. Sanidad verificada con gold contra gold (κ = 1.000,
52/52, ver wu22b/evidence-wu22b-sanity.json); el κ real queda pendiente del segundo
anotador humano.
Costo medido (API real, 2026-09/10)
Fuente | Cláusulas | Acierto | Costo | Latencia |
Sintético (WU1) | 12 | 11/12 (0.917) | $0.00017 | 12.9s (2 chunks) |
Nequi real (WU2) | 12 | 12/12 (1.0) | $0.00022 | 377 ms |
Banrep real no-Webflow (WU4/WU5) | 23 | gate fail-open | $0.00019 | 411 ms |
Gold set Nequi (WU20) | 26 | 22/26 (0.846) | $0.000893 | 963 ms |
Gold set multi-política (WU22a) | 52 | 37/52 (0.712) | $0.001895 | 2,100 ms |
Licencia
MIT. Proyecto open-source — tracción/redistribución, no venta directa.
Available Tools
1 tooltriageA
Triaje normativo LatAm (gate System One). Toma un documento legal (HTML o PDF de una política de tratamiento de datos / términos en español, Ley 1581 Colombia) o texto/HTML inline, normaliza cláusulas (heurística 0-IA sin palabras), y clasifica cada cláusula con Jev en choice [obligacion|riesgo|sin_accion] + confidence calibrada. Devuelve un reporte JSON con cola de revisión humana: toda cláusula con confianza < 0.8 marca gate_humano=true (fail-open: nunca matar por Jev solo).
Inputs: api, text, type, sample, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 1 tool
There is only one tool, so there is no possibility of misselection between tools. The tool's purpose—normalizing and classifying LatAm data-protection clauses with a human-review gate—is stated unambiguously.
With a single tool there is no pattern to violate, and 'triage' is a clear, concise action-oriented name. However the name alone is vague relative to the Spanish-language legal domain, so a fully self-describing name would be marginally better.
A single tool is thin for a server, even though it bundles parsing, normalization, classification, and report generation into one pipeline. It is defensible as a deliberate single-gate design, but leaves no room for separate concerns like batch runs or human-override submission.
The tool covers the core triage lifecycle end-to-end (document input → normalized clauses → classification → JSON report with human review queue). However, there is no batch/multi-document operation, no way to submit or persist human review decisions back, and no tool to expose the taxonomy/rules or a health/schema check, leaving the loop only half-closed.
Maintenance
Related MCP Connectors
Typed AI decisions for agents: classify, route, screen evidence, score and batch-label text.
Claim-level provenance preflight for sanitized nonfiction passages; automated triage only.
Deterministic trust gate for AI output: leaked-secret, prompt-injection & PII in one call.
Typed-question decisions from Jev: classify, moderate, route models and guard tool calls.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables MCP-compatible agent hosts to interact with TypeSafe AI's Jev System One API through dependency-free STDIO tools for classification, scoring, verification, gating, routing, review, and health checks.919 PyPIMIT
- FlicenseNot gradedqualityBmaintenanceEnables agents to triage personal communications and email through multi-factor urgency scoring, VIP filtering, and context-aware executive auto-drafting. Runs deterministically as a zero-dependency MCP server over JSON-RPC stdio, avoiding LLM round-trips for routine triage tasks.7-
- AlicenseNot gradedqualityBmaintenanceEnables maintainers to batch-triage local Issue JSON, optionally invoke the Jev model, and calibrate plus held-out evaluate a policy that gates which predictions may be auto-accepted versus sent to human review. Also supports task and usage checks with call limits, without editing issues, applying labels, or posting comments.1MIT
- AlicenseNot gradedqualityAmaintenanceExposes three decision tools over MCP stdio that return typed judgments — yes/no, choice, and score — with calibrated probabilities instead of prose. Runs on an offline mock unless a live provider credential is supplied, with a per-feature egress report printed to stderr.66 npmApache 2.0