Java MCP 的鉴权?好简单的啦

听说 mcp 的鉴权,是件很麻烦的事情?估计是没选好工具。

一、MCP Client 侧(负责传递,比较简单)

在客户端,一般是使用 queryString 或者 header 或者 env(stdio 方式用) 传递鉴权信息,比如变量:token(名字随便取)

(1)常见的 mcpServers json 配置方式

不同服务平台,mcpServers json 的配置格式可能会略有不同。具体需要按服务平台要求配置。

  • 使用 queryString 传递(http 类传输方式)
{     "mcpServers": {         "demo": {             "type":"sse"             "url": "https://localhost:8080/mcp?token=xxxx"         }     } } 
  • 使用 header 传递(http 类传输方式)
{     "mcpServers": {         "demo": {             "type":"streamable",             "url": "https://localhost:8080/mcp",             "headers": {"token":"xxx"}         }     } } 
  • 使用 env 传递(stdio 传输方式)
{     "mcpServers": {         "demo": {             "type":"stdio",             "command":"java",             "args": ["-jar", "/data/demo/target/demo-mcp-stdio.jar"]             "env": {"token": "xxx"}         }     } } 

(2)使用 solon-ai-mcp 作为客户端

solon-ai-mcp 是比较简洁的 mcp java client 框架。它的体验与 mcpServers json 配置相差不大。

  • 使用 queryString 传递(http 类传输方式)
import org.noear.solon.ai.mcp.client.McpClientProvider;  McpClientProvider mcpClient =  McpClientProvider.builder()                 .channel(McpChannel.SSE) //表示使用 sse 传输方式                 .apiUrl("https://localhost:8080/mcp?token=xxxx")                 .build();                  //mcpClient.getTools(); 
  • 使用 header 传递(http 类传输方式)
import org.noear.solon.ai.mcp.client.McpClientProvider;  McpClientProvider mcpClient =  McpClientProvider.builder()                 .channel(McpChannel.STREAMABLE) //表示使用 streamable 传输方式                 .apiUrl("https://localhost:8080/mcp")                 .headerSet("token", "xxxx")                 .build();                   //mcpClient.getTools(); 
  • 使用 env 传递(stdio 传输方式)
import org.noear.solon.ai.mcp.client.McpClientProvider;  McpClientProvider mcpClient = McpClientProvider.builder()                 .channel(McpChannel.STDIO) //表示使用 stdio 传输方式                 .serverParameters(McpServerParameters.builder("java")                         .args("-jar", "/data/demo/target/demo-mcp-stdio.jar")                         .addEnvVar("token","xxx")                         .build())                 .build();                                  //mcpClient.getTools(); 
  • 与 chatModel 结合使用示例:
import org.noear.solon.ai.chat.ChatModel; import org.noear.solon.ai.chat.ChatResponse;  ChatModel chatModel = ChatModel.of(apiUrl).provider(provider).model(model)                 .defaultToolsAdd(mcpClient) //重点是这一行                 .build();  ChatResponse resp = chatModel         .prompt("今天杭州的天气情况?")         .call(); 

二、MCP Server 侧(也好简单的)

(1)方式1:每个工具各自鉴权(适合 stdiossestreamable 三种传输方式)

在 solon-ai-mcp 里,可以使用 @Header 注解,获取 mcp 连接的元信息(比如 queryString、header、env)

import org.noear.solon.ai.annotation.ToolMapping; import org.noear.solon.ai.mcp.McpChannel; import org.noear.solon.ai.mcp.server.annotation.McpServerEndpoint; import org.noear.solon.annotation.Header; import org.noear.solon.annotation.Param;  @McpServerEndpoint(channel = McpChannel.STREAMABLE, mcpEndpoint = "/mcp") public class McpServerTool {     @ToolMapping(description = "你好世界")     public String hello(@Param(name="name", description = "名字") String name, @Header("token") String token) {         if(token == null) {             throw new IllegalArgumentException("你没有权限哦!");         }          return "你好," + name;     } } 

(2)方式2:为 http 传输的所有工具集中鉴权(适合 ssestreamable http类的传输方式)

solon-ai-mcp 也可以通过过滤器(Filter),实现单点鉴权。

@Managed public class McpServerTool implements Filter {     @Override     public void doFilter(Context ctx, FilterChain chain) throws Throwable {         if (ctx.pathNew().equals("/mcp")) {             String token = ctx.header("token"); //支持从 header 取             if (token == null) {                 token = ctx.param("token"); //支持从 queryString 取             }              if (token == null) {                 ctx.status(401, "你没有权限哦!");                 return;             }         }          chain.doFilter(ctx);     } } 

(3)方式3:程序启动时鉴权(适合 stdio 传输方式)

@SolonMain public class McpApp {     public static void main(String[] args) {         String token = System.getenv("token");         if (Utils.isEmpty(token)) {             throw new RuntimeException("你没有权限哦");         }          Solon.start(McpApp.class, args);     } } 

发表评论

评论已关闭。

相关文章