- 新增 Windows 11 RAGFlow + MCP 完整部署记录 - 添加 AI 栏目首页与免费模型 API 文档 - 更新 VuePress 配置与 collections 结构 - 添加缓存清理和文档同步脚本
1170 lines
26 KiB
Markdown
1170 lines
26 KiB
Markdown
# Windows 11 本地部署 RAGFlow 与 Cursor MCP 接入完整记录
|
||
|
||
这是一份按本次真实部署过程重新整理的操作文档。
|
||
|
||
我会尽量把每一步都写得温柔一点、清楚一点,让你以后自己回看时,不需要再从聊天记录里一点一点翻。
|
||
|
||
这份文档适用于:
|
||
|
||
- Windows 11
|
||
- Docker Desktop
|
||
- WSL2
|
||
- PowerShell
|
||
- 本地通过 Docker 部署 RAGFlow
|
||
- 在 Cursor 中通过 MCP 访问本地知识库
|
||
|
||
---
|
||
|
||
## 1. 最终落地状态
|
||
|
||
本次实际部署目录:
|
||
|
||
```powershell
|
||
D:\Project\ragflow
|
||
```
|
||
|
||
本次实际使用版本:
|
||
|
||
```powershell
|
||
infiniflow/ragflow:v0.23.1
|
||
```
|
||
|
||
本次实际对外端口如下:
|
||
|
||
| 服务 | 主机端口 | 容器端口 | 说明 |
|
||
|---|---:|---:|---|
|
||
| RAGFlow Web UI | 38180 | 80 | 浏览器主入口 |
|
||
| RAGFlow HTTPS | 38443 | 443 | HTTPS 入口 |
|
||
| RAGFlow API | 39380 | 9380 | 主 API |
|
||
| RAGFlow Admin API | 39381 | 9381 | 管理端接口 |
|
||
| RAGFlow MCP | 39382 | 9382 | Cursor 连接的 MCP |
|
||
| Elasticsearch | 31200 | 9200 | 向量检索底层 |
|
||
| MySQL | 35455 | 3306 | 元数据数据库 |
|
||
| Redis | 36379 | 6379 | 缓存 |
|
||
| MinIO API | 39010 | 9000 | 对象存储 |
|
||
| MinIO Console | 39011 | 9001 | MinIO 控制台 |
|
||
| OpenSearch | 31201 | 9200 | 可选组件 |
|
||
| Kibana | 36601 | 5601 | 可选组件 |
|
||
| Infinity Thrift | 33817 | 23817 | 可选组件 |
|
||
| Infinity HTTP | 33820 | 23820 | 可选组件 |
|
||
| Infinity PostgreSQL | 35432 | 5432 | 可选组件 |
|
||
| OceanBase | 32881 | 2881 | 可选组件 |
|
||
| TEI | 36380 | 80 | 可选嵌入服务 |
|
||
|
||
本次 Compose 项目名:
|
||
|
||
```powershell
|
||
simeng-ragflow
|
||
```
|
||
|
||
因此容器名会类似:
|
||
|
||
```powershell
|
||
simeng-ragflow-ragflow-cpu-1
|
||
simeng-ragflow-mysql-1
|
||
simeng-ragflow-minio-1
|
||
```
|
||
|
||
这样做的好处是,容器、网络、卷都不会以默认的 `docker-` 前缀出现,更容易识别。
|
||
|
||
---
|
||
|
||
## 2. 这次实际改动过的关键文件
|
||
|
||
下面这些文件,是这次部署和修复里真正动过的:
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docker\.env
|
||
D:\Project\ragflow\docker\docker-compose.yml
|
||
D:\Project\ragflow\mcp\server\server.py
|
||
C:\Users\35016\.cursor\mcp.json
|
||
```
|
||
|
||
它们分别负责:
|
||
|
||
- `docker\.env`
|
||
- 统一管理端口
|
||
- 指定镜像版本
|
||
- 指定 Compose 项目名
|
||
- 配置 MCP 的 host、port、base URL、mode、host API key
|
||
|
||
- `docker\docker-compose.yml`
|
||
- 让 `ragflow-cpu` 或 `ragflow-gpu` 真正带着 MCP 参数启动
|
||
- 将主机上的 `mcp/server/server.py` 挂载到容器里
|
||
|
||
- `mcp\server\server.py`
|
||
- 修复空知识库导致 MCP 无限刷日志的问题
|
||
|
||
- `C:\Users\35016\.cursor\mcp.json`
|
||
- 把 Cursor 指向本机 `http://127.0.0.1:39382/mcp/`
|
||
|
||
---
|
||
|
||
## 3. 为什么这次使用 v0.23.1
|
||
|
||
官方文档页面可能会展示更新的开发文档内容,但本次实际部署时,选择的是更稳妥的稳定版本:
|
||
|
||
```powershell
|
||
infiniflow/ragflow:v0.23.1
|
||
```
|
||
|
||
这样做的原因很简单:
|
||
|
||
- 稳定版更适合本地长期使用
|
||
- 与当前 Docker Compose 配置兼容性更稳定
|
||
- 便于把问题范围收敛到部署和配置,而不是开发版变更
|
||
|
||
如果你后续要升级版本,建议先备份:
|
||
|
||
- `docker\.env`
|
||
- `docker\docker-compose.yml`
|
||
- 自己修补过的 `mcp\server\server.py`
|
||
|
||
---
|
||
|
||
## 4. Windows 11 上从零部署 RAGFlow 的完整步骤
|
||
|
||
### 4.1 准备环境
|
||
|
||
请先确认下面这些基础组件已经装好:
|
||
|
||
- Windows 11
|
||
- WSL2
|
||
- Docker Desktop
|
||
- Git
|
||
- PowerShell 7 或 Windows PowerShell
|
||
- `curl.exe`
|
||
|
||
可以先简单检查:
|
||
|
||
```powershell
|
||
docker --version
|
||
docker compose version
|
||
git --version
|
||
wsl -l -v
|
||
curl.exe --version
|
||
```
|
||
|
||
---
|
||
|
||
### 4.2 创建部署目录
|
||
|
||
如果 `D:\Project` 不存在,先创建:
|
||
|
||
```powershell
|
||
New-Item -ItemType Directory -Path 'D:\Project' -Force
|
||
```
|
||
|
||
进入目录并克隆官方仓库:
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project'
|
||
git clone https://github.com/infiniflow/ragflow.git
|
||
Set-Location 'D:\Project\ragflow'
|
||
```
|
||
|
||
如果已经有仓库目录,可以直接进入:
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow'
|
||
```
|
||
|
||
---
|
||
|
||
### 4.3 设置 WSL 内核参数 `vm.max_map_count`
|
||
|
||
这是 Elasticsearch 常见要求。如果不设置,RAGFlow 依赖的 ES 组件很容易启动失败。
|
||
|
||
本次实际使用的是临时设置方式:
|
||
|
||
```powershell
|
||
wsl -d docker-desktop -u root -- sysctl -w vm.max_map_count=262144
|
||
```
|
||
|
||
如果输出类似下面这样,就表示成功:
|
||
|
||
```powershell
|
||
vm.max_map_count = 262144
|
||
```
|
||
|
||
这一步非常重要。
|
||
|
||
如果 Docker Desktop 重启过,这个值有可能需要重新执行一次。
|
||
|
||
---
|
||
|
||
### 4.4 修改 `docker\.env`
|
||
|
||
打开:
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docker\.env
|
||
```
|
||
|
||
本次实际关键配置如下:
|
||
|
||
```dotenv
|
||
COMPOSE_PROJECT_NAME=simeng-ragflow
|
||
|
||
ES_PORT=31200
|
||
OS_PORT=31201
|
||
KIBANA_PORT=36601
|
||
INFINITY_THRIFT_PORT=33817
|
||
INFINITY_HTTP_PORT=33820
|
||
INFINITY_PSQL_PORT=35432
|
||
OCEANBASE_PORT=32881
|
||
MYSQL_PORT=35455
|
||
MINIO_CONSOLE_PORT=39011
|
||
MINIO_PORT=39010
|
||
REDIS_PORT=36379
|
||
SVR_WEB_HTTP_PORT=38180
|
||
SVR_WEB_HTTPS_PORT=38443
|
||
SVR_HTTP_PORT=39380
|
||
ADMIN_SVR_HTTP_PORT=39381
|
||
SVR_MCP_PORT=39382
|
||
TEI_PORT=36380
|
||
|
||
RAGFLOW_MCP_HOST=0.0.0.0
|
||
RAGFLOW_MCP_PORT=9382
|
||
RAGFLOW_MCP_BASE_URL=http://127.0.0.1:9380
|
||
RAGFLOW_MCP_MODE=self-host
|
||
RAGFLOW_MCP_HOST_API_KEY=ragflow-请替换为你自己的值
|
||
|
||
RAGFLOW_IMAGE=infiniflow/ragflow:v0.23.1
|
||
TZ=Asia/Shanghai
|
||
```
|
||
|
||
请注意:
|
||
|
||
- `RAGFLOW_MCP_BASE_URL` 这里写的是容器内 MCP 访问容器内 RAGFlow API 的地址,所以是 `http://127.0.0.1:9380`
|
||
- `SVR_MCP_PORT=39382` 是主机暴露出来给 Cursor 用的外部端口
|
||
- `RAGFLOW_MCP_HOST_API_KEY` 不要直接公开写在文档、截图或聊天记录里
|
||
|
||
本机当前已经有一个可用的真实 key 存在于本地 `.env` 里。如果你是重新部署,请自行生成并填入。
|
||
|
||
---
|
||
|
||
### 4.5 修改 `docker\docker-compose.yml`
|
||
|
||
打开:
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docker\docker-compose.yml
|
||
```
|
||
|
||
需要让 `ragflow-cpu` 或 `ragflow-gpu` 真正带着 MCP 参数启动。
|
||
|
||
本次 `ragflow-cpu` 实际结构如下:
|
||
|
||
```yaml
|
||
ragflow-cpu:
|
||
depends_on:
|
||
mysql:
|
||
condition: service_healthy
|
||
profiles:
|
||
- cpu
|
||
image: ${RAGFLOW_IMAGE}
|
||
command:
|
||
- --enable-mcpserver
|
||
- --mcp-host=${RAGFLOW_MCP_HOST}
|
||
- --mcp-port=${RAGFLOW_MCP_PORT}
|
||
- --mcp-base-url=${RAGFLOW_MCP_BASE_URL}
|
||
- --mcp-script-path=/ragflow/mcp/server/server.py
|
||
- --mcp-mode=${RAGFLOW_MCP_MODE}
|
||
- --mcp-host-api-key=${RAGFLOW_MCP_HOST_API_KEY}
|
||
- --enable-adminserver
|
||
ports:
|
||
- ${SVR_WEB_HTTP_PORT}:80
|
||
- ${SVR_WEB_HTTPS_PORT}:443
|
||
- ${SVR_HTTP_PORT}:9380
|
||
- ${ADMIN_SVR_HTTP_PORT}:9381
|
||
- ${SVR_MCP_PORT}:9382
|
||
volumes:
|
||
- ./ragflow-logs:/ragflow/logs
|
||
- ./nginx/ragflow.conf:/etc/nginx/conf.d/ragflow.conf
|
||
- ./nginx/proxy.conf:/etc/nginx/proxy.conf
|
||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||
- ../history_data_agent:/ragflow/history_data_agent
|
||
- ../mcp/server/server.py:/ragflow/mcp/server/server.py
|
||
- ./service_conf.yaml.template:/ragflow/conf/service_conf.yaml.template
|
||
- ./entrypoint.sh:/ragflow/entrypoint.sh
|
||
env_file: .env
|
||
networks:
|
||
- ragflow
|
||
restart: unless-stopped
|
||
extra_hosts:
|
||
- "host.docker.internal:host-gateway"
|
||
```
|
||
|
||
如果你使用 GPU 版,也要把 `ragflow-gpu` 一起改掉,保持一致。
|
||
|
||
这里最重要的有三点:
|
||
|
||
1. `--enable-mcpserver`
|
||
- 这是让 MCP 真正启动的开关
|
||
|
||
2. `--mcp-host-api-key=${RAGFLOW_MCP_HOST_API_KEY}`
|
||
- 这是给容器内 MCP 进程访问 RAGFlow API 用的,不是给 Cursor 客户端用的
|
||
|
||
3. `- ../mcp/server/server.py:/ragflow/mcp/server/server.py`
|
||
- 这是为了让本地修补过的 `server.py` 真正进入容器
|
||
|
||
---
|
||
|
||
### 4.6 启动服务
|
||
|
||
进入 `docker` 目录:
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow\docker'
|
||
```
|
||
|
||
首次启动:
|
||
|
||
```powershell
|
||
docker compose up -d
|
||
```
|
||
|
||
查看状态:
|
||
|
||
```powershell
|
||
docker compose ps
|
||
```
|
||
|
||
也可以直接看全局容器:
|
||
|
||
```powershell
|
||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||
```
|
||
|
||
本次正常容器应至少包括:
|
||
|
||
```powershell
|
||
simeng-ragflow-ragflow-cpu-1
|
||
simeng-ragflow-mysql-1
|
||
simeng-ragflow-minio-1
|
||
simeng-ragflow-redis-1
|
||
simeng-ragflow-es01-1
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 首次启动后的验证
|
||
|
||
### 5.1 检查 Web UI
|
||
|
||
浏览器访问:
|
||
|
||
```powershell
|
||
http://127.0.0.1:38180
|
||
```
|
||
|
||
如果能打开前端页面,说明 Web 层已经起来了。
|
||
|
||
---
|
||
|
||
### 5.2 检查健康接口
|
||
|
||
运行:
|
||
|
||
```powershell
|
||
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz
|
||
```
|
||
|
||
本次正常返回示例:
|
||
|
||
```json
|
||
{"db":"ok","doc_engine":"ok","redis":"ok","status":"ok","storage":"ok"}
|
||
```
|
||
|
||
只要这里全部是 `ok`,就说明主链路正常。
|
||
|
||
---
|
||
|
||
## 6. 默认账号与登录说明
|
||
|
||
RAGFlow 默认管理员账号来自官方文档:
|
||
|
||
```text
|
||
admin@ragflow.io
|
||
admin
|
||
```
|
||
|
||
访问地址:
|
||
|
||
```powershell
|
||
http://127.0.0.1:38180/admin
|
||
```
|
||
|
||
请特别注意:
|
||
|
||
- 这个默认管理员账号只能登录 `/admin`
|
||
- 不能登录普通前台
|
||
- 如果你拿它去登录普通前台,会收到类似:
|
||
|
||
```text
|
||
Default admin account cannot be used to login normal services!
|
||
```
|
||
|
||
这不是密码错,而是 RAGFlow 本身就这样设计。
|
||
|
||
普通使用方式是:
|
||
|
||
- 管理后台:`/admin`
|
||
- 普通用户前台:`/`
|
||
- 普通用户需要注册新账号,或者由管理员创建
|
||
|
||
---
|
||
|
||
## 7. 这次实际遇到的问题与解决方案
|
||
|
||
这一节很重要,因为这里不是“理论问题”,而是这次在 Windows 11 本机部署时真实踩到的坑。
|
||
|
||
### 7.1 问题一:MinIO 缺少 bucket,健康检查返回 500
|
||
|
||
#### 现象
|
||
|
||
初次启动后,RAGFlow 的健康检查可能失败,日志里会出现类似 `NoSuchBucket`,接口返回 500。
|
||
|
||
#### 根因
|
||
|
||
MinIO 服务起来了,但 `ragflow-bucket` 没有自动建立。
|
||
|
||
#### 解决方案
|
||
|
||
进入一个能运行 Python 的 RAGFlow 容器,手工创建 bucket:
|
||
|
||
```powershell
|
||
docker exec simeng-ragflow-ragflow-cpu-1 python -c "from minio import Minio; c=Minio('minio:9000', access_key='rag_flow', secret_key='infini_rag_flow', secure=False); b='ragflow-bucket'; print('exists_before=' + str(c.bucket_exists(b))); (None if c.bucket_exists(b) else c.make_bucket(b)); print('exists_after=' + str(c.bucket_exists(b)))"
|
||
```
|
||
|
||
创建成功后,再次检查:
|
||
|
||
```powershell
|
||
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz
|
||
```
|
||
|
||
如果返回全 `ok`,说明已经恢复正常。
|
||
|
||
---
|
||
|
||
### 7.2 问题二:MCP 端口明明映射了,但 Cursor 还是连不上
|
||
|
||
#### 现象
|
||
|
||
宿主机上看到已经有:
|
||
|
||
```powershell
|
||
39382 -> 9382
|
||
```
|
||
|
||
但 Cursor 仍然不可用,或者访问时表现异常。
|
||
|
||
#### 根因
|
||
|
||
仅仅暴露端口并不等于 MCP 真的启动了。
|
||
|
||
之前的问题就是:
|
||
|
||
- Docker 做了 `39382 -> 9382` 的端口映射
|
||
- 但容器内其实没有 MCP 进程监听 `9382`
|
||
|
||
所以表现会像:
|
||
|
||
- `/sse` 访问空响应
|
||
- 或容器里 `127.0.0.1:9382` 直接 `Connection refused`
|
||
|
||
#### 解决方案
|
||
|
||
必须在 `docker-compose.yml` 里显式增加:
|
||
|
||
```yaml
|
||
command:
|
||
- --enable-mcpserver
|
||
- --mcp-host=${RAGFLOW_MCP_HOST}
|
||
- --mcp-port=${RAGFLOW_MCP_PORT}
|
||
- --mcp-base-url=${RAGFLOW_MCP_BASE_URL}
|
||
- --mcp-script-path=/ragflow/mcp/server/server.py
|
||
- --mcp-mode=${RAGFLOW_MCP_MODE}
|
||
- --mcp-host-api-key=${RAGFLOW_MCP_HOST_API_KEY}
|
||
```
|
||
|
||
然后重建容器:
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow\docker'
|
||
docker compose up -d --force-recreate ragflow-cpu
|
||
```
|
||
|
||
---
|
||
|
||
### 7.3 问题三:Cursor 配置写成 `/mcp`,实际应该写 `/mcp/`
|
||
|
||
#### 现象
|
||
|
||
MCP 有时看起来能通,有时又初始化失败,行为不稳定。
|
||
|
||
#### 根因
|
||
|
||
`/mcp` 会发生 `307` 重定向到 `/mcp/`。
|
||
|
||
有些 MCP 客户端对这个跳转处理得不够稳定,所以最好直接写最终地址。
|
||
|
||
#### 解决方案
|
||
|
||
Cursor 配置使用:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"RAGFlow": {
|
||
"url": "http://127.0.0.1:39382/mcp/"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
不要写成:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"RAGFlow": {
|
||
"url": "http://127.0.0.1:39382/mcp"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 7.4 问题四:MCP 查询一发起,容器日志疯狂刷屏
|
||
|
||
#### 现象
|
||
|
||
在容器 `simeng-ragflow-ragflow-cpu-1` 中,MCP 发起检索后,日志不断重复请求:
|
||
|
||
```text
|
||
/api/v1/datasets/<id>/documents?page=1
|
||
```
|
||
|
||
几乎像死循环一样不停输出。
|
||
|
||
#### 本次触发问题的请求示例
|
||
|
||
```json
|
||
{
|
||
"question": "vuepress-theme-plume 博客文章 frontmatter tags 标签配置",
|
||
"page_size": 8,
|
||
"similarity_threshold": 0.2
|
||
}
|
||
```
|
||
|
||
#### 根因
|
||
|
||
`mcp/server/server.py` 中有一段逻辑会在补齐 `document_metadata` 时遍历知识库文档分页。
|
||
|
||
如果某个知识库是空的,也就是:
|
||
|
||
```text
|
||
docs = []
|
||
```
|
||
|
||
原来的代码既没有翻页,也没有退出循环,于是它会一直打同一个:
|
||
|
||
```text
|
||
/documents?page=1
|
||
```
|
||
|
||
这次实际触发该问题的原因是:
|
||
|
||
- 查询时没有传 `dataset_ids`
|
||
- MCP 会自动遍历所有可用知识库
|
||
- 其中正好包含一个空知识库
|
||
- 空知识库触发了分页死循环
|
||
|
||
#### 修复方式
|
||
|
||
已在:
|
||
|
||
```powershell
|
||
D:\Project\ragflow\mcp\server\server.py
|
||
```
|
||
|
||
中补上保护逻辑。核心思路是:
|
||
|
||
- 请求失败就退出
|
||
- `docs` 为空就退出
|
||
- `code != 0` 就退出
|
||
- 当 `page * page_size >= total` 时退出
|
||
|
||
本次修补后的关键逻辑可以概括为:
|
||
|
||
```python
|
||
docs_res = self._get(f"/datasets/{dataset_id}/documents", {"page": page, "page_size": page_size})
|
||
if not docs_res or docs_res.status_code != 200:
|
||
break
|
||
|
||
docs_data = docs_res.json()
|
||
page_docs = docs_data.get("data", {}).get("docs") or []
|
||
total = docs_data.get("data", {}).get("total", 0) or 0
|
||
|
||
if docs_data.get("code") != 0 or not page_docs:
|
||
break
|
||
|
||
if page * page_size >= total:
|
||
break
|
||
```
|
||
|
||
#### 为什么还要挂载 `server.py`
|
||
|
||
因为容器内部默认使用镜像里自带的 `server.py`。
|
||
|
||
如果你只是改了主机文件,但没有在 Compose 里加:
|
||
|
||
```yaml
|
||
- ../mcp/server/server.py:/ragflow/mcp/server/server.py
|
||
```
|
||
|
||
那容器里运行的仍然是旧代码,问题不会真正消失。
|
||
|
||
---
|
||
|
||
### 7.5 问题五:PowerShell 里发中文 JSON,MCP 返回 `utf-8 decode` 错误
|
||
|
||
#### 现象
|
||
|
||
通过 PowerShell 把中文问题写进 JSON,再用 `curl` 提交时,MCP 返回类似编码错误。
|
||
|
||
#### 根因
|
||
|
||
Windows 下某些写文件方式默认带 BOM,或者不是严格的 UTF-8 无 BOM,服务端解析时会异常。
|
||
|
||
#### 解决方案
|
||
|
||
用 UTF-8 无 BOM 明确写文件:
|
||
|
||
```powershell
|
||
$tmp = Join-Path $env:TEMP 'ragflow_mcp_test.json'
|
||
$body = '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ragflow_retrieval","arguments":{"question":"vuepress-theme-plume 博客文章 frontmatter tags 标签配置","page_size":8,"similarity_threshold":0.2}}}'
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||
[System.IO.File]::WriteAllText($tmp, $body, $utf8NoBom)
|
||
```
|
||
|
||
然后再请求:
|
||
|
||
```powershell
|
||
curl.exe -s --noproxy "*" -H "Accept: application/json, text/event-stream" -H "Content-Type: application/json" --data-binary "@$tmp" http://127.0.0.1:39382/mcp/
|
||
```
|
||
|
||
---
|
||
|
||
### 7.6 问题六:刚重建容器后,MCP 短时间内 `Connection refused`
|
||
|
||
#### 现象
|
||
|
||
你刚执行完重建,立刻测试 `/mcp/` 或 `/sse`,可能会看到连接失败。
|
||
|
||
#### 根因
|
||
|
||
MCP 进程已经在起,但主 API `9380` 还没完全 ready,服务存在启动顺序窗口期。
|
||
|
||
#### 解决方案
|
||
|
||
先等健康检查恢复为 `ok`,再测:
|
||
|
||
```powershell
|
||
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz
|
||
```
|
||
|
||
只要主 API 健康了,再去测 MCP,通常就会稳定。
|
||
|
||
---
|
||
|
||
### 7.7 问题七:MCP 能连上,但检索报 Ollama 连接错误
|
||
|
||
#### 现象
|
||
|
||
MCP 初始化正常,但真正执行检索或召回时,返回类似:
|
||
|
||
```text
|
||
Failed to connect to Ollama. Please check that Ollama is downloaded, running and accessible.
|
||
```
|
||
|
||
#### 根因
|
||
|
||
这通常不是 MCP 网络层的问题,而是 RAGFlow 当前所绑定的模型服务不可用。
|
||
|
||
也就是说:
|
||
|
||
- MCP 通了
|
||
- RAGFlow 主服务也通了
|
||
- 但 RAGFlow 检索链路依赖的模型服务没有通
|
||
|
||
#### 解决方案
|
||
|
||
检查你在 RAGFlow 后台配置的模型是否真的可用:
|
||
|
||
- 如果使用 Ollama,确认 Ollama 进程在运行
|
||
- 如果使用 OpenAI 兼容接口,确认 API 地址和 key 正确
|
||
- 如果使用本地代理,确认代理服务本身是正常的
|
||
|
||
这个问题和 “Cursor 的 MCP 配置” 不是同一层,排障时不要混在一起看。
|
||
|
||
---
|
||
|
||
## 8. 如何配置 MCP
|
||
|
||
这一节分成两部分:
|
||
|
||
- RAGFlow 服务端如何启用 MCP
|
||
- Cursor 客户端如何接入 MCP
|
||
|
||
---
|
||
|
||
### 8.1 服务端 MCP 配置
|
||
|
||
服务端的关键不在 Cursor,而在 RAGFlow 的容器启动参数。
|
||
|
||
#### `.env` 中的 MCP 相关配置
|
||
|
||
```dotenv
|
||
RAGFLOW_MCP_HOST=0.0.0.0
|
||
RAGFLOW_MCP_PORT=9382
|
||
RAGFLOW_MCP_BASE_URL=http://127.0.0.1:9380
|
||
RAGFLOW_MCP_MODE=self-host
|
||
RAGFLOW_MCP_HOST_API_KEY=ragflow-请替换为你自己的值
|
||
```
|
||
|
||
#### `docker-compose.yml` 中必须有的参数
|
||
|
||
```yaml
|
||
command:
|
||
- --enable-mcpserver
|
||
- --mcp-host=${RAGFLOW_MCP_HOST}
|
||
- --mcp-port=${RAGFLOW_MCP_PORT}
|
||
- --mcp-base-url=${RAGFLOW_MCP_BASE_URL}
|
||
- --mcp-script-path=/ragflow/mcp/server/server.py
|
||
- --mcp-mode=${RAGFLOW_MCP_MODE}
|
||
- --mcp-host-api-key=${RAGFLOW_MCP_HOST_API_KEY}
|
||
```
|
||
|
||
这里最容易混淆的一点是:
|
||
|
||
- `RAGFLOW_MCP_HOST_API_KEY` 是给服务端 MCP 自己去访问 RAGFlow API 用的
|
||
- 不是说 Cursor 一定要把这个 key 带出去
|
||
|
||
本次实际验证下,Cursor 侧可以不配置 API key,仍可通过 `http://127.0.0.1:39382/mcp/` 正常工作。
|
||
|
||
---
|
||
|
||
### 8.2 Cursor 侧 MCP 配置
|
||
|
||
Cursor 全局配置文件位置:
|
||
|
||
```powershell
|
||
C:\Users\35016\.cursor\mcp.json
|
||
```
|
||
|
||
本次最终可用配置如下:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"RAGFlow": {
|
||
"url": "http://127.0.0.1:39382/mcp/"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
请注意两个细节:
|
||
|
||
1. 使用 `127.0.0.1`,不要混用 `localhost`
|
||
2. 使用 `/mcp/`,不要写成 `/mcp`
|
||
|
||
如果你已经改好配置,但 Cursor 面板没有刷新出来,可以:
|
||
|
||
- 重启 Cursor
|
||
- 或重新打开 MCP 面板
|
||
|
||
---
|
||
|
||
## 9. 如何验证 MCP 是否正常
|
||
|
||
这一节给出的是 Windows 11 下可以直接运行的 PowerShell 命令。
|
||
|
||
---
|
||
|
||
### 9.1 验证 `/sse`
|
||
|
||
```powershell
|
||
curl.exe -i --max-time 3 --noproxy "*" http://127.0.0.1:39382/sse
|
||
```
|
||
|
||
正常时会看到类似:
|
||
|
||
```text
|
||
HTTP/1.1 200 OK
|
||
content-type: text/event-stream; charset=utf-8
|
||
|
||
event: endpoint
|
||
data: /messages/?session_id=xxxx
|
||
```
|
||
|
||
这里超时是正常的,因为 SSE 本来就是长连接。
|
||
|
||
只要能看到 `HTTP/1.1 200 OK` 和 `event: endpoint`,就说明监听已经在了。
|
||
|
||
---
|
||
|
||
### 9.2 验证 `/mcp/ initialize`
|
||
|
||
```powershell
|
||
$tmp = Join-Path $env:TEMP 'ragflow_mcp_init.json'
|
||
$body = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"local-test","version":"1.0.0"}}}'
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||
[System.IO.File]::WriteAllText($tmp, $body, $utf8NoBom)
|
||
|
||
curl.exe -s -i --noproxy "*" `
|
||
-H "Accept: application/json, text/event-stream" `
|
||
-H "Content-Type: application/json" `
|
||
--data-binary "@$tmp" `
|
||
http://127.0.0.1:39382/mcp/
|
||
```
|
||
|
||
正常时会返回 `200 OK`,并带上 `serverInfo`。
|
||
|
||
---
|
||
|
||
### 9.3 验证 `tools/list`
|
||
|
||
```powershell
|
||
$tmp = Join-Path $env:TEMP 'ragflow_mcp_tools_list.json'
|
||
$body = '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||
[System.IO.File]::WriteAllText($tmp, $body, $utf8NoBom)
|
||
|
||
curl.exe -s --noproxy "*" `
|
||
-H "Accept: application/json, text/event-stream" `
|
||
-H "Content-Type: application/json" `
|
||
--data-binary "@$tmp" `
|
||
http://127.0.0.1:39382/mcp/
|
||
```
|
||
|
||
正常时你会看到 `ragflow_retrieval` 这个工具,以及当前可用知识库列表。
|
||
|
||
---
|
||
|
||
### 9.4 验证 `tools/call`
|
||
|
||
```powershell
|
||
$tmp = Join-Path $env:TEMP 'ragflow_mcp_tool_call.json'
|
||
$body = '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"ragflow_retrieval","arguments":{"question":"vuepress-theme-plume 博客文章 frontmatter tags 标签配置","page_size":8,"similarity_threshold":0.2}}}'
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||
[System.IO.File]::WriteAllText($tmp, $body, $utf8NoBom)
|
||
|
||
curl.exe -s --noproxy "*" `
|
||
-H "Accept: application/json, text/event-stream" `
|
||
-H "Content-Type: application/json" `
|
||
--data-binary "@$tmp" `
|
||
http://127.0.0.1:39382/mcp/
|
||
```
|
||
|
||
如果返回真正的 chunk 内容,说明 MCP 与知识库已经打通。
|
||
|
||
如果返回模型错误,而不是网络错误,说明:
|
||
|
||
- MCP 已通
|
||
- 但 RAGFlow 内部模型服务仍需单独检查
|
||
|
||
---
|
||
|
||
## 10. 本次 MCP 疯狂刷日志的修复记录
|
||
|
||
为了方便以后回看,这里单独整理一下这次最关键的故障。
|
||
|
||
### 问题表现
|
||
|
||
容器:
|
||
|
||
```powershell
|
||
simeng-ragflow-ragflow-cpu-1
|
||
```
|
||
|
||
在接到 MCP 检索请求后,日志不断刷:
|
||
|
||
```text
|
||
GET /api/v1/datasets/<dataset_id>/documents?page=1
|
||
```
|
||
|
||
### 问题原因
|
||
|
||
MCP 在查询时,如果没有传 `dataset_ids`,会遍历全部知识库。
|
||
|
||
其中只要有一个空知识库,就可能进入原逻辑的死循环。
|
||
|
||
### 修复文件
|
||
|
||
```powershell
|
||
D:\Project\ragflow\mcp\server\server.py
|
||
```
|
||
|
||
### 修复要点
|
||
|
||
- 当 `/documents` 返回空列表时,立即退出分页
|
||
- 当状态码非 200 时退出
|
||
- 当接口 `code != 0` 时退出
|
||
- 按 `total` 正确结束分页
|
||
|
||
### 为什么这一步非常关键
|
||
|
||
如果不修,表面上看是 “日志太多”,但本质上会带来:
|
||
|
||
- 不必要的 API 压力
|
||
- Cursor 端响应变慢
|
||
- 排障时非常容易误判成网络问题或死锁问题
|
||
|
||
---
|
||
|
||
## 11. RAGFlow 日常启动、停止、重建命令
|
||
|
||
### 启动前先设置内核参数
|
||
|
||
```powershell
|
||
wsl -d docker-desktop -u root -- sysctl -w vm.max_map_count=262144
|
||
```
|
||
|
||
### 启动
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow\docker'
|
||
docker compose up -d
|
||
```
|
||
|
||
### 停止
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow\docker'
|
||
docker compose down
|
||
```
|
||
|
||
### 只重建 RAGFlow 主容器
|
||
|
||
```powershell
|
||
Set-Location 'D:\Project\ragflow\docker'
|
||
docker compose up -d --force-recreate ragflow-cpu
|
||
```
|
||
|
||
### 查看日志
|
||
|
||
```powershell
|
||
docker logs --tail 200 simeng-ragflow-ragflow-cpu-1
|
||
```
|
||
|
||
持续跟踪:
|
||
|
||
```powershell
|
||
docker logs -f simeng-ragflow-ragflow-cpu-1
|
||
```
|
||
|
||
### 查看容器
|
||
|
||
```powershell
|
||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 不建议直接做的事情
|
||
|
||
### 12.1 不要轻易执行 `docker compose down -v`
|
||
|
||
这个命令会把卷一起删掉。
|
||
|
||
如果你没有明确打算重置数据,尽量不要这样做。
|
||
|
||
推荐只用:
|
||
|
||
```powershell
|
||
docker compose down
|
||
```
|
||
|
||
---
|
||
|
||
### 12.2 不要把默认管理员密码长期保留在对外环境中
|
||
|
||
默认管理员账号只适合本地测试。
|
||
|
||
如果要用于局域网或公网,建议尽快处理:
|
||
|
||
- 修改管理员密码
|
||
- 关闭不必要的注册入口
|
||
- 修改 `.env` 中的默认弱口令
|
||
|
||
---
|
||
|
||
### 12.3 不要把真实的 MCP host API key 写进文档或发给别人
|
||
|
||
这类 key 应只保存在:
|
||
|
||
- 本地 `.env`
|
||
- 安全的密码管理工具
|
||
|
||
这份文档里只保留占位符,是为了避免后续二次泄露。
|
||
|
||
---
|
||
|
||
## 13. 推荐的排障顺序
|
||
|
||
如果以后再出现问题,建议按这个顺序排:
|
||
|
||
1. 先看容器在不在
|
||
|
||
```powershell
|
||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||
```
|
||
|
||
2. 再看主服务健康不健康
|
||
|
||
```powershell
|
||
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz
|
||
```
|
||
|
||
3. 再看 MCP 端口是否在监听
|
||
|
||
```powershell
|
||
curl.exe -i --max-time 3 --noproxy "*" http://127.0.0.1:39382/sse
|
||
```
|
||
|
||
4. 再测 `/mcp/` 初始化
|
||
|
||
5. 最后才去看 Cursor 配置
|
||
|
||
这样排会比较稳,不容易把“模型问题”“服务问题”“客户端配置问题”混在一起。
|
||
|
||
---
|
||
|
||
## 14. 一份最小可用检查清单
|
||
|
||
如果你只想快速确认现在能不能用,可以看这一小节。
|
||
|
||
### RAGFlow 是否正常
|
||
|
||
- [ ] `http://127.0.0.1:38180` 能打开
|
||
- [ ] `http://127.0.0.1:38180/admin` 能打开
|
||
- [ ] `http://127.0.0.1:39380/v1/system/healthz` 返回全 `ok`
|
||
|
||
### MCP 是否正常
|
||
|
||
- [ ] `http://127.0.0.1:39382/sse` 能返回 `event: endpoint`
|
||
- [ ] `initialize` 返回 `200`
|
||
- [ ] `tools/list` 能列出 `ragflow_retrieval`
|
||
- [ ] `tools/call` 能返回知识库内容,或者至少返回模型层错误而不是网络层错误
|
||
|
||
### Cursor 是否配置正确
|
||
|
||
- [ ] `C:\Users\35016\.cursor\mcp.json` 已写入 `http://127.0.0.1:39382/mcp/`
|
||
- [ ] 地址使用了 `/mcp/`
|
||
- [ ] 改完后已重启 Cursor
|
||
|
||
---
|
||
|
||
## 15. 本次部署中可直接参考的文件路径总表
|
||
|
||
### 部署目录
|
||
|
||
```powershell
|
||
D:\Project\ragflow
|
||
```
|
||
|
||
### 环境变量
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docker\.env
|
||
```
|
||
|
||
### Compose 文件
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docker\docker-compose.yml
|
||
```
|
||
|
||
### MCP 服务端实现
|
||
|
||
```powershell
|
||
D:\Project\ragflow\mcp\server\server.py
|
||
```
|
||
|
||
### Cursor MCP 配置
|
||
|
||
```powershell
|
||
C:\Users\35016\.cursor\mcp.json
|
||
```
|
||
|
||
### 官方管理员文档
|
||
|
||
```powershell
|
||
D:\Project\ragflow\docs\guides\accessing_admin_ui.md
|
||
```
|
||
|
||
### 普通登录限制代码
|
||
|
||
```powershell
|
||
D:\Project\ragflow\api\apps\user_app.py
|
||
```
|
||
|
||
---
|
||
|
||
## 16. 一点温柔的提醒
|
||
|
||
这套链路表面上看只是 “把 RAGFlow 跑起来,再在 Cursor 里配个 MCP”。
|
||
|
||
但实际踩下来,你会发现它至少包含四层:
|
||
|
||
- Docker 层
|
||
- RAGFlow 服务层
|
||
- MCP 服务层
|
||
- Cursor 客户端层
|
||
|
||
任何一层不通,都会表现成 “好像 MCP 有问题”。
|
||
|
||
所以以后遇到异常时,别急,也别怀疑自己哪里全都弄错了。
|
||
|
||
多数时候只是某一层状态没有对齐。
|
||
|
||
按这份文档一层一层检查,通常就能很快找到问题点。
|
||
|
||
---
|
||
|
||
## 17. 参考链接
|
||
|
||
- 官方文档:<https://ragflow.io/docs>
|
||
- 官方仓库:<https://github.com/infiniflow/ragflow>
|
||
- 官方 Releases:<https://github.com/infiniflow/ragflow/releases>
|
||
|
||
---
|
||
|
||
## 18. 本次文档重建说明
|
||
|
||
这份文档是根据本次实际部署、修复、验证过程重新整理的。
|
||
|
||
它特别保留了这次真实发生过的关键问题:
|
||
|
||
- MinIO bucket 缺失
|
||
- 默认管理员账号不能登录普通前台
|
||
- MCP 端口映射了但实际没有启动
|
||
- Cursor `/mcp` 与 `/mcp/` 的差异
|
||
- 空知识库导致 MCP 日志无限刷屏
|
||
- PowerShell 中文 JSON 编码问题
|
||
- 模型服务异常与 MCP 异常的区分
|
||
|
||
如果以后你继续调整:
|
||
|
||
- 模型配置
|
||
- Docker 端口
|
||
- MCP 参数
|
||
- `server.py` 修补逻辑
|
||
|
||
建议同步更新这份文档,这样后面你自己维护会轻松很多。
|