GBrain MCP 集成技术日志

April 26, 2026

GBrain MCP 集成技术日志


目录


1. 项目背景与目标

2. 环境准备

3. Phase 1: 底层验证

4. Phase 2: MCP 集成

5. Phase 3: 优化与持久化

6. 核心问题与解决方案

7. 最终工作流程

8. 文件修改清单

9. 附录: 常用命令速查




1. 项目背景与目标


1.1 什么是 GBrain


GBrain 是 Garry Tan 开发的开源个人知识大脑,基于 PostgreSQL + pgvector 构建,提供:


- 知识图谱: 页面之间的自动链接提取

- 向量搜索: 语义相似度检索

- 全文搜索: PostgreSQL FTS (Full-Text Search)

- 混合搜索: RRF (Reciprocal Rank Fusion) 融合关键词 + 向量结果

- MCP 协议: 通过 Model Context Protocol 与 AI Agent 集成


1.2 集成目标


将 GBrain 通过 MCP 协议集成到 Hermes Agent 中,使 Hermes 能够:


1. 持久化存储对话中的重要信息到知识图谱

2. 通过语义搜索检索历史知识

3. 自动提取实体关系构建知识网络


1.3 平台挑战


挑战说明
Bun WASM 限制`bun build` 的二进制在 ARM64 上无法运行 WASM,必须用 `bun src/cli.ts`
中文支持PostgreSQL `english` 分词器不支持中文
网络代理通过 mihomo (127.0.0.1:7890) 访问外部 API



2. 环境准备


2.1 已安装依赖



# 系统级
- Debian trixie (aarch64)
- Ollama 0.6.6 (本地 LLM 推理)
- Tailscale 1.96.4 (异地组网)
- mihomo (HTTP 代理 127.0.0.1:7890)

# 应用级
- Bun (JavaScript 运行时)
- Node.js / npm
- Python 3 + Hermes Agent v0.11.0

2.2 GBrain 安装



# 克隆仓库
git clone https://github.com/garrytan/gbrain.git ~/gbrain
cd ~/gbrain

# 安装依赖
bun install

# 验证安装
bun src/cli.ts --help

2.3 嵌入模型配置


由于无法使用 OpenAI 官方 API,改用 BitFun 提供的 Qwen3-Embedding-0.6B


参数
维度1024
API 端点`https://api.openbitfun.com/v1`
费用免费



3. Phase 1: 底层验证


3.1 目标


验证 GBrain 核心功能在 ARM64 + 自定义嵌入模型下正常工作。


3.2 修改嵌入层


文件: src/core/embedding.ts


原始代码硬编码了 OpenAI 的 text-embedding-3-large (3072 维),需要修改为支持环境变量配置:



// 修改前: 硬编码 OpenAI 配置
const DEFAULT_MODEL = 'text-embedding-3-large';
const DEFAULT_DIMS = 3072;

// 修改后: 支持环境变量
const DEFAULT_MODEL = process.env.GBRAIN_EMBED_MODEL || 'text-embedding-3-large';
const DEFAULT_DIMS = parseInt(process.env.GBRAIN_EMBED_DIMENSIONS || '3072', 10);
const DEFAULT_BASE_URL = process.env.GBRAIN_EMBED_BASE_URL;
const DEFAULT_API_KEY = process.env.GBRAIN_EMBED_API_KEY;

3.3 修改 Schema 维度


文件: src/core/pglite-schema.ts



// 修改前
embedding vector(3072),
model TEXT NOT NULL DEFAULT 'text-embedding-3-large',

// 修改后
embedding vector(1024),
model TEXT NOT NULL DEFAULT 'Qwen/Qwen3-Embedding-0.6B',

3.4 初始化数据库



export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"

cd ~/gbrain
bun src/cli.ts init

输出:


Brain ready at /home/harryfan/.gbrain/brain.pglite
0 pages. Engine: PGLite (local Postgres).

3.5 验证核心功能



# 添加测试页面
echo "# GBrain 树莓派测试

这是一个测试页面。" | bun src/cli.ts put raspberry-pi-test

# 查看统计
bun src/cli.ts stats
# Pages: 1, Chunks: 1, Embedded: 1

# 搜索测试
bun src/cli.ts search "测试"
# [0.3040] raspberry-pi-test -- # GBrain 树莓派测试

3.6 Phase 1 结论


✅ GBrain 在 ARM64 + Qwen Embedding 下工作正常




4. Phase 2: MCP 集成


4.1 目标


将 GBrain 作为 MCP Server 接入 Hermes Agent。


4.2 MCP 协议简介


Model Context Protocol (MCP) 是 Anthropic 提出的标准协议,允许 AI Agent 通过 stdio 或 SSE 与外部工具通信:



┌─────────────┐     stdio      ┌─────────────────┐
│ Hermes Agent │ ◄────────────► │ GBrain MCP Server│
│  (Client)   │   JSON-RPC     │   (stdio mode)   │
└─────────────┘                └─────────────────┘

4.3 创建 MCP 启动脚本


文件: ~/gbrain/start-mcp.sh



#!/bin/bash
export PATH="$HOME/.bun/bin:$PATH"
export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"

# 清理可能残留的进程
pkill -9 -f "bun src/cli.ts serve" 2>/dev/null
sleep 1

cd "$HOME/gbrain"
exec bun src/cli.ts serve --stdio 2>/dev/null

> 关键: exec 确保子进程替换 shell 进程,2>/dev/null 防止日志干扰 MCP 协议解析。


4.4 配置 Hermes MCP


文件: ~/.hermes/config.yaml



mcp:
  gbrain:
    command: /home/harryfan/gbrain/start-mcp.sh
    timeout: 180
    connect_timeout: 120

> 注意: connect_timeout 必须设长(120s),因为 PGLite 首次初始化需要 ~30 秒。


4.5 发现 MCP 工具



# 在 Hermes 中调用
from hermes_agent.tools.mcp_tool import discover_mcp_tools

tools = await discover_mcp_tools()
print(f"发现 {len(tools)} 个工具")

输出:


发现 45 个 GBrain 工具
连接耗时: 0.8s

工具列表包括:

- get_stats - 获取数据库统计

- list_pages - 列出所有页面

- get_page - 获取单个页面

- put_page - 创建/更新页面

- query - 混合搜索

- search_keyword - 关键词搜索

- search_vector - 向量搜索

- ... (共 45 个)


4.6 验证工具调用



# 测试 get_stats
result = await handle_function_call("get_stats", {})
# {"pages": 6, "chunks": 6, "embedded": 2, "links": 1, "tags": 9}

# 测试 put_page
result = await handle_function_call("put_page", {
    "slug": "hermes-mcp-integration",
    "content": "# Hermes Agent MCP Integration\n\nIntegration verified..."
})
# {"slug": "hermes-mcp-integration", "status": "created_or_updated"}

# 测试 query
result = await handle_function_call("query", {
    "query": "MCP integration"
})
# 返回搜索结果列表

4.7 关键问题: 进程残留


现象: 每次 MCP 调用后,bun src/cli.ts serve 进程未自动关闭,导致后续调用卡死。


原因: Hermes 的 _run_on_mcp_loop 没有正确管理子进程生命周期。


临时解决方案:


# 每次调用前清理残留进程
pkill -9 -f "bun src/cli.ts serve"

长期方案: Phase 3a 创建管理脚本。


4.8 Phase 2 结论


✅ MCP 集成成功,45 个工具可用

⚠️ 进程残留问题待优化(Phase 3 解决)




5. Phase 3: 优化与持久化


5.1 3a: 进程管理脚本


问题: MCP 调用后 GBrain 进程残留


解决方案: 创建管理脚本


文件: ~/gbrain/gbrain-manager.sh



#!/bin/bash
GBRAIN_DIR="$HOME/gbrain"
PIDFILE="/tmp/gbrain-mcp.pid"
export PATH="$HOME/.bun/bin:$PATH"
export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"

case "$1" in
    start)
        pkill -f "bun src/cli.ts serve" 2>/dev/null
        sleep 1
        cd "$GBRAIN_DIR"
        bun src/cli.ts serve --stdio > /dev/null 2>&1 &
        echo $! > "$PIDFILE"
        echo "Started (PID: $(cat $PIDFILE))"
        sleep 2
        ;;
    stop)
        [ -f "$PIDFILE" ] && kill -9 $(cat "$PIDFILE") 2>/dev/null
        rm -f "$PIDFILE"
        pkill -9 -f "bun src/cli.ts serve" 2>/dev/null
        echo "Stopped"
        ;;
    status)
        if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") 2>/dev/null; then
            echo "Running (PID: $(cat $PIDFILE))"
        else
            echo "Not running"
        fi
        ;;
    *) echo "Usage: $0 {start|stop|status}" ;;
esac

使用:


~/gbrain/gbrain-manager.sh start   # 启动
~/gbrain/gbrain-manager.sh stop    # 停止
~/gbrain/gbrain-manager.sh status  # 查看状态

5.2 3b: 持久化环境变量


文件: ~/.profile



# ── GBrain 环境变量 ─────────────────────────────────────────────
export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"
export PATH="$HOME/.bun/bin:$PATH"
# ────────────────────────────────────────────────────────────────

文件: ~/.gbrain/env.sh (供脚本 source 使用)



export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"
export PATH="$HOME/.bun/bin:$PATH"

5.3 3c: 中文搜索支持


问题: PostgreSQL english 分词器不支持中文


分析:


-- english 分词器行为
SELECT to_tsvector('english', '中文知识图谱测试');
-- 结果: '' (空,所有中文被过滤)

-- simple 分词器行为
SELECT to_tsvector('simple', '中文知识图谱测试');
-- 结果: ''中文知识图谱测试':1' (整句作为一个词)

核心问题: simple 分词器对中文按整句分词,导致子串搜索失败:


SELECT to_tsvector('simple', '中文知识图谱测试') 
       @@ plainto_tsquery('simple', '知识');
-- 结果: false ("知识" 不等于 "中文知识图谱测试")

解决方案: 双重策略


1. 全局替换 englishsimple(支持中英文混合)

2. CJK Fallback: 当 tsvector 无结果时,自动使用 ILIKE 匹配


修改 1: src/core/pglite-schema.ts



-- 修改前
setweight(to_tsvector('english', coalesce(NEW.title, '')), 'A')

-- 修改后
setweight(to_tsvector('simple', coalesce(NEW.title, '')), 'A')

修改 2: src/core/pglite-engine.ts



// 修改搜索 SQL
ts_rank(cc.search_vector, websearch_to_tsquery('simple', $1))

// 添加 CJK Fallback
if (rows.length === 0 && /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query)) {
  // 使用 ILIKE 进行子串匹配
  const likePattern = `%${query}%`;
  // ... ILIKE 查询
}

效果:

- 英文查询: websearch_to_tsquery('simple', query) → 精确匹配

- 中文查询: tsvector 失败 → 自动 fallback 到 ILIKE '%关键词%'


5.4 3d: 宽松 Dedup 阈值


问题: 小数据集下搜索结果容易被过滤为空


分析: GBrain 的 4 层去重管道过于严格:


层级原始值修改后说明
类型多样性比例0.60.8同类型页面占比上限
每页最大块数23每页保留的 chunk 数

文件: src/core/search/dedup.ts



// 修改前
const COSINE_DEDUP_THRESHOLD = 0.85;
const MAX_TYPE_RATIO = 0.6;
const MAX_PER_PAGE = 2;

// 修改后
const COSINE_DEDUP_THRESHOLD = 0.92;
const MAX_TYPE_RATIO = 0.8;
const MAX_PER_PAGE = 3;

5.5 3e: 验证与备份


测试验证:



# 中文搜索
$ bun src/cli.ts search "知识"
[0.5000] chinese-knowledge -- # 中文知识图谱测试

# 英文搜索
$ bun src/cli.ts search "Graph"
[0.3040] english-knowledge -- # English Knowledge Graph Test

# 混合搜索
$ bun src/cli.ts search "test"
[0.3040] english-knowledge -- # English Knowledge Graph Test

备份:


~/.gbrain-backup-phase3-20260426-163533/
├── pglite-schema.ts      # FTS simple 分词器
├── pglite-engine.ts      # simple 搜索 + CJK fallback
├── dedup.ts              # 宽松阈值
├── start-mcp.sh          # MCP 启动脚本
├── gbrain-manager.sh     # 进程管理脚本
├── config.yaml           # Hermes MCP 配置
└── MODIFICATIONS.md      # 修改摘要



6. 核心问题与解决方案


6.1 问题汇总表


#问题原因解决方案
2嵌入模型不兼容硬编码 OpenAI 3072 维修改 embedding.ts 支持环境变量
3向量维度不匹配Schema 硬编码 3072修改 pglite-schema.ts 为 1024
4首次启动超时PGLite 初始化需 30sconnect_timeout 设为 120s
5进程残留MCP 客户端未正确关闭子进程启动脚本添加 pkill 清理
6中文搜索无结果english 分词器过滤中文改为 simple + CJK ILIKE fallback
7小数据集搜索为空dedup 阈值过于严格放宽阈值 (0.85→0.92, 2→3)
8MCP SDK 兼容性mcp 1.6.0 内部 API 变更重装 mcp 包修复

6.2 关键调试技巧



# 1. 检查 GBrain 进程
ps aux | grep "bun src/cli.ts"

# 2. 强制清理残留
pkill -9 -f "bun src/cli.ts serve"

# 3. 查看 PGLite 数据
ls -la ~/.gbrain/brain.pglite/

# 4. 直接查询数据库
bun -e "
import { PGlite } from '@electric-sql/pglite';
const db = await PGlite.create({ dataDir: '/home/harryfan/.gbrain/brain.pglite' });
const result = await db.query('SELECT slug, title FROM pages');
console.log(result.rows);
"

# 5. 检查 MCP 工具
python3 -c "
import asyncio
from hermes_agent.tools.mcp_tool import discover_mcp_tools
tools = asyncio.run(discover_mcp_tools())
print(f'{len(tools)} tools discovered')
"



7. 最终工作流程


7.1 日常使用流程


graph TD A[用户对话] --> B{需要存储知识?} B -->|是| C[调用 put_page] C --> D[GBrain 自动分块] D --> E[生成向量嵌入] E --> F[提取链接关系] B -->|否| G{需要检索知识?} G -->|是| H[调用 query/search] H --> I[混合搜索 RRF] I --> J[返回相关页面] G -->|否| K[正常对话]

7.2 Hermes 调用 GBrain 的两种方式


方式 1: handle_function_call (推荐)



from hermes_agent.model_tools import handle_function_call

# 存储知识
result = await handle_function_call("put_page", {
    "slug": "project-idea-2026",
    "content": "# 项目想法\n\n这是一个新的项目构思..."
})

# 检索知识
results = await handle_function_call("query", {
    "query": "项目构思",
    "limit": 5
})

方式 2: GBrain CLI



# 直接操作数据库
bun src/cli.ts put my-page --content "# 标题\n\n内容"
bun src/cli.ts search "关键词"
bun src/cli.ts query "问题描述"
bun src/cli.ts stats

7.3 数据流



用户输入
    │
    ▼
┌─────────────┐
│ Hermes Agent │
│  (推理决策)  │
└──────┬──────┘
       │
       ├────────────┬────────────┐
       ▼            ▼            ▼
   ┌───────┐   ┌────────┐   ┌─────────┐
   │put_page│   │ query  │   │get_stats│
   └───┬───┘   └───┬────┘   └────┬────┘
       │           │              │
       ▼           ▼              ▼
   ┌──────────────────────────────────┐
   │      GBrain MCP Server           │
   │  ┌─────────┐    ┌─────────────┐  │
   │  │ PGLite  │◄──►│  pgvector   │  │
   │  │ (本地)   │    │ (HNSW 索引) │  │
   │  └────┬────┘    └─────────────┘  │
   │       │                           │
   │       ▼                           │
   │  ┌─────────────┐  ┌───────────┐  │
   │  │ FTS (simple)│  │ 知识图谱   │  │
   │  │ + ILIKE     │  │ (links)   │  │
   │  └─────────────┘  └───────────┘  │
   └──────────────────────────────────┘
       │
       ▼
   返回结果给 Hermes

7.4 启动顺序



# 1. 确保环境变量已加载
source ~/.profile

# 2. 启动 GBrain MCP (如果需要独立运行)
~/gbrain/gbrain-manager.sh start

# 3. Hermes 会自动通过 start-mcp.sh 启动 GBrain
# 无需手动干预



8. 文件修改清单


8.1 GBrain 源码修改


文件修改类型说明
`src/core/pglite-schema.ts`修改FTS `english` → `simple`, 维度 3072 → 1024
`src/core/pglite-engine.ts`修改搜索 `english` → `simple`, 添加 CJK fallback
`src/core/search/dedup.ts`修改放宽去重阈值

8.2 新建文件


文件说明
`~/gbrain/gbrain-manager.sh`进程管理脚本
`~/.gbrain/env.sh`环境变量加载脚本
`~/.gbrain-backup-phase3-*/`配置备份目录

8.3 Hermes 配置


文件修改
`~/.profile`添加 GBrain 环境变量



9. 附录: 常用命令速查


9.1 GBrain CLI



# 数据库管理
bun src/cli.ts init                    # 初始化数据库
bun src/cli.ts stats                   # 查看统计
bun src/cli.ts doctor                  # 健康检查

# 页面操作
bun src/cli.ts list                    # 列出页面
bun src/cli.ts get               # 获取页面
bun src/cli.ts put  --content "..."  # 创建/更新页面
bun src/cli.ts delete            # 删除页面

# 搜索
bun src/cli.ts search         # 关键词搜索
bun src/cli.ts query         # 混合搜索 (RRF)
bun src/cli.ts ask           # query 别名

# 导入/导出
bun src/cli.ts import             # 导入目录
bun src/cli.ts export                  # 导出为 markdown
bun src/cli.ts sync                    # Git 同步

# MCP
bun src/cli.ts serve --stdio           # 启动 MCP server

9.2 进程管理



# GBrain 管理
~/gbrain/gbrain-manager.sh start       # 启动
~/gbrain/gbrain-manager.sh stop        # 停止
~/gbrain/gbrain-manager.sh status      # 状态

# 强制清理
pkill -9 -f "bun src/cli.ts serve"

9.3 Hermes MCP 工具调用



# Python 异步调用
from hermes_agent.model_tools import handle_function_call

# 获取统计
stats = await handle_function_call("get_stats", {})

# 列出页面
pages = await handle_function_call("list_pages", {"limit": 10})

# 获取页面
page = await handle_function_call("get_page", {"slug": "my-page"})

# 创建页面
result = await handle_function_call("put_page", {
    "slug": "new-page",
    "content": "# Title\n\nContent here"
})

# 混合搜索
results = await handle_function_call("query", {
    "query": "搜索内容",
    "limit": 5
})

# 关键词搜索
results = await handle_function_call("search_keyword", {
    "query": "关键词",
    "limit": 5
})

9.4 环境变量



# 必须设置
export GBRAIN_EMBED_MODEL="Qwen/Qwen3-Embedding-0.6B"
export GBRAIN_EMBED_DIMENSIONS="1024"
export GBRAIN_EMBED_BASE_URL="https://api.openbitfun.com/v1"
export GBRAIN_EMBED_API_KEY="sk-xxx"
export PATH="$HOME/.bun/bin:$PATH"

# 可选调试
export GBRAIN_SEARCH_DEBUG="1"         # 搜索调试日志



总结


本次集成成功将 GBrain 知识大脑通过 MCP 协议接入 Hermes Agent,主要成果:


1. 完整的中文支持: 通过 simple 分词器 + CJK ILIKE fallback 实现中英文混合搜索

2. ARM64 兼容: 解决 Bun WASM 限制,使用源码直接运行

3. 自定义嵌入模型: 集成 BitFun Qwen3-Embedding-0.6B (1024维)

4. 进程管理: 创建管理脚本解决进程残留问题

5. 配置持久化: 环境变量写入 ~/.profile,重启后自动生效


下一步建议:

- 测试大规模数据下的性能表现

- 配置自动同步机制(Git / 定时任务)

- 探索 GBrain 的知识图谱可视化功能




*日志生成时间: 2026-04-26*

*GBrain 版本: v0.22.0*

*Hermes 版本: v0.11.0*