Skip to content

Conversation

@johnlanni
Copy link
Collaborator

Ⅰ. Describe what this PR did

Summary

This pull request introduces a new Wasm-Go plugin, mcp-router, which enables dynamic routing for MCP (Model Context Protocol) tools/call requests. This is a key component for enabling tool composition from multiple backend MCP servers, allowing a single gateway endpoint to act as an aggregator for a diverse set of tools.

Background

Currently, an MCP Server instance is typically mapped to a single backend service. This one-to-one relationship makes it difficult to create a unified MCP endpoint that exposes tools from various independent services. To address this limitation and provide a more flexible tool-calling experience for AI agents, we need a mechanism to route tool calls to their appropriate backend servers dynamically.

Solution

The mcp-router plugin acts as an intelligent filter for MCP traffic. Its primary responsibilities are:

  1. Parsing Tool Names: It intercepts tools/call requests and inspects the name parameter. It's designed to recognize a composite tool name format: server-name/tool-name.

  2. Dynamic Rerouting: Based on the extracted server-name, the plugin looks up a pre-configured routing table to find the correct domain and path for the target backend MCP server. It then modifies the :authority and :path headers of the request to reroute it accordingly.

  3. Request Body Rewriting: After determining the correct route, the plugin rewrites the request body, stripping the server-name/ prefix from the tool name. This ensures that the backend MCP server receives a standard tools/call request with a tool name it can understand.

This approach, combined with the toolSet feature in the mcp-server plugin, allows users to define a single API endpoint that lists tools from multiple sources, and this mcp-router ensures that calls to those tools are correctly delivered to their respective backends.

Example Scenario: Combining mcp-server and mcp-router

To achieve a complete tool aggregation solution, mcp-router works in tandem with the mcp-server plugin's toolSet feature.

1. Configure the mcp-server with a toolSet

First, you create a new route (e.g., /mcp-toolsets/my-tool-a) and apply an mcp-server plugin configuration that defines a toolSet. This toolSet aggregates tools from different servers.

# mcp-server plugin config for a toolset endpoint
toolSet:
  name: "my-aggregated-tools"
  serverTools:
  - serverName: random-user-server
    tools:
    - get-user
  - serverName: rest-amap-server
    tools:
    - maps-geo

When a tools/list request is sent to this endpoint, it will return a combined list of tools, with their names prefixed by their original server name:

Request to toolSet endpoint:

curl http://<gateway>/mcp-toolsets/my-tool-a -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}'

Response from toolSet endpoint:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "random-user-server/get-user",
        ...
      },
      {
        "name": "rest-amap-server/maps-geo",
        ...
      }
    ]
  }
}

2. Configure the mcp-router

Next, you apply the mcp-router plugin globally or on a relevant route to handle the subsequent tools/call requests.

# mcp-router plugin config
servers:
- name: random-user-server
  domain: mcp.example.com
  path: /mcp-servers/mcp-random-user-server
- name: rest-amap-server
  domain: mcp.example.com
  path: /mcp-servers/mcp-rest-amap-server

3. Making a tools/call Request

When the client (e.g., an AI Agent) wants to call a tool from the list, it sends a tools/call request to the toolSet endpoint.

curl http://<gateway>/mcp-toolsets/my-tool-a -d '{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "rest-amap-server/maps-geo",
    "arguments": { ... }
  }
}'

The mcp-router intercepts this request, sees the rest-amap-server/ prefix, and automatically reroutes the request to mcp.example.com/mcp-servers/mcp-rest-amap-server, ensuring the call reaches the correct backend.

Ⅱ. 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

@johnlanni johnlanni requested review from CH3CHO and rinfx as code owners June 12, 2025 11:09
@lingma-agents
Copy link

lingma-agents bot commented Jun 12, 2025

新增 mcp-router 插件实现 MCP 工具调用动态路由功能

变更概述

新功能

  • mcp-router Wasm 插件:实现 MCP tools/call 请求的动态路由功能,支持根据工具名前缀(如 server-name/tool-name)将请求转发到不同后端 MCP 服务器
  • 路由配置能力:新增 servers 配置字段,定义后端服务器域名和路径映射关系
  • 请求头/体改造:自动修改 :authority:path 请求头,以及工具名参数(去除服务器前缀)

配置调整

  • 新增插件配置规范,包含 servers 数组配置项(name/domain/path 必填字段)
  • 支持通过 JSON 配置文件声明多服务器路由规则

依赖更新

  • 引入 github.com/tidwall/sjson 等依赖库实现 JSON 体修改
  • 依赖 proxy-wasm-go-sdkhigress-plugins 框架

文档更新

  • 新增英文和中文双语 README 文档(含配置示例和工作流程说明)
变更统计
  • 📁 修改文件: 5 个文件

  • ✅ 新增代码: +412 行

  • ❌ 删除代码: -0 行

变更文件
文件路径 变更说明
plugins/​wasm-go/​mcp-filters/​mcp-router/​README.​md 新增英文版插件功能说明文档,包含配置规范、工作原理和使用示例
plugins/​wasm-go/​mcp-filters/​mcp-router/​README_​ZH.​md 新增中文版插件功能说明文档,包含配置规范、工作原理和使用示例
plugins/​wasm-go/​mcp-filters/​mcp-router/​go.​mod 定义 Go 项目依赖关系,包含 Higress 插件框架和第三方库
plugins/​wasm-go/​mcp-filters/​mcp-router/​go.​sum 生成依赖校验文件确保依赖完整性
plugins/​wasm-go/​mcp-filters/​mcp-router/​main.​go 实现路由插件核心逻辑,包括配置解析、请求拦截、头部/体修改和路由转发

💡 小贴士

与 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 12, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 46.02%. Comparing base (ef31e09) to head (ffdfd26).
Report is 569 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #2409       +/-   ##
===========================================
+ Coverage   35.91%   46.02%   +10.11%     
===========================================
  Files          69       81       +12     
  Lines       11576    13020     +1444     
===========================================
+ Hits         4157     5993     +1836     
+ Misses       7104     6681      -423     
- Partials      315      346       +31     

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 0 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。
🟠 Critical 1 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。
🟡 Major 1 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。
🟢 Minor 0 次要问题,酬情优化。例如:代码格式不规范或注释缺失。

总计: 2 个问题

📋 评审意见详情
💡 代码实现建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
🔹 plugins/wasm-go/mcp-filters/mcp-router/main.go (2 💬)
🚀 架构设计建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍1. 遍历服务器配置列表可能导致性能问题

ProcessRequest 函数中,每次请求都会遍历整个 servers 配置列表以查找匹配的服务器名称。如果配置包含大量服务器条目,这会导致 O(n) 的时间复杂度,可能在高并发场景下显著增加处理延迟。建议将 servers 配置转换为以 name 为键的 map 结构,实现 O(1) 的查找效率,从而提升性能。

📌 关键代码

for _, server := range routerConfig.Servers {
    if server.Name == serverName {
        targetServer = &server
        break
    }
}

⚠️ 潜在风险

在高负载或服务器配置数量较多时,可能导致请求处理延迟增加,影响系统吞吐量。

🔍2. 缺乏核心路由逻辑的单元测试

该 PR 中未包含针对路由核心逻辑的单元测试,例如验证服务器名称匹配、请求头修改、请求体参数修改等关键操作的正确性。缺乏测试可能导致潜在逻辑漏洞未被发现,尤其是在配置变更或边界条件(如无效工具名称格式、未匹配的服务器名称)下。

⚠️ 潜在风险

核心路由逻辑未经过充分验证,可能在生产环境中出现路由错误、请求体参数未正确修改或请求路由到错误服务器等问题,导致服务不可用或数据不一致。

🔍3. 依赖管理引入冗余间接依赖

go.mod 文件中,多个依赖被标记为 // indirect(例如 github.com/davecgh/go-spewgithub.1485827954.workers.dev/stretchr/testify 等),但部分依赖可能并非真正间接使用。例如,github.com/stretchr/testify 可能未被直接引用,但被标记为间接依赖,这可能引入冗余的依赖项。建议检查并清理未被直接使用的间接依赖,以减少依赖树复杂性和潜在版本冲突风险。

📌 关键代码

github.com/davecgh/go-spew v1.1.1 // indirect
github.com/frankban/quicktest v1.14.6 // indirect
github.com/google/go-cmp v0.6.0 // indirect

⚠️ 潜在风险

冗余的依赖可能增加构建时间、二进制体积,或引入不必要的安全漏洞和版本兼容性问题。

审查详情
📒 文件清单 (5 个文件)
新增: 5 个文件

✅ 新增文件:

  • plugins/wasm-go/mcp-filters/mcp-router/README.md
  • plugins/wasm-go/mcp-filters/mcp-router/README_ZH.md
  • plugins/wasm-go/mcp-filters/mcp-router/go.mod
  • plugins/wasm-go/mcp-filters/mcp-router/go.sum
  • plugins/wasm-go/mcp-filters/mcp-router/main.go

💡 小贴士

与 lingma-agents 交流的方式

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

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

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

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

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

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

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

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

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

Copy link
Collaborator

@cr7258 cr7258 left a comment

Choose a reason for hiding this comment

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

🐉 LGTM

Copy link
Collaborator

@CH3CHO CH3CHO left a comment

Choose a reason for hiding this comment

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

按我的理解,这个插件要想工作的话,还需要配上一个 tools/list 的聚合插件?

还有这个插件是会被打包到 all-in-one 里,还是作为一个独立插件进行发布呢?

Copy link
Collaborator

@CH3CHO CH3CHO left a comment

Choose a reason for hiding this comment

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

LGTM

@CH3CHO CH3CHO merged commit 91f0709 into alibaba:main Jun 17, 2025
12 checks passed
erasernoob pushed a commit to erasernoob/higress that referenced this pull request Jun 18, 2025
@lingma-agents lingma-agents bot mentioned this pull request Jul 18, 2025
@stone955
Copy link

想请教一下mcp-router应该配合mcp-server的toolSet聚合来自不同mcp的tool,但是代码里面判断了如果toolSet不为空,那么不会进行opts.ToolRegistry.RegisterTool注册,导致在tool/list的时候会走到 Tool %s/%s not found in global registry for composed server

@johnlanni
Copy link
Collaborator Author

johnlanni commented Aug 26, 2025

@stone955 你看的不对哦,默认所有server都会注册的,toolSet只是从注册的里面选出来用而已


@stone955 You are not looking right. By default, all servers will be registered. ToolSet is just selected from the registered ones.

@stone955
Copy link

@stone955 你看的不对哦,默认所有server都会注册的,toolSet只是从注册的里面选出来用而已

@stone955 You are not looking right. By default, all servers will be registered. ToolSet is just selected from the registered ones.

我可能没表达清楚,我没有直接使用higress,而是用了wasm-go的插件,计划是在单个openapi后端服务的sidecar 注入 这个插件,将openapi 转成 mcp。然后在网关使用mcp-router进行路由和聚合多个mcp server 并选择 tool。

ink-hz pushed a commit to ink-hz/higress-ai-capability-auth that referenced this pull request Nov 5, 2025
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