找回密码
 立即注册
首页 业界区 安全 idea与cursor的整合方案

idea与cursor的整合方案

山真柄 10 小时前
众所周知,cursor是基于vs code魔改的一个独立应用,并不象copilot、通义灵码 这类采用plugin机制的AI辅助编码工具。在cursor-cli 与 idea MCP出来之前,只能通过idea里安装 Switch2Cursor Plugin for JetBrains IDEs | JetBrains Marketplace 插件,从idea 跳到cursor
1.png

反过来,cursor中也有1个类似插件Switch2IDEA – Open VSX Registry 可以跳回到IDEA。虽然也能凑合用吧,但是同时开着2个独立的重型应用,机器配置不够高的话,很容易卡顿,而且割裂感太强。
 
一、IDEA MCP server
最新版本的IDEA里,新增了 MCP 服务器 | IntelliJ IDEA 文档
2.png

127.0.0.1:64342/sse 可以访问看看,了解MCP的同学应该知道,这种sse的MCP 里通常会有一系列可用的工具(参见:spring-ai 学习系列(5)-MCP(webflux sse )
3.png

我们用cherry studio 查看一下 (不熟悉cherry studio的同学,可参见 spring-ai 学习系列(3)-MCP(stdio) 
4.png

切换到工具
5.png

这就有点意思了,从工具名称来看,idea把众多对项目编码相关的能力暴露出来了。 接下来,做个实验:

  • 在idea里随便打开1个项目
  • 在cherry studio里随便打开1个对话,使用idea的这个mcp,要求列出当前项目的结构
6.png

 cherry studio的会话中,我们使用deepseek模型,有了idea mcp的加持,deepseek正确列出了idea中当前项目的目录。
继续,我们让deepseek为com.cnblogs.yjmyzz.mcp.server.OrderService 这个类生成单元测试,看看能不能生成代码
7.png

还真可以(只是限于cherry studio的交互,代码全都挤在 json 的text字段中输出,但格式化后,生成的测试代码大致长这样:
8.gif
9.gif
  1.   1 package com.cnblogs.yjmyzz.mcp.server;
  2.   2
  3.   3 import org.junit.jupiter.api.BeforeEach;
  4.   4 import org.junit.jupiter.api.DisplayName;
  5.   5 import org.junit.jupiter.api.Test;
  6.   6 import org.junit.jupiter.api.extension.ExtendWith;
  7.   7 import org.mockito.InjectMocks;
  8.   8 import org.mockito.junit.jupiter.MockitoExtension;
  9.   9
  10. 10 import static org.junit.jupiter.api.Assertions.*;
  11. 11
  12. 12 /**
  13. 13  * OrderService单元测试类
  14. 14  * 使用Mockito框架进行测试
  15. 15  */
  16. 16 @ExtendWith(MockitoExtension.class)
  17. 17 @DisplayName("OrderService单元测试")
  18. 18 class OrderServiceTest {
  19. 19
  20. 20     @InjectMocks
  21. 21     private OrderService orderService;
  22. 22
  23. 23     @BeforeEach
  24. 24     void setUp() {
  25. 25         // 由于OrderService没有依赖其他服务,直接使用@InjectMocks即可
  26. 26         // 这里可以设置一些测试前的准备工作
  27. 27     }
  28. 28
  29. 29     @Test
  30. 30     @DisplayName("查询已发货订单状态 - 成功")
  31. 31     void queryOrderStatus_WhenOrderShipped_ShouldReturnShippedStatus() {
  32. 32         // Arrange
  33. 33         String orderNo = "25070601";
  34. 34         String expected = "订单号:25070601,订单状态:已发货";
  35. 35
  36. 36         // Act
  37. 37         String actual = orderService.queryOrderStatus(orderNo);
  38. 38
  39. 39         // Assert
  40. 40         assertEquals(expected, actual);
  41. 41     }
  42. 42
  43. 43     @Test
  44. 44     @DisplayName("查询已完成订单状态 - 成功")
  45. 45     void queryOrderStatus_WhenOrderCompleted_ShouldReturnCompletedStatus() {
  46. 46         // Arrange
  47. 47         String orderNo = "25070602";
  48. 48         String expected = "订单号:25070602,订单状态:已完成";
  49. 49
  50. 50         // Act
  51. 51         String actual = orderService.queryOrderStatus(orderNo);
  52. 52
  53. 53         // Assert
  54. 54         assertEquals(expected, actual);
  55. 55     }
  56. 56
  57. 57     @Test
  58. 58     @DisplayName("查询已取消订单状态 - 成功")
  59. 59     void queryOrderStatus_WhenOrderCancelled_ShouldReturnCancelledStatus() {
  60. 60         // Arrange
  61. 61         String orderNo = "25070603";
  62. 62         String expected = "订单号:25070603,订单状态:已取消";
  63. 63
  64. 64         // Act
  65. 65         String actual = orderService.queryOrderStatus(orderNo);
  66. 66
  67. 67         // Assert
  68. 68         assertEquals(expected, actual);
  69. 69     }
  70. 70
  71. 71     @Test
  72. 72     @DisplayName("查询未知订单状态 - 返回未知状态")
  73. 73     void queryOrderStatus_WhenOrderUnknown_ShouldReturnUnknownStatus() {
  74. 74         // Arrange
  75. 75         String orderNo = "99999999";
  76. 76         String expected = "订单号:99999999,订单状态:未知";
  77. 77
  78. 78         // Act
  79. 79         String actual = orderService.queryOrderStatus(orderNo);
  80. 80
  81. 81         // Assert
  82. 82         assertEquals(expected, actual);
  83. 83     }
  84. 84
  85. 85     @Test
  86. 86     @DisplayName("查询空订单号 - 返回未知状态")
  87. 87     void queryOrderStatus_WhenOrderNoIsEmpty_ShouldReturnUnknownStatus() {
  88. 88         // Arrange
  89. 89         String orderNo = "";
  90. 90         String expected = "订单号:,订单状态:未知";
  91. 91
  92. 92         // Act
  93. 93         String actual = orderService.queryOrderStatus(orderNo);
  94. 94
  95. 95         // Assert
  96. 96         assertEquals(expected, actual);
  97. 97     }
  98. 98
  99. 99     @Test
  100. 100     @DisplayName("查询null订单号 - 返回未知状态")
  101. 101     void queryOrderStatus_WhenOrderNoIsNull_ShouldReturnUnknownStatus() {
  102. 102         // Arrange
  103. 103         String orderNo = null;
  104. 104         String expected = "订单号:null,订单状态:未知";
  105. 105
  106. 106         // Act
  107. 107         String actual = orderService.queryOrderStatus(orderNo);
  108. 108
  109. 109         // Assert
  110. 110         assertEquals(expected, actual);
  111. 111     }
  112. 112
  113. 113     @Test
  114. 114     @DisplayName("查询非8位数字订单号 - 返回未知状态")
  115. 115     void queryOrderStatus_WhenOrderNoIsNot8Digits_ShouldReturnUnknownStatus() {
  116. 116         // Arrange
  117. 117         String orderNo = "1234567"; // 7位数字
  118. 118         String expected = "订单号:1234567,订单状态:未知";
  119. 119
  120. 120         // Act
  121. 121         String actual = orderService.queryOrderStatus(orderNo);
  122. 122
  123. 123         // Assert
  124. 124         assertEquals(expected, actual);
  125. 125     }
  126. 126
  127. 127     @Test
  128. 128     @DisplayName("查询包含字母的订单号 - 返回未知状态")
  129. 129     void queryOrderStatus_WhenOrderNoContainsLetters_ShouldReturnUnknownStatus() {
  130. 130         // Arrange
  131. 131         String orderNo = "2507060A";
  132. 132         String expected = "订单号:2507060A,订单状态:未知";
  133. 133
  134. 134         // Act
  135. 135         String actual = orderService.queryOrderStatus(orderNo);
  136. 136
  137. 137         // Assert
  138. 138         assertEquals(expected, actual);
  139. 139     }
  140. 140
  141. 141     @Test
  142. 142     @DisplayName("边界测试 - 最小订单号")
  143. 143     void queryOrderStatus_WhenOrderNoIsMinValue_ShouldReturnUnknownStatus() {
  144. 144         // Arrange
  145. 145         String orderNo = "00000000";
  146. 146         String expected = "订单号:00000000,订单状态:未知";
  147. 147
  148. 148         // Act
  149. 149         String actual = orderService.queryOrderStatus(orderNo);
  150. 150
  151. 151         // Assert
  152. 152         assertEquals(expected, actual);
  153. 153     }
  154. 154
  155. 155     @Test
  156. 156     @DisplayName("边界测试 - 最大订单号")
  157. 157     void queryOrderStatus_WhenOrderNoIsMaxValue_ShouldReturnUnknownStatus() {
  158. 158         // Arrange
  159. 159         String orderNo = "99999999";
  160. 160         String expected = "订单号:99999999,订单状态:未知";
  161. 161
  162. 162         // Act
  163. 163         String actual = orderService.queryOrderStatus(orderNo);
  164. 164
  165. 165         // Assert
  166. 166         assertEquals(expected, actual);
  167. 167     }
  168. 168 }
复制代码
View Code 这说明:有了IDEA开放的MCP能力,任何1个有推理能力的LLM,再挂1套MCP host和UI,理论上都可以手搓成1个AI编码辅助神器!
 
二、Cursor CLI
命令行界面(CLI) · Cursor 根据这份cursor官网的介绍,cursor可以在任何终端以cli 方式运行。
  1. curl https://cursor.com/install -fsS | bash
复制代码
只要这一行命令即可。注:windows上必须借助WSL (不熟悉wsl的同学可参考windows WSL2避坑指南 ),在wsl环境中使用该命令安装(比如:先wsl安装ubuntu,然后在ubuntu虚拟子环境中安装)
安装完后,就可以直接问一些编码相关的问题了
10.png

11.png

cursor也是支持MCP的,我们在cursor中,把IDEA的mcp地址也配置上
12.png

 
三、idea中设置terminal 为wsl
注:只有windows上需要设置成wsl.exe (mac / linux下,正常设置默认terminal即可)
13.png

 最终运行效果:idea中切换到terminal时,自动启动wsl环境,然后输入cursor-agent,自动将上下文切换到当前目录
14.png

唯一美中不足:虽然wsl的cursor-cli 也正确添加了mcp server,也通curl 访问到,但是cursor-cli 连接时总是报405,看上去是授权问题,如有园友知晓解法,请回复,感谢
15.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册