前言

人工智能技术的快速发展正在深刻改变软件开发的方式。众多AI编程工具通过智能代码补全、自然语言转代码等功能,显著提升了开发效率。这些工具不仅能够理解开发者的意图,还能自动生成高质量的代码片段,甚至协助完成复杂业务逻辑的构建。随着AI技术的持续迭代,AI编程工具正从辅助角色向协作伙伴转变,开发者与AI的协同模式逐渐成为行业新常态。

MCP(Model Context Protocol)

是 Anthropic 设计的一种开源协议,主要用于优化大规模语言模型(LLM)的上下文管理。相关信息可以在这里查看

  1. 核心功能
  • 上下文窗口扩展:通过动态管理输入输出的上下文长度,提升模型处理长文本任务的效率,避免传统固定窗口的局限性。
  • 多模态数据支持:支持文本、图像、结构化数据等多种形式的上下文输入,增强模型在复杂场景下的适应性。
  • 资源优化:通过压缩和选择性缓存技术,降低长上下文场景下的计算和内存开销。
  • 开源与标准化:提供统一的接口规范,便于开发者集成到不同框架中(如 transformers),促进生态协作。
  1. MCP 的发展趋势
  • 长程依赖处理:未来可能进一步优化对超长文本(如书籍、代码库)的连贯性理解能力,结合稀疏注意力等技术减少计算成本。
  • 实时交互增强:面向对话式 AI,探索低延迟的上下文更新机制,适用于客服、教育等实时场景。
  • 跨模型兼容性:推动与其他协议(如 OpenAI 的 ChatML)的兼容,形成行业通用的上下文管理标准。
  • 安全与隐私:引入端到端加密或差分隐私技术,确保敏感上下文数据(如医疗记录)的安全处理。

当前 MCP 仍处于早期阶段,但其开源特性与模块化设计为后续迭代提供了灵活性,可能成为 LLM 基础设施中的重要组件。将AI工具与自定义MCP服务相结合,本质上是通过软件定义硬件的能力突破。这种技术路径既能保留硬件稳定性优势,又能利用AI的动态优化能力,为传统嵌入式系统注入新的可能性。
简单来说就是自行编写自己需要的接口,实现通过AI对话调用,包括但不限于本地电脑的硬件端口操作(本文主要就以嵌入式开发比较常用的串口演示),目前又有非常多优秀的MCP服务可以在网上找到,比如魔搭社区

自定义MCP服务

实现自定义MCP服务的方式有很多种,本文使用spring boot基于SpringAI来手把手带着各位看官实现:
在这里插入图片描述
在这里插入图片描述
勾选上Model Context Protocol ServerSpring Web
在这里插入图片描述
重命名这个文件(个人习惯,不该改也行,只是格式有一点点区别)
在这里插入图片描述
在文件中添加必要配置参数,关键还是ai节点部分:

spring:
  application:
    name: serial_server

  ai:
    mcp:
      server:
        enabled: true
        name: mcp_serial_server
        version: 1.0.0
        sse-endpoint: /mcp/serial/v1/sse      # 自定义后续接入会用到
        sse-message-endpoint: /mcp/serial/v1/mcp
        type: SYNC
        capabilities:
          tool: true
server:
  port: 8000

logging:
  level:
    io.modelcontextprotocol: TRACE
    org.springframework.ai.mcp: TRACE

在这里插入图片描述
在pom.xml文件中添加必要依赖:

<!--串口开发依赖-->
        <dependency>
            <groupId>com.fazecast</groupId>
            <artifactId>jSerialComm</artifactId>
            <version>2.10.4</version>
        </dependency>
        <!--其他工具类依赖 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>33.4.0-jre</version>
        </dependency>

在这里插入图片描述
添加需要的jar包jSerialComm-2.10.4.jar
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来就可以开始写代码了(为了缩减篇幅,删除了一些注释,尽量以最容易理解的方式实现),
新建SerialManager类主要内容如下:
在这里插入图片描述

import com.fazecast.jSerialComm.SerialPort;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SerialManager {
    public static SerialPort userSerial;

    @Tool(description = "获取端口列表")
    public static List<String> findPorts() {
        // 获得当前所有可用串口
        SerialPort[] serialPorts = SerialPort.getCommPorts();
        List<String> portNameList = new ArrayList<>();
        // 将可用串口名添加到List并返回该List
        for (SerialPort serialPort : serialPorts) {
            portNameList.add(serialPort.getSystemPortName());
        }
        portNameList = portNameList.stream().distinct().collect(Collectors.toList());   //去重
        return portNameList;
    }


    @Tool(description = "打开端口")
    public static SerialPort openPort(@ToolParam(required = true, description = "端口名字")String portName,
                                      @ToolParam(required = true, description = "波特率")Integer baudRate) {
        if(baudRate==0)
        {
            baudRate = 115200;
        }
        // 设置串口参数
        userSerial = SerialPort.getCommPort(portName);
        userSerial.setBaudRate(baudRate);
        userSerial.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
        userSerial.setComPortParameters(baudRate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
        userSerial.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
        //开启串口
        if (!userSerial.isOpen()) {
            userSerial.openPort(1000);
        } else {
            return userSerial;
        }
        return userSerial;
    }

    
    @Tool(description = "关闭端口")
    public static void closePort() {
        if (userSerial != null && userSerial.isOpen()) {
            userSerial.closePort();
        }
    }


    @Tool(description = "发送字节数组")
    public static void sendToPort(@ToolParam(required = true, description = "需要发送的数据缓存")byte[] content,
                                  @ToolParam(required = true, description = "需要发送的字节数")Integer len) {
        if (!userSerial.isOpen()) {
            return;
        }
        userSerial.writeBytes(content, len);
    }
    
    @Tool(description = "读取字节数组")
    public static byte[] readFromPort() {
        byte[] reslutData = null;
        if (!userSerial.isOpen()) {
            return null;
        }

        if (userSerial.bytesAvailable() > 0) {
            byte[] readBuffer = new byte[userSerial.bytesAvailable()];
            int numRead = userSerial.readBytes(readBuffer, readBuffer.length);
            if (numRead > 0) {
                reslutData = readBuffer;
            }
        }
        return reslutData;
    }
}

代码中接口上面的@Tool(description = “”)是对应方法的描述,参数前面的
@ToolParam(required = true, description = “”)是对参数的描述,这些描述信息在被AI工具连接后作为接口提示存在,也是帮助AI联想到对应接口,应该尽量准确。

直接在SerialServerApplicationSerialManager注入到容器中:

@Bean
public ToolCallbackProvider serialManager(){
      return MethodToolCallbackProvider.builder().toolObjects(new SerialManager()).build();
  }

在这里插入图片描述
运行成功后在Console窗口中就可以看到启动的端口信息(application.yml中配置的)
在这里插入图片描述
先使用postman测试一下(如果没有这选项,选择最新版本注册并登录账号即可):
在这里插入图片描述
选择http方式
在这里插入图片描述
url输入http://localhost:8000/mcp/serial/v1/sse,端口后面这边部分就是application.yml文件中的sse-endpoint:配置。输入好后点击<Connect即可(有时候需要点击多次),连接成功后就会列出我们在SerialManager实现的方法:
在这里插入图片描述
选中对用方法,点击Run即可获取到返回值:
在这里插入图片描述
连接对应COM口,可以看到参数窗口上有参数对应的解释:
在这里插入图片描述
需要发送数据选中发送方法填入参数即可
在这里插入图片描述
这个看起来就熟悉了:
/direct/c3f7eefa7af94c40b79c5e2001c35ca0.png)
postman就测试到这里,接下来试试Cursor接入,打开软件,点击设置:
在这里插入图片描述
在这里插入图片描述
打开的json文件中填入如下信息(my-mcp-server: 在MCP Tools列表中显示的名字):

{
    "mcpServers": {
      "my-mcp-server": {
        "type": "sse",
        "url": "http://localhost:8000/mcp/serial/v1/sse"
      }
    }
  }

在这里插入图片描述
编辑好保存后关闭文件,在Cursor Settings界面中就可以看到对应MCP服务:
在这里插入图片描述
点击右侧的开关(有时需要多点两次),连接成功后如下:
在这里插入图片描述
点击如下位置就可以看到暴露出来的接口:
在这里插入图片描述
在这里插入图片描述
鼠标停在接口名字上就可以看到接口介绍和参数简介:
在这里插入图片描述
现在试试看使用对话的方式能否调用这些接口:
打开一个对话框,输入“获取本地端口列表“,意思相近即可:
在这里插入图片描述
点击Run Tool后就会得到返回值:
在这里插入图片描述
我本地有COM1和COM2端口是连接上的,也就是这2个端口可以相互收发数据,AI这边连接COM1,并发送数据看串口助手里面能否接收到对应内容:
在这里插入图片描述
串口助手这边发送几个数据看AI这边能否接收到:
在这里插入图片描述
到此Cursor就测试完成了,如果需要接入网上其他MCP服务,方法基本类似。
再来看看VScode中集成的通义灵码能否接入,基本要求和添加步骤(通义灵码的安装网上教程还是比较多就不再重复了):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
MCP广场选择中有一些MCP服务可以使用,这里我们直接手动添加刚才写的服务:
在这里插入图片描述
名称随意,类型选择SSE或HTTP,服务地址还是postman那个,编辑完后点击立即添加:
在这里插入图片描述
连接成功后就可以看熟悉的几个接口:
在这里插入图片描述
点击左上角智能会话,测试一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过以上测试基本验证了AI工具与硬件接口之间实现交互。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐