【高速缓存】 RedisVL MCP 运行指南(下)

9. 连接远程 MCP 客户端

当服务器以 Streamable HTTP 或 SSE 方式运行时,您需要在 MCP 客户端配置中指定服务器 URL。

  • Streamable HTTPhttp://<host>:<port>/mcp
  • SSEhttp://<host>:<port>/sse

其中 <host><port> 应与服务器启动参数一致。若服务器绑定 0.0.0.0,客户端需使用机器的实际 IP 或域名,并确保该主机名在 Host 白名单中。

示例(Claude Desktop 配置)

json 复制代码
{
  "mcpServers": {
    "redisvl": {
      "url": "http://192.168.1.10:8000/mcp",
      "transport": "streamable-http"
    }
  }
}

10. 工具合同(Tool Contracts)

RedisVL MCP 向客户端暴露三个核心工具,以下是每个工具的请求/响应格式及行为说明。

10.1 list-indexes(发现可用索引)

无参数,返回所有配置的逻辑索引及其元数据。

响应示例

json 复制代码
{
  "indexes": [
    {
      "id": "knowledge",
      "description": "内部运行手册",
      "upsert_available": true,
      "fields": [
        { "name": "title", "type": "text" },
        { "name": "category", "type": "tag" },
        { "name": "rating", "type": "numeric" }
      ],
      "limits": { "max_limit": 25 }
    }
  ]
}
  • fields 仅列出可用于过滤的字段(标签、数值、地理等),不含向量字段和用于嵌入的文本源字段。
  • limits 仅显示显式配置的运行时限制(默认值不输出)。
  • 底层的 Redis 索引名(redis_name)不会暴露给客户端。

10.2 search-records(执行检索)

参数 类型 必填 说明
index string 多索引时必填 逻辑索引 ID,单索引时可省略
query string 检索词(向量搜索时为文本;纯向量也可为空,但一般使用查询文本)
limit integer 返回结果条数,默认使用配置的 default_limit
offset integer 分页偏移,默认为 0
filter string/object 过滤条件,可为 Redis 原生过滤字符串,或 JSON DSL 对象
return_fields array 指定返回的字段列表,默认返回所有非向量字段

请求示例(JSON DSL 过滤器)

json 复制代码
{
  "index": "knowledge",
  "query": "incident response",
  "limit": 2,
  "filter": {
    "and": [
      { "field": "category", "op": "eq", "value": "operations" },
      { "field": "rating", "op": "gte", "value": 4 }
    ]
  },
  "return_fields": ["title", "content"]
}

响应示例

json 复制代码
{
  "index": "knowledge",
  "search_type": "hybrid",
  "offset": 0,
  "limit": 2,
  "results": [
    {
      "id": "knowledge:doc-123",
      "score": 0.82,
      "score_type": "hybrid_score",
      "record": {
        "title": "EU failover runbook",
        "content": "Restore traffic after a regional failover.",
        "category": "operations",
        "rating": 5
      }
    }
  ]
}
  • search_type 为响应元数据,反映配置的检索类型。
  • 返回的 record 中不包含向量字段(为节约带宽和安全性)。
  • 如果请求的 offset + limit 超出 max_result_window,请求会被拒绝。

10.3 upsert-records(写入或更新记录)

参数 类型 必填 说明
index string 多索引时必填 逻辑索引 ID
records array 要写入的记录对象列表
id_field string 记录中用作文档 ID 的字段名,默认使用随机 ID
skip_embedding_if_present boolean 是否跳过已有向量的重新生成,默认使用配置值

请求示例

json 复制代码
{
  "index": "knowledge",
  "records": [
    {
      "doc_id": "doc-42",
      "content": "Updated operational guidance",
      "category": "operations",
      "rating": 5
    }
  ],
  "id_field": "doc_id"
}

响应

json 复制代码
{
  "index": "knowledge",
  "status": "success",
  "keys_upserted": 1,
  "keys": ["knowledge:doc-42"]
}
  • 如果索引配置了 vectorizer,且记录中不包含向量字段,服务器会使用 default_embed_text_field 指定的源字段生成向量。
  • 如果记录中已包含向量字段且 skip_embedding_if_presenttrue,则直接写入原向量。
  • 若目标索引为只读(全局或单索引),写入请求会被拒绝。

11. 搜索与写入实战示例

11.1 多索引时的发现‑检索流程

在拥有多个索引的服务器上,客户端应首先调用 list-indexes 获取可用 ID,然后针对特定 ID 执行操作:

json 复制代码
// 第一步:列出索引
// 请求:list-indexes 无参
// 响应中包含 knowledge 和 tickets

// 第二步:在 knowledge 中搜索
{
  "index": "knowledge",
  "query": "cache invalidation",
  "limit": 3,
  "return_fields": ["title", "content"]
}

11.2 纯向量检索

search.typevector 时,只需提供查询文本,服务器会自动向量化并执行 KNN 搜索:

json 复制代码
{
  "query": "cache invalidation incident",
  "limit": 3,
  "return_fields": ["title", "content"]
}

11.3 混合检索(带权重配置)

在配置中设置 search.type: hybrid 并指定 combination_method: LINEARlinear_text_weight: 0.3,则最终得分 = 0.3文本得分 + 0.7 向量得分。客户端请求与向量检索类似,但响应中的 score_type 会显示 hybrid_score

11.4 过滤器使用

原始字符串过滤器(直接传递 Redis 查询语法):

json 复制代码
{
  "query": "science",
  "filter": "@category:{science}",
  "return_fields": ["content", "category"]
}

JSON DSL 过滤器 (更结构化,支持 and/or/not 及字段操作):

json 复制代码
{
  "query": "science",
  "filter": {
    "and": [
      { "field": "category", "op": "eq", "value": "science" },
      { "field": "rating", "op": "gte", "value": 4 }
    ]
  }
}

11.5 分页与字段投影

通过 limitoffset 实现分页,return_fields 精确控制返回内容:

json 复制代码
{
  "query": "science",
  "limit": 1,
  "offset": 1,
  "return_fields": ["content", "category"]
}

12. 写入(Upsert)进阶

12.1 自动生成向量(Server‑side Embedding)

当记录中缺少向量字段时,服务器自动调用配置的向量化器,将 default_embed_text_field 指定字段的文本转为向量并写入:

json 复制代码
{
  "records": [
    {
      "content": "First document",
      "category": "science",
      "rating": 5
    }
  ]
}

12.2 使用 id_field 更新现有文档

id_field 指定的值在 Redis 中已存在,则该记录会被更新;否则创建新文档:

json 复制代码
{
  "records": [
    {
      "doc_id": "doc-1",
      "content": "Updated content",
      "category": "engineering"
    }
  ],
  "id_field": "doc_id"
}

12.3 控制向量重新生成

  • skip_embedding_if_present: true(默认):若记录中已包含 vector_field_name 字段,则直接使用该向量,不重新生成。
  • skip_embedding_if_present: false:无论记录中是否有向量,都强制重新生成(覆盖原有向量)。

通常推荐让服务器管理向量,客户端只需提供源文本,避免传输大型向量。

12.4 纯文本索引的写入

如果索引只配置了全文检索(无 vectorizervector_field_name),则 upsert-records 仅写入文本字段,无需关心向量:

json 复制代码
{
  "records": [
    {
      "content": "New FAQ entry",
      "category": "support"
    }
  ]
}

13. 故障排查指南

问题现象 可能原因 解决方案
rvl mcp 命令报缺少依赖 未安装 MCP 额外依赖 执行 pip install redisvl[mcp]
启动失败,提示"Redis index does not exist" 配置的 redis_name 在 Redis 中不存在 先在 Redis 中创建该索引(使用 RedisVL 或 FT.CREATE
启动失败,提示环境变量缺失 YAML 中使用了 ${VAR} 但未定义 设置对应环境变量,或使用 ${VAR:-default} 提供默认值
启动失败,提示向量维度不匹配 向量化模型输出维度与 schema_overrides 或 Redis 索引中的维度不一致 检查模型维度(如 text-embedding-3-small 为 1536)并修正配置
HTTP 请求被拒绝(403) Host/Origin 校验未通过 检查是否添加了客户端实际使用的域名到 allowed_hostsallowed_origins
远程客户端连接不上 绑定了 127.0.0.1 或端口被防火墙拦截 使用 --host 0.0.0.0 并确保防火墙放行;同时正确配置 Host 白名单
upsert-records 返回 forbidden 目标索引设置了 read_only: true 或全局 --read-only 检查配置,若非必要请移除只读限制
混合检索结果不符合预期 可能缺少原生混合检索支持(旧版 Redis) 升级 Redis 和 redis-py,或移除不支持的参数(如 knn_ef_runtime

14. 总结

  • 配置先行:在启动服务器前,确保所有索引已在 Redis 中创建,且字段名称与配置完全匹配。
  • 单索引 vs 多索引 :单索引配置最简洁,客户端无需指定 index;多索引适合为不同业务场景(如知识库、工单)提供统一接入,但客户端需先调用 list-indexes 进行发现。
  • 安全 :生产环境绝对不要使用 --allow-unauthenticated 绑定到公网接口。请启用 JWT 认证,并通过环境变量或配置文件严格限制 Host/Origin。
  • 向量化成本 :若向量化服务(如 OpenAI)按量计费,请在 runtime 中合理设置 skip_embedding_if_present 避免重复生成,同时限制 max_upsert_records 防止批量写入产生高昂费用。
  • 分页与性能 :通过 max_result_window 限制深度翻页,避免大偏移量查询拖垮 Redis。max_limitmax_upsert_records 则防止单次请求数据量过大。

附录:服务器启动流程图

#mermaid-svg-7t7Db6ntItzc9oxR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7t7Db6ntItzc9oxR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7t7Db6ntItzc9oxR .error-icon{fill:#552222;}#mermaid-svg-7t7Db6ntItzc9oxR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7t7Db6ntItzc9oxR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7t7Db6ntItzc9oxR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7t7Db6ntItzc9oxR .marker.cross{stroke:#333333;}#mermaid-svg-7t7Db6ntItzc9oxR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7t7Db6ntItzc9oxR p{margin:0;}#mermaid-svg-7t7Db6ntItzc9oxR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7t7Db6ntItzc9oxR .cluster-label text{fill:#333;}#mermaid-svg-7t7Db6ntItzc9oxR .cluster-label span{color:#333;}#mermaid-svg-7t7Db6ntItzc9oxR .cluster-label span p{background-color:transparent;}#mermaid-svg-7t7Db6ntItzc9oxR .label text,#mermaid-svg-7t7Db6ntItzc9oxR span{fill:#333;color:#333;}#mermaid-svg-7t7Db6ntItzc9oxR .node rect,#mermaid-svg-7t7Db6ntItzc9oxR .node circle,#mermaid-svg-7t7Db6ntItzc9oxR .node ellipse,#mermaid-svg-7t7Db6ntItzc9oxR .node polygon,#mermaid-svg-7t7Db6ntItzc9oxR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7t7Db6ntItzc9oxR .rough-node .label text,#mermaid-svg-7t7Db6ntItzc9oxR .node .label text,#mermaid-svg-7t7Db6ntItzc9oxR .image-shape .label,#mermaid-svg-7t7Db6ntItzc9oxR .icon-shape .label{text-anchor:middle;}#mermaid-svg-7t7Db6ntItzc9oxR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7t7Db6ntItzc9oxR .rough-node .label,#mermaid-svg-7t7Db6ntItzc9oxR .node .label,#mermaid-svg-7t7Db6ntItzc9oxR .image-shape .label,#mermaid-svg-7t7Db6ntItzc9oxR .icon-shape .label{text-align:center;}#mermaid-svg-7t7Db6ntItzc9oxR .node.clickable{cursor:pointer;}#mermaid-svg-7t7Db6ntItzc9oxR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7t7Db6ntItzc9oxR .arrowheadPath{fill:#333333;}#mermaid-svg-7t7Db6ntItzc9oxR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7t7Db6ntItzc9oxR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7t7Db6ntItzc9oxR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7t7Db6ntItzc9oxR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7t7Db6ntItzc9oxR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7t7Db6ntItzc9oxR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7t7Db6ntItzc9oxR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7t7Db6ntItzc9oxR .cluster text{fill:#333;}#mermaid-svg-7t7Db6ntItzc9oxR .cluster span{color:#333;}#mermaid-svg-7t7Db6ntItzc9oxR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7t7Db6ntItzc9oxR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7t7Db6ntItzc9oxR rect.text{fill:none;stroke-width:0;}#mermaid-svg-7t7Db6ntItzc9oxR .icon-shape,#mermaid-svg-7t7Db6ntItzc9oxR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7t7Db6ntItzc9oxR .icon-shape p,#mermaid-svg-7t7Db6ntItzc9oxR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7t7Db6ntItzc9oxR .icon-shape .label rect,#mermaid-svg-7t7Db6ntItzc9oxR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7t7Db6ntItzc9oxR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7t7Db6ntItzc9oxR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7t7Db6ntItzc9oxR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任一失败
全部通过
启动 rvl mcp
解析 CLI 参数与环境变量
加载 YAML 配置文件
遍历 indexes 逐个验证
启动失败,记录错误
初始化索引管理器、向量化器、工具注册表
设置传输层(stdio/HTTP/SSE)
配置传输安全(Host/Origin/JWT)
绑定地址并开始监听
服务器就绪,等待 MCP 请求


通过以上步骤,能够顺利部署并运行 RedisVL MCP 服务器,将 Redis 的强大检索能力以标准化工具的形式提供给您的智能体或应用。

相关推荐
aneasystone本尊1 小时前
Headroom 上手:wrap 与 proxy 两种接入方式实战
人工智能
老猿AI洞察1 小时前
智能视觉检测平台——完整商业化项目全功能详解
人工智能·yolo·计算机视觉·视觉检测
小和尚同志1 小时前
超级慢讯:推推 Vercel 出的 skills.sh
人工智能·aigc
wechat_Neal1 小时前
BERT 家族
人工智能·产品运营
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-07-26
人工智能·深度学习·神经网络·搜索引擎·百度
m0_626535201 小时前
图搜相关损失 softmax 相关
人工智能
rain_sxr1 小时前
从压缩行列号到源码定位:前端错误监控的 Source Map 解析与聚合
人工智能
怪奇云呼军2 小时前
闪电智能 Voice Agent 怎样根据语速、停顿和追问方式切换话术?策略引擎拆解
开发语言·人工智能·网络协议·算法·语音识别·web app
北方的银狐-Zero2 小时前
OntoL对标Palantir功能简介-视频版
人工智能·图论·本体论