MCP服务端开发:图片搜索助力旅游计划

MCP-图片搜索MCP服务端开发

旅游计划如果是些文字 ,干巴巴没有吸引力,那我们就可以搜索一些景点相关的图片,添加到PDF中

接口盒子

"接口盒子"提供各种免费的API接口,集群服务器保障服务稳定,五年稳定运营。

官方网址:接口盒子 - 免费API-免费接口-站长工具-www.apihz.cn

接口盒子测试

进入官网完成注册并登录后进入首页会有一个KEY点击复制

测试接口

我们需要图片搜索功能,点击平台功能==>接口列表,在搜索框输入【图片搜索】关键字,可以搜索出两个接口,一个百度源,一个搜狗源

我们已百度源为例,点击进入接口文档

可以直接访问下面可以获取最优的接口

服务器的情况我们以了解,那怎么调用接口呢,继续往下发现可以直接使用GET请求进行测试,并且他以换成了你的ID和KEY

复制到浏览器地址栏进行测试

开发MCP服务

接口测试通过后,我们就需要将他开发成MCP服务,提供给旅游大师使用

创建MCP服务端项目

为保证项目的集中,我们直接在travel-ai-agent项目根目录下创建module

创建一个名为image-search-mcp-server的SpringBoot子模块:

注意创建好之后的子模块需要在新窗口打开

引入必要的依赖

XML 复制代码
<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.8.38</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
			<version>1.0.0-M6</version>
		</dependency>

编写服务端配置文件

我们先编写appliaction.yml配置文件:

XML 复制代码
spring:
  application:
    name : image-search-mcp-server
  profiles:
    active: stdio

server:
  port: 8666

为了演示STDIO和SSE两种模式的区别,我们编写两套配置文件分别实现stdio和sse模式的传输

1.stdio配置文件application-stdio.yml:

XML 复制代码
ai:
  mcp:
    name: image-search-mcp-server
    version: 0.0.1
    type: SYNC
    stdio: true
main:
  web-application-type: none
  banner-mode: off
interface-box:
  api:
    image-search-url: https://cn.apihz.cn/api/img/apihzimgbaidu.php
  id: ${INTERFACE_BOX_ID}
  key: ${INTERFACE_BOX_KEY}
spring:
  profiles:
    active: dev

SSE配置文件application-sse.yml:

XML 复制代码
ai:
  mcp:
    name: image-search-mcp-server
    version: 0.0.1
    type: SYNC
    stdio: false
interface-box:
  api:
    image-search-url: https://cn.apihz.cn/api/img/apihzimgbaidu.php
  id: ${INTERFACE_BOX_ID}
  key: ${INTERFACE_BOX_KEY}
spring:
  profiles:
    active: dev

开发ImageSearchTool图片搜索工具

配置完成我们就可以开始编写图片搜索的工具了

1.新建一个tools包并创建ImageSearchTool:

java 复制代码
@Slf4j
@Service
public class ImageSearchTool {
    @Value("${interface-box.api.image-search-url}")
    private String apiUrl;
    @Value("${interface-box.key}")
    private String apiKey;
    @Value("${interface-box.id}")
    private String apiId;

    /**
     * 搜索图片
     * @param keyword 搜索关键词
     * @return 搜索结果字符串
     */
    @Tool(description = "Search for images by keyword")
    public String searchImage(
            @ToolParam(description = "The keyword to search for images", required = true)
            String keyword){
        log.info("AI 调用searchImage工具搜索图片,关键词: {}", keyword);
        
        try {
            // 使用配置文件中的参数构建URL
            String url = apiUrl + "?id=" + apiId + "&key=" + apiKey + "&limit=10&page=1&words=" + keyword;
            
            log.info("图片搜索请求URL: {}", url);
            
            // 发送HTTP GET请求
            String response = HttpUtil.get(url);
            log.info("图片搜索API响应: {}", response);
            
            // 解析JSON响应
            JSONObject jsonObject = JSONUtil.parseObj(response);
            int code = jsonObject.getInt("code");
            
            if (code == 200) {
                // 构建返回结果
                StringBuilder result = new StringBuilder();
                result.append("图片搜索结果:\n");
                result.append("关键词:").append(keyword).append("\n");
                result.append("总数量:").append(jsonObject.getInt("count")).append("\n");
                result.append("当前页码:").append(jsonObject.getInt("page")).append("\n");
                result.append("最大页码:").append(jsonObject.getInt("maxpage")).append("\n");
                result.append("图片链接:\n");
                
                // 获取图片链接列表
                List<String> imageUrls = jsonObject.getBeanList("res", String.class);
                for (int i = 0; i < imageUrls.size(); i++) {
                    result.append(i + 1).append(". " ).append(imageUrls.get(i)).append("\n");
                }
                
                return result.toString();
            } else {
                // 错误处理
                String errorMsg = jsonObject.getStr("msg");
                log.error("图片搜索失败,错误信息: {}", errorMsg);
                return "图片搜索失败:" + errorMsg;
            }
        } catch (Exception e) {
            log.error("图片搜索异常", e);
            return "图片搜索异常:" + e.getMessage();
        }
    }
}

注册工具

编写了工具我们还要将他们注册为MCP服务集合,我们可以直接在Application主类,通过定义ToolCallbackProvider Bean来注册工具

修改 ImageSearchMcpServerApplication 主类:

打包模块

至此,我们搜索图片的MCP服务端,以开发完成,但是要使用还是要将他打成jar包,方便运行和部署。

打开Maven视图,并双击生命周期中的package打包,可以跳过测试如下所示:

编译打包后,在target目录中确认jar包正常生成成功

MCP-调用图片搜索MCP服务(STDIO模式)

服务端我们开发完成后,就可以开始进行客户端调用了,首先我们使用STDIO模式下进行调用,在上一章高德地图MCP时,就是用的此模式

配置图片搜索MCP服务

我们切换回travel-ai-agent主项目进行开发

确认必要的MCP客户端依赖:

创建或修改mcp-servers-config.json

在上一章我们以在配置高德地图时以创建了该配置文件,如果没创建的可以去resources目录下创建,并配置

java 复制代码
  "image-search": {
      "command": "java",
      "args": [
        "-Dspring.profiles.active=stdio",
        "-Dlogging.pattern.console=",
        "-jar",
        "image-search-mcp-server/target/image-search-mcp-server-0.0.1-SNAPSHOT.jar"
      ],
      "env": {
        "INTERFACE_BOX_ID": "你的ID",
        "INTERFACE_BOX_KEY":"你的KEY"
      }
    }

测试调用图片搜索MCP

运行testMCP测试方法

可以看到正确的执行了图片搜索并输出内容

MCP-调用图片搜索MCP服务(STDIO模式)

学会了STDIO模式,我们再来了解如何使用SSE模式

配置图片搜索MCP服务为SSE模式

在主项目travel-ai-agent中修改application-dev.yml

注释之前stdio的配置,添加sse配置,sse需要指定连接MCP服务的地址

运行图片搜索MCP服务器

启动ImageSearchMcpServerApplication主类

观察启动日志看到

说明我们的application-sse.yml配置成功,启动没有报错,环境变量也是生效的

测试调用图片搜索MCP

我们先要把之前配置的json给删除不然会有两个图片搜索的类冲突

再次测试

运行成功

相关推荐
我命由我123452 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
赛姐在努力.2 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
yxc_inspire2 小时前
Java学习第二天
java·面向对象
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 基于net超市销售管理系统为例,包含答辩的问题和答案
java
昀贝2 小时前
IDEA启动SpringBoot项目时报错:命令行过长
java·spring boot·intellij-idea
roman_日积跬步-终至千里3 小时前
【LangGraph4j】LangGraph4j 核心概念与图编排原理
java·服务器·数据库
野犬寒鸦3 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
wenzhangli73 小时前
ooderA2UI BridgeCode 深度解析:从设计原理到 Trae Solo Skill 实践
java·开发语言·人工智能·开源
HalvmånEver3 小时前
Linux:线程互斥
java·linux·运维