找回密码
 立即注册
首页 业界区 业界 Java MCP 的鉴权?好简单的啦

Java MCP 的鉴权?好简单的啦

泡市 7 天前
听说 mcp 的鉴权,是件很麻烦的事情?估计是没选好工具。
一、MCP Client 侧(负责传递,比较简单)

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

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

  • 使用 queryString 传递(http 类传输方式)
  1. {
  2.     "mcpServers": {
  3.         "demo": {
  4.             "type":"sse"
  5.             "url": "https://localhost:8080/mcp?token=xxxx"
  6.         }
  7.     }
  8. }
复制代码

  • 使用 header 传递(http 类传输方式)
  1. {
  2.     "mcpServers": {
  3.         "demo": {
  4.             "type":"streamable",
  5.             "url": "https://localhost:8080/mcp",
  6.             "headers": {"token":"xxx"}
  7.         }
  8.     }
  9. }
复制代码

  • 使用 env 传递(stdio 传输方式)
  1. {
  2.     "mcpServers": {
  3.         "demo": {
  4.             "type":"stdio",
  5.             "command":"java",
  6.             "args": ["-jar", "/data/demo/target/demo-mcp-stdio.jar"]
  7.             "env": {"token": "xxx"}
  8.         }
  9.     }
  10. }
复制代码
(2)使用 solon-ai-mcp 作为客户端

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

  • 使用 queryString 传递(http 类传输方式)
  1. import org.noear.solon.ai.mcp.client.McpClientProvider;
  2. McpClientProvider mcpClient =  McpClientProvider.builder()
  3.                 .channel(McpChannel.SSE) //表示使用 sse 传输方式
  4.                 .apiUrl("https://localhost:8080/mcp?token=xxxx")
  5.                 .build();
  6.                
  7. //mcpClient.getTools();
复制代码

  • 使用 header 传递(http 类传输方式)
  1. import org.noear.solon.ai.mcp.client.McpClientProvider;
  2. McpClientProvider mcpClient =  McpClientProvider.builder()
  3.                 .channel(McpChannel.STREAMABLE) //表示使用 streamable 传输方式
  4.                 .apiUrl("https://localhost:8080/mcp")
  5.                 .headerSet("token", "xxxx")
  6.                 .build();
  7.                
  8. //mcpClient.getTools();
复制代码

  • 使用 env 传递(stdio 传输方式)
  1. import org.noear.solon.ai.mcp.client.McpClientProvider;
  2. McpClientProvider mcpClient = McpClientProvider.builder()
  3.                 .channel(McpChannel.STDIO) //表示使用 stdio 传输方式
  4.                 .serverParameters(McpServerParameters.builder("java")
  5.                         .args("-jar", "/data/demo/target/demo-mcp-stdio.jar")
  6.                         .addEnvVar("token","xxx")
  7.                         .build())
  8.                 .build();
  9.                                 
  10. //mcpClient.getTools();
复制代码

  • 与 chatModel 结合使用示例:
  1. import org.noear.solon.ai.chat.ChatModel;
  2. import org.noear.solon.ai.chat.ChatResponse;
  3. ChatModel chatModel = ChatModel.of(apiUrl).provider(provider).model(model)
  4.                 .defaultToolsAdd(mcpClient) //重点是这一行
  5.                 .build();
  6. ChatResponse resp = chatModel
  7.         .prompt("今天杭州的天气情况?")
  8.         .call();
复制代码
二、MCP Server 侧(也好简单的)

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

在 solon-ai-mcp 里,可以使用 @Header 注解,获取 mcp 连接的元信息(比如 queryString、header、env)
  1. import org.noear.solon.ai.annotation.ToolMapping;
  2. import org.noear.solon.ai.mcp.McpChannel;
  3. import org.noear.solon.ai.mcp.server.annotation.McpServerEndpoint;
  4. import org.noear.solon.annotation.Header;
  5. import org.noear.solon.annotation.Param;
  6. @McpServerEndpoint(channel = McpChannel.STREAMABLE, mcpEndpoint = "/mcp")
  7. public class McpServerTool {
  8.     @ToolMapping(description = "你好世界")
  9.     public String hello(@Param(name="name", description = "名字") String name, @Header("token") String token) {
  10.         if(token == null) {
  11.             throw new IllegalArgumentException("你没有权限哦!");
  12.         }
  13.         return "你好," + name;
  14.     }
  15. }
复制代码
(2)方式2:为 http 传输的所有工具集中鉴权(适合 sse,streamable http类的传输方式)

solon-ai-mcp 也可以通过过滤器(Filter),实现单点鉴权。
  1. @Managed
  2. public class McpServerTool implements Filter {
  3.     @Override
  4.     public void doFilter(Context ctx, FilterChain chain) throws Throwable {
  5.         if (ctx.pathNew().equals("/mcp")) {
  6.             String token = ctx.header("token"); //支持从 header 取
  7.             if (token == null) {
  8.                 token = ctx.param("token"); //支持从 queryString 取
  9.             }
  10.             if (token == null) {
  11.                 ctx.status(401, "你没有权限哦!");
  12.                 return;
  13.             }
  14.         }
  15.         chain.doFilter(ctx);
  16.     }
  17. }
复制代码
(3)方式3:程序启动时鉴权(适合 stdio 传输方式)
  1. @SolonMain
  2. public class McpApp {
  3.     public static void main(String[] args) {
  4.         String token = System.getenv("token");
  5.         if (Utils.isEmpty(token)) {
  6.             throw new RuntimeException("你没有权限哦");
  7.         }
  8.         Solon.start(McpApp.class, args);
  9.     }
  10. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册