检索增强生成服务

一个基于Go的MCP服务器,通过查询Pinecone向量数据库并使用Google Vertex AI嵌入,提供检索增强生成(RAG)功能,适用于文档搜索和知识提取。

  • by aravindanugonda
  • Go
  • 本地部署
  • 更新于
在 GitHub 查看 aravindanugonda/mcp-pinecone-rag

使用说明

mcp松果抹布

基于Go的 MCP服务器 它通过查询提供RAG(检索增强生成)功能 松果 使用Google Vertex AI嵌入的矢量数据库。

两种运输方式:

  • 标准 (默认)--由本地MCP主机作为子进程启动,例如。 mcp走
  • 可流式传输HTTP (--transport http)--在港口供应 远程MCP主机 (Claude Code、Antigravity、GitHub Copilot、任何通过HTTP说MCP的东西)都可以跨网络连接——请参阅 连接MCP主机

为什么谷歌嵌入不能简单地换掉: 该索引由谷歌顶点RAG引擎填充 text-embedding-005 矢量。嵌入模型定义了自己的向量空间——查询向量必须来自 相同模型 构建索引或余弦相似性是没有意义的(测量:在开源嵌入器中交换约0.5%recall@1即随机)。因此,消除对谷歌的依赖需要用开源模型重新嵌入语料库(块文本存储在Pinecone元数据中,因此这在没有原始文档的情况下是可能的——将其嵌入到一个单独的名称空间中,使当前向量保持不变)。除非这样做,否则Vertex AI仍然只需要用于查询嵌入;其他一切(搜索、关键字增强、重新登录、MCP层)都是谷歌免费的。


它的作用

显示单个MCP工具-- rag_query --LLM可以使用 三层检索管道:

User question
  → rag_query tool called by LLM
    → text-embedding-005 (Vertex AI) embeds the query → 768-dim vector
    → Pinecone vector search → top-20 candidate chunks
    → Keyword boost — exact matches for module names, error codes, filenames promoted
    → (Optional) Cross-encoder reranker → final top-K results reordered
    → chunks rendered as compact readable text and returned to LLM
  → LLM synthesizes a grounded answer
  → trajectory entry written to log file (if configured)

回收管道

三层协同工作以获得更高的精度:

图层 功能 强度
语义嵌入 通过余弦相似度查找概念上相似的文档 处理释义、同义词
关键字提升 从查询中提升包含精确域标记的文档 捕获模块名称(SFILE.C),错误代码(CEE9901),缩略语(CAS, JCL)
交叉编码器重定器 根据完整的上下文相关性对候选人进行重新排序 最终权威——最精确

关键字提取规则

与这些模式中的任何一个匹配的令牌都被视为域关键字:

模式 示例
包含一个点 SFILE.C, DENV.PL1
所有大写字母(≥2个字符,非常见英语单词) CAS, JCL, COBOL
包含数字 CEE9901, COBRT162

关键字boost被标准化为 [0, 1] 加权为 0.2,所以语义相似性总是占主导地位——当两个结果接近时,关键字只是打破了平衡。

FetchK vs TopK

矢量搜索检索 20名候选人 (FetchK=20),然后对其进行评分和排名,然后将其调整为所需值 top_k (默认值5)。获取更多的候选词可以提高关键字的效率,并使重新排名的人有更多的工作机会。


先决条件

要求 注意事项
转到1.21+ 构建二进制文件
松果账户 具有填充的矢量索引
谷歌云项目 启用Vertex AI API
服务帐户JSON密钥 带 顶点AI平台Express用户 (或 顶点AI用户)角色

松果指数要求

索引必须已填充由生成的嵌入 text-embedding-005 (768个维度)。每个向量应有的元数据字段:

字段 内容
chunk_data 块的文本内容
file_original_uri 源文档路径(例如。 gs://bucket/file.pdf)

快速开始

1.克隆和构建

git clone https://github.com/aravindanugonda/mcp-pinecone-rag.git
cd mcp-pinecone-rag
go build -o mcp-pinecone-rag .

2a。作为网络服务运行(远程MCP主机)

scripts/mcp-ctl.sh start                  # builds, starts MCP server on 0.0.0.0:7778 (reranker OFF by default)
scripts/mcp-ctl.sh start --with-reranker  # also starts the local cross-encoder reranker
scripts/mcp-ctl.sh status
scripts/mcp-ctl.sh stop

MCP端点为 http://<vm-ip>:7778/mcp (健康检查: /health).配置来自 ./.env.用以下内容覆盖绑定地址 MCP_ADDR=host:port.

Reranker可选择加入。 默认情况下,服务器以普通模式运行(嵌入+松果矢量搜索+仅关键字增强),通常在不到一秒钟的时间内响应。重新登录会为每个查询增加约20-25s的CPU限制延迟(请参阅 本地排名)--在普通硬件上,这可能会超过MCP主机自己的工具调用超时,导致客户端取消请求并退回到未接地的答案。通过 --with-reranker 到 start/restart (或设置 WITH_RERANKER=1)选择更慢、更高精度的模式。即使 RERANKER_URL 开始 .env,默认(无标志)调用会忽略它,并在没有重新链接器的情况下运行。

安全: 服务器没有身份验证。绑定到localhost,或将防火墙/云安全组级别的端口限制为需要它的特定客户端IP地址——永远不要打开它 0.0.0.0/0.

2b。配置mcp以使用此服务器(本地stdio)

在你的 mcp-go config.yaml,添加:

mcp_servers:
  - name: "pinecone-rag"
    type: "stdio"
    command: "/path/to/mcp-pinecone-rag/mcp-pinecone-rag"
    args: []
    env:
      PINECONE_API_KEY: "your-pinecone-api-key"
      GOOGLE_CLOUD_PROJECT: "your-gcp-project-id"
      GOOGLE_APPLICATION_CREDENTIALS: "/path/to/service-account.json"
      VERTEX_AI_LOCATION: "us-central1"
      PINECONE_INDEX_HOST: "your-index-host.svc.aped-xxxx.pinecone.io"
      PINECONE_NAMESPACE: ""
      RAG_TOP_K: "5"
      RERANKER_URL: "http://localhost:8090"        # optional — see Local Reranker below
      TRAJECTORY_LOG_FILE: "/tmp/trajectory.jsonl" # optional — see Trajectory Logging below

环境变量

变量 必填 描述
PINECONE_API_KEY 是 Pinecone API密钥
GOOGLE_CLOUD_PROJECT 是 启用Vertex AI的GCP项目ID
PINECONE_INDEX_HOST 是 松果索引主机URL(有或没有 https://)
GOOGLE_APPLICATION_CREDENTIALS 是* 服务帐户JSON密钥的路径
VERTEX_AI_LOCATION 无 GCP区域(默认值: us-central1)
PINECONE_NAMESPACE 否 Pinecone命名空间(默认值: "")
RAG_TOP_K 否 最终结果返回给LLM(默认值: 5,最大值: 20)
RERANKER_URL 否 本地重新登录服务的基本URL(默认:禁用)。仅在直接二进制调用或以下情况下生效 scripts/mcp-ctl.sh 与一起运行 --with-reranker/WITH_RERANKER=1 --脚本的默认值 start/restart 忽略此变量并在不重新登录的情况下运行。
TRAJECTORY_LOG_FILE 否 JSON行轨迹日志的路径(默认:禁用)
MCP_TRANSPORT 没有 stdio (默认)或 http --也可通过以下方式设置 --transport 旗帜
MCP_ADDR 否 HTTP传输的绑定地址(默认值: :7778)--也 --addr 旗帜

*或使用 gcloud auth application-default login 如果gcloud CLI可用。


本地排名

重新登录是一个 可选,选择加入 Python服务(reranker.py)使用 快速嵌入 (ONNX运行时——不需要PyTorch)在本地运行交叉编码器模型。它是 默认情况下关闭 — scripts/mcp-ctl.sh start 在没有它的情况下运行普通管道(嵌入+Pinecone+关键字boost)。通过 scripts/mcp-ctl.sh start --with-reranker 也可以将其与MCP服务器一起启动。

为什么选择加入:重新登录增加了真正的精度,但付出了真正的延迟代价——请参阅 重新排序延迟 在......下面在适度的硬件上(例如2个vCPU),一次重新排序调用可能需要大约20-25秒,这可能会超过MCP主机自己的工具调用超时,并导致客户端在接地应答到达之前取消请求。只有在确认主机的超时预算足以覆盖延迟后,才能启用它。

重要提示:启动时间

开 首次运行,fastembed下载模型权重(约280 MB bge-reranker-base).这需要30-60秒。在此窗口期间发送的查询将优雅地回退到关键字增强的结果(reranked: false 在轨迹日志中)。在后续启动时,模型将在几秒钟内从缓存中加载。

手动启动

pip install fastembed flask
python3 reranker.py

环境变量

变量 默认值 描述
RERANKER_MODEL BAAI/bge-reranker-base 拥抱脸部模型ID
RERANKER_PORT 8090 要收听的端口

支持的型号

型号 尺寸 质量
BAAI/bge-reranker-base 约280 MB 良好——英语
BAAI/bge-reranker-v2-m3 约570 MB 最佳--多语言

模型文件在首次启动时自动下载并缓存到 ~/.cache/fastembed/.

健康检查

GET http://localhost:8090/health
→ {"model": "BAAI/bge-reranker-base", "status": "ok"}

如果 /health 挂起时,重新登录器仍在处理请求(服务器是多线程的,但CPU推理每批可能需要10-20秒)。请稍候,然后重试。

重新排序延迟

BAAI/bge-reranker-base 在CPU上运行,并独立地对每个(查询、块)对进行评分。对于20名候选人和典型的区块大小,重新排名需要 10-25秒 在现代CPU上(在低核数VM上更长)。HTTP客户端超时设置为 60秒 为了适应这一点。如果您需要更低的延迟,请减少 RAG_TOP_K 或者切换到较小的型号。

并发请求被序列化。 重新登录器是一个单CPU绑定进程(fastembed/ONX运行时),因此在vCPU较少的主机上,两个同时运行 rag_query 调用不是并行运行的——它们争夺同一个CPU,而且速度都变慢了。早期版本同时发出重新登录调用,这可能会导致 两者 请求超过HTTP超时,并自动退回到未重新登录(关键字增强)的结果。Go客户端(internal/reranker/local.go)现在,使用size-1信号量对重新排序的调用进行排队,这样每个请求都能让CPU自己处理,并在自己的超时窗口内完成,但代价是排队第二秒的任何调用都会增加延迟。


轨迹记录

当 TRAJECTORY_LOG_FILE 已设置,每 rag_query 调用会附加一个JSON行,记录完整的检索管道执行情况。这是理解和提高检索质量的主要工具。

日志格式(JSON行——每个查询一个对象)

{
  "timestamp": "2026-04-04T03:42:21Z",
  "query": "AMODE 31 64 cross mode calling P64 directive",
  "fetch_k": 20,
  "top_k": 10,
  "retrieved": [
    {"id": "...", "source": "gs://bucket/file.pdf", "score": 0.936},
    ...
  ],
  "final": [
    {"id": "...", "source": "gs://bucket/file.pdf", "score": 5.27},
    ...
  ],
  "reranked": true,
  "latency_ms": 14823
}

retrieved --所有20个松果候选词在关键字增强后,按分数排序。
final --前K个结果返回给LLM(当以下情况发生时,重新分级分数将替换余弦分数 reranked: true).

有用的jq查询

# Pretty-print all entries
jq . /tmp/trajectory.jsonl

# Last query summary
tail -1 /tmp/trajectory.jsonl | jq '{query, reranked, latency_ms}'

# Check if reranking is working
jq '{query, reranked}' /tmp/trajectory.jsonl

# See how reranker reordered results (compare retrieved vs final source order)
tail -1 /tmp/trajectory.jsonl | jq '{retrieved: [.retrieved[].source], final: [.final[].source]}'

# Watch live
tail -f /tmp/trajectory.jsonl | jq .

块渲染

松果指数中存储的块为 JSON数组 (例如,来自结构化提取管道)在返回LLM之前会自动转换为紧凑、可读的项目符号线:

• EXEC (JCL Keywords) [Enterprise Developer for Eclipse (UNIX)]: Executes a program, a JCL procedure or a REXX procedure.
• DLBL (JCL Keywords) [Enterprise Developer for Eclipse (UNIX)]: Associates a DD name with a dataset.

纯文本块将原封不动地返回。此转换发生在 internal/server/server.go 并且显著减少了发送到LLM的令牌计数,同时保留了所有相关信息。


MCP工具: rag_query

说明: 搜索知识库。查询矢量数据库以查找相关文档段落。

输入架构:

参数 类型 必填 说明
query string 是 自然语言搜索查询
top_k integer 否 结果数(默认值:5,最大值:20)

项目结构

.
├── main.go                          # Entry point: env config, transport selection, stdio loop
├── reranker.py                      # Local cross-encoder reranker (fastembed + Flask, threaded)
├── scripts/
│   └── mcp-ctl.sh                   # start/stop/status for reranker + HTTP MCP server
├── internal/
│   ├── embedding/
│   │   └── google.go                # Vertex AI text-embedding-005 client (via ADC)
│   ├── protocol/
│   │   └── types.go                 # MCP JSON-RPC 2.0 protocol types
│   ├── reranker/
│   │   └── local.go                 # HTTP client for local reranker (30s timeout)
│   ├── retriever/
│   │   ├── retriever.go             # 3-layer pipeline: embed → hybrid → rerank
│   │   └── logger.go                # Trajectory logger (JSON lines)
│   ├── server/
│   │   ├── server.go                # MCP server + chunk JSON→text rendering
│   │   └── http.go                  # Streamable HTTP transport (POST /mcp, /health)
│   └── vectordb/
│       └── pinecone.go              # Pinecone query client
├── go.mod
└── go.sum

身份验证的工作原理

此服务器使用 应用程序默认凭据(ADC).何时 GOOGLE_APPLICATION_CREDENTIALS 指向服务帐户JSON密钥时,Vertex AI客户端库会自动拾取它。

服务帐户需要以下之一:

  • roles/aiplatform.expressUser --顶点AI平台快速用户(测试版)
  • roles/aiplatform.user --顶点AI用户

连接MCP主机

服务器必须在VM上以HTTP模式运行(scripts/mcp-ctl.sh start),并且VM的防火墙/安全组必须允许端口7778上的入站TCP 仅来自连接主机的IP (端点上没有身份验证)。

Claude 代码

claude mcp add --transport http pinecone-rag http://<vm-ip>:7778/mcp

或在 .mcp.json / ~/.claude.json:

{
  "mcpServers": {
    "pinecone-rag": {
      "type": "http",
      "url": "http://<vm-ip>:7778/mcp"
    }
  }
}

反重力

进入 ~/.gemini/antigravity/mcp_config.json (注意字段名称为 serverUrl,不 url):

{
  "mcpServers": {
    "pinecone-rag": {
      "serverUrl": "http://<vm-ip>:7778/mcp"
    }
  }
}

仅启动本地stdio服务器的主机

过桥 mcp-remote (需要节点/npx 在客户端机器上):

{
  "mcpServers": {
    "pinecone-rag": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://<vm-ip>:7778/mcp"]
    }
  }
}

本地stdio(同一台机器)

直接运行二进制文件,不带任何标志(stdio是默认传输)——请参阅上面的mcp-go示例。


MCP协议

实施MCP协议版本 2024-11-05 / 2025-03-26 / 2025-06-18 (客户端请求的版本在支持时会被回显)通过两种传输方式:

  • 标准 --stdin上每个请求一行JSON-RPC,stdout上一行响应
  • 可流式传输HTTP — POST /mcp 具有JSON-RPC主体→ application/json 回应;通知→ 202 Accepted;无状态(无会话ID); GET /mcp → 405 (无服务器启动的流)
方法 行为
initialize 返回服务器信息和 tools 能力
initialized 通知--已确认,未发送响应
tools/list 返回 rag_query 工具定义
tools/call 执行 rag_query:嵌入→ 混合搜索→ 重新排序→ 渲染块
ping 退货 {}

许可证

麻省理工学院