Skip to content

Conversation

@undertaker86001
Copy link
Collaborator

@undertaker86001 undertaker86001 commented Jun 11, 2025

Ⅰ. Describe what this PR did

Related to ISSUE#2259

Ⅱ. Does this pull request fix one issue?

Ⅲ. Why don't you add test cases (unit test/integration test)?

Ⅳ. Describe how to verify it

Ⅴ. Special notes for reviews

@CLAassistant
Copy link

CLAassistant commented Jun 11, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ kaori-seasons
✅ johnlanni
❌ undertaker86001


undertaker86001 seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@lingma-agents
Copy link

lingma-agents bot commented Jun 11, 2025

新增Redis MCP服务器支持及端到端测试

变更概述

新功能

  • 新增Redis MCP服务器实现:
    • plugins/golang-filter/mcp-server/servers/redis/server.go中实现完整的Redis工具接口,支持getsetdelkeysexistsexpirettlpublish等Redis操作
    • 通过RedisConfig结构体配置Redis连接参数(地址、用户名、密码、数据库等)
    • config.go中注册Redis服务器支持,扩展MCP服务器类型

测试更新

  • 新增Redis MCP服务器端到端测试:
    • test/e2e/conformance/tests/go-wasm-redis-mcpserver.go包含对setgetdelttl等操作的验证
    • 配置文件go-wasm-redis-mcpserver.yaml定义了Redis服务部署和Ingress路由规则

配置调整

  • redis.go中补充Redis客户端接口实现:
    • 新增DelKeysExistsExpireTTL等方法的客户端封装
变更统计
  • 📁 修改文件: 6 个文件

  • ✅ 新增代码: +843 行

  • ❌ 删除代码: -1 行

变更文件
文件路径 变更说明
plugins/​golang-filter/​mcp-server/​config.​go 新增Redis服务器的依赖导入和注册
plugins/​golang-filter/​mcp-server/​servers/​redis/​server.​go 实现完整的Redis MCP服务器功能及工具接口
plugins/​golang-filter/​mcp-session/​common/​redis.​go 补充Redis客户端缺失的接口实现
test/​e2e/​conformance/​tests/​go-wasm-redis-mcpserver.​go 新增Redis MCP服务器端到端测试用例
test/​e2e/​conformance/​tests/​go-wasm-redis-mcpserver.​yaml 定义Redis服务部署和Ingress路由配置

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

@codecov-commenter
Copy link

codecov-commenter commented Jun 11, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 46.05%. Comparing base (ef31e09) to head (7743614).
Report is 559 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #2399       +/-   ##
===========================================
+ Coverage   35.91%   46.05%   +10.14%     
===========================================
  Files          69       81       +12     
  Lines       11576    13018     +1442     
===========================================
+ Hits         4157     5995     +1838     
+ Misses       7104     6678      -426     
- Partials      315      345       +30     

see 78 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@lingma-agents lingma-agents bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 代码评审报告

🎯 评审意见概览
严重度 数量 说明
🔴 Blocker 1 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。
🟠 Critical 2 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。
🟡 Major 3 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。
🟢 Minor 0 次要问题,酬情优化。例如:代码格式不规范或注释缺失。

总计: 6 个问题

⚠️ 需要立即关注的阻断性问题

plugins/golang-filter/mcp-session/common/redis.go

📋 评审意见详情
💡 代码实现建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
🔹 plugins/golang-filter/mcp-server/servers/redis/server.go (3 💬)
🔹 plugins/golang-filter/mcp-session/common/redis.go (1 💬)
🔹 test/e2e/conformance/tests/go-wasm-ai-security-guard.go (1 💬)
🔹 test/e2e/conformance/tests/go-wasm-redis-mcpserver.go (1 💬)
🚀 架构设计建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍1. 代码重复问题:多个工具处理函数存在相似结构

在新增的redis/server.go文件中,多个工具处理函数(如HandleGetTool、HandleSetTool等)的结构高度相似,均包含参数解析、错误处理和客户端调用的流程。这种重复代码增加了维护成本,当需要修改通用逻辑时(如错误处理方式),需逐个修改所有函数。建议将公共逻辑抽象为工具辅助函数或基类,提升代码复用性和可维护性。

📌 关键代码

func HandleGetTool(client *common.RedisClient) common.ToolHandlerFunc {
  return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    params := struct {
      Key string `json:"key"`
    }{}
    if err := request.ParseParams(&params); err != nil {
      return nil, fmt.Errorf("invalid parameters: %w", err)
    }
    // 具体逻辑
  }
}
func HandleSetTool(client *common.RedisClient) common.ToolHandlerFunc {
  return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    params := struct {
      Key        string `json:"key"`
      Value      string `json:"value"`
      Expiration int    `json:"expiration,omitempty"`
    }()
    if err := request.ParseParams(&params); err != nil {
      return nil, fmt.Errorf("invalid parameters: %w", err)
    }
    // 具体逻辑
  }
}

⚠️ 潜在风险

重复代码导致维护成本上升,修改逻辑时容易遗漏部分函数,引发不一致问题。

🔍2. 测试覆盖不足:未包含关键错误场景验证

新增的测试文件test/e2e/conformance/tests/go-wasm-redis-mcpserver.go中,测试用例主要验证了正常操作(如Set/Get/Del),但缺少对以下错误场景的覆盖:

  1. 配置缺失或无效(如未指定Redis地址)
  2. 连接失败(如Redis服务不可达)
  3. 密钥不存在时的异常处理(如TTL对不存在的key)
  4. 参数校验失败(如Set命令未提供value)
    这些场景未被覆盖可能导致实际使用中出现未捕获的异常。

📌 关键代码

// 测试用例仅包含正常操作和部分TTL验证
testcases := []http.Assertion{
  // Set、Get、Del等正常操作
  // TTL测试仅检查响应长度
}

⚠️ 潜在风险

未覆盖的错误场景可能导致系统在异常情况下崩溃或返回错误结果。

🔍3. 安全风险:Keys命令可能引发数据暴露

Redis的Keys工具允许通过通配符匹配所有键(如Keys "*"),这在生产环境中可能导致敏感数据暴露或性能问题。虽然Keys命令本身是Redis原生功能,但作为MCP Server的接口暴露给外部调用时,需增加安全限制:

  1. 限制匹配模式的复杂度(如禁止"*")
  2. 添加调用频率限制
  3. 在文档中明确警告该命令的潜在风险

📌 关键代码

// KeysSchema允许任意pattern输入
func KeysSchema() string {
  return `{ "type": "object", "properties": {"pattern": {"type": "string"}}, "required": ["pattern"] }`
}

⚠️ 潜在风险

恶意调用Keys命令可能暴露系统中所有Redis键,导致敏感数据泄露或服务性能下降。

🔍4. Redis客户端创建方式可能导致资源浪费

在RedisConfig.NewServer函数中,每次调用都会创建新的Redis客户端实例:

redisClient, err := common.NewRedisClient(redisConfig)

若该客户端未被复用(如单例模式),可能导致重复连接和资源浪费。需确认common.RedisClient是否实现了连接池或单例管理。

📌 关键代码

redisClient, err := common.NewRedisClient(redisConfig)
if err != nil {
  return nil, fmt.Errorf("failed to create Redis client: %w", err)
}

⚠️ 潜在风险

频繁创建客户端可能增加连接开销,影响系统性能和稳定性。

🔍5. 依赖管理问题:Redis客户端库缺失导入

在修改的common/redis.go文件中,删除了Redis客户端库的导入(github.com/go-redis/redis/v8),可能导致编译失败。虽然用户已标注该文件存在"缺失的Redis客户端库导入"问题,需确认是否已通过其他方式解决依赖问题。

📌 关键代码

// 缺少redis/v8导入
import (
  "time"
  "github.com/envoyproxy/envoy/contrib/golang/common/go/api"
)

⚠️ 潜在风险

缺失依赖将导致代码无法编译,影响部署。

审查详情
📒 文件清单 (6 个文件)
新增: 4 个文件
📝 变更: 2 个文件

✅ 新增文件:

  • plugins/golang-filter/mcp-server/servers/redis/server.go
  • test/e2e/conformance/tests/go-wasm-ai-security-guard.go
  • test/e2e/conformance/tests/go-wasm-redis-mcpserver.go
  • test/e2e/conformance/tests/go-wasm-redis-mcpserver.yaml

📝 变更文件:

  • plugins/golang-filter/mcp-server/config.go
  • plugins/golang-filter/mcp-session/common/redis.go

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。


}

api.LogDebugf("RedisConfig ParseConfig: %+v", config)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

避免在日志中记录敏感配置信息

🟠 Critical | 🔒 Security Hotspots

📋 问题详情

ParseConfig函数的日志记录了整个配置对象(包括可能包含密码的字段),存在敏感信息泄露风险。

💡 解决方案

添加过滤敏感字段的日志处理函数:

+func filterConfig(config map[string]any) map[string]any {
+    filtered := make(map[string]any)
+    for k, v := range config {
+        if k == "password" || k == "secret" {
+            filtered[k] = "******"
+        } else {
+            filtered[k] = v
+        }
+    }
+    return filtered
+}
-
-api.LogDebugf("RedisConfig ParseConfig: %+v", config)
+api.LogDebugf("RedisConfig ParseConfig: %+v", filterConfig(config))

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Comment on lines +309 to +312
exp := time.Duration(0)
if params.Expiration > 0 {
exp = time.Duration(params.Expiration) * time.Second

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

添加Set命令的过期时间合法性校验

🟡 Major | 🐞 Bugs

📋 问题详情

HandleSetTool函数未验证expiration参数是否为非负值,可能导致Redis设置无效的过期时间。

💡 解决方案

添加过期时间非负校验:

+if params.Expiration < 0 {
+    return nil, fmt.Errorf("invalid parameters: expiration must be non-negative")
+}
-if params.Expiration > 0 {
-    exp = time.Duration(params.Expiration) * time.Second
-}
+exp := time.Duration(params.Expiration) * time.Second

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Comment on lines +427 to +462
func HandleTTLTool(client *common.RedisClient) common.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
params := struct {
Key string `json:"key"`
}{}

if err := request.ParseParams(&params); err != nil {
return nil, fmt.Errorf("invalid parameters: %w", err)
}
ttl, err := client.TTL(params.Key)
if err != nil {
return &mcp.CallToolResult{
Output: fmt.Sprintf("Error getting TTL: %v", err),
}, nil
}

if ttl < 0 {
if ttl == -1 {
return &mcp.CallToolResult{
Output: "Key exists but has no expiration",
}, nil
} else {
return &mcp.CallToolResult{
Output: "Key does not exist",
}, nil
}

}

return &mcp.CallToolResult{
Output: fmt.Sprintf("%d", int(ttl.Seconds())),
}, nil
}
}

// Publish工具处理函数
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

修复HandleTTLTool函数中未处理键不存在的情况

🟡 Major | 🐞 Bugs

📋 问题详情

在HandleTTLTool函数中,当Redis键不存在时(TTL返回-2),当前逻辑仅处理了-1(无过期时间)和非负值(有剩余时间)情况,导致键不存在时返回错误信息不准确。

💡 解决方案

修改HandleTTLTool函数的TTL判断逻辑,明确处理-2(键不存在)的情况:

- if ttl < 0 {
-     if ttl == -1 {
-         return &mcp.CallToolResult{Output: "Key exists but has no expiration"}, nil
-     } else {
-         return &mcp.CallToolResult{Output: "Key does not exist"}, nil
-     }
- }
+ switch {
+ case ttl == -1:
+     return &mcp.CallToolResult{Output: "Key exists but has no expiration"}, nil
+ case ttl == -2:
+     return &mcp.CallToolResult{Output: "Key does not exist"}, nil
+ default:
+     // 正常处理剩余时间
+ }

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Comment on lines +280 to +323
// Del 删除一个或多个key
func (r *RedisClient) Del(keys ...string) (int64, error) {
result, err := r.client.Del(r.ctx, keys...).Result()
if err != nil {
return 0, fmt.Errorf("failed to delete keys: %w", err)
}
return result, nil
}

// Keys 返回匹配指定模式的所有key
func (r *RedisClient) Keys(pattern string) ([]string, error) {
result, err := r.client.Keys(r.ctx, pattern).Result()
if err != nil {
return nil, fmt.Errorf("failed to get keys: %w", err)
}
return result, nil
}

// Exists 检查key是否存在
func (r *RedisClient) Exists(keys ...string) (int64, error) {
result, err := r.client.Exists(r.ctx, keys...).Result()
if err != nil {
return 0, fmt.Errorf("failed to check keys: %w", err)
}
return result, nil
}

// Expire 设置key的过期时间
func (r *RedisClient) Expire(key string, expiration time.Duration) (bool, error) {
result, err := r.client.Expire(r.ctx, key, expiration).Result()
if err != nil {
return false, fmt.Errorf("failed to set expiration: %w", err)
}
return result, nil
}

// TTL 返回key的剩余生存时间
func (r *RedisClient) TTL(key string) (time.Duration, error) {
result, err := r.client.TTL(r.ctx, key).Result()
if err != nil {
return 0, fmt.Errorf("failed to get TTL: %w", err)
}
return result, nil
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

缺失的Redis客户端库导入导致编译错误

🔴 Blocker | 🐞 Bugs

📋 问题详情

删除了github.com/go-redis/redis/v8的导入语句,但新增的Redis方法如Del/Keys/Expire依赖该包。这会导致编译失败,因为r.client的类型无法识别,且缺少Redis客户端方法的定义。

💡 解决方案

需要恢复github.com/go-redis/redis/v8的导入以保证客户端方法可用:

@@ -6,7 +6,7 @@
-import (
+import (
+	"github.com/go-redis/redis/v8"
  "time"
  "github.com/envoyproxy/envoy/contrib/golang/common/go/api"
)

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

}}, Response: http.AssertionResponse{ExpectedResponse: http.Response{
StatusCode: 200,
ContentType: http.ContentTypeApplicationJson,
Body: []byte(`"很抱歉,我无法回答您的问题"`),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

无效的JSON响应体格式

🟠 Critical | 🐞 Bugs

📋 问题详情

case4的期望响应体"很抱歉..."缺少外层大括号,导致JSON解析失败。有效的JSON必须是对象或数组结构,当前格式无法被正确解析。

💡 解决方案

修改为有效JSON格式:

-Body: []byte(`"很抱歉,我无法回答您的问题"`),
+Body: []byte(`{"message":"很抱歉,我无法回答您的问题"}`),

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Comment on lines +87 to +90
JsonBodyMatcher: func(t *testing.T, body []byte) bool {
// TTL值会不断变化,所以我们只检查是否能获取到TTL,不检查具体值
return len(body) > 0
}}}}, {Meta: http.AssertionMeta{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TTL响应验证不够严格

🟡 Major | 🧹 Code Smells

📋 问题详情

TTL测试用例仅检查响应长度>0,未验证JSON结构。可能导致非预期格式的响应被误认为成功,建议添加结构校验。

💡 解决方案

添加结构化验证:

-return len(body) > 0
+var resp struct{ Result struct{ Output int64 } }
+return json.Unmarshal(body, &resp) == nil && resp.Result.Output >= 0

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

@johnlanni
Copy link
Collaborator

johnlanni commented Jun 12, 2025

@undertaker86001 Please add the license head. And the commit user information is also problematic, the CLA check has not passed.

@undertaker86001
Copy link
Collaborator Author

@undertaker86001请添加许可证头。提交的用户信息也有问题,CLA 检查未通过。

Sorry, I just saw this, I will change it soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants