Skip to content

Commit ce86496

Browse files
committed
feat(mcp): add tool execution capability to result panel
Add execute button and result display to McpResultPanel, enabling direct tool execution from the UI.
1 parent 6d37030 commit ce86496

File tree

3 files changed

+109
-3
lines changed

3 files changed

+109
-3
lines changed

core/src/main/kotlin/cc/unitmesh/devti/mcp/editor/McpPreviewEditor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ open class McpPreviewEditor(
118118
background = UIUtil.getPanelBackground()
119119
}
120120

121-
resultPanel = McpResultPanel().apply {
121+
resultPanel = McpResultPanel(project, config).apply {
122122
background = UIUtil.getPanelBackground()
123123
isVisible = false
124124
}

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

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
package cc.unitmesh.devti.mcp.ui
22

3+
import cc.unitmesh.devti.AutoDevNotifications
4+
import cc.unitmesh.devti.mcp.client.CustomMcpServerManager
5+
import cc.unitmesh.devti.mcp.ui.model.McpLlmConfig
36
import cc.unitmesh.devti.util.parser.CodeFence
7+
import com.intellij.openapi.project.Project
48
import com.intellij.ui.JBColor
59
import com.intellij.ui.components.JBLabel
610
import com.intellij.ui.components.JBScrollPane
711
import com.intellij.ui.components.JBTabbedPane
812
import com.intellij.util.ui.JBUI
913
import com.intellij.util.ui.UIUtil
14+
import io.modelcontextprotocol.kotlin.sdk.Tool
15+
import kotlinx.serialization.encodeToString
16+
import kotlinx.serialization.json.Json
1017
import java.awt.BorderLayout
18+
import java.awt.FlowLayout
1119
import java.awt.GridBagConstraints
1220
import java.awt.GridBagLayout
1321
import java.io.StringReader
@@ -16,7 +24,10 @@ import javax.swing.border.CompoundBorder
1624
import javax.swing.border.EmptyBorder
1725
import javax.swing.border.MatteBorder
1826

19-
class McpResultPanel : JPanel(BorderLayout()) {
27+
class McpResultPanel(private val project: Project, val config: McpLlmConfig) : JPanel(BorderLayout()) {
28+
private val mcpServerManager = CustomMcpServerManager.instance(project)
29+
private val json = Json { prettyPrint = true }
30+
2031
private val rawResultTextArea = JTextArea().apply {
2132
isEditable = false
2233
wrapStyleWord = true
@@ -162,12 +173,106 @@ class McpResultPanel : JPanel(BorderLayout()) {
162173
paramsPanel.add(valueLabel, valueGbc)
163174
}
164175

176+
// Add execute button and result panel
177+
val executeButton = JButton("Execute").apply {
178+
font = JBUI.Fonts.label(12f)
179+
addActionListener {
180+
executeToolCall(toolCall, panel)
181+
}
182+
}
183+
184+
val buttonsPanel = JPanel(FlowLayout(FlowLayout.LEFT)).apply {
185+
isOpaque = false
186+
add(executeButton)
187+
}
188+
189+
val resultPanel = JPanel(BorderLayout()).apply {
190+
isOpaque = false
191+
border = JBUI.Borders.emptyTop(8)
192+
isVisible = false
193+
}
194+
195+
val contentPanel = JPanel(BorderLayout()).apply {
196+
isOpaque = false
197+
add(paramsPanel, BorderLayout.CENTER)
198+
add(buttonsPanel, BorderLayout.SOUTH)
199+
}
200+
165201
panel.add(titleLabel, BorderLayout.NORTH)
166-
panel.add(paramsPanel, BorderLayout.CENTER)
202+
panel.add(contentPanel, BorderLayout.CENTER)
203+
panel.add(resultPanel, BorderLayout.SOUTH)
167204

168205
return panel
169206
}
170207

208+
private fun executeToolCall(toolCall: ToolCall, parentPanel: JPanel) {
209+
val panel = parentPanel.components
210+
.filterIsInstance<JPanel>()
211+
.find { it.border != null && it.border.toString().contains("empty") }
212+
213+
if (panel == null) {
214+
AutoDevNotifications.error(project, "Cannot find result panel")
215+
return
216+
}
217+
218+
panel.removeAll()
219+
panel.layout = BorderLayout()
220+
221+
// Create loading indicator
222+
val loadingLabel = JBLabel("Executing tool ${toolCall.name}...").apply {
223+
horizontalAlignment = SwingConstants.CENTER
224+
}
225+
panel.add(loadingLabel, BorderLayout.CENTER)
226+
panel.isVisible = true
227+
panel.revalidate()
228+
panel.repaint()
229+
230+
// Run execution in background
231+
SwingUtilities.invokeLater {
232+
// Convert parameters to JSON
233+
val params = try {
234+
val jsonParams = json.encodeToString(toolCall.parameters)
235+
jsonParams
236+
} catch (e: Exception) {
237+
"{}"
238+
}
239+
240+
// Find matching tool
241+
val matchingTool = findMatchingTool(toolCall.name)
242+
243+
val result = if (matchingTool != null) {
244+
mcpServerManager!!.execute(project, matchingTool, params)
245+
} else {
246+
"Error: Could not find matching tool '${toolCall.name}'"
247+
}
248+
249+
// Display result
250+
panel.removeAll()
251+
val textArea = JTextArea(result).apply {
252+
lineWrap = true
253+
wrapStyleWord = true
254+
isEditable = false
255+
font = JBUI.Fonts.create("Monospaced", 12)
256+
border = JBUI.Borders.empty(4)
257+
}
258+
259+
panel.add(JBScrollPane(textArea), BorderLayout.CENTER)
260+
panel.isVisible = true
261+
panel.revalidate()
262+
panel.repaint()
263+
}
264+
}
265+
266+
private fun findMatchingTool(toolName: String): Tool? {
267+
for (tool in config.enabledTools) {
268+
if (tool.name == toolName) {
269+
return tool
270+
}
271+
}
272+
273+
return null
274+
}
275+
171276
data class ToolCall(
172277
val name: String,
173278
val parameters: Map<String, String>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ data class McpLlmConfig(
1414
) {
1515
fun createSystemPrompt(): String {
1616
val systemPrompt = """
17+
You an tool-use expert, answer the user's request using the relevant tool.
1718
In this environment you have access to a set of tools you can use to answer the user's question.
1819
You can invoke functions by writing a "<devins:function_calls>" inside markdown code-block like the following as part of your reply to the user:
1920

0 commit comments

Comments
 (0)