Install
$ agentstack add mcp-jinyangpeng-study-rag ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
study_rag
> 基于 LlamaIndex 的企业知识库检索服务,通过 MCP 协议暴露给 Agent 调用。 > > Enterprise knowledge base retrieval service built on LlamaIndex, exposed to AI agents via MCP.
[](LICENSE) [](https://www.python.org/) [](https://fastapi.tiangolo.com/) [](https://modelcontextprotocol.io/) [](https://milvus.io/) [](https://react.dev/)
项目简介
study_rag 是一个可插拔、多租户的企业级 RAG(检索增强生成)知识库服务。它把「知识库管理 + 文档处理 + 多策略检索」打包成一组能力,既提供 MCP Tool 供 AI Agent 直接调用,也提供 Admin REST + Web 控制台 供人工管理。
核心价值:
- Agent 即用:符合 MCP 规范,Claude / Cursor / 任意 MCP 客户端接上即可检索你的知识库
- 多策略检索:Dense / Sparse / Hybrid / Milvus 原生 BM25 / Hybrid-Milvus 五种策略可按请求切换
- 能力可插拔:Embedding / VectorStore / Reranker / Parser 均为接口化设计,配置即切换
- 生产就绪:structlog 结构化日志、Prometheus 指标、限流、熔断、Docker Compose 一键部署
技术栈
| 层 | 技术 | |---|---| | 后端 | Python 3.10+、FastAPI、Pydantic、structlog | | 检索框架 | LlamaIndex(NodeParser 切块)、自研 RetrievalEngine 抽象 | | 向量库 | Milvus 2.5+(原生 BM25)、可扩展 Qdrant / InMemory | | Embedding | OpenAI / Ollama / BGE,接口化可替换 | | Reranker | BGE / Cohere / TEI,接口化可替换 | | MCP | FastMCP、Streamable HTTP transport | | 前端 | React + Vite + TypeScript + shadcn/ui | | 可观测 | Prometheus 指标、structlog 日志、限流、熔断 | | 部署 | Docker Compose(admin + mcp 双进程)、tini、非 root | | 工程化 | ruff(lint)、pytest、justfile、TypeScript typecheck |
知识库管理端UI
仪表盘 Dashboard
知识库管理
文档管理
检索测试
模型配置
异步任务
特性
- 多知识库管理:支持按部门/主题配置多个知识库
- 多租户隔离:基于 api_key 的用户 ↔ 知识库权限矩阵
- MCP 协议(Streamable HTTP):10 个核心 Tool,提供发现/检索/文档管理完整能力
- 能力可插拔:Embedding / VectorStore / Reranker 均可替换实现
- LlamaIndex 整合:NodeParser 切块、双检索路径(自研 + LlamaIndex)
- 文档管理增强:支持文本输入 / 文件上传(txt / md / html / pdf / docx),
多种切块策略(whole / sentence / token / semantic 通过命名 parser), 分块预览(提交前看到每块内容/大小),策略通过 configs/llamaindex.yaml 配置
- 分块查看:管理 UI「文档」列表的「查看分块」按钮 → Drawer 显示该文档
所有 chunk 的 #索引 / 字符数 / 完整文本 / 源 metadata,分页 20/页 (对应 GET /admin/kbs/{kb_id}/documents/{doc_id}/chunks 端点)
- Parser Registry:命名 parser 实体,类似 embedder / reranker 的注册表设计,
提供 get_parser(name) / list_parsers() 接口
- 新 API 端点:
GET /admin/parsers/POST /documents/preview-chunk/
POST /documents/upload
- 统一管理面:FastAPI 提供知识库 CRUD + 健康检查
文档
| 文档 | 内容 | |---|---| | [部署指南](docs/deployment.md) | Docker Compose、镜像构建、Milvus、生产清单、运维操作 | | [配置参考](docs/configuration.md) | 所有 YAML 配置文件、环境变量、provider 对照表 | | [MCP Tool](#mcp-tool-完整列表) | MCP Tool 完整 API、客户端示例、错误码 |
快速开始
Docker Compose(推荐)
# 1. 准备环境变量
cp .env.example .env
# 按需编辑 .env(至少配置一个 embedding 后端的 API_KEY)
# 2. 构建并启动 admin + mcp
docker compose -f docker/docker-compose.yml up -d --build
# 或: just docker-up
# 3. 带 Milvus 向量库一体化启动
docker compose -f docker/docker-compose.yml --profile vector up -d --build
# 或: just docker-up-vector
# 端点:
# 管理 UI http://localhost:3200/admin/ui/
# OpenAPI 文档 http://localhost:3200/docs
# MCP 端点 http://localhost:3220/mcp
# 健康检查 http://localhost:3200/health / http://localhost:3220/health
详见 [部署指南](docs/deployment.md)。
本地 Python
# 安装依赖
pip install -e ".[dev,llamaindex,vector-milvus,embedding-bge,reranker-bge]"
# 启动 admin REST(port 3200)
study-rag
# 启动 MCP standalone server(port 3220,streamable_http transport)
study-rag-mcp
# MCP 端点
http://localhost:3220/mcp
# Admin REST 端点
http://localhost:3200/admin/docs
本地开发
# 一键脚本(PowerShell)
pwsh scripts/dev.ps1 mcp # 启 MCP server
pwsh scripts/dev.ps1 inspector # 启 MCP Inspector(浏览器调试)
pwsh scripts/dev.ps1 admin # 启 admin REST
pwsh scripts/dev.ps1 all-verify # 跑 lint + typecheck + 全 verify
架构
study_rag/
├── capabilities/ # 能力层(embedding/vector_store/reranker/llamaindex/retrieval)
├── knowledge_bases/ # 知识库管理(registry/manager/models/config_store)
├── auth/ # 鉴权(占位实现,含 writable_kbs)
├── mcp/ # MCP 服务(10 个 Tool + 3 Resource + 2 Prompt + filter)
├── api/ # FastAPI 管理面(admin/health)
├── jobs/ # 异步任务(文档切块流水线)
├── observability/ # 日志(structlog)/指标(Prometheus)/限流/熔断/中间件
├── web/ # Admin UI SPA 构建产物挂载(/admin/ui/)
├── mcp_standalone.py # MCP 独立部署入口(streamable_http)
├── app.py # Admin REST 入口
├── settings.py # 全局配置(pydantic-settings)
├── frontend/ # React + Vite + shadcn/ui 管理控制台源码
├── configs/ # YAML 配置(支持 ${ENV_VAR} 占位符)
│ ├── knowledge_bases.yaml
│ ├── embeddings.yaml
│ ├── vector_store.yaml
│ ├── reranker.yaml
│ ├── retrieval.yaml
│ ├── llamaindex.yaml
│ └── llm.yaml
├── docker/ # 容器化(Dockerfile + docker-compose + entrypoint)
├── docs/ # 文档(deployment.md / configuration.md)
└── scripts/ # 开发脚本(dev.ps1 / inspector.ps1)
部署拓扑(两进程独立扩缩容):
Agent / LLM ──MCP──▶ mcp:3220 ──▶ ┌─ embeddings (OpenAI/BGE/Ollama)
├─ rerankers (BGE/Cohere/TEI)
浏览器 ──HTTP──▶ admin:3200 ──▶ └─ vector_store (Milvus/Qdrant/mock)
└─ /admin/ui/ (React SPA)
└─ /admin/* (KB/文档 CRUD)
└─ /metrics (Prometheus)
详见 [配置参考](docs/configuration.md)。
环境变量
核心变量(完整列表见 [.env.example](.env.example) 和 [配置参考](docs/configuration.md#环境变量参考)):
| 变量 | 默认 | 说明 | |---|---|---| | STUDY_RAG_PORT | 3200 | admin REST 端口 | | MCP_PORT | 3220 | MCP 端口 | | STUDY_RAG_LOG_LEVEL | INFO | 日志级别 | | STUDY_RAG_ADMIN_TOKEN | (空) | admin Bearer Token(生产必设) | | STUDY_RAG_MCP_REQUIRE_API_KEY | false | 强制 MCP api_key | | MILVUS_URI | http://milvus:19530 | 向量库地址 | | OPENAI_API_KEY | (空) | OpenAI embedding key |
YAML 配置内的 ${VAR} 占位符在运行时解析为环境变量,无需改代码即可切换后端。
MCP Tool 完整列表
study_rag 在 Streamable HTTP transport 下暴露 10 个核心 Tool。 所有 Tool 都接受 api_key: str 作为第一个参数(当前为占位鉴权)。
返回值为 JSON 字符串(避免 FastMCP 对 list[dict] 的副作用),客户端用 json.loads(text) 解析。
1. list_accessible_kbs — 发现可用知识库
任何检索操作的第一步。先调用本 Tool 了解有哪些 KB 可用、每个 KB 的描述。
| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | api_key | str | ✓ | 用户凭证 |
返回:list[KBInfo],每个元素包含:
[
{
"kb_id": "rd_frontend",
"name": "前端研发文档",
"description": "React / Vue 组件库、状态管理、性能优化",
"department": "rd",
"enabled": true,
"document_count": 42
}
]
异常:
- 鉴权失败 →
permission_denied
适用场景:
- 任何检索前必调
- 不确定有哪些 KB
- 需要根据 description 判断查询相关 KB
2. get_kb_info — 获取知识库详情
确认 KB 的 embedding / reranker / 文档数等细节,决定是否检索它。
| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | api_key | str | ✓ | | | kb_id | str | ✓ | 知识库 ID(命名规范 {dept}_{name}) |
返回:
{
"kb_id": "rd_frontend",
"name": "前端研发文档",
"description": "...",
"department": "rd",
"enabled": true,
"document_count": 42,
"embedding": "bge-large-zh",
"reranker": "bge-reranker-large",
"extra": {}
}
异常:
- KB 不存在 / 用户无权 →
kb_not_found
3. search_kb — 单知识库检索(核心)
在指定 KB 中检索 top-k 相关文档。可选启用 rerank、metadata filter。
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | kb_id | str | ✓ | | 知识库 ID | | query | str | ✓ | | 检索问题 | | top_k | int | | 5 | 返回数量,范围 (0, 50] | | use_rerank | bool | | true | 是否启用重排 | | filter_expr | dict | | null | metadata 过滤条件 |
filter_expr 操作符后缀:
| 后缀 | 含义 | 示例 | |---|---|---| | 无 / __eq | 等于 | {"source": "wiki"} | | __ne | 不等于 | {"status__ne": "draft"} | | __in | 在列表中 | {"tag__in": ["api", "db"]} | | __nin | 不在列表中 | {"tag__nin": ["internal"]} | | __gt / __gte | 大于 / ≥ | {"year__gte": 2024} | | __lt / __lte | 小于 / ≤ | {"score__lt": 0.5} | | __contains | 字符串包含 | {"title__contains": "API"} | | __exists | 字段是否存在 | {"draft__exists": false} |
多条件用 AND 连接:{"year__gte": 2024, "tag__in": ["api"]} 表示 year >= 2024 AND tag in [api]。
返回:
[
{
"doc_id": "doc-123",
"title": "React 18 并发渲染机制",
"text": "React 18 引入了并发渲染...",
"score": 0.87,
"metadata": {
"source": "wiki",
"year": 2024,
"tag": "frontend"
}
}
]
异常:
- KB 不存在 / 无权 →
kb_not_found query为空 /top_k超范围 →invalid_parameterfilter_expr字段名非法 →invalid_parameter
4. search_all_accessible_kbs — 跨知识库综合检索
不确定查哪个 KB 时的兜底入口。在所有可访问 KB 中并行检索,按相关度合并排序。
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | query | str | ✓ | | | | top_k | int | | 5 | 最终返回条数 | | use_rerank | bool | | true | | | filter_expr | dict | | null | 下推到每个 KB |
返回:与 search_kb 一致,但每条 hit 的 metadata._source_kb 标识来源 KB ID。
实现细节:每个 KB 内部用各自 reranker 重排,跨 KB 层仅按分数合并(不同 KB 的 reranker 分数量纲不同,硬合并不严谨)。
5. get_document — 获取文档完整内容
search_kb 返回的是文档片段,看全文用本 Tool。
| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | api_key | str | ✓ | | | kb_id | str | ✓ | | | doc_id | str | ✓ | 文档 ID |
返回:文档元数据 + 完整 content。
异常:
- 文档不存在 →
document_not_found
6. list_documents — 列出 KB 中的文档
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | kb_id | str | ✓ | | | | limit | int | | 100 | 返回条数上限,范围 (0, 1000] | | offset | int | | 0 | 跳过条数(分页) |
返回:list[DocumentSummary],按创建时间倒序。
7. add_document — 添加文档(整篇一个 chunk)
需要写权限(writable_kbs 包含 kb_id)。
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | kb_id | str | ✓ | | | | doc_id | str | ✓ | | KB 内唯一 | | title | str | ✓ | | | | content | str | ✓ | | | | source | str | | null | 来源;自动存为 metadata['source'] | | metadata | dict | | null | 额外 metadata | | overwrite | bool | | false | 已存在时是否覆盖 |
source / metadata 字段可在后续 search_kb 的 filter_expr 中引用。
异常:
- 无写权限 →
permission_denied - doc_id 已存在 +
overwrite=False→document_already_exists - 参数非法 →
invalid_parameter
8. add_document_chunked — 添加文档(NodeParser 切块)
需要写权限。整篇文档会按 LlamaIndex NodeParser 切块后入库。
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | kb_id | str | ✓ | | | | doc_id | str | ✓ | | | | title | str | ✓ | | | | content | str | ✓ | | | | source | str | | null | | | metadata | dict | | null | | | parser_config | dict | | null | NodeParser 配置 | | overwrite | bool | | false | |
parser_config 示例:
{
"strategy": "sentence",
"chunk_size": 512,
"chunk_overlap": 50
}
适用场景:长文档(> 1000 字)建议用本接口。
9. add_documents_batch — 批量添加文档
需要写权限。失败的单条不影响其他(通过日志记录)。
| 参数 | 类型 | 必填 | 默认 | 说明 | |---|---|---|---|---| | api_key | str | ✓ | | | | kb_id | str | ✓ | | | | documents | list[dict] | ✓ | | 每项:{"doc_id", "title", "content", "source"?, "metadata"?} | | overwrite | bool | | false | |
上限 500 条/次。
10. delete_document — 删除文档
需要写权限。向量 + meta 一起删。
| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | api_key | str | ✓ | | | kb_id | str | ✓ | | | doc_id | str | ✓ | |
异常:
- 无写权限 →
permission_denied - 文档不存在 →
document_not_found
典型工作流
1. list_accessible_kbs(api_key) # 了解有哪些 KB
2. (可选) get_kb_info(api_key, kb_id) # 确认 KB 范围
3. search_kb(api_key, kb_id, query, top_k=5) # 检索
4. (可选) get_document(api_key, kb_id, doc_id) # 拿完整文档
兜底:search_all_accessible_kbs(api_key, query) 跨 KB 检索。
客户端示例
Python(用官方 mcp SDK)
import asyncio
import json
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
async with streamablehttp_client("http://localhost:3220/mcp") as (
read_stream,
write_stream,
_get_session_id,
):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
# 列工具
tools = await session.list_tools()
# 检索
result = await session.call_tool(
"search_kb_tool",
arguments={
"api_key": "test",
"kb_id": "rd_frontend",
"query": "React 18 怎么用并发渲染?",
"top_k": 5,
},
)
# content[0].text 是 JSON 字符串
hits = json.loads(result.content[0].text)
for h in hits:
print(f"[{h['score']:.2f}] {h['title']}")
asyncio.run(main())
TypeScript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({ name: "my-agent", version: "1.0.0" });
const transport = new StreamableHTTPClientTransport(
new URL("http://localhost:3220/mcp")
);
await client.connect(transport);
const result = await client.callTool({
name: "search_kb_tool",
arguments: {
api_key: "test",
kb_id: "rd_frontend",
query: "React 18 怎么用并发渲染?",
top_k: 5,
},
});
const hits = JSON.parse(result.content[0].text);
Claude Desktop 配置
~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或对应平台路径:
{
"mcpServers": {
"study-rag": {
"url": "http://localhost:3220/mcp",
"transport": "streamable_http"
}
}
}
错误码
| code | 含义 | 触发场景 | |---|---|---| | permission_denied | 鉴权失败 | apikey 无效 / 用户无权访问该 KB | | kb_not_found | KB 不存在 | kbid 不存在或被禁用 | | document_not_found | 文档不存在 | docid 不存在 | | document_already_exists | 文档已存在 | adddocument 时 docid 重复,且未传 overwrite | | invalid_parameter | 参数非法 | query 为空、topk 超范围、filter_expr 字段名非法 |
所有错误通过 MCP 标准的 error.code 字段返回(JSON-RPC 格式)。
调试
# 启动 MCP server
pwsh scripts/dev.ps1 mcp
# 启动 MCP Inspector(浏览器)
pwsh scripts/dev.ps1 inspector
# 浏览器打开 http://localhost:3210
# 选 transport: streamable_http
# URL: http://localhost:3220/mcp
# Connect → List Tools → 选 Tool → 填参数 → Call Tool
协议版本
- MCP protocol:
2025-03-26 - Transport: Streamable HTTP
- Python:
>=3.10 - FastMCP:
>=1.0
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jinyangpeng
- Source: jinyangpeng/study_rag
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.