Java开发MCP服务器
前言
预训练的大语言模型虽然强大,但是知识库停留在训练的那一刻,无法获取实时的数据,导致大模型在某些场景下表现的很不好。
例如,你询问大模型关于实时天气、实时新闻的看法,大模型要么无法回答,要么胡乱编造结果,这显然不是我们想看到的结果。
好在,MCP 协议的诞生,打通了 AI 应用和外部系统的集成问题,大模型不仅可以获取互联网上公开的最新数据,甚至可以访问企业内部系统的保密数据,只要你开发好相应的MCP服务器即可。
本文通过一个“天气MCP服务器”为例。
MCP服务器开发
MCP 是 Model Context Protocol 的缩写,中文译为“模型上下文协议”。
协议即标准,有了标准,厂商就可以根据标准开发并封装成依赖包,减少重复开发的成本。官方提供了各语言的开发包,以 Java 为例,仓库地址:https://github.com/modelcontextprotocol/java-sdk
在 Spring 项目中,为了更好的集成 MCP,Spring 做了进一步的封装。
首先,引入spring-ai-bom
<dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
如果通过webmvc
的方式集成,就引入spring-ai-starter-mcp-server-webmvc
<dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webmvc</artifactId></dependency>
</dependencies>
到这里,环境就搭建好了。
MCP 服务器,最核心的是 Tool 的开发。Tool 是供 MCP 客户端调用的工具,由大模型负责推理该调用哪个 Tool。在代码层面,Tool 就是一个普通的 Java 方法,额外要做的,就是对这个方法加以描述,让大模型能理解,这个方法是干什么用的,需要哪些参数。
如下所示,方法weatherQuery
就是一个 Tool,通过@Tool
注解对方法加以描述,让 Spring 知道有这么个 Tool。为了简单,这里数据是随机生成的。
@Service
public class WeatherService {@Tool(name = "weather_query", description = "根据商品关键字搜索商品,返回一个商品列表")public String weatherQuery(@ToolParam(description = "位置", required = true) String location) {// 天气、温度 随机生成int temperature = ThreadLocalRandom.current().nextInt(10, 40);String[] weathers = {"晴", "多云", "阴", "小雨", "中雨", "大雨", "雨夹雪", "大雪"};String weatherText = weathers[ThreadLocalRandom.current().nextInt(weathers.length)];return "location=%s,temperature=%d°C,weatherText=%s".formatted(location, temperature, weatherText);}
}
最后,将包含 Tool 的对象封装到 ToolCallbackProvider,注册到 Spring 上下文容器,再由 Spring 注册到 MCP 服务器。
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}@Beanpublic ToolCallbackProvider toolCallbackProvider(WeatherService weatherService) {return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();}
}
启动 Spring 应用,访问http://127.0.0.1:8080/sse
能打开新的会话,表示MCP服务正常。
MCP 服务器默认由两个端点:
- /sse sse连接,创建会话的端点
- **/mcp/message **MCP客户端和服务器消息收发的端点
如果像修改端点,可以通过如下配置:
spring:ai:mcp:server:enabled: truetype: syncsse-endpoint: /ssesse-message-endpoint: /mcp/message
MCP客户端测试
MCP 服务器开发好以后,可以对外发布,然后添加到大模型服务平台,供AI应用调用。
当然,我们也可以先通过 MCP 客户端本地调试下,确保没问题,再发布。
开发 MCP 客户端,需要先引入依赖
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>
然后,构建 McpSyncClient 和服务器建立连接,并通信。
如下所示,先初始化,再列举服务器支持的 Tools。
public static void main(String[] args) {McpClientTransport transport = new HttpClientSseClientTransport("http://127.0.0.1:8080/sse");McpSyncClient client = McpClient.sync(transport).requestTimeout(Duration.ofSeconds(10)).capabilities(McpSchema.ClientCapabilities.builder().roots(false).build()).build();// 初始化McpSchema.InitializeResult initialize = client.initialize();// 列举服务器支持的ToolsMcpSchema.ListToolsResult tools = client.listTools();for (McpSchema.Tool tool : tools.tools()) {System.err.println(tool);}client.closeGracefully();
}
正常情况下应该有下图所示的输出
客户端发起 Tool 调用,代码示例:
McpSchema.CallToolRequest callToolRequest = new McpSchema.CallToolRequest("weather_query", Map.of("location", "杭州"));
McpSchema.CallToolResult callToolResult = client.callTool(callToolRequest);
System.err.println(callToolResult.content());
正常应该得到结果
[TextContent[audience=null, priority=null, text="location=杭州,temperature=38°C,weatherText=中雨"]]
部署到大模型服务平台
自己写 MCP 客户端去调用 MCP 服务器是没有意义的,MCP 服务器对外部署后,可以注册到大模型服务平台,供所有AI应用调用,增强AI应用的能力。
这里以阿里云的百炼为例,官网地址:https://bailian.console.aliyun.com
注册账号后,在“MCP管理”页面创建MCP服务,如下图所示:
依次填写MCP服务的名称、描述、和服务配置。因为MCP服务器我们已经开发部署完了,所以这里选http的安装方式,填写MCP服务器地址即可。
平台会创建MCP客户端和MCP服务器通信,列举服务器支持的所有工具。
可以在页面上,直接对工具发起调用,进行调试。
MCP 服务调试完成,就可以直接添加到智能体,在用户和大模型对话时,大模型会智能判断何时调用哪个工具。
例如,我们问天气相关的问题,大模型就会判断该调用天气工具了,然后MCP客户端就会发起工具调用,然后再把天气结果喂给大模型,由大模型推理回答。
![](https://i-blog.csdnimg.cn/img_convert/1bf74d2deb88bbef0542c8339d48dc22.png