如何给自研MCP加上安全验证

发布于:2025-05-27 ⋅ 阅读:(204) ⋅ 点赞:(0)

在这里插入图片描述

前言
刚过去两个月,市面的 MCP 服务,如雨后春笋一般不断涌现出来,包括;百度、高德、网盘、支付宝。这些 MCP 服务,可以让我们基于 Spring AI 框架构建的 Agent 具备非常丰富的使用功能。同时这也说明,程序员👨🏻‍💻,应该具备开发 MCP 服务的能力,Spring AI 让 Java 再次牛逼!
举例
如对接高德地图 MCP

{
  "mcpServers": {
    "amap-amap-sse": {
      "url": "https://mcp.amap.com/sse?key=您在高德官网上申请的key"
    }
  }
}

官网 - 官网提供了创建对接 Key
二:代码案例

@Configuration
publicclass McpConfig {
   

    @Bean
    public List<NamedClientMcpTransport> mcpClientTransport() {
   
        McpClientTransport transport = HttpClientSseClientTransport
                .builder("https://mcp.amap.com")
                .sseEndpoint("/sse?key=<your_key>")
                .objectMapper(new ObjectMapper())
                .build();

        return Collections.singletonList(new NamedClientMcpTransport("amap", transport));
    }
    
}

1:对接时,需要设定 sseEndpoint 如果不设定个,Spring AI 默认是对 builder 的 baseUrl 值添加 /sse 的。

2:所以,如果你要对接外部带有验证权限的 MCP 服务,需要手动设置下 sseEndpoint 值。

项目中的配置
支持了外部的这些带有权限校验的 MCP 服务。你可以,以多种方式进行配置。如

{
 "baseUri":"https://mcp.amap.com",
        "sseEndpoint":"/sse?key=****"
}
{
 "baseUri":"https://mcp.amap.com",
        "sseEndpoint":"/sse?key=****"
}

以上两种配置方式,在 项目案例代码中 都做了兼容处理。以下是兼容代码,有案例项目的,可以直接阅读课程代码。

@Slf4j
@Component
publicclass AiClientToolMcpNode extends AbstractArmorySupport {
   

   // ... 省略部分代码

    protected McpSyncClient createMcpSyncClient(AiClientToolMcpVO aiClientToolMcpVO) {
   
        String transportType = aiClientToolMcpVO.getTransportType();

        switch (transportType) {
   
            case"sse" -> {
   
                AiClientToolMcpVO.TransportConfigSse transportConfigSse = aiClientToolMcpVO.getTransportConfigSse();
                // http://127.0.0.1:9999/sse?apikey=DElk89iu8Ehhnbu
                String originalBaseUri = transportConfigSse.getBaseUri();
                String baseUri;
                String sseEndpoint;

                int queryParamStartIndex = originalBaseUri.indexOf("sse");
                if (queryParamStartIndex != -1) {
   
                    baseUri = originalBaseUri.substring(0, queryParamStartIndex - 1);
                    sseEndpoint = originalBaseUri.substring(queryParamStartIndex - 1);
                } else {
   
                    baseUri = originalBaseUri;
                    sseEndpoint = transportConfigSse.getSseEndpoint();