idea與cursor的整合方案
眾所周知,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 }
這說明:有了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,看上去是授權問題,如有園友知曉解法,請回復,感謝

出處:http://yjmyzz.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
浙公網安備 33010602011771號