import{_ as i,c as a,a as e,o as l}from"./app-t8Vldhgr.js";const h={};function n(t,s){return l(),a("div",null,[...s[0]||(s[0]=[e(`
这是一份按本次真实部署过程重新整理的操作文档~
我会尽量把每一步都写得温柔一点、清楚一点,让你以后自己回看的时候,不需要再从聊天记录里一点一点翻找啦。
这份文档适用于:
本次实际部署目录:
D:\\Project\\ragflow本次实际使用版本:
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 项目名:
simeng-ragflow因此容器名会类似:
simeng-ragflow-ragflow-cpu-1
simeng-ragflow-mysql-1
simeng-ragflow-minio-1这样做的好处是,容器、网络、卷都不会以默认的 docker- 前缀出现,更容易识别~
下面这些文件,是这次部署和修复里真正动过的:
D:\\Project\\ragflow\\docker\\.env
D:\\Project\\ragflow\\docker\\docker-compose.yml
D:\\Project\\ragflow\\mcp\\server\\server.py
C:\\Users\\~\\.cursor\\mcp.json它们分别负责:
docker\\.env
docker\\docker-compose.yml
ragflow-cpu 或 ragflow-gpu 真正带着 MCP 参数启动mcp/server/server.py 挂载到容器里mcp\\server\\server.py
C:\\Users\\~\\.cursor\\mcp.json
http://127.0.0.1:39382/mcp/官方文档页面可能会展示更新的开发文档内容,但本次实际部署的时候,选择的是更稳妥的稳定版本:
infiniflow/ragflow:v0.23.1这样做的原因很简单:
如果你后续要升级版本,建议先备份:
docker\\.envdocker\\docker-compose.ymlmcp\\server\\server.py请先确认下面这些基础组件已经装好:
curl.exe可以先简单检查:
docker --version
docker compose version
git --version
wsl -l -v
curl.exe --version如果 D:\\Project 不存在,先创建:
New-Item -ItemType Directory -Path 'D:\\Project' -Force进入目录并克隆官方仓库:
Set-Location 'D:\\Project'
git clone https://github.com/infiniflow/ragflow.git
Set-Location 'D:\\Project\\ragflow'如果已经有仓库目录,可以直接进入:
Set-Location 'D:\\Project\\ragflow'vm.max_map_count这是 Elasticsearch 常见的要求。如果不设置,RAGFlow 依赖的 ES 组件很容易启动失败。
本次实际使用的是临时设置方式:
wsl -d docker-desktop -u root -- sysctl -w vm.max_map_count=262144如果输出类似下面这样,就表示成功:
vm.max_map_count = 262144这一步非常重要。
如果 Docker Desktop 重启过,这个值有可能需要重新执行一次。
docker\\.env打开:
D:\\Project\\ragflow\\docker\\.env本次实际关键配置如下:
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:9380SVR_MCP_PORT=39382 是主机暴露出来给 Cursor 用的外部端口RAGFLOW_MCP_HOST_API_KEY 不要直接公开写在文档、截图或聊天记录里本机当前已经有一个可用的真实 key 存在于本地 .env 里。如果你是重新部署,请自行生成并填入~
docker\\docker-compose.yml打开:
D:\\Project\\ragflow\\docker\\docker-compose.yml需要让 ragflow-cpu 或 ragflow-gpu 真正带着 MCP 参数启动。
本次 ragflow-cpu 实际结构如下:
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 一起改掉,保持一致。
这里最重要的有三点:
--enable-mcpserver
--mcp-host-api-key=\${RAGFLOW_MCP_HOST_API_KEY}
- ../mcp/server/server.py:/ragflow/mcp/server/server.py
server.py 真正进入容器进入 docker 目录:
Set-Location 'D:\\Project\\ragflow\\docker'首次启动:
docker compose up -d查看状态:
docker compose ps也可以直接看全局容器:
docker ps --format "table {{.Names}}\\t{{.Status}}\\t{{.Ports}}"本次正常容器应至少包括:
simeng-ragflow-ragflow-cpu-1
simeng-ragflow-mysql-1
simeng-ragflow-minio-1
simeng-ragflow-redis-1
simeng-ragflow-es01-1浏览器访问:
http://127.0.0.1:38180如果能打开前端页面,说明 Web 层已经起来啦~
运行:
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz本次正常返回示例:
{"db":"ok","doc_engine":"ok","redis":"ok","status":"ok","storage":"ok"}只要这里全部是 ok,就说明主链路正常。
RAGFlow 默认管理员账号来自官方文档:
admin@ragflow.io
admin访问地址:
http://127.0.0.1:38180/admin请特别注意:
/adminDefault admin account cannot be used to login normal services!这不是密码错,而是 RAGFlow 本身就这样设计。
普通使用方式是:
/admin/这一节很重要,因为这里不是"理论问题",而是这次在 Windows 11 本机部署时真实踩到的坑。
初次启动后,RAGFlow 的健康检查可能失败,日志里会出现类似 NoSuchBucket,接口返回 500。
MinIO 服务起来了,但 ragflow-bucket 没有自动建立。
进入一个能运行 Python 的 RAGFlow 容器,手工创建 bucket:
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)))"创建成功后,再次检查:
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz如果返回全 ok,说明已经恢复正常。
宿主机上看到已经有:
39382 -> 9382但 Cursor 仍然不可用,或者访问时表现异常。
仅仅暴露端口并不等于 MCP 真的启动了。
之前的问题就是:
39382 -> 9382 的端口映射9382所以表现会像:
/sse 访问空响应127.0.0.1:9382 直接 Connection refused必须在 docker-compose.yml 里显式增加:
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}然后重建容器:
Set-Location 'D:\\Project\\ragflow\\docker'
docker compose up -d --force-recreate ragflow-cpu/mcp,实际应该写 /mcp/MCP 有时看起来能通,有时又初始化失败,行为不稳定。
/mcp 会发生 307 重定向到 /mcp/。
有些 MCP 客户端对这个跳转处理得不够稳定,所以最好直接写最终地址。
Cursor 配置使用:
{
"mcpServers": {
"RAGFlow": {
"url": "http://127.0.0.1:39382/mcp/"
}
}
}不要写成:
{
"mcpServers": {
"RAGFlow": {
"url": "http://127.0.0.1:39382/mcp"
}
}
}在容器 simeng-ragflow-ragflow-cpu-1 中,MCP 发起检索后,日志不断重复请求:
GET /api/v1/datasets/<dataset_id>/documents?page=1几乎像死循环一样不停输出。
{
"question": "vuepress-theme-plume 博客文章 frontmatter tags 标签配置",
"page_size": 8,
"similarity_threshold": 0.2
}mcp/server/server.py 中有一段逻辑会在补齐 document_metadata 时遍历知识库文档分页。
如果某个知识库是空的,也就是:
docs = []原来的代码既没有翻页,也没有退出循环,于是它会一直打同一个:
/documents?page=1这次实际触发该问题的原因是:
dataset_ids已在:
D:\\Project\\ragflow\\mcp\\server\\server.py中补上保护逻辑。核心思路是:
docs 为空就退出code != 0 就退出page * page_size >= total 时退出本次修补后的关键逻辑可以概括为:
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:
breakserver.py因为容器内部默认使用镜像里自带的 server.py。
如果你只是改了主机文件,但没有在 Compose 里加:
- ../mcp/server/server.py:/ragflow/mcp/server/server.py那容器里运行的仍然是旧代码,问题不会真正消失。
utf-8 decode 错误通过 PowerShell 把中文问题写进 JSON,再用 curl 提交时,MCP 返回类似编码错误。
Windows 下某些写文件方式默认带 BOM,或者不是严格的 UTF-8 无 BOM,服务端解析时会异常。
用 UTF-8 无 BOM 明确写文件:
$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)然后再请求:
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/Connection refused你刚执行完重建,立刻测试 /mcp/ 或 /sse,可能会看到连接失败。
MCP 进程已经在起,但主 API 9380 还没完全 ready,服务存在启动顺序窗口期。
先等健康检查恢复为 ok,再测:
curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthz只要主 API 健康了,再去测 MCP,通常就会稳定。
MCP 初始化正常,但真正执行检索或召回时,返回类似:
Failed to connect to Ollama. Please check that Ollama is downloaded, running and accessible.这通常不是 MCP 网络层的问题,而是 RAGFlow 当前所绑定的模型服务不可用。
也就是说:
检查你在 RAGFlow 后台配置的模型是否真的可用:
这个问题和 "Cursor 的 MCP 配置" 不是同一层,排障时不要混在一起看。
这一节分成两部分:
服务端的关键不在 Cursor,而在 RAGFlow 的容器启动参数。
.env 中的 MCP 相关配置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 中必须有的参数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 侧可以不配置 API key,仍可通过 http://127.0.0.1:39382/mcp/ 正常工作。
Cursor 全局配置文件位置:
C:\\Users\\~\\.cursor\\mcp.json本次最终可用配置如下:
{
"mcpServers": {
"RAGFlow": {
"url": "http://127.0.0.1:39382/mcp/"
}
}
}请注意两个细节:
127.0.0.1,不要混用 localhost/mcp/,不要写成 /mcp如果你已经改好配置,但 Cursor 面板没有刷新出来,可以:
这一节给出的是 Windows 11 下可以直接运行的 PowerShell 命令。
/ssecurl.exe -i --max-time 3 --noproxy "*" http://127.0.0.1:39382/sse正常时会看到类似:
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,就说明监听已经在了。
/mcp/ initialize$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。
tools/list$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 这个工具,以及当前可用知识库列表。
tools/call$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 与知识库已经打通。
如果返回模型错误,而不是网络错误,说明:
wsl -d docker-desktop -u root -- sysctl -w vm.max_map_count=262144Set-Location 'D:\\Project\\ragflow\\docker'
docker compose up -dSet-Location 'D:\\Project\\ragflow\\docker'
docker compose downSet-Location 'D:\\Project\\ragflow\\docker'
docker compose up -d --force-recreate ragflow-cpudocker logs --tail 200 simeng-ragflow-ragflow-cpu-1持续跟踪:
docker logs -f simeng-ragflow-ragflow-cpu-1docker ps --format "table {{.Names}}\\t{{.Status}}\\t{{.Ports}}"docker compose down -v这个命令会把卷一起删掉。
如果你没有明确打算重置数据,尽量不要这样做。
推荐只用:
docker compose down默认管理员账号只适合本地测试。
如果要用于局域网或公网,建议尽快处理:
.env 中的默认弱口令这类 key 应只保存在:
.env这份文档里只保留占位符,是为了避免后续二次泄露。
如果以后再出现问题,建议按这个顺序排:
docker ps --format "table {{.Names}}\\t{{.Status}}\\t{{.Ports}}"curl.exe -s --noproxy "*" http://127.0.0.1:39380/v1/system/healthzcurl.exe -i --max-time 3 --noproxy "*" http://127.0.0.1:39382/sse再测 /mcp/ 初始化
最后才去看 Cursor 配置
这样排会比较稳,不容易把"模型问题""服务问题""客户端配置问题"混在一起。
如果你只想快速确认现在能不能用,可以看这一小节。
D:\\Project\\ragflowD:\\Project\\ragflow\\docker\\.envD:\\Project\\ragflow\\docker\\docker-compose.ymlD:\\Project\\ragflow\\mcp\\server\\server.pyC:\\Users\\~\\.cursor\\mcp.jsonD:\\Project\\ragflow\\docs\\guides\\accessing_admin_ui.mdD:\\Project\\ragflow\\api\\apps\\user_app.py这套链路表面上看只是 "把 RAGFlow 跑起来,再在 Cursor 里配个 MCP"。
但实际踩下来,你会发现它至少包含四层:
任何一层不通,都会表现成 "好像 MCP 有问题"。
所以以后遇到异常时,别急,也别怀疑自己哪里全都弄错了。
多数时候只是某一层状态没有对齐。
按这份文档一层一层检查,通常就能很快找到问题点。
这份文档是根据本次实际部署、修复、验证过程重新整理的。
它特别保留了这次真实发生过的关键问题:
/mcp 与 /mcp/ 的差异如果以后你继续调整:
server.py 修补逻辑建议同步更新这份文档,这样后面你自己维护会轻松很多。
`,316)])])}const p=i(h,[["render",n]]),d=JSON.parse('{"path":"/article/windows11-ragflow-deployment-mcp/","title":"Windows 11 本地部署 RAGFlow 与 Cursor MCP 完整记录 | 模型","lang":"zh-CN","frontmatter":{"title":"Windows 11 本地部署 RAGFlow 与 Cursor MCP 完整记录","createTime":"2026/03/29 18:00:00","permalink":"/article/windows11-ragflow-deployment-mcp/","sidebar":"/ai/","description":"这是一份按本次真实部署过程重新整理的操作文档~ 我会尽量把每一步都写得温柔一点、清楚一点,让你以后自己回看的时候,不需要再从聊天记录里一点一点翻找啦。 这份文档适用于: Windows 11 Docker Desktop WSL2 PowerShell 本地通过 Docker 部署 RAGFlow 在 Cursor 中通过 MCP 访问本地知识库 1....","head":[["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Windows 11 本地部署 RAGFlow 与 Cursor MCP 完整记录\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2026-03-29T05:21:46.000Z\\",\\"author\\":[]}"],["meta",{"property":"og:url","content":"https://www.simengweb.com/article/windows11-ragflow-deployment-mcp/"}],["meta",{"property":"og:site_name","content":"仲夏夜之梦"}],["meta",{"property":"og:title","content":"Windows 11 本地部署 RAGFlow 与 Cursor MCP 完整记录"}],["meta",{"property":"og:description","content":"这是一份按本次真实部署过程重新整理的操作文档~ 我会尽量把每一步都写得温柔一点、清楚一点,让你以后自己回看的时候,不需要再从聊天记录里一点一点翻找啦。 这份文档适用于: Windows 11 Docker Desktop WSL2 PowerShell 本地通过 Docker 部署 RAGFlow 在 Cursor 中通过 MCP 访问本地知识库 1...."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2026-03-29T05:21:46.000Z"}],["meta",{"property":"article:modified_time","content":"2026-03-29T05:21:46.000Z"}]]},"readingTime":{"minutes":15.7,"words":4710},"git":{"createdTime":1774761706000,"updatedTime":1774761706000,"contributors":[{"name":"祀梦","username":"","email":"3501646051@qq.com","commits":1,"avatar":"https://gravatar.com/avatar/6406a81eeddc359cf3d3ce018797689fc6d014ff06215c27d0210b42e8f5a8ab?d=retro"}]},"autoDesc":true,"filePathRelative":"notes/ai/ragflow-windows11-mcp.md","headers":[]}');export{p as comp,d as data};