一、介绍

        官方文档:模型上下文协议(Model Context Protocol, MCP)可帮助大模型使用外部工具与数据,相比 Function Calling,MCP 更灵活且易于使用。

        咱们用生活化的比喻,一分钟讲明白:

1. 核心定位

        MCP(模型上下文协议)和 Function Calling(函数调用)做的是同一件事:帮大模型 “借力”—— 调用外部工具(比如查天气、算数据、查数据库)、访问外部数据,弥补大模型自身的不足(比如不会实时查数据、算复杂公式)。

2. 关键差异:Function Calling vs MCP

1. Function Calling(函数调用):“格式化填表”

就像你去银行办业务,必须填固定格式的申请表:

  • 要调用工具,得先严格定义好 “函数名、参数格式、返回格式”(比如必须写 get_weather(city="北京"),少一个引号、错一个参数名就不行);
  • 交互方式固定:大模型发一次调用请求,工具返回一次结果,流程死板;
  • 开发 / 使用门槛高:得专门写 “格式说明书(Schema)”,新手容易卡格式错误。

2. MCP(模型上下文协议):“自然对话”

就像你跟客服说话,不用填表单,直接说需求就行:

  • 不用严格定义格式,大模型可以用自然语言和工具 “沟通”(比如直接说 “帮我查下北京今天的天气”,工具就能理解);
  • 交互更灵活:工具返回结果后,大模型还能追问、调整需求(比如 “再查下上海的,对比下温度”),不用重新走一遍固定流程;
  • 易用性高:开发人员不用花大量时间写格式说明书,工具接入更简单,大模型使用起来也更顺滑。

3.总结

        两者都能帮大模型用外部工具,但 Function Calling 是 “按固定表单办事”,MCP 是 “按自然对话办事”,所以 MCP 更灵活(适配更多场景)、更好用(门槛低、少踩格式坑)。

二、实现

1. 获取MCP

        想要获取MCP,我们需要考虑自己要什么功能?

        这里我想要实现对目的地线路的规划,那么毫无疑问,我需要获得地图方面的支持,那么就是你了!上把高德地图!!

开发指南-Web服务 API | 高德地图API 通过该链接进入高德地图开放平台

有账号的就登录,没有的就注册一个然后注册一下开发者

接着创建一个应用

这里我们主要做线路的规划,所以应用类型我们就选择出行

添加key

命名随意,当然建议你按照官方给的规则 [应用名 + 应用场景]

然后选择web服务平台,下面就会出现你可以使用的各种服务

确定后就确定好了你的MCP了

接下来我们就可以复制我们的key开始使用了,你可以去控制台查看你的额度,正常开发的话基本是够用的。

2. 部署MCP

        官方文档 大模型服务平台百炼控制台 大家可以看看,接下来是我的操作,目前部署的这个也是限时free的,大家可以去试一试,后续就算收费也是几分钱甚至更好,在账号里面充个十块钱,方便我们后续学习。

1.搜索 Amap Maps

2.开通服务并输入我们的key

3.将MCP添加到单智能体中

然后就会自动跳转到我们的智能体应用当中了,这个时候下滑就可以看到高德地图的所有MCP都已经接入到了我们的智能体之中了,之后就发布就可以了。

3.代码修改

基于上一文章 千问通义plus - 代码解释器的使用-CSDN博客 一文,我来做一下代码的修改

1.新增appId

在类中新增 appid 的配置注入(与现有 apiKey/model 同级):


    @Value("${spring.ai.dashscope.agent.options.app-id}")
    private String appId;

2.在 GenerationParam 中传递 appid

GenerationParam param = GenerationParam.builder()
        .model(model) // 如 qwen-plus
        .apiKey(apiKey)
        .messages(messages)
        .tools(Collections.unmodifiableList(toolFunctions)) // 替换为包含Java工具的列表
        .enableSearch(true) // 启用联网搜索
        .resultFormat(GenerationParam.ResultFormat.MESSAGE)
        .incrementalOutput(true) // 流式输出
        .headers(Collections.singletonMap("X-DashScope-AppID", appId))
        .build();

3.完整代码

// 省略原有无关代码,仅展示修改部分
@Slf4j
@Service
@RequiredArgsConstructor
public class DashScopeServiceImpl implements DashScopeService {
    // 缓存工具类(原有)
    private final ChatContextCacheUtil chatContextCacheUtil;

    // 通义千问配置(原有 + 新增 appid)
    @Value("${spring.ai.dashscope.api-key}")
    private String apiKey;
    @Value("${spring.ai.dashscope.model}")
    private String model;
    @Value("${spring.ai.dashscope.app-id}") // 新增 appid 配置
    private String appId;

    // 聚合数据天气接口配置(原有)
    @Value("${jute.weather.api-key}")
    private String juheWeatherApiKey;

    // 其他原有配置...

    @Override
    public SseEmitter streamChat(ChatRequestDTO requestDTO, HttpServletResponse response) {
        // 原有逻辑...
        // 构建 GenerationParam 时添加 headers 传递 appid
        GenerationParam param = GenerationParam.builder()
                .model(model)
                .apiKey(apiKey)
                .messages(messages)
                .tools(Collections.unmodifiableList(toolFunctions))
                .enableSearch(true)
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .incrementalOutput(true)
                .headers(Collections.singletonMap("X-DashScope-AppID", appId)) // 新增
                .build();
        // 原有逻辑...
    }

    // 其他原有方法保持不变...
}

4.结果

这里的数据都变成一个类被输出了,估计是因为前面的代码解释器没有做好内容鉴别,这个需要在智能体中写好逻辑判断的话语,后续我会修改好代码,或者大家可以使用我 Springboot调用单智能体-CSDN博客 这一版的代码。

如果你有任何疑问都可以私信或者评论区留言,如果你觉得我写的还行,可以点点关注

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐