Skip to main content
Glama
ranjit534

ontology-mcp

by ranjit534

Login Query Agent — Ontology MCP & Knowledge Graph

一个 POC,使用 OWL/SHACL/SKOS 知识图谱 + 两个 MCP 服务器,在 SQL Server 和 MongoDB 之间路由登录诊断查询,并支持有条件的 New Relic 升级。


架构概览

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

服务概览

服务

类型

由谁启动

用途

Apache Jena Fuseki

本地进程

你(手动)

ontology-mcp 知识图谱查询

ontology-mcp

stdio 子进程

VS Code 自动启动

诊断规划

data-mcp

stdio 子进程

VS Code 自动启动

数据库查询 + 验证

SQL Server

远程/LocalDB

已在运行

数据查询

MongoDB

远程服务器

已在运行

数据查询

New Relic

云服务

始终可用

升级(所有形状均通过)

只有 Fuseki 需要手动启动。两个 MCP 服务器均由 VS Code 自动启动。


前提条件

1. Java 11+

java -version

2. Apache Jena Fuseki JAR

该 JAR 已从 git 中排除(54 MB)。请从 jena.apache.org 下载并放置到:

infra/fuseki/fuseki-server.jar

3. Python 3.12+

python --version

4. Python 依赖项

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

5. SQL Server 的 ODBC 驱动程序

如果尚未安装,请从 Microsoft 下载 ODBC Driver 17 or 18 for SQL Server

6. 带有 GitHub Copilot(Agent 模式)的 VS Code

VS Code 1.99+ 并安装 GitHub Copilot 扩展。


分步本地启动

步骤 1 — 启动 Fuseki

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

保持此终端窗口打开。在 http://localhost:3030 验证。

步骤 2 — 加载知识图谱

首次运行或任何 schema/artifact 变更后需要执行。

$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

步骤 3 — 配置机密

.env.example 复制为 .env 并填写你的值:

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

步骤 4 — 注册两个 MCP 服务器

在工作区根目录创建 .vscode/mcp.json

{
  "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"
      }
    }
  }
}

重新加载 VS Code(Ctrl+Shift+PDeveloper: Reload Window)。


完整诊断流程

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)

仅获取 required_entities 中列出的实体。对于不需要这些步骤的类别,会跳过步骤 ②–⑤(例如 account_locked 会跳过合作方和移动端查询)。


MCP 工具参考

ontology-mcp — 知识图谱规划工具(3 个工具)

工具

步骤

输入

返回

get_diagnosis_plan

0 — 必须首先调用

category, schema

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

list_capabilities

仅回退时使用

schema

全部 8 个类别,包含 id, description, covers

get_entity_descriptor

按需使用

class_name, schema

来自 KG descriptors 图的完整列/字段映射

get_diagnosis_plan 直接login.yaml 读取能力注册表——无需调用 Fuseki。 get_entity_descriptor 查询 Fuseki descriptors 图——需要 Fuseki 正在运行。

data-mcp — 实时数据工具(7 个工具)

全部 7 个工具都需要来自 get_diagnosis_plancapability_id。未携带该参数调用将返回结构化错误。

工具

步骤

数据源

返回

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

query_sql_partner_mappings

1c

UM_UserPartnermapping

所有映射行、总计数、活跃计数

query_mongo_user

1d

users 集合

9 个投影字段 + 已执行的查询

validate_login_shapes

2

SQL + MongoDB

每个 shape 的 PASS/FAIL、all_shapes_passadvisoriesnext_step

query_newrelic_login_mfa

3a

New Relic NerdGraph

针对 /Account/Login 的 Transaction + Log(dr_010)

query_newrelic_reset_password

3b

New Relic NerdGraph

针对 3 个重置 URI 的 Transaction + Log(dr_011)


诊断类别(8 个)

类别

触发条件

login_failure

无法登录 / 无法通过身份验证 / 无法访问应用,SSO 失败,凭据被拒绝

password_reset

未收到重置链接或忘记密码邮件

otp_email

重置过程中未收到 OTP 邮件

sms_otp

未收到短信 OTP(手机号已验证)

account_state

账户已停用 / 不活跃 / 已暂停 / 已禁用

account_locked

多次尝试失败后账户被锁定

partner_mapping

合作方(BPC)映射缺失 / 不活跃

data_sync

SQL 与 MongoDB 字段不匹配


SHACL 形状(8 个,按顺序评估)

#

形状

条件

规则

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

没有活跃的合作方映射行

dr_004

5

SupplierPartnerMappingShape

供应商没有活跃的非零 BPC

dr_007

6

EmailVerificationShape

没有有效的已注册电子邮件地址(重置/OTP 流程)

7

MobileConsistencyShape

SQL 与 MongoDB 的 isMobileNumberVerified 不匹配

dr_002

8

PartnerMappingDataSyncShape

SQL 与 MongoDB 的合作方映射字段不匹配

dr_008

每个类别的 validation_sequence 仅运行这些形状中相关的子集。 advisories(例如 dr_012 电子邮件不匹配)会与形状一起返回,但不会影响 all_shapes_pass


New Relic 查询结构(两步)

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}

知识图谱 — 命名图

KG 为每个版本存储 6 个命名图 + 1 个元图:

命名图 IRI

内容

查询方

urn:kg:login:v1.0.0:capabilities

诊断手册 — 8 个类别、必需实体、验证序列

get_diagnosis_plan(步骤 0)

urn:kg:login:v1.0.0:descriptors

实体列/字段映射

get_entity_descriptor + validate_login_shapes(物化)

urn:kg:login:v1.0.0:rules

决策规则(dr_001..dr_012)

validate_login_shapes — 形状→规则映射在运行时读取

urn:kg:login:v1.0.0:shacl

SHACL 节点形状 + 约束

validate_login_shapes — 在运行时读取并执行形状(KG 驱动)

urn:kg:login:v1.0.0:ontology

OWL 类 + 属性

可供检查

urn:kg:login:v1.0.0:skos

SKOS 概念体系 + 标签

可供检查

urn:kg:login:meta

活动版本指针

每个 Fuseki 查询(图发现)

在每次诊断的两个阶段都会查询 Fuseki:

  1. get_diagnosis_plan(步骤 0)——get_active_graphs(元图)+ get_capability_plan(capabilities 图)→ 完整诊断手册

  2. validate_login_shapes(步骤 2)——读取 shacl 图(形状)、descriptors 图(用于物化的字段/类型映射)和 rules 图(形状→规则)——验证器由 KG 驱动

回退机制(每次都会记录警告):如果 Fuseki 不可达,get_diagnosis_plan 会从 login.yaml 读取 x_capability_registry,而 validate_login_shapes 会回退到程序化的 shacl_validator.py


工件重新生成

当任何 YAML schema 文件发生更改时:

$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

项目结构

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

故障排除

错误

原因

修复

sparql_failed

Fuseki 未运行

启动 Fuseki(步骤 1)

capability_id_required

Agent 跳过了 get_diagnosis_plan

重新开始对话;CLAUDE.md / copilot-instructions.md 会强制该顺序

schema_not_found

registry.yaml 缺少 schema 条目

检查 ontology/schemas/registry.yaml

registry_load_failed

login.yaml 缺少 x_capability_registry

确认 login.yaml 包含该配置块

SQL Server connection error

.env 中的主机/凭据错误

检查 SQL_SERVER_HOSTTRUSTED_CONNECTION

No module named 'pyodbc'

缺少依赖

pip install pyodbc

UnicodeEncodeError

Windows 控制台编码

添加 $env:PYTHONIOENCODING = "utf-8"

Fuseki 图数据为空

重启后 Fuseki 全新启动

运行 load_kg.py + promote.py


每日工作流

# 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

扩展 Schema

添加新实体(新的 SQL 表或 MongoDB 集合)

  1. 创建 ontology/schemas/login/v1.0.0/entities/new_entity.yaml

  2. login.yaml 的 imports 中添加 - entities/new_entity

  3. 运行 generate + load + promote

添加或更改诊断类别

  1. 编辑 login.yaml 中的 x_capability_registry

  2. x_shacl_ruleslogin.yaml)中添加/更新匹配的 shape — KG 驱动的 校验器从 shacl 图读取该 shape;无需修改 Python 即可支持 sh_in/sh_property/sparql/cross_source 此类 shape

  3. 运行 generate + load + promote(让新的 shape/规则进入 KG)

  4. 重启 MCP 服务器

添加或更改 SHACL shape

Shape 从 KG 中执行,而非从代码中执行。编辑 login.yaml 中的 x_shacl_rules,然后重新运行 regenerate + reload。除非你引入一种全新的约束 类型,否则 kg_shacl_validator.py(通用引擎)无需更改。

添加新的 schema 版本

  1. ontology/schemas/login/v1.0.0/ 复制为 v1.1.0/

  2. 编辑 v1.1.0/ 中的实体文件

  3. v1.1.0 运行 generate + load + promote

两个版本在 KG 中并存 — 始终可以通过 promote.py 回滚。

Related MCP Connectors

Related MCP Servers