听说 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"
- }
- }
- }
复制代码- {
- "mcpServers": {
- "demo": {
- "type":"streamable",
- "url": "https://localhost:8080/mcp",
- "headers": {"token":"xxx"}
- }
- }
- }
复制代码- {
- "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();
复制代码- 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();
复制代码- 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();
复制代码- 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:每个工具各自鉴权(适合 stdio,sse,streamable 三种传输方式)
在 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 传输的所有工具集中鉴权(适合 sse,streamable 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);
- }
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |