文章目录
1. MCP 概述与背景
1.1 什么是 MCP
- MCP(Model Context Protocol)是一种开放协议,标准化了 AI 应用(主机)与上下文与工具提供方(服务器)之间的通信方式,基于 JSON-RPC 2.0,同 LSP 在 IDE 生态中的作用类似,为 LLM 与数据源/工具之间提供统一接口。
1.2 起源与动机
- 由 Anthropic 于 2024 年 11 月提出,旨在解决过去为每个数据源/工具编写专用连接器的 N×M 问题,实现模型与任意数据源的“即插即用”集成。
1.3 为什么要用 MCP
- 简化 AI 应用接入工具与数据源的流程,加速开发效率;
- 提供模型无关(model-agnostic)的扩展能力,使不同 LLM 均可复用同一套服务;
- 避免绕过人机界面,直接以协议方式高效获取上下文,提升自动化程度。
1.4 典型应用场景
- IDE 智能助理(如 Zed、Replit 集成 MCP 获取实时代码上下文)
- 企业内部知识库查询(如 Block、Apollo 通过 MCP 访问 CRM、文档库)
- 自然语言数据库查询(AI2SQL 等将自然语言转为 SQL 并通过 MCP 执行)
2. MCP 架构与协议要素
2.1 三方角色
- Host:LLM 应用,发起连接与上下文请求;
- Client:嵌入 Host 内的连接器,负责协议握手与消息编解码,比如:Claude Desktop,Cursor IDE,Dive等等;
- Server:提供资源(Resources)、提示(Prompts)与工具(Tools)等功能的后端服务。
2.2 基础协议:JSON-RPC 2.0
- 所有消息采用 JSON-RPC 2.0 格式,支持请求、通知、响应及批处理;
- 会话保持状态(stateful),支持能力协商与会话内多次交互。
2.3 核心功能
- Resources:提供上下文数据(如文件片段、数据库记录);
- Prompts:预定义模板,供 Host 拼装提示;
- Tools:模型可调用的函数(如执行外部 API);
3. MCP 常用传输协议及对比
3.1 stdio 传输
- 客户端以子进程方式启动 Server,双向通过 stdin/stdout 交换 JSON-RPC 消息;
- 以换行分隔消息,保证纯粹 MCP 消息流。
3.2 Streamable HTTP(HTTP+SSE)
- Server 暴露同一 HTTP 端点,客户端用 POST 发送请求,用 SSE(text/event-stream)或 JSON 响应;
- 支持可恢复的 SSE 流,客户端需显式发送 CancelledNotification 取消请求。
3.3 自定义 & 扩展
- 支持插件式添加 WebSocket、MessagePack 等传输;
- 客户端应优先支持 stdio,必要时再集成 HTTP。
3.4 与其它协议对比
- 与 OpenAI Function Calling:MCP 更通用、支持发现与流式交互;
- 与 LSP:MCP 专注于 AI 上下文而非编程语言服务;
- 与 OpenAI Plugins/Google Bard Extensions:MCP 去中心、开发者自定义程度更高。
4. 使用 Go + Redis 实现 MCP 服务
本节将以实际项目为例,详细讲解如何用 Go 语言和 Redis 构建一个符合 MCP(Model Context Protocol)规范的服务端。我们将逐步剖析项目结构、配置、核心代码实现,并结合 MCP 协议的工具注册与调用机制,帮助读者理解如何将 Redis 能力以“工具(Tool)”形式暴露给 AI 应用。
4.1 项目结构与依赖
项目采用 go-zero(版本>= 1.8.3) 框架,目录结构清晰,主要分为以下几部分:
mcp-redis/
├── etc/ # 配置文件
│ └── config-api.yaml
├── internal/
│ ├── config/ # 配置结构体定义
│ ├── handler/ # MCP工具注册与实现
│ │ ├── redis/ # Redis相关工具实现
│ │ └── toolshandler.go
│ └── svc/ # 服务上下文
├── main.go # 启动入口
主要依赖:
github.com/zeromicro/go-zero
:高性能 Go 微服务框架,提供 Redis 客户端、配置、日志等基础能力。github.com/zeromicro/go-zero/mcp
:MCP 协议实现,支持工具注册、JSON-RPC 消息编解码等。
4.2 配置文件说明
配置文件 etc/config-api.yaml
统一管理 Redis 连接参数和 MCP 服务端口:
Redis:
Host: localhost:46379
Type: node
Pass: "123456"
McpConf:
Name: mcp-redis
Host: 0.0.0.0
Port: 8083
4.3 服务启动流程
main.go
是服务启动入口,主要流程如下:
- 解析配置文件,初始化 Redis 和 MCP 服务端。
- 创建
ServiceContext
,用于依赖注入。 - 注册所有 Redis 工具(Tool)。
- 启动 MCP Server,监听指定端口,等待客户端连接。
核心代码片段:
func main() {
flag.Parse()
logx.DisableStat()
var c config.Config
conf.MustLoad(*configFile, &c)
mcpSrv := mcp.NewMcpServer(c.McpConf)
defer mcpSrv.Stop()
svcCtx := svc.NewServiceContext(c)
handler.NewToolsetHandler(mcpSrv, svcCtx)
fmt.Printf("Starting MCP Server on %s:%d\n", c.McpConf.Host, c.McpConf.Port)
mcpSrv.Start()
}
4.4 工具注册与实现
所有 Redis 操作都以“工具(Tool)”的形式注册到 MCP Server,便于 LLM 客户端通过标准协议动态发现和调用。
4.4.1 工具注册
internal/handler/toolshandler.go
负责批量注册所有 Redis 工具:
func (t *ToolsetHandler) registerTool() {
t.mcpSrv.RegisterTool(redis.RedisSet(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisGet(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisDel(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisLPush(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisRPush(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisLpop(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisRpop(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisLrange(t.svcCtx))
t.mcpSrv.RegisterTool(redis.RedisLlen(t.svcCtx))
}
每个工具都实现了 mcp.Tool
接口,包含名称、描述、输入参数模式(InputSchema)和实际处理函数(Handler)。
4.4.2 工具实现举例
以 RedisSet
为例,完整代码见 internal/handler/redis/string.go
:
func RedisSet(svcCtx *svc.ServiceContext) mcp.Tool {
redisSetHandler := func(ctx context.Context, params map[string]any) (any, error) {
var req struct {
Key string `json:"key"`
Value string `json:"value"`
Expire float64 `json:"expire"`
}
err := mcp.ParseArguments(params, &req)
if err != nil {
return nil, fmt.Errorf("参数解析错误: %v", err)
}
err = svcCtx.Redis.SetexCtx(ctx, req.Key, req.Value, int(req.Expire))
if err != nil {
return nil, fmt.Errorf("Redis写入失败: %v", err)
}
return nil, nil
}
return mcp.Tool{
Name: "redis_set",
Description: "Set a Redis key",
InputSchema: mcp.InputSchema{
Properties: map[string]any{
"key": {"type": "string", "description": "Redis key"},
"value": {"type": "string", "description": "Redis value"},
"expire": {"type": "number", "description": "Expire time in seconds"},
},
Required: []string{"key", "value"},
},
Handler: redisSetHandler,
}
}
其他如 RedisGet
、RedisDel
、RedisLPush
、RedisLrange
等工具实现方式类似,均通过 mcp.Tool
结构体描述,并将 Redis 操作封装为 Handler。
4.4.3 工具自动发现与调用
MCP 客户端可通过协议自动发现所有已注册工具及其参数定义,调用时只需按 JSON-RPC 格式传递参数即可。例如:
{
"jsonrpc": "2.0",
"method": "redis_set",
"params": {"key": "foo", "value": "bar", "expire": 60},
"id": 1
}
5. 时序图 / 流程图
以下以“设置 Redis 键值对”为例,展示 MCP 客户端与服务端的交互流程:
流程说明:
- 客户端通过 MCP 协议发送
redis_set
请求。 - 服务端解析参数,调用 Redis 客户端执行写入。
- Redis 返回结果,服务端封装为 JSON-RPC 响应返回客户端。
6. 使用指南
6.1 启动 MCP Redis 服务
确保本地 Redis 服务已启动,并配置好 etc/config-api.yaml
,然后运行:
go run main.go
控制台输出:
Starting MCP Server on 0.0.0.0:8083
6.2 连接客户端示例
可使用支持 MCP 协议的客户端(如 Claude Desktop、Cursor、Zed 等),配置连接到 localhost:8083
,本文主要是用Cursor IDE。
Cursor IDE配置流程如下:
- 点击Cursor Settings
- 点击MCP
- 点击Add new global MCP server
- 再旧的配置文件中添加下面的内容:
"redis": {
"name": "Redis MCP",
"description": "Redis Management Control Panel",
"command": "npx",
"args": ["mcp-remote", "http://localhost:8083/sse"]
}
- 保存
就能发现Cursor开始有调用Redis的工具的服务了,Redis的工具的服务下面也会开始产生log。
绿色的就代表ok了。
6.3 示例交互
写入键值对:
- 在Cursor中输入:
set foo bar expire 60
会弹出是否调用Redis的工具的服务。
- 点击Run tool
就设置成功了
获取键值:
- 在Cursor中输入:
get foo
会弹出是否调用Redis的工具的服务。
- 点击Run tool
就能获取redis中的值了
7. 结语与参考
本项目完整演示了如何用 Go + Redis 快速实现一个标准 MCP 服务端,将 Redis 能力以“工具”形式暴露给 AI 应用。通过 MCP 协议,AI 应用可动态发现、调用后端工具,极大提升了上下文集成与自动化能力。推荐进一步阅读 MCP 官方规范与社区实践,探索更多应用场景与扩展方式。
如需完整代码与部署脚本,请参考本项目仓库。