MCP:LLM与知识库之间的通信协议—(2) 简单实现

引言

上一部分,简单介绍了什么是MCP协议,并根据官方示例实现了一个STDIO模式的。不过STDIO模式的一般只适用于本地使用,不适合网络共享。同时,由于写上文时,关于Client与SSE服务器的BUG未处理完毕,故在本文主要是展示一下这俩东西的代码。

STDIO实现

见上一部分,或者见下方Github,本部分不再指赘述。

SSE模式实现

导入以来

在STDIO下,我们导入的包为

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>

而在SSE下,本部分改用了webmvc模式的mcp-server开发依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

可见,该依赖是上一依赖的超集,多出了spring-boot-starter-web以及mcp-spring-webmvc

实际上仅需这一步,就能将STDIO转成SSE了,不需要再做任何额外更改,这也算是Spring Boot的优势。

定义工具

与STDIO类似,但由于使用网络连接,其编码格式为UTF-8。不需要再像STDIO(window系统)模式一样需要先把编码转回GBK再转到UTF-8了。

java 复制代码
@Service
public class WeatherService {

    // 响应模板,自然语句格式
    private static final String RESPONSE_TEMPLATE = """
            %s的天气为%s, 气温为%s
            """;

    private final RestClient restClient;

    public WeatherService() {
        String apiUrl = "http://apis.juhe.cn/simpleWeather/query";
        this.restClient = RestClient.builder()
                .baseUrl(apiUrl)
                .defaultHeader("Content-Type", "application/x-www-form-urlencoded")
                .defaultHeader("Accept", "application/json")
                .defaultHeader("User-Agent", "WeatherApiClient/1.0")
                .build();
    }

    @Tool(description = "获得中国的天气信息")
    public String getWeather(
            @ToolParam(description = "城市") String city
    ) throws UnsupportedEncodingException {

        String apiKey = "xxxxxxxxx";
        // 发起网络连接
        RestClient.ResponseSpec retrieve = this.restClient.get()
                .uri("?key=" + apiKey + "&city=" + city)
                .retrieve();
        WeatherPojo body = retrieve.body(WeatherPojo.class);
        try {
            return String.format(RESPONSE_TEMPLATE,
                    city,
                    body.getResult().getRealtime().getInfo(),
                    body.getResult().getRealtime().getTemperature()
            );
        } catch (NullPointerException e) {
            return "抱歉,我无法获取到" + city + "的天气信息";
        }
    }
}

与STDIO相同

java 复制代码
@SpringBootApplication
public class McpServerSseApplication {

    public static void main(String[] args) {
        SpringApplication.run(McpServerSseApplication.class, args);
    }

    // 需要先把对应的类注册为工具
    @Bean
    public ToolCallbackProvider weatherTools(WeatherService weatherService) {
        return  MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
    }
}

Client实现

依赖导入

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>

配置信息

有两种配置方式,命令模式与sse模式

json 复制代码
{
  "mcpServers": {  // 这是必须的
    "mcp-server": {  // 名字自己起
      "command": "java",
      "args": [
        "-jar",
        "D:\Documents\IdeaProjects\mcp-server\target\mcpserver-0.0.1-SNAPSHOT.jar"
      ]
    },
    "sse-server": {  // 名字自己起
        "url": "http://localhost:8080/sse"
    }
  }
}
ini 复制代码
// 这个是要有的,不然tools无法被自动注册
spring.ai.mcp.client.toolcallback.enabled=true

下面是Spring AI的文档内容

When tool callbacks are enabled, the registered MCP Tools with all MCP clients are provided as a ToolCallbackProvider instance:

构造Chat客户端

java 复制代码
@Configuration
public class ChatClientConfig {

    @Bean
    // 必须spring.ai.mcp.client.toolcallback.enabled=true
    // ToolCallbackProvider才能被导入
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) {
        return chatClientBuilder
                .defaultTools(tools)
                .build();
    }
}

主函数

在 Spring Boot 完成应用上下文初始化并启动后立即运行。CommandLineRunner 是 Spring Boot 提供的一个接口,用于在应用启动后执行一些自定义逻辑。

java 复制代码
@SpringBootApplication
public class McpClientApplication  {

    @Autowired
    private ChatClient chatClient;

    public static void main(String[] args) {
        SpringApplication.run(McpClientApplication.class, args);
    }

    @Bean
    public CommandLineRunner predefinedQuestions(ConfigurableApplicationContext context) {

        return args -> {
            System.out.println(">>> ASSISTANT: " + chatClient
                    .prompt()
                    .user("今天福州这个城市天气怎么样")
                    .call()
                    .content());
            context.close();
        };
    }
}

GitHub

具体的代码以及依赖在该代码库里 github.com/Vocal-map/m...

相关推荐
码哥字节6 小时前
码哥实测:写了20行SKILL.md,Claude的代码质量提升了一倍
agent·mcp
qdprobot7 小时前
AIcam智能ESP32视觉摄像头体识万物
人工智能·esp32s3·图形化编程·mcp·mixly小智ai
一心同学8 小时前
MCP:Agent 时代的“USB-C”,还是新的供应链风险?
安全·agent·mcp
TickDB9 小时前
统一行情 API 查 A 股、港股、美股和数字货币:code=0 不代表 symbol 一个没少
人工智能·python·websocket·mcp·行情数据 api
星野云联AIoT技术洞察15 小时前
AG-UI 在 IoT 控制台里怎么落地:设备状态、命令确认与人机协同
ai agent·技术方案·mcp·ag-ui·平台架构·命令确认·iot设备控制
砍光二叉树1 天前
一文打通 AI 认知:LLM、Agent、MCP、Skill 完整体系
人工智能·llm·agent·skill·mcp
MageGojo1 天前
R-Shell开源项目实战解析:用Rust打造命令行SSH工具,支持连接管理、远程执行、SFTP与MCP
运维·rust·开源项目·命令行工具·ssh客户端·mcp
deepdata_cn1 天前
AI大模型通用上下文标准(MCP)
人工智能·mcp
宋哥转AI2 天前
@Tool写了但tools/list为空?Spring AI MCP Server注册的两种路径和四个坑
java·agent·mcp