掘金 人工智能 前天 13:58
MCP实践:MCP server 开发保姆教程(附全部代码)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了MCP-server的开发、调试及注意事项,旨在通过MCP解耦工具与大模型之间的强耦合关系,推动工具服务的组件化发展。MCP允许一个工具服务被不同厂商的大模型调用,从而加速AI的落地应用。文章详细阐述了基于Spring AI的MCP服务器开发,包括环境依赖(JDK17+,SpringBoot 3.4.0+)和两种开发模式(stdio和sse)。着重讲解了webmvc模式下的依赖引入、代码结构、服务开发(如OpenMeteo天气和空气质量查询工具),以及如何使用inspector进行接口验证。最后总结了MCP在工具组件化方面的潜力,并指出了未来需要完善的方向。

💡MCP的核心价值在于解耦工具和大模型,促进工具服务组件化,使得不同厂商的大模型可以调用同一工具服务,加速AI应用落地。

🛠️MCP服务器开发支持stdio和sse两种模式,推荐使用JDK17+和SpringBoot 3.4.0+。本文以webmvc模式为例,详细介绍了依赖引入和代码结构,包括OpenMeteoService(天气和空气质量查询)的开发。

🧪接口验证通过开源组件inspector进行,启动服务后,可调试MCP服务。添加【sse-endpoint】配置后,可自定义sse端点。

☁️OpenMeteoService集成了两个MCP工具:根据经纬度查询天气和根据经纬度查询空气质量,展示了MCP如何通过工具服务与外部API交互。

🚧MCP目前还处于发展阶段,未来需要在鉴权、依赖完善以及服务提供商数据完备性等方面进行改进,但其工具组件化的理念具有重要意义。

1、概述

MCP的出现为AI的落地发展摁下了加速键,我们通过MCP可以解耦工具和大模型之间的强耦合关系。使一个工具服务可以供不同厂商的大模型调用。加速了工具服务组件化发展。

具体介绍可以看 模型上下文协议(MCP):AI 代理与真实世界交互的桥梁

这篇文章介绍MCP-server的开发及相关调试及一些注意点。文章最后附有全部代码

2、MCP server开发

MCP server 开发有两种模式,一种是stdio模式,另一种是sse模式。stdio相当于是依赖包加载到本地进行运行,

2.1、依赖相关

开发mcp对环境有要求,jdk要求17+,SpringBoot要求【3.4.0+】

MCP-server开发有两个依赖包,底层的技术一个是依赖webmvc,另一个是依赖webflux。webmvc是基于servlet的阻塞式模型,webflux是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。

具体两个依赖如下(目前最新版本【1.0.0-M7】):

<!--  webmvc-mcp --><dependency>    <groupId>org.springframework.ai</groupId>    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>    <version>1.0.0-M7</version></dependency><!-- webflux-mcp --><dependency>    <groupId>org.springframework.ai</groupId>    <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>    <version>1.0.0-M7</version></dependency>

我们选其中之一【webmvc】进行演示讲解。

2.2、代码开发

大家可以看下目录结构,结构比较简单。主要核心是【OpenMeteoService】和【MCPSpringAiRegisterConfiguration】

服务开发

我们使用open-meteo服务,【open-meteo】是一个开源免费的天气api服务。

这里我们开发两个MCP工具

根据经纬度查询天气

根据经纬度查询空气质量

配置开发

初始化restTemplate

Tools服务注册

application.yml配置

目前使用的都是默认配置,只添加了一个name和version,具体配置可参考官网

目前【sse-endpoint】配置不起作用,原因是依赖初始化时使用默认值,因此如果要使用自定义,需要重写初始化。

解决方案:创建配置,重写WebMvcSseServerTransportProvider初始化

3、接口验证

我们使用开源组件inspector进行验证mcp服务

运行inspector需要安装node、npm、npx环境

执行【npx @modelcontextprotocol/inspector】命令便可安装运行启动服务地址为【http://127.0.0.1:6274】

具体调试信息如下:

添加【sse-endpoint】配置后如下:

4、总结

目前只是运行了一个简单的demo,离服务化还是较远。但提出了工具组件化的概念。

对于MCP,还有好多需要完善,比如鉴权、相关依赖完善、各个服务提供商的数据是否完备等。但是这一技术理念还是值得我们现在去理解去学习。

5、代码

代码结构如下:

BeanConfiguration

package com.young.server.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;/** * @author 刘子洋 * @date 2025年05月13日 下午3:22 * @description:初始化组件bean */@Configurationpublic class BeanConfiguration {    @Bean    public RestTemplate restTemplate() {        return new RestTemplate();    }}

MCPSpringAiRegisterConfiguration

package com.young.server.config;import com.young.server.mcp.springAi.OpenMeteoService;import org.springframework.ai.tool.ToolCallbackProvider;import org.springframework.ai.tool.method.MethodToolCallbackProvider;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author 刘子洋 * @date 2025年05月13日 下午3:18 * @description:MCP 服务注册 */@Configurationpublic class MCPSpringAiRegisterConfiguration {    /**     * 创建并配置一个天气工具回调提供者     * 该方法通过接收一个OpenMeteoService实例来构建一个MethodToolCallbackProvider对象     * 主要用于在调用OpenMeteoService的方法时提供回调功能     *     * @param openMete OpenMeteoService的实例,用于获取天气信息     * @return 返回一个配置好的MethodToolCallbackProvider对象     */    @Bean    public ToolCallbackProvider weatherTools(OpenMeteoService openMete){        return MethodToolCallbackProvider.builder()                .toolObjects(openMete)                .build();    }}

MyMcpServerConfig

package com.young.server.config;//package com.young.server.config;import com.fasterxml.jackson.databind.ObjectMapper;import io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider;import org.springframework.ai.mcp.server.autoconfigure.McpServerProperties;import org.springframework.beans.factory.ObjectProvider;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.web.servlet.function.RouterFunction;import org.springframework.web.servlet.function.ServerResponse;/** * @author 刘子洋 * @date 2025年05月14日 上午10:53 * @description:重写 WebMvcSseServerTransportProvider 初始化 */@Configurationpublic class MyMcpServerConfig {    @Bean    @Primary    public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider(            ObjectProvider<ObjectMapper> objectMapperProvider, McpServerProperties serverProperties) {        ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);        return new WebMvcSseServerTransportProvider(objectMapper, serverProperties.getSseMessageEndpoint(),                serverProperties.getSseEndpoint());    }    @Bean    public RouterFunction<ServerResponse> mvcMcpRouterFunction(WebMvcSseServerTransportProvider transportProvider) {        return transportProvider.getRouterFunction();    }}

OpenMeteoService

package com.young.server.mcp.springAi;import lombok.extern.slf4j.Slf4j;import org.springframework.ai.tool.annotation.Tool;import org.springframework.ai.tool.annotation.ToolParam;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;/** * @author 刘子洋 * @date 2025年05月13日 下午2:53 * @description:空气服务类 */@Service@Slf4jpublic class OpenMeteoService {    private final RestTemplate restTemplate;    private static final String WEATHER_TEMPLATE = "当前位置(纬度:%s,经度:%s)的天气信息:\n %s";    public OpenMeteoService(RestTemplate restTemplate) {        this.restTemplate = restTemplate;    }    /**     * 根据给定的经纬度获取天气预报     * 此方法使用RestTemplate调用外部天气API,获取JSON格式的天气信息,并将其格式化为字符串返回     *     * @param latitude  纬度,表示地理位置的南北位置     * @param longitude 经度,表示地理位置的东西位置     * @return 格式化后的天气预报信息字符串     */    @Tool(description = "根据给定的经纬度获取天气预报")    public String getWeatherForecastByLocation(        @ToolParam(description = "经纬度,例如:39.9042") String latitude,        @ToolParam(description = "经纬度,例如:116.4074") String longitude    ) {        String url = "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m&timezone=auto";        String response = restTemplate.getForObject(url, String.class, latitude, longitude);        log.info("response: {}", response);        return String.format(WEATHER_TEMPLATE, latitude, longitude, response);    }    /**     * 根据给定的经纬度获取空气质量信息     *     * @param latitude  纬度,表示地理位置的南北位置     * @param longitude 经度,表示地理位置的东西位置     * @return 空气质量信息字符串     */    @Tool(description = "根据经纬度获取空气质量信息")    public String getAirQualityByLocation(        @ToolParam(description = "经纬度,例如:39.9042") String latitude,        @ToolParam(description = "经纬度,例如:116.4074") String longitude    ) {        // 模拟数据,实际应用中应调用真实API        return "当前位置(纬度:" + latitude + ",经度:" + longitude + ")的空气质量:\n" +                "- PM2.5: 15 μg/m³ (优)\n" +                "- PM10: 28 μg/m³ (良)\n" +                "- 空气质量指数(AQI): 42 (优)\n" +                "- 主要污染物: 无";    }}

maven(有些组件没有在maven中心仓库,因此自定义加入了一些仓库)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>com.young</groupId>        <artifactId>my-agi</artifactId>        <version>0.0.1-SNAPSHOT</version>    </parent>    <artifactId>mcp-server</artifactId>    <packaging>war</packaging>    <name>mcp-server Maven Webapp</name>    <url>http://maven.apache.org</url>    <properties>        <java.version>17</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.ai</groupId>            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>            <version>1.0.0-M7</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.18.22</version>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <version>3.4.0</version>            </plugin>        </plugins>    </build>    <repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>        <repository>            <id>spring-snapshots</id>            <name>Spring Snapshots</name>            <url>https://repo.spring.io/snapshot</url>            <releases>                <enabled>false</enabled>            </releases>        </repository>        <repository>            <id>central-portal-snapshots</id>            <name>Central Portal Snapshots</name>            <url>https://central.sonatype.com/repository/maven-snapshots/</url>            <releases>                <enabled>false</enabled>            </releases>            <snapshots>                <enabled>true</enabled>            </snapshots>        </repository>    </repositories></project>

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

MCP AI工具 Spring AI 组件化 API服务
相关文章