@@ -3,13 +3,15 @@ package cc.unitmesh.devti.mcp.editor
3
3
import cc.unitmesh.devti.AutoDevIcons
4
4
import cc.unitmesh.devti.llm2.model.LlmConfig
5
5
import cc.unitmesh.devti.llms.custom.CustomLLMProvider
6
- import cc.unitmesh.devti.mcp.client.CustomMcpServerManager
7
6
import cc.unitmesh.devti.sketch.ui.patch.readText
8
7
import cc.unitmesh.devti.util.AutoDevCoroutineScope
8
+ import com.intellij.openapi.actionSystem.Presentation
9
+ import com.intellij.openapi.actionSystem.impl.ActionButton
9
10
import com.intellij.openapi.application.runReadAction
10
11
import com.intellij.openapi.editor.Editor
11
12
import com.intellij.openapi.fileEditor.FileEditor
12
13
import com.intellij.openapi.fileEditor.FileEditorState
14
+ import com.intellij.openapi.project.DumbAwareAction
13
15
import com.intellij.openapi.project.Project
14
16
import com.intellij.openapi.util.UserDataHolder
15
17
import com.intellij.openapi.util.UserDataHolderBase
@@ -23,22 +25,15 @@ import com.intellij.ui.dsl.builder.Align
23
25
import com.intellij.ui.dsl.builder.panel
24
26
import com.intellij.util.ui.JBUI
25
27
import com.intellij.util.ui.UIUtil
26
- import com.intellij.openapi.actionSystem.Presentation
27
- import com.intellij.openapi.actionSystem.impl.ActionButton
28
- import com.intellij.openapi.project.DumbAwareAction
29
28
import com.intellij.util.ui.components.BorderLayoutPanel
30
29
import io.modelcontextprotocol.kotlin.sdk.Tool
31
- import kotlinx.coroutines.CoroutineScope
32
- import kotlinx.coroutines.Dispatchers
33
- import kotlinx.coroutines.Job
34
30
import kotlinx.coroutines.flow.Flow
35
31
import kotlinx.coroutines.flow.MutableStateFlow
36
32
import kotlinx.coroutines.flow.cancellable
37
33
import kotlinx.coroutines.launch
38
34
import java.awt.BorderLayout
39
35
import java.awt.Dimension
40
36
import java.awt.FlowLayout
41
- import java.awt.GridLayout
42
37
import java.beans.PropertyChangeListener
43
38
import javax.swing.*
44
39
import javax.swing.border.CompoundBorder
@@ -51,22 +46,15 @@ open class McpPreviewEditor(
51
46
private var mainEditor = MutableStateFlow <Editor ?>(null )
52
47
private val mainPanel = JPanel (BorderLayout ())
53
48
54
- private val mcpServerManager = CustomMcpServerManager .instance(project)
55
- private val allTools = mutableMapOf<String , List <Tool >>()
56
- private var loadingJob: Job ? = null
57
- private val serverLoadingStatus = mutableMapOf<String , Boolean >()
58
- private val serverPanels = mutableMapOf<String , JPanel >()
59
-
60
- private lateinit var toolsContainer: JPanel
49
+ private var allTools = mutableMapOf<String , List <Tool >>()
50
+ private lateinit var toolListPanel: McpToolListPanel
61
51
private lateinit var chatbotSelector: JComboBox <String >
62
52
private lateinit var chatInput: JBTextField
63
53
private lateinit var testButton: ActionButton
64
54
private lateinit var configButton: JButton
65
55
private lateinit var resultPanel: McpResultPanel
66
56
private val config = McpLlmConfig ()
67
57
private val borderColor = JBColor (0xE5E7EB , 0x3C3F41 ) // Equivalent to Tailwind gray-200
68
- private val textGray = JBColor (0x6B7280 , 0x9DA0A8 ) // Equivalent to Tailwind gray-500
69
- private val headerColor = JBColor (0xF3F4F6 , 0x2B2D30 ) // Light gray for section headers
70
58
71
59
init {
72
60
createUI()
@@ -75,150 +63,9 @@ open class McpPreviewEditor(
75
63
76
64
private fun loadTools () {
77
65
val content = runReadAction { virtualFile.readText() }
78
- loadingJob?.cancel()
79
- serverLoadingStatus.clear()
80
- serverPanels.clear()
81
- allTools.clear()
82
-
83
- SwingUtilities .invokeLater {
84
- toolsContainer.removeAll()
85
- toolsContainer.revalidate()
86
- toolsContainer.repaint()
87
- }
88
-
89
- loadingJob = CoroutineScope (Dispatchers .IO ).launch {
90
- val serverConfigs = mcpServerManager.getServerConfigs(content)
91
-
92
- if (serverConfigs.isNullOrEmpty()) {
93
- SwingUtilities .invokeLater {
94
- showNoServersMessage()
95
- }
96
- return @launch
97
- }
98
-
99
- SwingUtilities .invokeLater {
100
- serverConfigs.keys.forEach { serverName ->
101
- serverLoadingStatus[serverName] = true
102
- createServerSection(serverName)
103
- }
104
- }
105
-
106
- serverConfigs.forEach { (serverName, serverConfig) ->
107
- try {
108
- val tools = mcpServerManager.collectServerInfo(serverName, serverConfig)
109
- allTools[serverName] = tools
110
-
111
- SwingUtilities .invokeLater {
112
- updateServerSection(serverName, tools)
113
- serverLoadingStatus[serverName] = false
114
- }
115
- } catch (e: Exception ) {
116
- SwingUtilities .invokeLater {
117
- showServerError(serverName, e.message ? : " Unknown error" )
118
- serverLoadingStatus[serverName] = false
119
- }
120
- }
121
- }
122
- }
123
- }
124
-
125
- private fun createServerSection (serverName : String ) {
126
- val serverPanel = JPanel (BorderLayout ()).apply {
127
- background = UIUtil .getPanelBackground()
128
- border = BorderFactory .createCompoundBorder(
129
- BorderFactory .createMatteBorder(0 , 0 , 1 , 0 , borderColor),
130
- JBUI .Borders .empty(4 , 0 )
131
- )
132
- }
133
-
134
- val headerPanel = JPanel (BorderLayout ()).apply {
135
- background = headerColor
136
- border = JBUI .Borders .empty(4 , 8 )
137
- }
138
-
139
- val serverLabel = JBLabel (serverName).apply {
140
- font = JBUI .Fonts .label(14.0f ).asBold()
141
- foreground = UIUtil .getLabelForeground()
142
- }
143
-
144
- headerPanel.add(serverLabel, BorderLayout .WEST )
145
- serverPanel.add(headerPanel, BorderLayout .NORTH )
146
-
147
- val toolsPanel = JPanel (GridLayout (0 , 3 , 4 , 4 )).apply {
148
- background = UIUtil .getPanelBackground()
149
- border = JBUI .Borders .empty()
150
- }
151
-
152
- val loadingLabel = JBLabel (" Loading tools from $serverName ..." ).apply {
153
- font = JBUI .Fonts .label(12.0f )
154
- foreground = textGray
155
- horizontalAlignment = SwingConstants .LEFT
156
- icon = AutoDevIcons .LOADING
157
- iconTextGap = JBUI .scale(8 )
66
+ toolListPanel.loadTools(content) { tools ->
67
+ this .allTools = tools
158
68
}
159
-
160
- toolsPanel.add(loadingLabel)
161
- serverPanel.add(toolsPanel, BorderLayout .CENTER )
162
-
163
- serverPanels[serverName] = toolsPanel
164
-
165
- toolsContainer.add(serverPanel)
166
- toolsContainer.revalidate()
167
- toolsContainer.repaint()
168
- }
169
-
170
- private fun updateServerSection (serverName : String , tools : List <Tool >) {
171
- val toolsPanel = serverPanels[serverName] ? : return
172
- toolsPanel.removeAll()
173
-
174
- if (tools.isEmpty()) {
175
- val noToolsLabel = JBLabel (" No tools available for $serverName " ).apply {
176
- foreground = textGray
177
- horizontalAlignment = SwingConstants .LEFT
178
- }
179
- toolsPanel.add(noToolsLabel)
180
- } else {
181
- tools.forEach { tool ->
182
- val panel = McpToolDetailPanel (project, serverName, tool)
183
- toolsPanel.add(panel)
184
- }
185
- }
186
-
187
- toolsPanel.revalidate()
188
- toolsPanel.repaint()
189
- }
190
-
191
- private fun showServerError (serverName : String , errorMessage : String ) {
192
- val toolsPanel = serverPanels[serverName] ? : return
193
- toolsPanel.removeAll()
194
-
195
- val errorLabel = JBLabel (" Error loading tools: $errorMessage " ).apply {
196
- foreground = JBColor .RED
197
- horizontalAlignment = SwingConstants .LEFT
198
- }
199
-
200
- toolsPanel.add(errorLabel)
201
- toolsPanel.revalidate()
202
- toolsPanel.repaint()
203
- }
204
-
205
- private fun showNoServersMessage () {
206
- toolsContainer.removeAll()
207
-
208
- val noServersPanel = JPanel (BorderLayout ()).apply {
209
- background = UIUtil .getPanelBackground()
210
- border = JBUI .Borders .empty(16 )
211
- }
212
-
213
- val noServersLabel = JBLabel (" No MCP servers configured. Please check your configuration." ).apply {
214
- foreground = textGray
215
- horizontalAlignment = SwingConstants .CENTER
216
- }
217
-
218
- noServersPanel.add(noServersLabel, BorderLayout .CENTER )
219
- toolsContainer.add(noServersPanel)
220
- toolsContainer.revalidate()
221
- toolsContainer.repaint()
222
69
}
223
70
224
71
fun refreshMcpTool () {
@@ -244,12 +91,9 @@ open class McpPreviewEditor(
244
91
border = JBUI .Borders .empty(4 )
245
92
}
246
93
247
- toolsContainer = JPanel ().apply {
248
- layout = BoxLayout (this , BoxLayout .Y_AXIS )
249
- background = UIUtil .getPanelBackground()
250
- }
251
-
252
- val toolsScrollPane = JBScrollPane (toolsContainer).apply {
94
+ toolListPanel = McpToolListPanel (project)
95
+
96
+ val toolsScrollPane = JBScrollPane (toolListPanel).apply {
253
97
border = BorderFactory .createEmptyBorder()
254
98
background = UIUtil .getPanelBackground()
255
99
}
@@ -401,7 +245,6 @@ open class McpPreviewEditor(
401
245
override fun addPropertyChangeListener (listener : PropertyChangeListener ) {}
402
246
override fun removePropertyChangeListener (listener : PropertyChangeListener ) {}
403
247
override fun dispose () {
404
- loadingJob?.cancel ()
248
+ toolListPanel.dispose ()
405
249
}
406
250
}
407
-
0 commit comments