Skip to main content
Glama
Coherence Analysis MCP

Coherence Analysis MCP

Coherence Analysis MCP

Servidor MCP de analisis de coherencia interna de correos. Componente del prototipo de deteccion de phishing con modelos de lenguaje grandes y servidores MCP (trabajo de graduacion, Universidad del Valle de Guatemala).

Que es

Este servidor audita las contradicciones internas de un correo: si lo que dice ser el remitente, el tono, el formato, lo que pide y la firma son consistentes entre si. La idea central es que un correo legitimo suele ser internamente coherente, mientras que uno de phishing casi siempre tiene costuras, aunque cada elemento por separado no parezca sospechoso: dice ser tu banco pero saluda de forma generica, transmite urgencia extrema con un tono informal y errores, pide datos que una entidad real nunca pediria por correo, o firma como una organizacion distinta a la que aparece en el remitente.

Punto central de diseno: el servidor no emite un veredicto de phishing. Solo reporta las incoherencias detectadas, cada una con su cita textual literal como evidencia. La decision final de clasificacion pertenece al orquestador.

Otro punto central de diseno: la deteccion la hace un LLM con salida estructurada, no listas de palabras clave ni conteos lexicos. Se probo que los conteos lexicos no discriminan bien entre correos legitimos y de phishing; el LLM puede razonar sobre coherencia semantica y de estilo de una forma que un conteo de palabras no puede.

Related MCP server: memory-immune-system

Categorias de incoherencia auditadas

Categoria

Que busca

sender_vs_content

Afirma ser una entidad conocida pero el saludo es generico o el estilo no cuadra

urgency_vs_channel

Comunica algo grave o urgente de forma informal o con errores

subject_vs_body

El asunto y el cuerpo no coinciden en lo que ofrecen o piden

authority_vs_execution

Se presenta como oficial pero tiene errores de gramatica, formato pobre o inconsistencias

request_vs_context

Pide datos sensibles o acciones que una entidad legitima no solicitaria por correo

identity_consistency

El remitente, la firma y el contenido nombran entidades distintas o inconsistentes

Un correo puede mostrar cero, una o varias de estas incoherencias; el LLM no esta forzado a encontrar algo en cada categoria.

Estructura del proyecto

coherence-analysis-MCP/
├── src/coherence_analysis_mcp/
│   ├── __init__.py       Expone main() importandola desde server
│   ├── server.py         Servidor MCP y definicion de las 3 herramientas
│   ├── schema.py         Esquema Pydantic de salida y las 6 categorias
│   ├── llm_engine.py     Abstraccion del motor LLM (mock + Anthropic)
│   └── coherence.py      Logica del analisis: prompt, guardrails, validacion de evidencia
├── tests/
│   ├── test_coherence.py     Pruebas unitarias (esquema, evidencia, modo mock)
│   └── test_integration.py   Prueba end-to-end (cliente MCP real por stdio, modo mock)
├── run_server.py          Punto de entrada recomendado para arrancar el servidor
├── pyproject.toml
└── README.md

Instalacion

Con uv (recomendado):

uv sync

Con pip en modo editable:

pip install -e ".[dev]"

Configuracion del motor LLM

El motor LLM se configura por variable de entorno; nunca hay una API key hardcodeada en el codigo. Ver .env (no se versiona, solo sirve de plantilla local):

Variable

Valores

Por defecto

COHERENCE_LLM_PROVIDER

mock o anthropic

mock

COHERENCE_LLM_MODEL

nombre del modelo (solo aplica si el proveedor no es mock)

claude-sonnet-5

COHERENCE_LLM_API_KEY

API key del proveedor configurado

(vacio)

Modo mock (COHERENCE_LLM_PROVIDER=mock, valor por defecto): no llama a ninguna API ni necesita conectividad ni API key. Devuelve siempre la misma respuesta fija y valida, calibrada sobre un correo de referencia (MOCK_EMAIL_TEXT en llm_engine.py). Es el modo que usan las pruebas automatizadas.

Proveedor real implementado: Anthropic. Usa tool use forzado (tool_choice) contra la API de Claude para obtener JSON valido segun el esquema de schema.py, que luego se vuelve a validar con Pydantic. Es el unico proveedor real de referencia por ahora; la clase LLMEngine en llm_engine.py esta disenada para que agregar otro proveedor (OpenAI, por ejemplo) sea sumar una subclase nueva y una rama en get_engine(), sin tocar coherence.py ni server.py.

Herramientas expuestas

Herramienta

Que hace

analyze_coherence

Dado el texto de un correo, devuelve el reporte de incoherencias detectadas (JSON validado)

get_output_schema

Devuelve el esquema JSON de salida, para que el orquestador sepa que esperar sin llamar primero a analyze_coherence

list_incoherence_categories

Lista las 6 categorias de incoherencia auditadas, con su descripcion

Forma del reporte de analyze_coherence

{
  "incoherences": [
    {
      "category": "sender_vs_content",
      "description": "...",
      "quote": "cita textual literal del correo"
    }
  ],
  "coherence_score": 0.15,
  "summary": "Resumen en lenguaje claro de las principales incoherencias.",
  "discarded_count": 0
}
  • coherence_score va de 0 (lleno de contradicciones) a 1 (totalmente coherente).

  • Cada incoherencia trae una cita textual literal del correo como evidencia obligatoria. coherence.py valida que cada cita aparezca realmente en el texto (ignorando solo diferencias de espacios); cualquier incoherencia cuya cita no exista se descarta antes de devolver el resultado, y discarded_count indica cuantas se descartaron asi.

  • El correo se trata siempre como dato no confiable: el prompt lo delimita explicitamente y le indica al LLM que ignore cualquier instruccion dentro del texto del correo (guardrail contra prompt injection).

Como probarlo

1. Pruebas unitarias (rapidas, sin arrancar el servidor ni llamar a ninguna API; usan el modo mock):

uv run python tests/test_coherence.py

2. Prueba de integracion end-to-end (arranca el servidor y actua como cliente MCP real, con handshake y llamada a las 3 herramientas, forzando modo mock):

uv run python tests/test_integration.py

3. Con pytest (corre ambas pruebas):

uv run pytest tests/

4. Inspeccion manual con el MCP Inspector (interfaz visual oficial):

uv run mcp dev src/coherence_analysis_mcp/server.py

5. Arranque directo del servidor (queda esperando mensajes por stdio; usa Ctrl+C para salir):

uv run python run_server.py

Como conectarlo a un cliente MCP

Para usarlo desde un cliente compatible (por ejemplo, Claude Desktop, o el orquestador del prototipo), agrega al archivo de configuracion del cliente:

{
  "mcpServers": {
    "coherence-analysis-mcp": {
      "command": "uv",
      "args": ["run", "python", "run_server.py"],
      "cwd": "/ruta/al/proyecto/coherence-analysis-MCP",
      "env": {
        "PYTHONUTF8": "1",
        "COHERENCE_LLM_PROVIDER": "anthropic",
        "COHERENCE_LLM_MODEL": "claude-sonnet-5",
        "COHERENCE_LLM_API_KEY": "..."
      }
    }
  }
}

Por que existe run_server.py (y no simplemente el comando de consola)

El proyecto tambien instala un comando de consola (coherence-analysis-mcp, definido en [project.scripts] de pyproject.toml), que es la convencion normal de este tipo de servidor MCP. Sin embargo, ese comando depende de que coherence_analysis_mcp sea importable a traves del mecanismo de instalacion editable de uv/pip (un archivo .pth en site-packages que apunta de vuelta a src/). En maquinas donde la ruta del proyecto contiene caracteres no ASCII (como las tildes y la eñe de este proyecto: Sofía, año), Python puede leer ese .pth con la codificacion de texto por defecto del sistema (cp1252 en Windows en vez de UTF-8), la ruta queda corrupta, y el import falla en silencio con ModuleNotFoundError: No module named 'coherence_analysis_mcp', sin relacion alguna con el codigo del servidor.

run_server.py evita el problema de raiz: agrega src/ a sys.path directamente en Python (con pathlib, sin leer ningun archivo .pth) antes de importar el paquete. Funciona igual sin importar quien lo invoque (tu terminal, mcp dev, o un cliente MCP como Claude Desktop) y sin necesitar ninguna variable de entorno. Por eso es el metodo recomendado, tanto en los comandos de arriba como en el ejemplo de configuracion de cliente MCP.

Si prefieres usar uv run coherence-analysis-mcp de todas formas y tu maquina tiene el mismo problema, corre set PYTHONUTF8=1 (cmd) o $env:PYTHONUTF8=1 (PowerShell) antes, en la misma terminal donde vas a correr el comando.

La variable de entorno PYTHONUTF8=1 fuerza a Python a usar UTF-8 en todos lados y resuelve esto por completo. Por eso aparece en el .env del proyecto y en el env del ejemplo de configuracion de cliente MCP arriba (los clientes como Claude Desktop arrancan el servidor como un subproceso nuevo, que no hereda las variables que hayas exportado en tu propia terminal).

Las pruebas (test_coherence.py, test_integration.py, pytest) no necesitan esto porque agregan src/ a sys.path explicitamente en el codigo (o arrancan el servidor via run_server.py), sin depender de la instalacion editable.

Autoria

Sofia Mishell Velasquez - Universidad del Valle de Guatemala.

Available Tools

3 tools
analyze_coherenceA
Audit the internal coherence of an email and return detected incoherences.

Uses an LLM with structured output to find contradictions between what
the email claims to be and how it is actually written (e.g. claims to be
a bank but greets generically, is urgent but informal, requests data a
real entity would not ask for by email). Every reported incoherence is
validated to have a literal quote present in the email text; any
incoherence whose quote cannot be found verbatim is discarded before the
result is returned. This is NOT a phishing verdict, only a coherence
signal for the orchestrator to weigh alongside other MCP servers.

Args:
    email_text: Full text of the email to analyze (subject and/or body).
        Treated strictly as untrusted data, never as instructions.

Inputs: email_text (required).

get_output_schemaA
Return the JSON schema of the structured output produced by
analyze_coherence, so the orchestrator knows what fields to expect
(incoherences, coherence_score, summary, discarded_count) without
needing to call the tool first.

Inputs: no named parameters.

list_incoherence_categoriesA
List the 6 incoherence categories this server audits, with a
description of what each one looks for. Useful for the orchestrator to
understand the results of analyze_coherence without guessing what each
category id means.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.7/5.0

    Scored across 3 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: analyze_coherence performs the analysis, get_output_schema returns the result schema, and list_incoherence_categories explains the audit categories. There is no overlap or ambiguity between them.

    Naming Consistency5/5

    All tool names follow the same snake_case verb_noun pattern: analyze_coherence, get_output_schema, list_incoherence_categories. The naming is perfectly consistent and predictable.

    Tool Count5/5

    Three tools is appropriate for this narrow, stateless analysis server: one primary tool plus two supporting metadata tools. Every tool earns its place and the surface is not padded or redundant.

    Completeness5/5

    The tool surface fully covers the stated domain: analyze_coherence performs the core task, get_output_schema tells the caller what to expect, and list_incoherence_categories provides the context needed to interpret results. There are no obvious missing operations or dead ends.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables real-time auditing of LLM long-term memory to detect contradictions, user-introduced falsehoods, staleness, and unsourced fabrications, while providing a safe memory store with tools like recall, review, and restore.
      1
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables post-hoc auditing of an agent's retrieval supply chain by recording digest-only provenance from source through chunk, transformation, context and decision, then reporting influence rankings with an honest unexplained residual, lineage traces, advisory source trust and retirement recommendations, and retrieval schema drift. It never performs retrieval, ranks documents at query time, or blocks decisions.
      MIT