OpenViking 实战:用 MCP 打通 Claude Code 与 GLM 的跨模型上下文共享

发布时间:2026/10/12 15:41:43
OpenViking 实战:用 MCP 打通 Claude Code 与 GLM 的跨模型上下文共享 1. 为什么要在 Claude Code 和 GLM 之间共享上下文如果你同时用 Claude Code 写代码、用 GLM 做中文推理或文档整理大概率遇到过这个尴尬在 Claude Code 里聊了半小时的架构方案切到 GLM 想让它接着分析结果它完全不知道前面发生了什么你得把上下文重新贴一遍。模型之间没有共享记忆每次切换都像换了个失忆的助手。这个问题的本质是每个模型的会话上下文都锁在自己的客户端里没有一个中间层来存、来查、来复用。OpenViking 就是干这个的——它是一个面向 AI Agent 的上下文数据库支持语义检索、自动分块向量化、多格式存储。配合 MCPModel Context ProtocolClaude Code 可以把对话内容写进去、搜出来GLM 那边通过 CLI 或 HTTP API 也能读到同一份上下文。我试过把这套流程跑通之后最直观的变化是Claude Code 里讨论的接口设计切到 GLM 让它写单元测试时它能直接引用之前的字段定义和边界条件不用我再复述。跨模型上下文共享不是炫技它解决的是真实的多模型协作断点问题。这篇文章面向的是已经在用 Claude Code、同时手头有 GLM API Key 的开发者。你需要会基本的 Python 环境操作、能改 JSON 配置文件、看得懂 curl 请求。不需要你懂向量数据库原理OpenViking 把这些都封装好了。整个流程分四步装 OpenViking、配 MCP Server、接 Claude Code、验证两端消息一致。每一步我都会给可复制的配置片段和验证命令。先说清楚架构这样后面排错时你知道该查哪一层Claude Code (VSCode) │ MCP Protocol (stdio) ▼ openviking_mcp.py (MCP Server) │ HTTP API ▼ OpenViking HTTP Server (localhost:8765) │ ▼ Vector DB Local Storage ▲ │ CLI / HTTP API GLM (命令行检索或脚本调用)Claude Code 通过 MCP 协议调用你写的 MCP ServerMCP Server 再通过 HTTP 请求 OpenViking 的本地服务。GLM 那边不直接支持 MCP所以走 CLI 或 HTTP API 读同一份数据。两条路径最终落到同一个向量库这就是上下文共享的实现方式。2. 前置准备装好 OpenViking 并拿到可用的 API Key这一节的目标是让 OpenViking 服务在本地跑起来并且 embedding 和 VLM 都能正常工作。OpenViking 本身不提供 embedding 模型它需要你接一个外部的 embedding API。这里用智谱的 embedding-3 模型中文语义检索效果比较稳。2.1 环境检查和安装先确认 Python 版本OpenViking 要求 3.8 以上python --version然后安装 OpenViking 和 MCP 依赖pip install openviking pip install mcp装完验证一下pip show openviking预期输出里能看到Version: 0.1.17或更高版本。如果 pip 装的时候报编译错误大概率是缺少 C 编译工具链Windows 上装个 Visual Studio Build Tools 就行。2.2 创建配置目录和主配置文件OpenViking 的配置放在用户目录下的.openviking文件夹里# Windows mkdir %USERPROFILE%\.openviking # macOS/Linux mkdir ~/.openviking然后创建主配置文件ov.conf。Windows 路径是C:\Users\YourUsername\.openviking\ov.confmacOS/Linux 是~/.openviking/ov.conf。内容如下{ embedding: { dense: { provider: openai, api_base: https://open.bigmodel.cn/api/paas/v4/embeddings, api_key: 你的_API_KEY, model: embedding-3, dimension: 2048 } }, vlm: { provider: openai, api_base: https://open.bigmodel.cn/api/paas/v4, api_key: 你的_API_KEY, model: glm-4v } }这里的api_key需要你去智谱 AI 开放平台注册账号在 API Keys 页面创建一个密钥。embedding 模型选embedding-3维度 2048中文支持好。VLM 部分配的是glm-4v用于处理图像类资源如果你暂时不处理图片这部分可以先留着不影响。注意api_base的地址要写完整embedding 的路径是/api/paas/v4/embeddingsVLM 的路径是/api/paas/v4两者不一样别写混了。2.3 创建 CLI 配置文件CLI 工具需要知道 OpenViking 服务的地址创建ovcli.conf# Windows echo {url: http://localhost:8765} %USERPROFILE%\.openviking\ovcli.conf # macOS/Linux echo {url: http://localhost:8765} ~/.openviking/ovcli.conf2.4 启动 OpenViking 服务临时启动测试用关掉终端就停python -m openviking serve --port 8765后台启动推荐Windows PowerShellStart-Process -WindowStyle Hidden python -ArgumentList -m openviking serve --port 8765macOS/Linux 后台启动nohup python -m openviking serve --port 8765 启动后验证服务是否正常curl http://localhost:8765/health预期输出{status:ok}。如果这一步就失败了先别往下走检查端口 8765 是否被占用# Windows netstat -ano | findstr :8765 # macOS/Linux lsof -i :8765有占用就换端口或者把占用进程杀掉。服务跑起来之后OpenViking 这一层就准备好了。3. 可复制配置写 MCP Server 并接入 Claude CodeOpenViking 本身不带 MCP Server 模块需要你自己写一个桥接脚本。这个脚本的作用是接收 Claude Code 通过 MCP 协议发来的工具调用请求转成 HTTP 请求发给 OpenViking 服务再把结果返回给 Claude Code。3.1 创建 MCP Server 脚本文件路径放在C:\Users\YourUsername\.openviking\openviking_mcp.pymacOS/Linux 对应~/.openviking/openviking_mcp.py。完整代码如下#!/usr/bin/env python3 OpenViking MCP Server for Claude Code integration. import asyncio import json import logging import tempfile import subprocess from pathlib import Path from typing import Any from datetime import datetime from urllib.request import Request, urlopen from urllib.error import URLError from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) OPENVIKING_URL http://localhost:8765 server Server(openviking-server) def http_post(path: str, data: dict) - dict: url f{OPENVIKING_URL}{path} body json.dumps(data).encode(utf-8) req Request(url, databody, headers{Content-Type: application/json}) with urlopen(req, timeout30) as response: return json.loads(response.read().decode(utf-8)) def http_get(path: str) - dict: url f{OPENVIKING_URL}{path} req Request(url) with urlopen(req, timeout30) as response: return json.loads(response.read().decode(utf-8)) server.list_tools() async def list_tools() - list[Tool]: return [ Tool( nameov_save_context, descriptionSave conversation context to OpenViking, inputSchema{ type: object, properties: { content: {type: string, description: Content to save}, title: {type: string, description: Title (optional)} }, required: [content] } ), Tool( nameov_search, descriptionSearch OpenViking using semantic search, inputSchema{ type: object, properties: { query: {type: string, description: Search query}, limit: {type: integer, default: 5} }, required: [query] } ), Tool( nameov_health, descriptionCheck OpenViking server health, inputSchema{type: object, properties: {}} ), Tool( nameov_list, descriptionList resources in OpenViking, inputSchema{ type: object, properties: { uri: {type: string, default: viking://resources} } } ) ] server.call_tool() async def call_tool(name: str, arguments: dict[str, Any]) - list[TextContent]: try: if name ov_health: result http_get(/health) return [TextContent(typetext, textjson.dumps({ status: ok, server: result }, indent2))] elif name ov_save_context: content arguments.get(content, ) title arguments.get(title, ) if not title: title fconversation_{datetime.now().strftime(%Y%m%d_%H%M%S)} with tempfile.NamedTemporaryFile( modew, suffix.md, deleteFalse, encodingutf-8 ) as f: f.write(f# {title}\n\n{content}) temp_path f.name try: result subprocess.run( [python, -m, openviking, add-resource, temp_path, --to, fviking://resources/claude_conversations/{title}, --reason, Auto-saved from Claude Code MCP, --wait], capture_outputTrue, textTrue, timeout60 ) Path(temp_path).unlink(missing_okTrue) if result.returncode 0: return [TextContent(typetext, textjson.dumps({ status: success, title: title, location: fviking://resources/claude_conversations/{title} }, indent2))] else: return [TextContent(typetext, textjson.dumps({ status: error, error: result.stderr }, indent2))] except Exception as e: Path(temp_path).unlink(missing_okTrue) raise elif name ov_search: query arguments.get(query, ) limit arguments.get(limit, 5) result subprocess.run( [python, -m, openviking, find, query, --uri, viking://resources, --limit, str(limit)], capture_outputTrue, textTrue, timeout30 ) return [TextContent(typetext, textjson.dumps({ status: success if result.returncode 0 else error, query: query, results: result.stdout or result.stderr }, indent2, ensure_asciiFalse))] elif name ov_list: uri arguments.get(uri, viking://resources) result subprocess.run( [python, -m, openviking, ls, uri], capture_outputTrue, textTrue, timeout30 ) return [TextContent(typetext, textjson.dumps({ status: success if result.returncode 0 else error, uri: uri, output: result.stdout or result.stderr }, indent2, ensure_asciiFalse))] else: return [TextContent(typetext, textfUnknown tool: {name})] except Exception as e: logger.error(fError in {name}: {e}, exc_infoTrue) return [TextContent(typetext, textjson.dumps({ status: error, tool: name, error: str(e) }, indent2))] async def main(): logger.info(Starting OpenViking MCP Server...) try: health http_get(/health) logger.info(fConnected to OpenViking: {health}) except Exception as e: logger.error(fCannot connect to OpenViking: {e}) async with stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, server.create_initialization_options() ) if __name__ __main__: asyncio.run(main())这个脚本定义了四个 MCP 工具ov_save_context保存上下文、ov_search语义搜索、ov_health健康检查、ov_list列出资源。Claude Code 会根据你的自然语言指令自动选择调用哪个工具。3.2 配置 Claude Code 的 MCP 设置找到 Claude Code 的配置文件位置WindowsC:\Users\YourUsername\AppData\Roaming\Claude\claude_desktop_config.jsonmacOS~/Library/Application Support/Claude/claude_desktop_config.jsonLinux~/.config/Claude/claude_desktop_config.json如果文件不存在就创建它写入以下内容{ mcpServers: { openviking: { command: python, args: [ C:/Users/YourUsername/.openviking/openviking_mcp.py ], env: { OPENVIKING_CONFIG_FILE: C:/Users/YourUsername/.openviking/ov.conf } } } }三个关键点必须对齐command是 Python 可执行文件路径如果在 PATH 里直接写python就行、args里是 MCP 脚本的绝对路径、env里指向主配置文件。路径用正斜杠/或双反斜杠\\别用单反斜杠JSON 会转义出错。注意如果你用的是 Claude Code CLI 而不是桌面版MCP 配置在~/.claude/settings.json或项目根目录的.mcp.json里格式类似但字段名可能不同以你本地版本为准。3.3 重启并确认 MCP 加载完全关闭 VSCode 再重新打开Claude Code 启动时会自动加载 MCP Server。你可以在 Claude Code 的对话里输入「检查 OpenViking 状态」如果配置正确它会调用ov_health工具并返回服务状态。如果 Claude Code 没有识别到 MCP 工具先手动跑一下脚本看有没有报错python C:/Users/YourUsername/.openviking/openviking_mcp.py正常的话会输出日志然后挂起等待 stdio 输入。如果报ModuleNotFoundError: No module named mcp说明 MCP 依赖没装到当前 Python 环境里重新pip install mcp。4. 验证请求确认两端消息一致配置写完不算完得实际验证 Claude Code 写进去的上下文GLM 那边能搜到、内容一致。这一节给完整的验证步骤。4.1 验证 OpenViking 服务层先确认服务活着curl http://localhost:8765/health返回{status:ok}就对了。4.2 从 Claude Code 写入上下文在 Claude Code 对话框里输入把这段对话保存到 OpenViking我们在设计一个用户认证模块采用 JWT refresh token 方案access token 有效期 15 分钟refresh token 有效期 7 天存储用 Redis。Claude Code 会调用ov_save_context工具把内容写到viking://resources/claude_conversations/下面。返回结果里会有status: success和保存路径。4.3 用 CLI 验证写入结果在终端里列出资源确认内容进去了python -m openviking ls viking://resources/claude_conversations应该能看到刚才保存的那条记录。然后做语义搜索python -m openviking find JWT token 有效期 --uri viking://resources --limit 3预期能搜到刚才保存的认证模块设计内容。这一步验证的是 OpenViking 的向量化和检索链路是通的。4.4 从 GLM 侧读取同一份上下文GLM 不直接支持 MCP所以走 CLI 或 HTTP API。最简单的方式是写个搜索脚本# Windows echo echo off ov_search.bat echo python -m openviking find %1 --uri viking://resources --limit 5 ov_search.bat # macOS/Linux echo python -m openviking find $1 --uri viking://resources --limit 5 ov_search.sh chmod x ov_search.sh用的时候ov_search.bat 认证模块的 token 方案把搜出来的内容贴到 GLM 对话里GLM 就能基于这份上下文继续工作。你也可以用 Python 直接调 HTTP APIimport requests response requests.post(http://localhost:8765/api/v1/search/find, json{ query: JWT refresh token 有效期, target_uri: viking://resources, limit: 5 }) print(response.json())4.5 一致性核对验证两端消息一致的关键是Claude Code 写入的原文和 GLM 侧搜出来的内容语义上要对得上。具体操作在 Claude Code 里保存一段带明确标识的文本比如「项目代号 Falcon数据库用 PostgreSQL 15缓存用 Redis 7」。然后在 GLM 侧搜「Falcon 项目用什么数据库」看返回结果里有没有「PostgreSQL 15」。如果有说明跨模型上下文共享链路是通的。我实测下来embedding-3 对中文技术术语的检索准确率不错但如果你搜的是很短的英文缩写比如只搜「JWT」可能会召回多条不相关记录。这时候把查询写具体一点比如「JWT access token 过期时间」命中率会明显提升。5. 常见报错排查401、local proxy failed、reading choices这一节列几个实际跑的时候最容易撞上的错误以及对应的排查路径。5.1 401 Unauthorized现象add-resource或find返回 401日志里提示 authentication failed。原因ov.conf里的api_key无效或者api_base写错了。排查# 直接测 embedding API 是否可用 curl -X POST https://open.bigmodel.cn/api/paas/v4/embeddings \ -H Authorization: Bearer 你的_API_KEY \ -H Content-Type: application/json \ -d {model:embedding-3,input:test}如果这个 curl 也返回 401说明 Key 本身有问题去智谱平台重新生成一个。如果 curl 通了但 OpenViking 还报 401检查ov.conf里api_key字段有没有多余空格或引号嵌套错误。5.2 local proxy failed / connection refused现象MCP Server 启动时报Cannot connect to OpenViking server或者 Claude Code 调用工具时返回local proxy failed。原因OpenViking HTTP 服务没跑起来或者端口不对。排查curl http://localhost:8765/health如果连不上先确认服务进程在不在# Windows tasklist | findstr python # macOS/Linux ps aux | grep openviking服务没跑就重新启动。如果服务在跑但 curl 不通检查ovcli.conf里的 URL 和实际启动端口是否一致。MCP 脚本里的OPENVIKING_URL也要和这个端口对齐。5.3 reading choices / JSON 解析错误现象Claude Code 调用 MCP 工具后返回error reading choices或 JSON 解析失败。原因MCP Server 返回的内容不是合法 JSON或者 subprocess 调用的 CLI 输出里混了非 JSON 内容。排查手动跑一次 CLI 命令看输出格式python -m openviking find test --uri viking://resources --limit 3如果 CLI 输出里带了进度条、日志行或者 ANSI 颜色码MCP 脚本直接把它塞进 JSON 就会解析失败。解决办法是在 subprocess 调用时加--quiet参数如果 CLI 支持或者在脚本里对输出做清洗只取 JSON 部分。5.4 OAuth / token 过期现象之前能用过了一段时间突然报 OAuth 相关错误。原因智谱 API Key 有有效期或者账户余额不足。排查登录智谱开放平台检查 API Key 状态和账户余额。如果 Key 过期了重新生成一个更新ov.conf里的api_key然后重启 OpenViking 服务。5.5 Claude Code 看不到 MCP 工具现象重启 VSCode 后Claude Code 里输入「检查 OpenViking 状态」它没有调用ov_health而是直接用自然语言回复。原因MCP 配置没被加载或者脚本路径不对。排查检查claude_desktop_config.json的 JSON 格式是否合法可以用在线 JSON 校验工具过一遍。确认args里的脚本路径是绝对路径且文件存在。然后看 Claude Code 的 MCP 日志通常在输出面板里选 Claude Code 频道里面会打印 MCP Server 的启动日志和报错信息。6. 把上下文共享接进日常编码流程跑通验证之后接下来是怎么把它用顺。这里给几个实际场景的操作方式。6.1 在 Claude Code 里自动保存关键对话你可以在 Claude Code 的对话里直接说「把这段保存到 OpenViking」它会调用ov_save_context。更省事的做法是在项目根目录放一个CLAUDE.md里面写一条规则每当讨论完一个架构决策或接口设计自动调用 ov_save_context 保存摘要标题用「决策-模块名-日期」格式。这样 Claude Code 会在合适的时候自动保存不用你每次手动提醒。6.2 在 GLM 侧做检索增强GLM 那边没有 MCP但你可以把搜索脚本包一层做成一个简单的检索增强流程。比如写个 Python 脚本先搜 OpenViking 拿到相关上下文拼进 prompt 再发给 GLMimport requests def ask_glm_with_context(question, api_key): # 先从 OpenViking 搜上下文 search_resp requests.post(http://localhost:8765/api/v1/search/find, json{ query: question, target_uri: viking://resources, limit: 3 }) context search_resp.json().get(results, ) # 拼进 prompt 发给 GLM prompt f参考以下上下文\n{context}\n\n问题{question} glm_resp requests.post( https://open.bigmodel.cn/api/paas/v4/chat/completions, headers{Authorization: fBearer {api_key}}, json{ model: glm-4, messages: [{role: user, content: prompt}] } ) return glm_resp.json()这个模式的好处是GLM 不需要原生支持 MCP你通过脚本把上下文注入进去就行。Claude Code 写进去的内容GLM 这边通过检索拿到跨模型上下文共享就闭环了。6.3 批量导入文档构建知识库如果你有一堆本地文档想让两个模型都能查批量导入for file in docs/*.pdf; do python -m openviking add-resource $file \ --to viking://resources/docs \ --wait done导入后Claude Code 里搜「文档里关于 XX 的内容」GLM 侧用同样的查询也能搜到同一批结果。6.4 多模型协作的实际工作流一个我常用的流程在 Claude Code 里做代码实现和重构每完成一个模块就保存上下文摘要切到 GLM 做代码审查或写文档时先搜相关模块的上下文让 GLM 基于 Claude Code 的实现细节来审查。这样两个模型的输出是连贯的不会出现「Claude Code 改了接口但 GLM 还在按旧接口写测试」的情况。如果你需要更稳定的长期编码和 Agent 协作能力可以考虑用 Coding Plan 来管理多模型调用配额和路由。接入文档里有完整的 MCP 配置示例和 API 说明API Key 在控制台的 API Keys 页面生成。模型对话入口可以用来快速验证 GLM 侧的检索增强效果不用每次都写脚本。整套流程跑下来核心就三件事OpenViking 服务活着、MCP Server 配置对、两端用同一个向量库。把这三件事盯住跨模型上下文共享就能稳定工作。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询