众所周知,cursor是基于vs code魔改的一个独立应用,并不象copilot、通义灵码 这类采用plugin机制的AI辅助编码工具。在cursor-cli 与 idea MCP出来之前,只能通过idea里安装 Switch2Cursor Plugin for JetBrains IDEs | JetBrains Marketplace 插件,从idea 跳到cursor
反过来,cursor中也有1个类似插件Switch2IDEA – Open VSX Registry 可以跳回到IDEA。虽然也能凑合用吧,但是同时开着2个独立的重型应用,机器配置不够高的话,很容易卡顿,而且割裂感太强。
一、IDEA MCP server
最新版本的IDEA里,新增了 MCP 服务器 | IntelliJ IDEA 文档
127.0.0.1:64342/sse 可以访问看看,了解MCP的同学应该知道,这种sse的MCP 里通常会有一系列可用的工具(参见:spring-ai 学习系列(5)-MCP(webflux sse )
我们用cherry studio 查看一下 (不熟悉cherry studio的同学,可参见 spring-ai 学习系列(3)-MCP(stdio)
切换到工具
这就有点意思了,从工具名称来看,idea把众多对项目编码相关的能力暴露出来了。 接下来,做个实验:
- 在idea里随便打开1个项目
- 在cherry studio里随便打开1个对话,使用idea的这个mcp,要求列出当前项目的结构
cherry studio的会话中,我们使用deepseek模型,有了idea mcp的加持,deepseek正确列出了idea中当前项目的目录。
继续,我们让deepseek为com.cnblogs.yjmyzz.mcp.server.OrderService 这个类生成单元测试,看看能不能生成代码
还真可以(只是限于cherry studio的交互,代码全都挤在 json 的text字段中输出,但格式化后,生成的测试代码大致长这样:
- 1 package com.cnblogs.yjmyzz.mcp.server;
- 2
- 3 import org.junit.jupiter.api.BeforeEach;
- 4 import org.junit.jupiter.api.DisplayName;
- 5 import org.junit.jupiter.api.Test;
- 6 import org.junit.jupiter.api.extension.ExtendWith;
- 7 import org.mockito.InjectMocks;
- 8 import org.mockito.junit.jupiter.MockitoExtension;
- 9
- 10 import static org.junit.jupiter.api.Assertions.*;
- 11
- 12 /**
- 13 * OrderService单元测试类
- 14 * 使用Mockito框架进行测试
- 15 */
- 16 @ExtendWith(MockitoExtension.class)
- 17 @DisplayName("OrderService单元测试")
- 18 class OrderServiceTest {
- 19
- 20 @InjectMocks
- 21 private OrderService orderService;
- 22
- 23 @BeforeEach
- 24 void setUp() {
- 25 // 由于OrderService没有依赖其他服务,直接使用@InjectMocks即可
- 26 // 这里可以设置一些测试前的准备工作
- 27 }
- 28
- 29 @Test
- 30 @DisplayName("查询已发货订单状态 - 成功")
- 31 void queryOrderStatus_WhenOrderShipped_ShouldReturnShippedStatus() {
- 32 // Arrange
- 33 String orderNo = "25070601";
- 34 String expected = "订单号:25070601,订单状态:已发货";
- 35
- 36 // Act
- 37 String actual = orderService.queryOrderStatus(orderNo);
- 38
- 39 // Assert
- 40 assertEquals(expected, actual);
- 41 }
- 42
- 43 @Test
- 44 @DisplayName("查询已完成订单状态 - 成功")
- 45 void queryOrderStatus_WhenOrderCompleted_ShouldReturnCompletedStatus() {
- 46 // Arrange
- 47 String orderNo = "25070602";
- 48 String expected = "订单号:25070602,订单状态:已完成";
- 49
- 50 // Act
- 51 String actual = orderService.queryOrderStatus(orderNo);
- 52
- 53 // Assert
- 54 assertEquals(expected, actual);
- 55 }
- 56
- 57 @Test
- 58 @DisplayName("查询已取消订单状态 - 成功")
- 59 void queryOrderStatus_WhenOrderCancelled_ShouldReturnCancelledStatus() {
- 60 // Arrange
- 61 String orderNo = "25070603";
- 62 String expected = "订单号:25070603,订单状态:已取消";
- 63
- 64 // Act
- 65 String actual = orderService.queryOrderStatus(orderNo);
- 66
- 67 // Assert
- 68 assertEquals(expected, actual);
- 69 }
- 70
- 71 @Test
- 72 @DisplayName("查询未知订单状态 - 返回未知状态")
- 73 void queryOrderStatus_WhenOrderUnknown_ShouldReturnUnknownStatus() {
- 74 // Arrange
- 75 String orderNo = "99999999";
- 76 String expected = "订单号:99999999,订单状态:未知";
- 77
- 78 // Act
- 79 String actual = orderService.queryOrderStatus(orderNo);
- 80
- 81 // Assert
- 82 assertEquals(expected, actual);
- 83 }
- 84
- 85 @Test
- 86 @DisplayName("查询空订单号 - 返回未知状态")
- 87 void queryOrderStatus_WhenOrderNoIsEmpty_ShouldReturnUnknownStatus() {
- 88 // Arrange
- 89 String orderNo = "";
- 90 String expected = "订单号:,订单状态:未知";
- 91
- 92 // Act
- 93 String actual = orderService.queryOrderStatus(orderNo);
- 94
- 95 // Assert
- 96 assertEquals(expected, actual);
- 97 }
- 98
- 99 @Test
- 100 @DisplayName("查询null订单号 - 返回未知状态")
- 101 void queryOrderStatus_WhenOrderNoIsNull_ShouldReturnUnknownStatus() {
- 102 // Arrange
- 103 String orderNo = null;
- 104 String expected = "订单号:null,订单状态:未知";
- 105
- 106 // Act
- 107 String actual = orderService.queryOrderStatus(orderNo);
- 108
- 109 // Assert
- 110 assertEquals(expected, actual);
- 111 }
- 112
- 113 @Test
- 114 @DisplayName("查询非8位数字订单号 - 返回未知状态")
- 115 void queryOrderStatus_WhenOrderNoIsNot8Digits_ShouldReturnUnknownStatus() {
- 116 // Arrange
- 117 String orderNo = "1234567"; // 7位数字
- 118 String expected = "订单号:1234567,订单状态:未知";
- 119
- 120 // Act
- 121 String actual = orderService.queryOrderStatus(orderNo);
- 122
- 123 // Assert
- 124 assertEquals(expected, actual);
- 125 }
- 126
- 127 @Test
- 128 @DisplayName("查询包含字母的订单号 - 返回未知状态")
- 129 void queryOrderStatus_WhenOrderNoContainsLetters_ShouldReturnUnknownStatus() {
- 130 // Arrange
- 131 String orderNo = "2507060A";
- 132 String expected = "订单号:2507060A,订单状态:未知";
- 133
- 134 // Act
- 135 String actual = orderService.queryOrderStatus(orderNo);
- 136
- 137 // Assert
- 138 assertEquals(expected, actual);
- 139 }
- 140
- 141 @Test
- 142 @DisplayName("边界测试 - 最小订单号")
- 143 void queryOrderStatus_WhenOrderNoIsMinValue_ShouldReturnUnknownStatus() {
- 144 // Arrange
- 145 String orderNo = "00000000";
- 146 String expected = "订单号:00000000,订单状态:未知";
- 147
- 148 // Act
- 149 String actual = orderService.queryOrderStatus(orderNo);
- 150
- 151 // Assert
- 152 assertEquals(expected, actual);
- 153 }
- 154
- 155 @Test
- 156 @DisplayName("边界测试 - 最大订单号")
- 157 void queryOrderStatus_WhenOrderNoIsMaxValue_ShouldReturnUnknownStatus() {
- 158 // Arrange
- 159 String orderNo = "99999999";
- 160 String expected = "订单号:99999999,订单状态:未知";
- 161
- 162 // Act
- 163 String actual = orderService.queryOrderStatus(orderNo);
- 164
- 165 // Assert
- 166 assertEquals(expected, actual);
- 167 }
- 168 }
复制代码 View Code 这说明:有了IDEA开放的MCP能力,任何1个有推理能力的LLM,再挂1套MCP host和UI,理论上都可以手搓成1个AI编码辅助神器!
二、Cursor CLI
命令行界面(CLI) · Cursor 根据这份cursor官网的介绍,cursor可以在任何终端以cli 方式运行。- curl https://cursor.com/install -fsS | bash
复制代码 只要这一行命令即可。注:windows上必须借助WSL (不熟悉wsl的同学可参考windows WSL2避坑指南 ),在wsl环境中使用该命令安装(比如:先wsl安装ubuntu,然后在ubuntu虚拟子环境中安装)
安装完后,就可以直接问一些编码相关的问题了
cursor也是支持MCP的,我们在cursor中,把IDEA的mcp地址也配置上
三、idea中设置terminal 为wsl
注:只有windows上需要设置成wsl.exe (mac / linux下,正常设置默认terminal即可)
最终运行效果:idea中切换到terminal时,自动启动wsl环境,然后输入cursor-agent,自动将上下文切换到当前目录
唯一美中不足:虽然wsl的cursor-cli 也正确添加了mcp server,也通curl 访问到,但是cursor-cli 连接时总是报405,看上去是授权问题,如有园友知晓解法,请回复,感谢
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |