Java MCP 的鉴权?好简单的啦

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

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

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

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

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

  • 使用 queryString 传递(http 类传输方式)
json 复制代码
{
    "mcpServers": {
        "demo": {
            "type":"sse"
            "url": "https://localhost:8080/mcp?token=xxxx"
        }
    }
}
  • 使用 header 传递(http 类传输方式)
json 复制代码
{
    "mcpServers": {
        "demo": {
            "type":"streamable",
            "url": "https://localhost:8080/mcp",
            "headers": {"token":"xxx"}
        }
    }
}
  • 使用 env 传递(stdio 传输方式)
json 复制代码
{
    "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 类传输方式)
java 复制代码
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 类传输方式)
java 复制代码
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 传输方式)
java 复制代码
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 结合使用示例:
java 复制代码
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)

java 复制代码
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),实现单点鉴权。

java 复制代码
@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 传输方式)

java 复制代码
@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);
    }
}
相关推荐
jason成都5 分钟前
ignav-next|Java 层封装 GNSS/INS 组合导航框架,隔离 RTKLIB 与 INS 内核,双模块独立演进、最小侵入
java·开发语言
抓不住时间的沙5 分钟前
butterfly主题美化,打造属于自己的个性博客
java·开发语言·前端·javascript·node.js·github
Zane199416 分钟前
从一个发短信的类到多态调用:封装、继承、多态到底是怎么长出来的
java·后端
MarkHD19 分钟前
Stable Diffusion入门第19-20天:保存与分享你的工作流——第一阶段收官,从“能用”到“可复用”
java·开发语言·stable diffusion
爱敲键盘的猴子23 分钟前
Spring MVC 详解(一):全注解开发与请求响应处理
java·spring·mvc
counting money31 分钟前
SpringBoot 项目创建(IDEA不全,还需要修改)
java·spring boot·spring·maven
Dr.kangder32 分钟前
嵌入式面试总结(二十二)——指针
java·面试·职场和发展·架构·嵌入式
MacroZheng36 分钟前
几行代码给项目集成AI功能,Spring AI 2.0太香了!
java·人工智能·spring boot
Devin~Y1 小时前
从内容社区到AI智能客服:Spring Boot + Spring Cloud + Spring AI 全栈实战面试拆解
java·spring boot·redis·elasticsearch·spring cloud·kafka·mybatis
未秃头的程序猿1 小时前
从写CRUD到做AI Agent:我花了6个月转型,这是我的完整路线图
java·后端·ai编程