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...

相关推荐
TGITCIC2 小时前
智驱未来:AI大模型重构数据治理新范式
大模型·数据治理·ai agent·rag检索增强·mcp·大模型数据·ai数据
吏部侍郎3 小时前
从“玩”到“用”:LLM + MCP 如何真正赋能业务?——继续深挖信贷风控场景
mcp
justdoit5213 小时前
前端的AI路其之三:用MCP做一个日程助理
前端·aigc·mcp
掉鱼的猫4 小时前
能用 Java8 开发 MCP(或 MCP Server),这才是 MCP 自由(Solon AI MCP)!
java·spring·mcp
唐诗4 小时前
前端也需要了解的 mcp 知识
前端·github·mcp
酱酱们的每日掘金16 小时前
🔥 4 月精选:AICoding Cursor上新与 MCP 实战揭秘!- AI Coding 周刊第 5 期
前端·ai编程·mcp
Captaincc17 小时前
手摸手教你入门到实践最全 MCP 整理
mcp
Captaincc17 小时前
分享一下有意思的Xcode 的 MCP
mcp
带刺的坐椅18 小时前
能用 Java8 开发 MCP(或 MCP Server),这才是 MCP 自由(Solon AI MCP)!
java·spring·ai·solon·mcp·mcp-server