当前位置: 首页 > news >正文

通过Spring AI框架搭建mcp服务端说明

简介

MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 提出的开源协议,旨在标准化大语言模型(LLM)与外部数据源、工具的集成方式,实现安全高效的双向连接。

项目结构

代码示例

这里是以查询城市天气的mcp server做的示例,框架用的是spring ai

pom依赖

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>3.4.5</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <artifactId>mcp-server-demo</artifactId>

    <properties>

        <java.version>17</java.version>

        <maven.compiler.source>17</maven.compiler.source>

        <maven.compiler.target>17</maven.compiler.target>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>

    <dependencyManagement>

        <dependencies>

            <dependency>

                <groupId>org.springframework.ai</groupId>

                <artifactId>spring-ai-bom</artifactId>

                <version>1.0.0-SNAPSHOT</version>

                <type>pom</type>

                <scope>import</scope>

            </dependency>

        </dependencies>

    </dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.ai</groupId>

            <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>

        </dependency>

        <dependency>

            <groupId>com.alibaba.fastjson2</groupId>

            <artifactId>fastjson2</artifactId>

            <version>2.0.51</version>

        </dependency>

        <dependency>

            <groupId>cn.hutool</groupId>

            <artifactId>hutool-all</artifactId>

            <version>5.8.32</version>

        </dependency>

    </dependencies>

    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

</project>

application.properties

# spring.main.web-application-type=none

# NOTE: You must disable the banner and the console logging

# to allow the STDIO transport to work !!!

spring.main.banner-mode=off

# logging.pattern.console=

spring.ai.mcp.server.name=my-mcp-server

spring.ai.mcp.server.version=0.0.1

spring.ai.mcp.server.sse-message-endpoint=/message

ServerApplication(启动类)

package org.springframework.ai.mcp.sample.server;

import java.util.List;

import java.util.concurrent.CountDownLatch;

import io.modelcontextprotocol.server.McpServerFeatures.SyncToolSpecification;

import io.modelcontextprotocol.server.McpSyncServer;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.ai.mcp.McpToolUtils;

import org.springframework.ai.support.ToolCallbacks;

import org.springframework.ai.tool.ToolCallbackProvider;

import org.springframework.ai.tool.method.MethodToolCallbackProvider;

import org.springframework.boot.CommandLineRunner;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication

@RestController

public class ServerApplication {

private static final Logger logger = LoggerFactory.getLogger(ServerApplication.class);

CountDownLatch latch = new CountDownLatch(1);

public static void main(String[] args) {

SpringApplication.run(ServerApplication.class, args);

}

@GetMapping("/updateTools")

public String greeting() {

latch.countDown();

return "Update signal received!";

}

@Bean

public ToolCallbackProvider weatherTools(WeatherService weatherService) {

return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();

}

@Bean

public CommandLineRunner commandRunner(McpSyncServer mcpSyncServer) {

return args -> {

logger.info("Server: " + mcpSyncServer.getServerInfo());

latch.await();

List<SyncToolSpecification> newTools = McpToolUtils

.toSyncToolSpecifications(ToolCallbacks.from(new MathTools()));

for (SyncToolSpecification newTool : newTools) {

logger.info("Add new tool: " + newTool);

mcpSyncServer.addTool(newTool);

}

logger.info("Tools updated: ");

};

}

}

WeatherService(查询天气服务)

/*

* Copyright 2025 - 2025 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* https://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.springframework.ai.mcp.sample.server;

import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import com.fasterxml.jackson.annotation.JsonProperty;

import org.springframework.ai.chat.model.ToolContext;

import org.springframework.ai.tool.annotation.Tool;

import org.springframework.ai.tool.annotation.ToolParam;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestClient;

@Service

public class WeatherService {

private final RestClient restClient;

public WeatherService() {

this.restClient = RestClient.builder()

.defaultHeader("Accept", "application/geo+json")

.defaultHeader("User-Agent", "WeatherApiClient/1.0 (your@email.com)")

.build();

}

@JsonIgnoreProperties(ignoreUnknown = true)

public record WeatherResponse(@JsonProperty("current") Current current) { // @formatter:off

public record Current(

@JsonProperty("time") LocalDateTime time,

@JsonProperty("interval") int interval,

@JsonProperty("temperature_2m") double temperature_2m) {

}

} // @formatter:on

@Tool(description = "Get the temperature (in celsius) for a specific location") // @formatter:off

public WeatherResponse weatherForecast(

@ToolParam(description = "The location latitude") double latitude,

@ToolParam(description = "The location longitude") double longitude,

ToolContext toolContext) { // @formatter:on

WeatherResponse weatherResponse = restClient

.get()

.uri("https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}¤t=temperature_2m",

latitude, longitude)

.retrieve()

.body(WeatherResponse.class);

return weatherResponse;

}

}

启动服务

调试验证

这里直接使用idea的扩展插件通义灵码做的测试,大家也可以用cursor或trae进行测试

这里就可以看到自己写好的mcp服务了

对话测试

http://www.xdnf.cn/news/908605.html

相关文章:

  • 【Block总结】DBlock,结合膨胀空间注意模块(Di-SpAM)和频域模块Gated-FFN|即插即用|CVPR2025
  • FineReport模板认证找不到模板
  • pyarmor加密python程序
  • 【DAY41】简单CNN
  • 深入浅出Java ParallelStream:高效并行利器还是隐藏的陷阱?
  • 【使用conda】安装pytorch
  • python:基于pyside6的桌宠源码分享
  • java面试场景提题:
  • 全球知名具身智能/AI机器人实验室介绍之AI FACTORY基于慕尼黑工业大学
  • 数字孪生:如同为现实世界打造的“克隆体”,解锁无限可能
  • RabbitMQ 队列模式
  • CRM管理软件的审批流程设计与优化:提升企业运营效率的关键策略
  • DLL动态库实现文件遍历功能(Windows编程)
  • 浅谈不同二分算法的查找情况
  • hot100 -- 8.二叉树系列
  • 3D Web轻量化引擎HOOPS Communicator的定制化能力全面解析
  • LlamaIndex 工作流简介以及基础工作流
  • Linux驱动:class_create、device_create
  • java面试场景题:电商平台中订单未⽀付过期如何实现⾃动关单
  • 本地部署企业邮箱,让企业办公更安全高效
  • 【51单片机】0. 基础软件安装
  • Blazor-表单提交的艺术:如何优雅地实现 (下)
  • WorldExplorer:基于文本生成的可探索3D虚拟世界
  • 深克隆java对象的方式
  • 基于 openEuler 22.03 LTS SP1 构建 DPDK 22.11.8 开发环境指南
  • Xshell 详细安装与配置教程:从下载到高效使用
  • error: subprocess-exited-with-error【已解决】
  • docker 部署redis集群 配置
  • 【学习笔记】单例类模板
  • 深入理解二叉搜索树:原理到实践