MCP网桥插件
一个EMQX插件,通过MQTT将可流式HTTP或MCP-SSE桥接到MCP。
概述
此插件允许HTTP MCP客户端通过桥接两种协议,通过MQTT客户端与MCP通信。此插件还允许用户直接创建MCP工具并将其暴露给HTTP MCP客户端。
配置
这 listening_address 参数指定流式HTTP MCP客户端的地址和路径。这 sse_path 参数指定传统SSE MCP客户端的路径。两个端点都在同一台服务器上运行(主机和端口取自 listening_address).
listening_address = "http://0.0.0.0:9998/mcp"
sse_path = "/sse"如果 sse_path 未配置,默认为 "/sse".如果 listening_address 未配置自定义路径,默认为 "/mcp".
它是如何工作的
从MCP服务器加载工具
当使用MQTT协议上的MCP的MCP服务器连接到EMQX时,插件通过两种方式从MCP服务器加载工具:
- 如果MCP服务器报告“通知/服务器/在线”事件,且其“元数据”中有“工具”字段,则插件直接使用此字段中的工具列表。
- 如果“通知/服务器/在线”事件中不存在“工具”字段,则插件会向MCP服务器发送“工具/列表”请求以检索工具列表。
按工具类型存储工具
工具使用其工具类型作为主键进行存储,其中工具类型是MQTT服务器上的MCP的ServerName。如果多个MCP服务器报告相同的ServerName,则插件仅保留最新MCP服务器的工具列表。
从MCP服务器加载工具后,插件按如下方式转换工具列表:
- 它为每个工具名称添加工具类型前缀,从而形成“ToolType:ToolName”的格式。这避免了不同MCP服务器之间的工具名称冲突,并允许MCP-HTTP客户端按类型过滤工具。
- 如果
get_target_clientid_from设置为tool_params,MCP桥注入一个名为target-mqtt-client-id进入每个工具。MCP-HTTP客户端在调用工具时必须提供此参数,插件使用其值将工具调用请求发送到指定的MQTT MCP服务器。
- 如果
get_target_clientid_from设置为http_headers或jwt_claims,MCP-HTTP客户端不需要提供target-mqtt-client-id参数。相反,该插件从HTTP标头或JWT声明中获取目标MQTT客户端ID。此方法仅适用于MCP-HTTP客户端和MQTT MCP服务器之间存在一对一映射的情况,即每个MCP-HTTP客户机访问单个MQTT MCP Server上的工具。
仅列出特定的工具类型
当MCP-HTTP客户端请求工具列表时,它可以指定在响应中包含哪些工具类型。插件检索所需的 tool-types 基于HTTP标头或JWT声明 get_tool_types_from 配置。
当通过 tool-types 在HTTP标头中,客户端应使用 Tool-Types 带有逗号分隔的工具类型列表的标题。例如:
tool-types: type1,type2,type3当通过 tool-types 在JWT声明中,客户端应包含一个名为 tool-types 带有工具类型列表。例如:
{
"sub": "client1",
"tool-types": ["type1", "type2", "type3"]
}如果没有指定工具类型,插件将返回所有可用工具类型中的工具。
创建自定义MCP工具
要创建自定义MCP工具,用户需要创建一个带有前缀的模块 mcp_bridge_tools_ 并实现回调函数。该模块应该只有一个 -mcp_tool_type 属性指定工具类型,以及至少一个 -mcp_tool 属性来定义工具。查看模块 mcp_bridge_tools_clients 举个例子。
这是一个最小的示例模块,它导出一个添加两个数字的工具:
-module(mcp_bridge_tools_sample).
-export([add/3]).
-mcp_tool_type(>).
-mcp_tool_vsn(>).
-mcp_tool(#{
name => >,
title => >,
description => >,
inputSchema => #{
type => >,
properties => #{
num1 => #{
type => >,
title => >,
description => >
},
num2 => #{
type => >,
title => >,
description => >
}
},
required => [num1, num2]
},
opts => #{}
}).
add(_ReqId, #{> := Num1, > := Num2} = _Params, _Opts) ->
{ok, Num1 + Num2}.部署
看 EMQX文件 有关如何部署自定义插件的详细信息。
