SNOMED GraphRAG MCP Server
# SNOMED GraphRAG MCP Server
基于 Neo4j 与 SNOMED 子集的 GraphRAG MCP 服务,提供 `graph_search_concept`、`graph_get_related` 两个 Tools。
---
## 1. 快速开始
**环境**:Python 3.10+、Neo4j 5.x(Docker Desktop 且 Docker 已运行)、`uv` 或 `pip`、PowerShell 或 CMD。以下在**项目根**执行。
### 1.1 数据与 Neo4j
```powershell
# 生成 concept_minimal、复制 DR
python scripts/gen_concept_minimal.py
copy SNOMED_CSV\DR_118170007_new.csv docker\import\
# 启动 Neo4j
cd docker && docker compose up -d --force-recreate && cd ..
# Neo4j 启动约 10s 后执行 build(PowerShell)
Get-Content docker\import\build_minimal.cypher -Raw | docker exec -i neo4j cypher-shell -u neo4j -p password
# 校验(PowerShell)
$env:NEO4J_PASSWORD="password"
uv run python scripts/check_neo4j.py
```
> CMD 下:`type docker\import\build_minimal.cypher | docker exec -i neo4j cypher-shell -u neo4j -p password`;`set NEO4J_PASSWORD=password` 再执行 `check_neo4j.py`。Neo4j 密码非 `password` 时替换。
### 1.2 安装依赖
```powershell
uv sync
```
或 `pip install "mcp[cli]" neo4j`。
### 1.3 配置 MCP(Cursor / Claude Desktop)
在 MCP 配置中加入(`cwd`、`command` 改成本机项目**绝对路径**):
```json
{
"mcpServers": {
"snomed-graph-rag": {
"command": "D:/ai/gientech/code/rag-neo-mcp-week6/.venv/Scripts/python.exe",
"args": ["-u", "-m", "mcp_server.main"],
"cwd": "D:/ai/gientech/code/rag-neo-mcp-week6",
"env": { "PYTHONUNBUFFERED": "1", "NEO4J_PASSWORD": "password" }
}
}
}
```
- Cursor:设置 → MCP,或编辑 `%USERPROFILE%\.cursor\mcp.json`。完整示例见 `mcp_config_example.json`。
- 若出现「No server info found」:确保 `command` 指向 **项目根\\.venv\\Scripts\\python.exe**,`args` 含 `-u`,或改用 `run_mcp.bat` 作 `command`、`args: []`。
### 1.4 重启 Cursor,确认 Docker 中 Neo4j 已启动
---
## 2. 探索更复杂的 RAG 应用场景和范式
相对「文档切片 + 向量检索 + 一次查回」的简单 RAG,本项目从**应用场景**和**检索范式**两方面做更复杂探索,并落实到实现。
### 2.1 应用场景
| 维度 | 简单 RAG | 本项目 |
|------|----------|--------|
| 数据形态 | 扁平文本/切片 | **领域知识图谱**:SNOMED 本体(ObjectConcept、RoleGroup、定义关系) |
| 领域 | 通用文档 | **医学术语**:FSN、sctid、SPECIMEN_SOURCE_IDENTITY 等 |
| 语义结构 | 语义相似 | **显式关系**:`(概念)-[:HAS_ROLE_GROUP]->(RoleGroup)-[关系类型]->(目标概念)` |
**本项目实现**:`build_minimal.cypher` 构建 ObjectConcept、RoleGroup、HAS_ROLE_GROUP、SPECIMEN_SOURCE_IDENTITY;`mcp_server/neo4j_client` + Cypher 查询该图。
### 2.2 检索范式
- **多范式并存**(非单一向量检索):
- **graph_search_concept**:按 FSN 子串或 sctid 的**关键词/属性检索**(图上的索引查找);
- **graph_get_related**:按**图结构 + 关系类型**的**图遍历检索**,模式
`(c:ObjectConcept)-[:HAS_ROLE_GROUP]->(rg:RoleGroup)-[r]->(c2:ObjectConcept)`,`type(r) IN $types`。
- **图原生检索**:用 Cypher 在 Neo4j 上做模式匹配,关系类型直接参与查询,替代「向量检索 + 过滤」。
### 2.3 工具化 / Agent 范式
- **RAG 即工具**:图检索封装为 MCP 的 `graph_search_concept`、`graph_get_related`,由 Cursor/LLM **按问题选工具、组合调用**,而非固定一条检索流水线。
- **检索与生成解耦**:模型根据自然语言选工具与参数(如 `rel_types`),再基于图返回结果生成回答(Tool-augmented / Agent-RAG)。
---
## 3. MCP 应用
### 3.1 在 Cursor 里用
- 在对话中**用自然语言提问**,例如:「sctid 119299002 有哪些 SPECIMEN_SOURCE_IDENTITY 相关概念?」、「按 FSN 搜 Concept (119299002)」。
- 模型会**自动选** `graph_search_concept` 或 `graph_get_related`,把 Neo4j 查到的结果当上下文再回答。
- 流程:**提问 → Cursor 调用 Tool → MCP 查 Neo4j → 文本结果给模型 → 生成回答**。
### 3.2 两个 Tool
| Tool | 作用 |
|------|------|
| **graph_search_concept** | 按 FSN 子串或 sctid 检索 ObjectConcept;参数 `keyword`、`limit`。 |
| **graph_get_related** | 按 sctid 与关系类型(如 SPECIMEN_SOURCE_IDENTITY)查经 RoleGroup 的相邻概念;参数 `sctid`、`rel_types`(可选)。 |
### 3.3 示例问题
- 「sctid 119299002 有哪些 SPECIMEN_SOURCE_IDENTITY 相关概念?」→ `graph_get_related`
- 「在 SNOMED 图里查和 116154003 有定义关系的概念」→ `graph_get_related`
- 「按 FSN 搜 Concept (119299002)」→ `graph_search_concept`
### 3.4 前端界面(可选)
不通过 Cursor 时,可在浏览器查图:`uv sync --extra web`,然后
`$env:NEO4J_PASSWORD="password"`;`uv run uvicorn web.app:app --host 127.0.0.1 --port 8000`,打开 http://127.0.0.1:8000。
### 3.5 错误与边界
sctid 不存在、keyword 无匹配、Neo4j 断线时,Tool 返回明确提示,不抛错。
TDQS
Scored across 2 tools
The two tools have completely distinct purposes: graph_search_concept retrieves concepts by search, and graph_get_related fetches related concepts via relationships. There is no overlap or ambiguity.
Both tools follow the consistent 'graph_<verb>_<noun>' pattern with snake_case. 'graph_search_concept' and 'graph_get_related' are parallel and predictable.
With only 2 tools for a complex domain like SNOMED CT, the server is severely under-scoped. Typical SNOMED interactions require many more operations (e.g., detail retrieval, hierarchy browsing, multiple relation types).
The tool surface has major gaps: no tool to get full concept details (descriptions, synonyms), no hierarchy navigation, and graph_get_related is limited to a single relation type (SPECIMEN_SOURCE_IDENTITY). Missing core CRUD-like operations for a knowledge graph.