Skip to content

Commit 308758e

Browse files
committed
fix(mcp): enhance loading behavior and error handling in tool tree
1 parent d991581 commit 308758e

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

core/src/main/kotlin/cc/unitmesh/devti/mcp/ui/McpConfigPopup.kt

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class McpConfigPopup {
149149
.setResizable(true)
150150
.setMovable(true)
151151
.setRequestFocus(true)
152+
.setCancelOnClickOutside(false)
152153
.createPopup()
153154

154155
if (component != null) {
@@ -183,7 +184,7 @@ class McpConfigPopup {
183184
rootNode.removeAllChildren()
184185
val loadingNode = CheckedTreeNode("Loading tools...")
185186
rootNode.add(loadingNode)
186-
treeModel.reload()
187+
treeModel.reload(rootNode) // Reload to show the loading node
187188
expandAllNodes(tree)
188189

189190
CoroutineScope(Dispatchers.IO).launch {
@@ -193,35 +194,59 @@ class McpConfigPopup {
193194
val selectedTools = configService.getSelectedTools()
194195

195196
invokeLater {
196-
rootNode.removeAllChildren()
197+
rootNode.removeAllChildren() // Remove "Loading tools..." node
197198

198-
allTools.forEach { (serverName, tools) ->
199-
val serverNode = ServerTreeNode(serverName)
200-
rootNode.add(serverNode)
199+
if (allTools.isEmpty()) {
200+
val noToolsNode = CheckedTreeNode("No tools available.")
201+
rootNode.add(noToolsNode)
202+
} else {
203+
allTools.forEach { (serverName, tools) ->
204+
val serverNode = ServerTreeNode(serverName)
205+
rootNode.add(serverNode)
201206

202-
tools.forEach { tool ->
203-
val toolNode = ToolTreeNode(serverName, tool)
204-
val isSelected = selectedTools[serverName]?.contains(tool.name) == true
205-
toolNode.isChecked = isSelected
206-
serverNode.add(toolNode)
207+
if (tools.isEmpty()) {
208+
val noToolsForServerNode = CheckedTreeNode("No tools from this server.")
209+
serverNode.add(noToolsForServerNode)
210+
} else {
211+
tools.forEach { tool ->
212+
val toolNode = ToolTreeNode(serverName, tool)
213+
val isSelected = selectedTools[serverName]?.contains(tool.name) == true
214+
toolNode.isChecked = isSelected
215+
serverNode.add(toolNode)
216+
}
217+
}
207218
}
208219
}
209220

210-
treeModel.reload()
221+
treeModel.nodeStructureChanged(rootNode) // Notify that rootNode's children changed
211222
expandAllNodes(tree)
212-
tree.repaint() // 添加显式重绘
223+
213224
loadingPanel.stopLoading()
214-
loadingPanel.revalidate() // 确保布局更新
225+
226+
tree.revalidate() // Ensure tree layout is updated
227+
tree.repaint()
228+
loadingPanel.revalidate()
229+
loadingPanel.repaint()
230+
// Also revalidate and repaint parent in case its layout depends on loadingPanel
231+
(loadingPanel.parent as? JComponent)?.revalidate()
232+
(loadingPanel.parent as? JComponent)?.repaint()
215233
}
216234
} catch (e: Exception) {
217235
invokeLater {
218236
rootNode.removeAllChildren()
219237
val errorNode = CheckedTreeNode("Error loading tools: ${e.message}")
220238
rootNode.add(errorNode)
221-
treeModel.reload()
222-
tree.repaint() // 添加显式重绘
239+
treeModel.nodeStructureChanged(rootNode) // Notify change
240+
expandAllNodes(tree)
241+
223242
loadingPanel.stopLoading()
224-
loadingPanel.revalidate() // 确保布局更新
243+
244+
tree.revalidate()
245+
tree.repaint()
246+
loadingPanel.revalidate()
247+
loadingPanel.repaint()
248+
(loadingPanel.parent as? JComponent)?.revalidate()
249+
(loadingPanel.parent as? JComponent)?.repaint()
225250
}
226251
}
227252
}
@@ -248,15 +273,12 @@ class McpConfigPopup {
248273
}
249274

250275
private fun filterTree(tree: CheckboxTree, rootNode: CheckedTreeNode, searchText: String) {
251-
// Simple implementation - in a real scenario, you might want more sophisticated filtering
252276
tree.expandPath(TreePath(rootNode.path))
253277
}
254278

255279
private fun expandAllNodes(tree: CheckboxTree) {
256280
for (i in 0 until tree.rowCount) {
257281
tree.expandRow(i)
258282
}
259-
260-
tree.updateUI()
261283
}
262-
}
284+
}

0 commit comments

Comments
 (0)