@@ -54,7 +54,8 @@ open class McpPreviewEditor(
54
54
private val mcpServerManager = CustomMcpServerManager .instance(project)
55
55
private val allTools = mutableMapOf<String , List <Tool >>()
56
56
private var loadingJob: Job ? = null
57
- private var isLoading = false
57
+ private val serverLoadingStatus = mutableMapOf<String , Boolean >()
58
+ private val serverPanels = mutableMapOf<String , JPanel >()
58
59
59
60
private lateinit var toolsContainer: JPanel
60
61
private lateinit var chatbotSelector: JComboBox <String >
@@ -65,6 +66,7 @@ open class McpPreviewEditor(
65
66
private val config = McpLlmConfig ()
66
67
private val borderColor = JBColor (0xE5E7EB , 0x3C3F41 ) // Equivalent to Tailwind gray-200
67
68
private val textGray = JBColor (0x6B7280 , 0x9DA0A8 ) // Equivalent to Tailwind gray-500
69
+ private val headerColor = JBColor (0xF3F4F6 , 0x2B2D30 ) // Light gray for section headers
68
70
69
71
init {
70
72
createUI()
@@ -74,52 +76,152 @@ open class McpPreviewEditor(
74
76
private fun loadTools () {
75
77
val content = runReadAction { virtualFile.readText() }
76
78
loadingJob?.cancel()
77
- isLoading = true
78
- showLoadingState()
79
+ serverLoadingStatus.clear()
80
+ serverPanels.clear()
81
+ allTools.clear()
82
+
83
+ SwingUtilities .invokeLater {
84
+ toolsContainer.removeAll()
85
+ toolsContainer.revalidate()
86
+ toolsContainer.repaint()
87
+ }
79
88
80
89
loadingJob = CoroutineScope (Dispatchers .IO ).launch {
81
90
val serverConfigs = mcpServerManager.getServerConfigs(content)
82
- serverConfigs?.forEach { (serverName, serverConfig) ->
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) ->
83
107
try {
84
108
val tools = mcpServerManager.collectServerInfo(serverName, serverConfig)
85
- if (tools.isNotEmpty()) {
86
- allTools[serverName] = tools
87
- SwingUtilities .invokeLater {
88
- updateToolsContainer( )
89
- }
109
+ allTools[serverName] = tools
110
+
111
+ SwingUtilities .invokeLater {
112
+ updateServerSection(serverName, tools )
113
+ serverLoadingStatus[serverName] = false
90
114
}
91
115
} catch (e: Exception ) {
92
- // Handle exception for this server but continue with others
93
- println (" Error loading tools from server $serverName : ${e.message} " )
116
+ SwingUtilities .invokeLater {
117
+ showServerError(serverName, e.message ? : " Unknown error" )
118
+ serverLoadingStatus[serverName] = false
119
+ }
94
120
}
95
121
}
96
-
97
- isLoading = false
98
- SwingUtilities .invokeLater {
99
- updateToolsContainer()
100
- }
101
122
}
102
123
}
103
-
104
- private fun showLoadingState () {
105
- SwingUtilities .invokeLater {
106
- toolsContainer.removeAll()
107
- val loadingLabel = JBLabel (" Loading tools... Please wait" ).apply {
108
- font = JBUI .Fonts .label(14.0f )
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 )
158
+ }
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 {
109
176
foreground = textGray
110
- horizontalAlignment = SwingConstants .CENTER
111
- icon = AutoDevIcons .LOADING
112
- iconTextGap = JBUI .scale(8 )
177
+ horizontalAlignment = SwingConstants .LEFT
113
178
}
114
-
115
- toolsContainer.add(loadingLabel)
116
- toolsContainer.revalidate()
117
- toolsContainer.repaint()
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
118
216
}
217
+
218
+ noServersPanel.add(noServersLabel, BorderLayout .CENTER )
219
+ toolsContainer.add(noServersPanel)
220
+ toolsContainer.revalidate()
221
+ toolsContainer.repaint()
119
222
}
120
223
121
224
fun refreshMcpTool () {
122
- allTools.clear()
123
225
loadTools()
124
226
}
125
227
@@ -142,7 +244,8 @@ open class McpPreviewEditor(
142
244
border = JBUI .Borders .empty(4 )
143
245
}
144
246
145
- toolsContainer = JPanel (GridLayout (0 , 2 , 16 , 16 )).apply {
247
+ toolsContainer = JPanel ().apply {
248
+ layout = BoxLayout (this , BoxLayout .Y_AXIS )
146
249
background = UIUtil .getPanelBackground()
147
250
}
148
251
@@ -244,33 +347,6 @@ open class McpPreviewEditor(
244
347
mainPanel.add(bottomPanel, BorderLayout .SOUTH )
245
348
}
246
349
247
- private fun updateToolsContainer () {
248
- toolsContainer.removeAll()
249
-
250
- if (isLoading) {
251
- showLoadingState()
252
- return
253
- }
254
-
255
- if (allTools.isEmpty()) {
256
- val noToolsLabel = JBLabel (" No tools available. Please check MCP server configuration." ).apply {
257
- foreground = textGray
258
- horizontalAlignment = SwingConstants .CENTER
259
- }
260
- toolsContainer.add(noToolsLabel)
261
- } else {
262
- allTools.forEach { (serverName, tools) ->
263
- tools.forEach { tool ->
264
- val panel = McpToolDetailPanel (project, serverName, tool)
265
- toolsContainer.add(panel)
266
- }
267
- }
268
- }
269
-
270
- toolsContainer.revalidate()
271
- toolsContainer.repaint()
272
- }
273
-
274
350
private fun showConfigDialog () {
275
351
val dialog = McpLlmConfigDialog (project, config, allTools)
276
352
0 commit comments