kb-mcp-server
Serves as the production vector storage backend (via pgvector) for the knowledge base, enabling semantic retrieval and graph data storage, with an in-memory mode for offline development.
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., "@kb-mcp-serverWhat's the status of order 12345 and related return policy?"
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.
KB MCP Server · 企业级 B2B 客服工单知识库 RAG 系统
基于 MCP 协议 + Python 3.13 的可调用外部 API 的知识库。给 Agent 一套「检索知识 + 调用实时数据 + 结构化合成答复」的工具,让客服工单场景的问答既有据可依(知识库)、又实时准确(订单/库存等外部系统)。
🌐 在线演示:https://Doy369.github.io/kb-mcp-server/
演示为离线模式(本地私有化检索 + mock 实时数据),无需任何外部依赖,开箱即跑。 (页面挂在 GitHub Pages;后端 Render 可选——见「演示部署」章节。静态部署模式下侧边栏会显示"📦 静态演示"。)
✨ 特性
MCP 工具化:通过 MCP 协议把知识库能力暴露给任意 MCP 客户端(Claude Desktop、自研 Agent 等)。
混合检索(RAG):向量语义召回 + 关键词,命中片段带相似度分数与可解释来源。
知识图谱(P6 · GraphRAG):摄取时自动抽取三元组建图;问答时语义召回与图谱多跳并行,答复附带可解释关系路径(路径即证据)。
实时数据接入(P4):内置订单状态 / 库存适配器,按问题意图自动调用外部 API,合成为「知识 + 实时数据」结构化答复(含置信度与轨迹)。
多格式摄取:
.md / .txt / .docx(零依赖解析),支持单文档、文件夹批量、文件上传。可切换存储 / 嵌入:
存储:
memory(纯 Python 离线开发)⇄pgvector(生产,Postgres + 向量索引)。嵌入:
dev(离线条目哈希,零依赖)⇄bge(sentence-transformers 本地模型,数据不出域)。
Web 控制台:内置前端(
static/index.html),知识摄取、检索、指标、知识图谱、Agent 协作、接口配置、对话一体。生产加固(P5):可选 Bearer 鉴权、按 IP 限流、结构化访问日志、
/api/metrics指标。实时数据接入韧性(P0-2):订单 / 库存适配器统一支持重试(指数退避)+ 熔断 (按后端独立,开路期不发调用)+ 降级 + 可重试性分级——后端不可用时返回
degraded卡片并在 答复中写明「实时数据暂不可用」,问答主链路不中断;4xx(除 408/429)是确定性失败, 不重试、也不计入熔断(否则一个 401 配置错误会把熔断打开、掩盖真因);404单独判为「查不到」终态,渲染成「未查询到该单号(后端明确返回不存在,非故障)」, 与「后端挂了」严格区分;/api/status暴露熔断状态与降级 / 查不到计数。 真实 HTTP 往返已由 CIadaptersjob 每次推送验证。多 agent 协作(P7 / P1-4):编排器调度多个职责 agent,按问题动态组队(LLM 任务分解)、 子任务按
depends_on依赖分层(同层并行、层间串行)、证据不足时双向协商补人 (请求 / 应答账本,沉默不算数)、需复核时转人工队列;全过程留可观测轨迹。动作型工具 + 真实 MCP(P2-9):agent 不止会答,还能真正执行「建工单 / 改单 / 退款」, 按风险分级(read / write / destructive)+ 确认门(不可逆动作未确认绝不执行)+ 全量审计; 执行结果可回写知识图谱(
KB_ACTION_GRAPH),打通「执行 → 关系 → 再检索」; MCP 侧已由真实 stdio 子进程 + 官方客户端完成协议端到端验证(CImcpjob)。质量保障(P2-10):358 例 pytest 单测(离线约 12s 跑完)+ GitHub Actions CI 九 job 全绿 (
CI #23/ run36677436460;八 job 基线:CI #21/ run36673194795;七 job 基线:CI #19/ run36663136008) —— ① 单测 → 回归评测 → 基线校验(通过率低于阈值即阻断合并); ② 容器镜像构建 → 启动 → 健康检查 → 容器内端到端冒烟; ③ 真实 Postgres + pgvector:建表 → 完整回归跑在 PG → 校验 schema 与落库数据; ④ 真实 MCP 协议:stdio 子进程 + 客户端握手 → 工具调用 → 动作确认门与审计; ⑤ 负载测试:真实 HTTP 并发,断言零错误 / 并发写入不丢数据 / 限流精确 / 指标自洽; ⑥ 真实 HTTP 往返(实时适配器):起真实 socket 替身后端 + 真实 app 子进程,断言 重试计数 / 超时受约束 / 熔断后请求数冻结 / 404 与 401 不重试 / 429 重试 / 端到端带出真实后端数据; ⑦ 真实 Apache AGE:扩展 → 建图 → 不静默降级 → 语法能力探针 → 真实摄取写入 → 原始ag_catalog表对账(真跑凭据:7 顶点 / 6 边); ⑧ 真实 bge 嵌入(夜间 + 手动,阈值 0.95)——保「质量上限」,不拖慢每次推送。容器化(P0-3):
Dockerfile+docker-compose.yml,镜像按 build arg 分档 (轻量 ~150MB / 含 bge / 含 pgvector),内置HEALTHCHECK;构建与启动由 CI 每次提交验证。
Related MCP server: mcp-business-bot
🏗 架构
MCP Client ──▶ MCP Server (FastMCP)
(Agent / IDE) ingest · search · ask_with_live
graph_query · graph_expand · graph_paths
│
▼
┌──────────────────────────────────────────────────┐
│ KB MCP Server 核心 │
│ │
│ Ingestion ──┬─▶ Embeddings ────▶ 向量库 │
│ └─▶ TripleExtractor ▶ 知识图谱 │
│ │
│ Retrieval(向量+BM25) ─┐ │
│ graph.expand_facts ───┼─▶ Synthesis 合成答复 │
│ Adapters(实时数据) ───┘ │
└────┬──────────────┬───────────────┬─────────────┘
│ │ │
▼ ▼ ▼
memory / pgvector memory / AGE 订单 · 库存 · CRM
(向量:管语义) (图谱:管关系) (实时数据)
└──────── 同一个 PostgreSQL 实例 ─────────┘
│
▼
Web 控制台 (app.py → static/index.html)
知识库 / 检索·指标 / 知识图谱 / 接口配置 / 对话GraphRAG 的分工:向量检索回答「哪段话像这个问题」,知识图谱回答「这些实体之间什么关系、能推出什么」。 两者互补——图谱是向量库的关系增强层,不是替代品。
📁 目录结构
kb-mcp-server/
├── kb_mcp_server/ # 核心包
│ ├── server.py # MCP Server(FastMCP 工具定义,含图谱与多 agent 工具)
│ ├── config.py # 配置(环境变量 + 运行时配置持久化)
│ ├── embeddings.py # 嵌入层(DevEmbedder / BGEEmbedder)
│ ├── storage.py # 向量存储(MemoryVectorStore / PGVectorStore)
│ ├── graph.py # 知识图谱(本体 / 双后端 / 三元组抽取 / 多跳查询)
│ ├── llmclient.py # 本地 LLM 客户端(代理绕过 + 60s 熔断,三处调用共用)
│ ├── ingestion.py # 摄取管线(切片 + 嵌入 + 写入,顺带抽取三元组入图)
│ ├── retrieval.py # 混合检索
│ ├── synthesis.py # 合成层(知识 + 图谱 + 实时数据 + 动作结果 → 结构化答复)
│ ├── adapters.py # 外部 API 适配器(订单/库存)
│ ├── actions.py # 动作型工具实现层(P2-9:ActionRunner 校验/确认门/审计 + 4 个动作)
│ ├── agents/ # 多 agent 协作层(P7)
│ │ ├── base.py # AgentContext 黑板 + BaseAgent 模板(计时/异常兜底/参与闸门)
│ │ ├── workers.py # GraphBuilder / Retriever / GraphReasoner / LiveData / ActionAgent / Synthesizer
│ │ └── orchestrator.py # 编排器(deterministic / llm 路由,多路并行 + 协商补轮 + HITL)
│ └── __main__.py
├── app.py # Web 控制台(HTTP 服务 + 前端)
├── run_demo.py # 演示入口(离线播种,用于云端/演示部署)
├── static/index.html # 前端控制台页面(含知识图谱面板)
├── demo_offline.py # 离线自检脚本(摄取→检索整条链路)
├── demo_graph.py # 图谱自检脚本(建图→多跳→推理路径→融合答复)
├── demo_agents.py # 多 agent 自检脚本(补图→并行召回→合成→轨迹)
├── setup_db.py # pgvector 建表初始化(--graph 额外初始化 AGE 图)
├── make_samples.py # 生成多格式测试样本
├── fake_order_api.py # 本地假订单后端(验证字段映射用)
├── eval_run.py # 回归评测入口(golden 集 → 基线指标 + eval_report.json)
├── bench_scale.py # 规模化召回评测(992 条公开语料,Recall/MRR/NDCG/Precision)
├── pytest.ini
├── tests/ # 自动化测试(358 例,离线零依赖,见 tests/README.md)
├── scripts/
│ ├── check_baseline.py # CI 基线校验:通过率低于阈值则退出码 1(阈值/报告路径可覆盖)
│ ├── check_pg.py # CI 存储校验:schema 落库 / 数据非空(堵静默退回 memory)
│ ├── check_mcp.py # P2-9 真实 MCP 协议端到端(stdio 子进程 + 官方客户端)
│ ├── check_load.py # P2-10 补:真实 HTTP 并发压测(零错误 / 不丢数据 / 限流精确)
│ ├── check_adapters_live.py # P0-2 收尾:真实 HTTP 往返(真实 socket 替身后端,26 项断言)
│ ├── check_age.py # P2-10 补:真实 Apache AGE 图侧(扩展/建图/不降级/原始表对账)
│ └── verify_collaboration.py # P1-4 动态协作真实链路联调(依赖分层 / 双向协商,28 项断言)
├── .github/workflows/ci.yml # CI 九 job:单测+评测+基线 / 容器 / PG / MCP / 负载 / 适配器 / 协作 / AGE / bge(夜间)
├── Dockerfile # 容器镜像(默认轻量档,ARG 可选 bge / pgvector)
├── docker-compose.yml # 编排:web + 数据卷 + 可选 pgvector 服务
├── .dockerignore
├── requirements.txt
├── .env.example # 全部配置项示例
└── samples/ test-docs/ # 示例知识库文档🚀 快速开始(离线模式)
1. 环境
Python 3.13+
离线默认模式零额外依赖(仅
pydantic、python-dotenv)
pip install pydantic python-dotenv
# 生产模式按需:pip install "psycopg[binary]" pgvector2. 运行 Web 控制台(最直观)
python app.py
# 自动打开浏览器:http://localhost:8000控制台包含:
📚 知识库:粘贴文本入库 / 载入示例 FAQ / 选择文件夹或输入路径批量导入(自动建图)。
🔍 检索 · 指标:测试查询、查看命中片段与相似度、查看
/api/metrics运行指标。🕸 知识图谱:图谱统计、实体列表、点实体查多跳路径、用问题试关系侧召回、一键重建。
🤝 Agent 协作:agent 团队清单、协作问答——答复附带每个 agent 的耗时/成败/摘要轨迹。
⚙ 接口配置:在页面上填写外部 API 地址、鉴权、字段路径等,立即生效并持久化。
💬 对话:多轮问答,自动召回知识 + 图谱路径 + 拉取实时数据(订单/库存)合成答复。
3. 运行 MCP Server
python -m kb_mcp_server.server
# 也可 mcp.run() 默认 stdio 传输,供 MCP 客户端连接4. 演示 / 云端部署入口
python run_demo.py
# 强制离线默认 + 重新播种示例知识库 + mock 实时数据
# 端口优先读 $PORT,回退 $KB_WEB_PORT,再回退 8000🧰 MCP 工具一览
工具 | 说明 |
| 健康检查 |
| 把文档灌入知识库,返回切片数 |
| 混合检索,返回带相似度分数的知识片段 |
| 检索 + 调外部 API + 查图谱 + 合成结构化答复(含置信度/关系路径/轨迹),支持多轮 |
| 列出知识库所有文档(含片段数与预览) |
| 删除某篇文档及其全部片段,并清理它在图谱中抽出的关系 |
知识图谱工具(P6)
工具 | 说明 |
| GraphRAG 关系侧召回:从问题抽实体 → 查图谱多跳邻居 → 返回可解释路径 |
| 查某实体的关联(1-4 跳),返回每个邻居的完整路径 |
| 查两实体间的推理路径,例如「物流配送」到「全额退款」走了几跳 |
| 列出图谱实体(模糊匹配 / 按类型过滤),按关联度排序 |
| 图谱概况:节点/边数量、类型分布、本体定义 |
| 用向量库已有文档重新抽取建图(存量知识补建 / 换本体后重建) |
多 agent 协作工具(P7)
工具 | 说明 |
| 多 agent 协作问答:编排器调度 5 个职责 agent,答复附带每个 agent 的耗时/成败/摘要轨迹 |
| agent 清单、当前编排模式、规划器与动作层概况 |
动作型工具(P2-9)—— 与检索型工具的本质区别是有副作用
工具 | 说明 |
| 列出可用动作(风险分级 / 是否需要确认 / 参数契约)+ 最近动作审计 |
| 执行动作(建工单 / 改单 / 退款 / 查工单)。destructive 动作未 |
风险分级:read(只读,如查工单)/ write(改业务数据,如建工单、改单)/ destructive(不可逆或涉及资金,如退款)。
每次尝试(含被拒 / 待确认)都写动作审计(KB_ACTION_LOG,默认 kb_actions.jsonl)。
🕸 知识图谱(GraphRAG 关系层)
它解决什么问题
纯向量检索答不准关系型多跳问题——「这个客户的问题是不是和前几单同一根因」 「这条产品线适用哪条 SLA 例外条款」。这类问题的答案不在任何一段文本里,而在实体之间的关系里。 知识图谱就是把这层关系显式建出来,给向量检索补上「推理 + 可解释」。
本体(最小可行:8 类节点 / 7 类关系)
本体驱动的意义:抽取与查询都在这个边界内,不合规的三元组直接丢弃,图谱不会发散。
节点类型:
类型 | 含义 | 类型 | 含义 |
| 问题类别 |
| 产品 |
| SLA 条款 |
| 根因 |
| 解决方案 |
| 工单 |
| 文档(知识来源) |
| 客户 |
关系(带主宾类型约束):
关系 | 含义 | 主语 → 宾语 |
| 适用条款 | 问题类别 → SLA 条款 |
| 解决方案为 | 问题类别 → 解决方案 |
| 根因为 | 问题类别/工单 → 根因 |
| 涉及产品 | 问题类别/工单 → 产品 |
| 归类为 | 工单 → 问题类别 |
| 由…提交 | 工单 → 客户 |
| 提及 | 文档 → 各类实体 |
三元组怎么来的
本地 LLM 抽取(
KB_LLM_ENABLED=1):按本体约束输出 JSON 三元组,数据不出域。规则词典兜底(默认,离线零依赖):关键词/正则匹配问题类别、SLA 时限、解决方案、产品、根因。 例:「付款后 48 小时内发货」→
(物流配送) --适用条款--> (48小时内发货)。抽取挂在摄取管线上:每摄入一篇文档顺带把三元组写进图,不需要额外步骤。 图谱失败绝不阻断摄取——向量库写成功即算成功。
三种用法
MCP 工具(给任意 agent):
graph_expand/graph_query/graph_paths。Web 控制台:侧栏「🕸 知识图谱」——看统计、翻实体、点实体查多跳、用问题试关系侧召回。
代码:
from kb_mcp_server.graph import get_graph_store, expand_facts g = get_graph_store() g.add_triples(triples) # 建图(本体校验内置) facts = expand_facts(g, "物流超时怎么赔偿") # 关系侧召回,返回带路径的事实
自检
python demo_graph.py跑完整链路:4 篇示例文档摄取建图 → 图谱统计 → 多跳查询 → 推理路径 → GraphRAG 融合答复。 实测输出(memory 后端、离线零依赖):
节点 34 / 边 34
按类型: Document 4, IssueCategory 6, SLAClause 12, Solution 6, Product 4, RootCause 2
─
物流配送 --适用条款--> 48小时内发货
退款退货 --解决方案为--> 全额退款
退款退货 --提及--> sla_policy ; sla_policy --提及--> 服务响应 ; 服务响应 --解决方案为--> 全额退款最后一行正是图谱的价值所在:两段知识在向量空间里毫无相似之处,图谱却把它们串成了一条 跨文档、可解释的推理链——这就是「路径即证据」。
🤝 多 agent 协作(P7)
架构:按职责切分,共享同一张图
Orchestrator(编排 · 路由)
│ 增量补图
▼
GraphBuilder ──写入──▶ 知识图谱
│
┌───────────┼───────────┬───────────┐ (无依赖 worker 并行执行)
▼ ▼ ▼ ▼
Retriever GraphReasoner LiveData ActionAgent ← 各自只写黑板(AgentContext)里自己的字段
语义召回 图谱多跳 订单/库存 动作执行(P2-9,默认关闭)
└───────────┼───────────┴───────────┘
▼
Synthesizer ──▶ 结构化答复 + agent 轨迹 + 动作结果按职责切,不按知识域切(初期知识域太小,按域切会切出一堆空 agent)。
协作靠共享黑板(
AgentContext)传递中间结果,不引入消息总线——协议仍然是 MCP(决策 D6)。每个 agent 只写自己负责的字段;单个 agent 失败只降级、不阻断链路(沿用全项目的降级约定)。
两种编排模式(KB_AGENT_MODE)
模式 | 行为 | 适用 |
| 固定流水线,零 LLM 依赖 | 离线演示 / 生产兜底 |
| 本地 LLM 判断要不要查图 / 查实时数据,裁剪流水线 | LLM 可用时降低延迟;失败自动回退 deterministic |
动态协作(P1-4):按问题临时组队,而不是固定全跑
三个可选开关,默认全关时行为与旧版固定流水线完全一致:
配置 | 默认 | 作用 |
| 跟随 |
|
|
|
|
|
|
|
子任务依赖编排(P1-4 收尾):Subtask.depends_on 不再是预留字段,真的被消费——
一轮内按依赖分层,同层并行、层间串行。三条边界写死在 _dep_layers:
无依赖 → 恰好一层,且顺序 = 计划顺序。所以默认(确定性规划器不产出依赖)行为与旧版逐字等价。
依赖指向本轮之外(已执行过 / 不在计划里)视为已满足,不等待、不报错。
成环不重排、不卡死:降级成一层照跑,并在该轮记
dep_cycles——「顺序略有偏差」远好于「卡住」。
双向消息协商(P1-4 收尾):不再只有「评审点名」这一个方向。worker 也能在 on_run 里
主动委托(BaseAgent.request_help → 对方 reply_to),评审缺口则登记为同一本账上的请求。
账本 AgentContext.negotiation 是 append-only 的,四种结局都能被追问:
结局 | 含义 |
| 被点名方跑完确实产出了该能力的新证据 |
| 跑完了但没有证据——明确说「我也没有」,不是含糊放过 |
| 共同体里没人具备该能力 / 本应服务者已执行过 → 当场关账 |
悬空请求 | 不允许存在:轮次结束仍无人应答的请求一律由编排器关账 |
被拒 / 无主的能力进「别再提」名单(declined),既不重复索要,也让「为什么没补轮」可解释。
协作过程落在返回的 collaboration 段(每轮分工 / 子任务理由 / 协商结论),例如:
规划器=llm 轮次=2 协商=True
第1轮 [llm] Retriever → 协商[需补轮] 缺: ['live']
· Retriever(retrieval):纯知识问答,只需语义检索
第2轮 [negotiation] LiveData真发生协商时另带一段账本摘要(未协商则不出现,不给轨迹添噪音):
"negotiation": {
"requests": 1, "replies": 1, "declined": [], "delegated": false,
"ledger": [
{"kind": "request", "id": "req-1", "by": "EvidenceCritic", "capability": "live", "ask": "..."},
{"kind": "reply", "id": "req-1", "by": "LiveData", "status": "provided", "note": "已产出该项证据"}
]
}delegated=true 表示这轮补人是 worker 自己提的(而非评审),补轮来源相应记为 delegation。
设计取舍:LLM 只用在「任务分解」上(这一步真的需要语义理解),
「证据够不够」这类判定用确定性规则——可解释、零额外 token、离线可测。
两条降级路径都保证「开启协作不会比不开更脆弱」。
declined 名单同理是确定性规则:把「谁被问过、谁拒绝了」变成可解释的状态,而不是再问一次模型。
轨迹即可观测性
multi_agent_ask 的返回里带 agents.trace——每个 agent 的名称、耗时、成败、一句话摘要:
[OK] GraphBuilder 10ms 图谱已是最新(4 篇已入图)
[OK] Retriever 18ms 召回 1 个片段
[OK] GraphReasoner 18ms 命中 1 个实体,10 条关系事实
[OK] LiveData 1ms 取到 1 条实时数据
[OK] Synthesizer 1ms 合成完成(template,置信度高,5 条关系路径)动作型工具(P2-9):从「只会答」到「能执行」
编排层默认只检索不动作。开 KB_AGENT_ACTIONS=1 后多一个 ActionAgent,
它识别「退款 / 改单 / 建工单」等动作意图并真正执行;有副作用,因此设三道闸:
闸门 | 机制 |
参与闸门 |
|
意图闸门 | 只认规则能明确识别的动作意图,识别不出就什么都不做(宁可不做,不可乱做:猜错一次就是一次错误的退款) |
确认闸门 |
|
与 P1-4 闭环:存在待确认动作时,若 KB_AGENT_HITL=1,答复一并标 pending_human=true
(否则「agent 发起了退款」会静默通过,确认门形同虚设)。合成层新增【执行动作】段,
三种终态——已执行 / 待确认 / 被拒——在答复与前端里都能一眼区分。
三条安全底线收口在 ActionRunner(校验 → 确认门 → 执行 → 审计),新动作注册即自动获得:
$ python scripts/check_mcp.py # 真实 stdio 子进程 + 官方 MCP 客户端
[OK] 未确认的退款被拦在待确认(未执行)
[OK] 待确认动作没有产生业务结果(确实没执行)
[OK] 确认后执行成功:RF-6552F732
[OK] list_tickets 能回读出前面建的工单(count=1) ← 副作用真的落盘了动作结果回写图谱(P2-9 收尾):把「执行」接回「再检索」
动作默认只落审计与答复,图谱里不留痕迹——于是「执行 → 关系 → 再检索」是断的: 客户接着问「刚给 A 客户建的工单涉及哪个产品」,图谱答不出来。
本体的 Ticket / Customer / Product 与 SUBMITTED_BY / ABOUT_PRODUCT 早已就绪,
但只有「LLM 从文档抽取」这一条写入路径。开 KB_ACTION_GRAPH=1 后补上第二条:
Ticket:TKT-XXXXXXXX props: subject / priority / sla_response / status
├─ SUBMITTED_BY ──→ Customer:ACME (customer 为空则整条跳过,不建空节点)
└─ ABOUT_PRODUCT ─→ Product:LM3-ARM (sku 来自提问上下文或入参)三条底线,与前三条闸门同一性质(写死在代码里,不可配置):
底线 | 为什么 |
只有真执行成功才写 |
|
写失败不改动作结论 | 图谱不可用 → 返回 |
映射必须过本体校验 | 三元组统一过 |
映射是声明式的(action_graph.ACTION_EFFECTS,一个动作一条 Effect),
所以「新增动作要不要回写、写成什么形状」是一个可评审的条目,而不是散落的 if。
刻意不回写的动作(不是遗漏):update_order / request_refund —— 本体里没有
Order / Refund 节点,而它们的真相在实时后端(P0-2)不在知识图谱里;
把运行态数据塞进知识图会污染检索。list_tickets 是只读动作,不产生新事实。
方向语义(踩过):回写建立的是 Ticket → Customer 出边,所以「按客户查工单」是入边,
必须 direction=both / in;用默认的 out 会静默返回空列表——
又一个「不报错、答案悄悄变错」的例子。scripts/check_age.py 阶段七把这条也钉成断言。
真跑在真实 Apache AGE 上验(CI age job,全部旁路对账,不信 store 的话):
关掉开关时动作照常成功且 AGE 里零写入 → 打开后 Ticket / SUBMITTED_BY / ABOUT_PRODUCT
label 表真的多出行来 → 独立 Cypher 读回 props → 从客户反查得到该工单。
自检
python demo_agents.py # 固定流水线协作(只入向量库 → 自动补图 → 多路召回 → 合成)
python scripts/verify_collaboration.py # P1-4 动态协作:任务分解 / 依赖分层 / 双向协商 / 降级 / 人工介入(28 项断言)
python scripts/check_mcp.py # P2-9 真实 MCP 协议端到端(握手 / 工具 / 动作确认门 / 审计 / 多 agent)
python scripts/check_load.py # P2-10 补:真实 HTTP 并发压测(会临时起 app 子进程)
python scripts/check_age.py # P2-10 补:真实 Apache AGE 图侧(含 P2-9 收尾的动作回写,需目标 PG 带 age 扩展)check_load.py 的四个场景与实际断言:
[1] 只读并发 并发 8 发 160 次 /api/ask:~150 req/s,p50 29ms / p95 38–58ms / p99 ~515ms
[2] 混合读写 并发 40 写 + 80 读:写入成功 40,store 实际 +40(丢失 0)
[3] 限流门 限流 5/min:并发发 24 次 → 放行 5、限流 19;/healthz 不受限流误伤
[4] 指标自洽 /api/metrics requests_total 不少于本次发送数压测脚本会启动真实 app 子进程并强制关闭浏览器自动打开(
KB_NO_BROWSER=1): 浏览器会真的加载控制台页面、打出一串 API 请求,从而吃掉限流配额并污染指标计数—— 这是实测踩到的坑(限流场景「应放行 5」被观测成「放行 1」),也是KB_NO_BROWSER存在的理由。
完整演示「知识只入向量库 → GraphBuilder 自动补图 → 多路并行召回 → 合成 → 第二轮秒回」。 LLM 不可达时自动熔断(60s 内不再重试)并回退规则/模板,链路照常跑通。
⚙️ 配置
复制 .env.example 为 .env 后按需修改,关键项:
分组 | 变量 | 说明 |
存储 |
|
|
图谱 |
|
|
图谱 |
| 总开关,摄取时是否自动抽取三元组入图(默认 |
图谱 |
| AGE 模式下的图名(默认 |
嵌入 |
|
|
合成 |
| 本地 LLM(OpenAI 兼容,如 Ollama),失败自动回退模板 |
实时 API |
|
|
加固 |
| Bearer 鉴权 / 每 IP 限流 / 结构化日志 |
协作 |
| 编排模式 / 动态任务分解 / 证据协商轮次 / 人工介入 |
动作 |
| 动作执行者是否参与编排(默认 |
动作 |
| 执行成功的动作是否把结果回写知识图谱(默认 |
页面「接口配置」提交的配置会持久化到
runtime_config.json,优先级高于.env。
🏭 生产部署
方式一 · 容器(推荐)
docker compose up -d # 起 web 服务,数据落 named volume
# 打开 http://localhost:8000镜像默认只装离线档依赖(memory 存储 + dev 嵌入),约 150MB;需要更强能力用 build arg 分档:
docker build --build-arg ENABLE_BGE=true -t kb-mcp-server:bge . # 本地 bge 语义嵌入(拉 torch,镜像 2GB+)
docker build --build-arg ENABLE_PGVECTOR=true -t kb-mcp-server:pg . # pgvector 客户端环境变量 | 默认 | 说明 |
|
| 数据目录(compose 已挂 named volume 持久化) |
|
| 监听端口 |
|
|
|
|
|
|
|
| 实时数据走 mock |
|
| 实时后端重试次数(总尝试 = 该值 + 1) |
|
| 指数退避基数(秒),单次退避上限 8s |
|
| 熔断开关;开路期不再发起调用 |
|
| 连续失败多少次后开路 |
|
| 开路冷却秒数,之后放半开探测 |
|
|
|
|
|
|
|
|
|
|
| 动作审计日志路径( |
镜像内置 HEALTHCHECK 探 /healthz(docker compose ps 可直接看健康状态)。
需要 pgvector 时,docker-compose.yml 里已备好注释掉的 pgvector/pgvector:pg16 服务,取消注释即可。
这一步已被 CI 持续验证:每次提交都会构建镜像、启动容器、轮询健康检查, 并在容器内真实调用
/api/ask做端到端冒烟(.github/workflows/ci.yml的dockerjob)。 因此「镜像能构建、容器能跑」不是一次性检查,而是提交门禁的一部分。
pgvector 生产存储同样被 CI 真跑:
pgjob 用pgvector/pgvector:pg16service container 起真实 Postgres →python setup_db.py --graph建表 → 完整回归评测读写全部落在 PG →scripts/check_pg.py校验「vector 扩展 /kb_chunks表 / HNSW 索引 /vector(1024)维度」与 「表内非空」。最后两项专门堵住「存储连不上 → 悄悄退回 memory → 评测照样过」的静默降级。 注:该镜像不含 Apache AGE,--graph的建图部分会按设计降级为 memory 图(不阻断)。
方式二 · 直接跑(无容器)
存储切 pgvector
pip install "psycopg[binary]" pgvector # 目标 PG 安装 vector 扩展后: KB_STORAGE_BACKEND=pgvector KB_DATABASE_URL=postgresql://user:pass@host:5432/kb python setup_db.py图谱切 AGE(可选,与 pgvector 同库,不额外引入数据库)
# 前提:目标 PG 已安装 age 扩展(CREATE EXTENSION age 可用) KB_STORAGE_BACKEND=pgvector KB_GRAPH_BACKEND=age \ KB_DATABASE_URL=postgresql://user:pass@host:5432/kb python setup_db.py --graphAGE 不可用时会自动回退
memory图并在日志里说明,主链路不受影响。嵌入切 bge(数据不出域)
pip install sentence-transformers KB_EMBEDDING_BACKEND=bge # 默认 BAAI/bge-large-zh-v1.5启用本地 LLM 合成:
KB_LLM_ENABLED=1+ 可达的KB_LLM_BASE_URL(如 Ollamahttp://localhost:11434/v1)。接真实外部 API:在
.env配KB_ORDER_API_URL/KB_INVENTORY_API_URL+ 字段路径,并设KB_API_MOCK=0。加固:设置
KB_API_TOKEN启用 Bearer 鉴权,KB_RATE_LIMIT限流,KB_LOG_FILE落结构化日志。
演示部署 · GitHub Pages(仅前端,零成本)
适合作品集/汇报/界面预览。零成本、零后端,但功能受限——页面上按钮可点,但 摄取/检索/对话等 API 调用会返回 404(页面顶部会出现"📦 静态演示模式"蓝色横幅提示)。
Step 1 · 启用 GitHub Pages
仓库 → Settings → Pages:
Source: Deploy from a branch
Branch:
main· Folder:/docsSave
几分钟后站点出现在 https://<user>.github.io/kb-mcp-server/(默认 Doy369 用户)。
无需修改任何代码——docs/index.html 里 window.KB_API_BASE 保持空字符串即可。
🧪 质量保障(P2-10)
自动化测试
pip install pytest
python -m pytest tests/ -v # 358 例,离线约 12s覆盖范围(全部零外部依赖,dev 嵌入 + memory 后端):
文件 | 例数 | 覆盖重点 |
| 43 | 分块三要素(标题前缀 / 一行多档拆条 / Q-A 成对)、嵌入单例、存储持久化与容错、图谱本体约束、PG 懒连接 / 注册时序 / 写库参数适配 |
| 27 | BM25 分数越界回归护栏、RRF 融合、MMR 去重、硬阈值、分词、余弦边界 |
| 36 | 数字边界断言(防假通过)、证据段剔除、禁止词反向断言、护栏分级、审计容错 |
| 24 | Agent 异常兜底、黑板隔离、路由裁剪、降级链路、合成契约、16 工具注册完整性 |
| 51 | 重试次数语义与指数退避封顶、熔断状态机、降级不抛异常、失败不写缓存、可重试性分级(4xx 不重试 / 不计熔断)、 |
| 72 | 动态任务分解的四条降级回退、协商只提未执行能力、多轮补轮不重复执行、HITL 开关;P1-4 收尾:依赖分层(无依赖单层等价旧行为 / 跨层串行 / 轮外依赖视为满足 / 自依赖忽略 / 成环降级不卡死)、 |
| 53 | 动作参数契约、确认门、审计三终态、意图识别与参数抽取、参与闸门、HITL 闭环 |
| 26 | 动作结果回写图谱(P2-9 收尾):默认关时零写入且返回/审计里连 |
| 11 | 基线校验脚本本身:阈值覆盖、报告路径三来源、恰好等于阈值放行、低于必红、缺失必失败 |
| 15 | AGE |
test_baseline_gate.py的理由:该脚本同时把守test与bge两个 job。 参数解析写错时表现不是报错,而是静默失效——CI 照样绿,只是不再拦任何东西。
test_graph_age_cypher.py锁的是两条只在真机上才暴露的 AGE 契约:cypher()会被post_parse_analyze_hook拦截做语法改写,因此 ① 列定义列表列数必须等于RETURN表达式数(否则return row and column definition list do not match); ② 图名与 Cypher 原文必须是常量字面量(否则 AGE 读不到原文,报a name constant is expected)。_cypher()曾同时违反这两条,而本地单测(memory 后端) 根本不生成 SQL——「一直没错」;直到agejob 上真机才被一一打挂。把契约钉进单测后, 任何新接口忘了传nout、或有人改回绑定参数,都会在本地就红。
其中多条用例直接锁住 ROADMAP 记录过的真 bug——不报错、只是答案悄悄变差的那类问题, 没有测试就只能靠肉眼发现。
CI 流水线
.github/workflows/ci.yml 九个 job:
job | 触发 | 内容 | 验证什么 |
| 推送 / PR | 单测 → 回归评测 → 基线校验 | 逻辑正确性;通过率低于基线(72%)则阻断合并 |
| 推送 / PR | 构建镜像 → 启动 → 健康检查 → 容器内端到端冒烟 | 「镜像能构建」且「容器能跑」(build 成功 ≠ 能跑) |
| 推送 / PR | 起真实 PG + pgvector → 建表 → 回归跑在 PG → 校验 schema 与落库数据 | 生产存储路径真通,且没有静默退回 memory |
| 推送 / PR | stdio 子进程 + 官方客户端走完整 JSON-RPC | MCP 是协议实质而非标题;动作确认门与审计真落盘 |
| 推送 / PR | 真实 HTTP 并发压测(只读 / 混合读写 / 限流门 / 指标自洽) | 并发下不丢数据、限流精确、零错误 |
| 推送 / PR | 起真实 socket + 真实 HTTP 协议的本地替身后端,让真实 | 出站适配层真能完成一次 HTTP 往返:重试计数 / 超时受约束 / 熔断后请求数冻结 / 404 与 401 不重试 / 429 重试 |
| 推送 / PR |
| 协作轨迹结构真对:依赖真分层 / 补轮真来源 / 账本真关账 / 沉默真不算数(不是「脚本跑完没报错」) |
| 推送 / PR | 官方 | 图侧真跑,且 |
| 夜间 03:00 + 手动 | 真实 bge 嵌入回归(阈值 0.95) | 质量上限;缓存 1.3GB 模型,不拖慢每次推送 |
评测报告作为 artifact 归档 30 天;load / adapters / collab / age 的报告同样归档。
七 job 基线实测:CI #19 / run 36663136008,全绿(bge 按 schedule 跳过属正常);
后新增 adapters job(真实 HTTP 往返)成八 job,CI #21 / run 36673194795 八 job 全绿;
再加 collab job(P1-4 收尾)成九 job,CI #23 / run 36677436460 九 job 全绿——
collab job 的 ::notice:: 注解凭据:共 28 项,失败 0 项;语料 63 片段;多轮场景轮次 2。
其中 age job 的真跑凭据由 ::notice:: 注解直接可见:age=1.6.0,
顶点 Document 1 / IssueCategory 3 / SLAClause 2 / Product 1、
边 MENTIONS 3 / GOVERNED_BY 2 / ABOUT_PRODUCT 1(= 7 顶点 / 6 边,与 stats() 口径一致)。
为何 bge 不跟每次推送:dev 嵌入下通过率 91%(语义级断言前 82%;唯一 FAIL 是 P2 哨兵用例,
受限于 dev 对 P0/P1/P2 字面相似片段的区分能力),bge 下 100%。
装 torch + 下 1.3GB 模型会让单次 CI 从 ~40s 涨到数分钟——高频 job 一旦变慢就会被习惯性忽略。
所以职责分离:推送跑快口径(保「不许变差」),夜间跑重口径(保「质量上限」),
两者共用同一份 check_baseline.py,只是阈值与报告路径不同。
本地复现 CI 的基线校验
python eval_run.py # 产出 eval_report.json(dev 口径)
python scripts/check_baseline.py # 与 CI 同一份逻辑,通过则退出码 0
# bge 口径(报告写独立文件,别覆盖 dev 基线;阈值单独指定)
python eval_run.py --embedding bge --out eval_report_bge.json
KB_BASELINE_MIN=0.95 python scripts/check_baseline.py eval_report_bge.json📌 备注
runtime_config.json、kb_store.json、.env均已 gitignore,不进仓库(含本地私有数据)。离线
dev嵌入为条目哈希实现,语义召回能力有限,仅用于跑通管线与演示;生产请用bge。外部 API 适配器为可扩展框架:继承
APIAdapter实现call()+_mock(),在build_registry注册即可新增后端(CRM / 工单系统等)。
📄 License
内部 B2B 项目,使用请遵循团队内部约定。
This server cannot be deployed
Maintenance
Related MCP Connectors
Make your knowledge agent-ready. One MCP endpoint, 5 connectors, 3 search modes.
Cloud or self-hosted knowledge for AI agents: hybrid search, reranking, GraphRAG, scoped MCP tools.
The knowledge base your AI reads and writes, under your rules — over MCP, EU-hosted.
Knowledge base MCP for AI agents on iknow.dev. Search, read, and maintain via OAuth.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables document-based Q&A with multi-modal RAG, hybrid retrieval, knowledge graph reasoning, and multi-agent orchestration via MCP tools.4MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying company knowledge base using RAG, providing accurate answers from internal documents via MCP.-
- AlicenseNot gradedqualityCmaintenanceEnables document ingestion, semantic search, and retrieval-augmented generation via MCP tools and REST API, using vector embeddings and intelligent chunking.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to query and manage a document knowledge base via MCP, with RAG-powered search and grounded answers with citations.MIT