Skip to main content
Glama
ranjit534

ontology-mcp

by ranjit534

Login Query Agent — Ontología MCP y grafo de conocimiento

Un POC que utiliza un grafo de conocimiento OWL/SHACL/SKOS + dos servidores MCP para enrutar consultas de diagnóstico de inicio de sesión entre SQL Server y MongoDB, con escalación condicional a New Relic.


Arquitectura de un vistazo

User prompt (VS Code Copilot)
        │
        ▼  LLM classifies category natively — no tool call
        │
  ontology-mcp  ──► Fuseki KG (SPARQL)
        │              get_diagnosis_plan(category)
        │              returns: capability_id, required_entities,
        │                       validation_sequence, newrelic_tool
        ▼
  data-mcp  ──► SQL Server  (UM_Users, UM_UserPartnermapping,
        │                    UM_UserMobileNumberVerified)
        ├──────► MongoDB     (users collection — 9 projected fields)
        ├──────► SHACL Validator  (shapes read from KG shacl graph, evaluated in sequence order)
        └──────► New Relic   (only when all_shapes_pass=true — 2-step NRQL)

Related MCP server: OntoRamp Graph Query

Resumen de servicios

Servicio

Tipo

Quién lo inicia

Requerido para

Apache Jena Fuseki

Proceso local

Tú (manual)

Consultas KG de ontology-mcp

ontology-mcp

Proceso hijo stdio

VS Code lo inicia automáticamente

Planificación del diagnóstico

data-mcp

Proceso hijo stdio

VS Code lo inicia automáticamente

Consultas a BD + validación

SQL Server

Remoto/LocalDB

Ya en ejecución

Consultas de datos

MongoDB

Servidor remoto

Ya en ejecución

Consultas de datos

New Relic

Servicio en la nube

Siempre disponible

Escalación (todas las formas pasan)

Solo Fuseki requiere un inicio manual. Ambos servidores MCP son iniciados automáticamente por VS Code.


Requisitos previos

1. Java 11+

java -version

2. JAR de Apache Jena Fuseki

El JAR está excluido de git (54 MB). Descárgalo desde jena.apache.org y colócalo en:

infra/fuseki/fuseki-server.jar

3. Python 3.12+

python --version

4. Dependencias de Python

cd c:\Ontology
python -m pip install -r requirements.txt

5. Controlador ODBC para SQL Server

Descarga ODBC Driver 17 or 18 for SQL Server de Microsoft si aún no está instalado.

6. VS Code con GitHub Copilot (modo agente)

VS Code 1.99+ con la extensión GitHub Copilot.


Inicio local paso a paso

Paso 1 — Iniciar Fuseki

cd c:\Ontology
java -jar infra\fuseki\fuseki-server.jar --config infra\fuseki\config\login-kg.ttl

Mantén esta terminal abierta. Verifícalo en http://localhost:3030.

Paso 2 — Cargar el grafo de conocimiento

Requerido en la primera ejecución o después de cualquier cambio de esquema/artefacto.

$env:PYTHONIOENCODING = "utf-8"
python scripts/generate/generate.py --schema login --version 1.0.0
python scripts/kg/load_kg.py        --schema login --version 1.0.0
python scripts/kg/promote.py        --schema login --version 1.0.0

Paso 3 — Configurar los secretos

Copia .env.example a .env y completa tus valores:

SQL_SERVER_HOST=your-server
SQL_SERVER_DATABASE=your-database
SQL_SERVER_TRUSTED_CONNECTION=yes
SQL_SERVER_ENCRYPT=yes
SQL_SERVER_TRUST_CERT=yes

MONGODB_URI=mongodb://your-host:27017
MONGODB_DATABASE=your-database

NEW_RELIC_API_KEY=NRAK-xxxxxxxxxxxxxxxxxxxx
NEW_RELIC_ACCOUNT_ID=your-account-id
NEW_RELIC_REGION=US

APP_ENV=prod

Paso 4 — Registrar ambos servidores MCP

Crea .vscode/mcp.json en la raíz del espacio de trabajo:

{
  "servers": {
    "ontology-mcp": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "mcp_server.server"],
      "cwd": "c:\\Ontology",
      "env": {
        "PYTHONPATH": "c:\\Ontology\\src",
        "PYTHONIOENCODING": "utf-8"
      }
    },
    "data-mcp": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "mcp_server.diagnostic_server"],
      "cwd": "c:\\Ontology",
      "env": {
        "PYTHONPATH": "c:\\Ontology\\src",
        "PYTHONIOENCODING": "utf-8"
      }
    }
  }
}

Recarga VS Code (Ctrl+Shift+PDeveloper: Reload Window).


Flujo de diagnóstico completo

User: "testgdpr1235@gep.com can't reset password"
        │
        │  LLM classifies: category = "password_reset"  (no tool call)
        │
        ▼
① ontology-mcp / get_diagnosis_plan(category="password_reset")
     Reads x_capability_registry from login.yaml (no Fuseki needed for this step)
     Returns: capability_id, required_entities, validation_sequence, newrelic_tool
        │
        ▼  (agent extracts username from user message; asks if missing)
        │
② data-mcp / query_sql_user(username, capability_id)
     SELECT from UM_Users → islocked, isactive, isdeleted, usertype, emailaddress, ...
        │
③ data-mcp / query_sql_mobile_verification(username, capability_id)
     SELECT from UM_UserMobileNumberVerified → ismobilenumberverified
        │
④ data-mcp / query_sql_partner_mappings(username, capability_id)
     SELECT from UM_UserPartnermapping → bpc, partnercode, isactive, contactcode
        │
⑤ data-mcp / query_mongo_user(username, capability_id)
     db.users.find_one({...}, { 9 diagnostic fields }) → MongoDB document
        │
⑥ data-mcp / validate_login_shapes(username, capability_id, validation_sequence)
     Runs only the shapes in validation_sequence (plan-scoped)
     Returns: per-shape PASS/FAIL, all_shapes_pass, advisories (e.g. dr_012)
        │
   ┌────┴──────────────────────────┐
violations found              all_shapes_pass = true
   │                               │
report per shape              ⑦a data-mcp / query_newrelic_login_mfa(username, capability_id)
with mapped rule                   OR
dr_003..dr_008                ⑦b data-mcp / query_newrelic_reset_password(username, capability_id)
                                    → Transaction → Log per traceId (max 7 days)

Solo se obtienen las entidades listadas en required_entities. Los pasos ②–⑤ se omiten para categorías que no los necesitan (p. ej. account_locked omite las consultas de partner + móvil).


Referencia de herramientas MCP

ontology-mcp — Herramientas de planificación del grafo de conocimiento (3 herramientas)

Herramienta

Paso

Entrada

Devuelve

get_diagnosis_plan

0 — primera llamada obligatoria

category, schema

capability_id, required_entities, validation_sequence, newrelic_tool, required_parameters, datasources, additional_checks

list_capabilities

solo respaldo

schema

Las 8 categorías con id, description, covers

get_entity_descriptor

bajo demanda

class_name, schema

Mapeo completo de columna/campo desde el grafo de descriptores del KG

get_diagnosis_plan lee el registro de capacidades directamente desde login.yaml — no se necesita ninguna llamada a Fuseki. get_entity_descriptor consulta el grafo de descriptores de Fuseki — requiere que Fuseki esté en ejecución.

data-mcp — Herramientas de datos en vivo (7 herramientas)

Las 7 herramientas requieren capability_id de get_diagnosis_plan. Llamarlas sin él devuelve un error estructurado.

Herramienta

Paso

Origen

Devuelve

query_sql_user

1a

UM_Users

userid, username, emailaddress, usertype, authenticationtype, islocked, isactive, isdeleted, issystemuser, mobileno

query_sql_mobile_verification

1b

UM_UserMobileNumberVerified

ismobilenumberverified + SQL ejecutado

query_sql_partner_mappings

1c

UM_UserPartnermapping

Todas las filas de mapeo, recuento total, recuento activo

query_mongo_user

1d

colección users

9 campos proyectados + consulta ejecutada

validate_login_shapes

2

SQL + MongoDB

PASS/FAIL por forma, all_shapes_pass, advisories, next_step

query_newrelic_login_mfa

3a

New Relic NerdGraph

Transacción + Log para /Account/Login (dr_010)

query_newrelic_reset_password

3b

New Relic NerdGraph

Transacción + Log para 3 URI de restablecimiento (dr_011)


Categorías de diagnóstico (8)

Categoría

Se activa cuando

login_failure

No puede iniciar sesión / autenticarse / acceder a la aplicación, fallo de SSO, credenciales rechazadas

password_reset

Enlace de restablecimiento o correo de contraseña olvidada no recibido

otp_email

Correo OTP no recibido durante el restablecimiento

sms_otp

SMS OTP no recibido (el móvil está verificado)

account_state

Cuenta desactivada / inactiva / suspendida / inhabilitada

account_locked

Cuenta bloqueada después de varios intentos fallidos

partner_mapping

Falta el mapeo de partner (BPC) o está inactivo

data_sync

Discrepancia de campos entre SQL y MongoDB


Formas SHACL (8, evaluadas en orden de secuencia)

#

Forma

Condición

Regla

1

LoginBlockShape

isLocked=1 OR isActive=0 OR isDeleted=1

dr_003

2

SystemUserShape

isSystemUser=1

dr_005

3

BuyerSSOShape

userType=Buyer AND authenticationType=SSO

dr_006

4

PartnerMappingShape

No hay ninguna fila de mapeo de partner activo

dr_004

5

SupplierPartnerMappingShape

Proveedor sin un BPC activo distinto de cero

dr_007

6

EmailVerificationShape

No hay ninguna dirección de correo electrónico registrada válida (flujos de restablecimiento/OTP)

7

MobileConsistencyShape

Discrepancia de isMobileNumberVerified entre SQL y MongoDB

dr_002

8

PartnerMappingDataSyncShape

Discrepancia en los campos de mapeo de partner entre SQL y MongoDB

dr_008

La validation_sequence de cada categoría ejecuta solo el subconjunto relevante de estas formas. Los advisories (p. ej. dr_012 discrepancia de correo) se devuelven junto con las formas pero no afectan a all_shapes_pass.


Estructura de consulta de New Relic (2 pasos)

Step 1: Transaction table (max 7 days lookback, filtered by APP_ENV)
  /Account/Login            → LoginUserName, traceId, RequiresTwoFactor, TwoFactorDetails
  /Account/RecoverPassword  → traceId, errorMessage, RecoveryUserName, RecoveryEmail
  /Account/PreResetPassword → traceId, errorMessage, PreResetUserName
  /Account/ResetPassword    → LoginUserName, traceId, errorMessage

Step 2: Log table (per traceId from Step 1)
  SELECT * FROM Log WHERE `trace.id` = '{traceId}' SINCE {transaction_timestamp}

Grafo de conocimiento — Grafos con nombre

El KG almacena 6 grafos con nombre por versión + 1 metagrafo:

IRI del grafo con nombre

Contenido

Consulta por

urn:kg:login:v1.0.0:capabilities

Playbooks de diagnóstico — 8 categorías, entidades requeridas, secuencias de validación

get_diagnosis_plan (Paso 0)

urn:kg:login:v1.0.0:descriptors

Mapeos de columna/campo de entidades

get_entity_descriptor + validate_login_shapes (materialización)

urn:kg:login:v1.0.0:rules

Reglas de decisión (dr_001..dr_012)

validate_login_shapes — mapeo forma→regla leído en tiempo de ejecución

urn:kg:login:v1.0.0:shacl

Formas de nodo SHACL + restricciones

validate_login_shapes — formas leídas y ejecutadas en tiempo de ejecución (impulsado por KG)

urn:kg:login:v1.0.0:ontology

Clases y propiedades OWL

Disponible para inspección

urn:kg:login:v1.0.0:skos

Esquema de conceptos SKOS + etiquetas

Disponible para inspección

urn:kg:login:meta

Puntero de versión activa

Cada consulta a Fuseki (descubrimiento de grafos)

Fuseki se consulta en dos etapas de cada diagnóstico:

  1. get_diagnosis_plan (Paso 0) — get_active_graphs (metagrafo) + get_capability_plan (grafo de capacidades) → el playbook de diagnóstico completo

  2. validate_login_shapes (Paso 2) — lee el grafo shacl (formas), el grafo descriptors (mapeo de campo/tipo para la materialización) y el grafo rules (forma→regla) — el validador está impulsado por KG

Resguardos (cada uno registra una advertencia): si Fuseki no está disponible, get_diagnosis_plan lee x_capability_registry de login.yaml, y validate_login_shapes recurre al shacl_validator.py programático.


Regeneración de artefactos

Cuando cambie cualquier archivo de esquema YAML:

$env:PYTHONIOENCODING = "utf-8"
python scripts/generate/generate.py --schema login --version 1.0.0
python scripts/kg/load_kg.py        --schema login --version 1.0.0
python scripts/kg/promote.py        --schema login --version 1.0.0

Estructura del proyecto

c:\Ontology\
├── src/
│   └── mcp_server/                        # PYTHONPATH=c:\Ontology\src
│       ├── server.py                      # ontology-mcp entrypoint (KG planning tools)
│       ├── diagnostic_server.py           # data-mcp entrypoint (DB/NR tools)
│       ├── tool_meta.py                   # loads config/tool_descriptions.yaml
│       ├── connectors/
│       │   ├── sql_connector.py           # pyodbc — UM_Users, UM_UserPartnermapping, ...
│       │   ├── mongo_connector.py         # pymongo — users collection (projected)
│       │   └── newrelic_connector.py      # NerdGraph GraphQL — 2-step NRQL
│       ├── diagnostics/
│       │   ├── data_fetcher.py            # orchestrates SQL + MongoDB fetch
│       │   ├── kg_shacl_validator.py      # KG-driven SHACL interpreter (PRIMARY)
│       │   └── shacl_validator.py         # programmatic evaluation (Fuseki-down fallback)
│       ├── tools/
│       │   ├── get_diagnosis_plan.py      # ontology-mcp: reads x_capability_registry
│       │   ├── list_capabilities.py       # ontology-mcp: lists all 8 categories
│       │   ├── get_descriptor.py          # ontology-mcp: SPARQL descriptors graph
│       │   ├── fetch_user_data.py         # data-mcp: 4 individual SQL/Mongo queries
│       │   ├── validate_shapes.py         # data-mcp: shape evaluation + advisories
│       │   └── query_newrelic.py          # data-mcp: NR login + reset handlers
│       ├── kg/
│       │   └── sparql_client.py           # Fuseki HTTP client + graph discovery
│       └── registry/
│           └── schema_registry.py         # registry.yaml + load_capability_registry()
│
├── ontology/
│   ├── schemas/
│   │   ├── registry.yaml
│   │   └── login/v1.0.0/
│   │       ├── login.yaml                 # root: x_capability_registry + x_shacl_rules + x_decision_rules
│   │       ├── shared/types.yaml
│   │       ├── shared/enums.yaml          # AuthenticationTypeEnum, UserTypeEnum
│   │       ├── shared/subsets.yaml
│   │       └── entities/
│   │           ├── abstract_user.yaml
│   │           ├── user.yaml              # SQL UM_Users
│   │           ├── partner_mapping.yaml   # SQL UM_UserPartnermapping
│   │           ├── mobile_verification.yaml # SQL UM_UserMobileNumberVerified
│   │           └── user_document.yaml     # MongoDB users collection
│   └── sparql/
│       ├── get_entity_descriptor.sparql
│       └── get_decision_rules.sparql
│
├── artifacts/login/v1.0.0/
│   ├── owl/login.owl.ttl
│   ├── shacl/login.shacl.ttl
│   ├── skos/login.skos.ttl
│   ├── rules/login.rules.ttl
│   ├── descriptors/login.descriptors.json
│   └── jsonld/login.context.jsonld + login.agent_template.json
│
├── scripts/
│   ├── generate/generate.py + gen_*.py + _yaml_loader.py
│   └── kg/load_kg.py + promote.py
│
├── config/
│   └── tool_descriptions.yaml             # single source of truth for all MCP tool descriptions
│
├── infra/fuseki/
│   ├── fuseki-server.jar                  # not committed — download separately
│   ├── config/login-kg.ttl
│   └── data/                              # TDB2 storage — gitignored
│
├── .github/copilot-instructions.md        # Copilot workspace instructions (auto-loaded)
├── CLAUDE.md                              # Claude Code workspace instructions (auto-loaded)
├── .vscode/mcp.json                       # MCP server registration (2 servers)
├── .env / .env.example                    # secrets — .env never committed to git
└── requirements.txt

Solución de problemas

Error

Causa

Solución

sparql_failed

Fuseki no está en ejecución

Inicia Fuseki (Paso 1)

capability_id_required

El agente omitió get_diagnosis_plan

Reinicia la conversación; CLAUDE.md / copilot-instructions.md imponen la secuencia

schema_not_found

registry.yaml no tiene la entrada del esquema

Comprueba ontology/schemas/registry.yaml

registry_load_failed

Falta x_capability_registry en login.yaml

Verifica que login.yaml tenga el bloque

SQL Server connection error

Host/credenciales incorrectos en .env

Comprueba SQL_SERVER_HOST, TRUSTED_CONNECTION

No module named 'pyodbc'

Falta una dependencia

pip install pyodbc

UnicodeEncodeError

Codificación de la consola de Windows

Añade $env:PYTHONIOENCODING = "utf-8"

Grafos de Fuseki vacíos

Inicio de Fuseki limpio tras un reinicio

Ejecuta load_kg.py + promote.py


Flujo de trabajo diario

# 1. Start Fuseki
java -jar infra\fuseki\fuseki-server.jar --config infra\fuseki\config\login-kg.ttl

# 2. Load KG (only after schema or artifact changes)
$env:PYTHONIOENCODING = "utf-8"
python scripts/kg/load_kg.py --schema login --version 1.0.0
python scripts/kg/promote.py --schema login --version 1.0.0

# 3. Open VS Code — both MCP servers start automatically

Ampliar el esquema

Añadir una nueva entidad (nueva tabla SQL o colección de MongoDB)

  1. Crea ontology/schemas/login/v1.0.0/entities/new_entity.yaml

  2. Añade - entities/new_entity a los imports de login.yaml

  3. Ejecuta generate + load + promote

Añadir o cambiar una categoría de diagnóstico

  1. Edita x_capability_registry en login.yaml

  2. Añade/actualiza la forma correspondiente en x_shacl_rules (login.yaml) — el validador impulsado por el KG la lee desde el grafo shacl; no se necesita editar Python para las formas sh_in/sh_property/sparql/cross_source

  3. Ejecuta generate + load + promote (para que la nueva forma/regla entre en el KG)

  4. Reinicia los servidores MCP

Añadir o cambiar una forma SHACL

Las formas se ejecutan desde el KG, no desde el código. Edita x_shacl_rules en login.yaml, y luego regenera + recarga. kg_shacl_validator.py (el motor genérico) no necesita cambios a menos que introduzcas un tipo de restricción completamente nuevo.

Añadir una nueva versión del esquema

  1. Copia ontology/schemas/login/v1.0.0/v1.1.0/

  2. Edita los archivos de entidades en v1.1.0/

  3. Ejecuta generate + load + promote para v1.1.0

Ambas versiones coexisten en el KG — la reversión siempre está disponible mediante promote.py.

Related MCP Connectors

Related MCP Servers