mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
Add auto approve settings for mcp tools
This commit is contained in:
parent
8ec0b2cf08
commit
d9e1031f85
8 changed files with 123 additions and 14 deletions
|
|
@ -2489,7 +2489,14 @@ export class Cline {
|
|||
arguments: mcp_arguments,
|
||||
} satisfies ClineAskUseMcpServer)
|
||||
|
||||
if (this.shouldAutoApproveTool(block.name)) {
|
||||
const isToolAlwaysAllowed = this.providerRef
|
||||
.deref()
|
||||
?.mcpHub?.connections?.find((conn) => conn.server.name === server_name)
|
||||
?.server.tools?.find((tool) => tool.name === tool_name)?.alwaysAllow
|
||||
|
||||
// console.log("isToolAlwaysAllowed", server_name, tool_name, isToolAlwaysAllowed)
|
||||
|
||||
if (this.shouldAutoApproveTool(block.name) && isToolAlwaysAllowed) {
|
||||
this.removeLastPartialMessageIfExistsWithType("ask", "use_mcp_server")
|
||||
await this.say("use_mcp_server", completeMessage, undefined, false)
|
||||
this.consecutiveAutoApprovedRequestsCount++
|
||||
|
|
|
|||
|
|
@ -608,6 +608,14 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
}
|
||||
break
|
||||
}
|
||||
case "toggleToolAlwaysAllow": {
|
||||
try {
|
||||
await this.mcpHub?.toggleToolAlwaysAllow(message.serverName!, message.toolName!, message.alwaysAllow!)
|
||||
} catch (error) {
|
||||
console.error(`Failed to toggle auto-approve for tool ${message.toolName}:`, error)
|
||||
}
|
||||
break
|
||||
}
|
||||
case "restartMcpServer": {
|
||||
try {
|
||||
await this.mcpHub?.restartConnection(message.text!)
|
||||
|
|
|
|||
|
|
@ -25,11 +25,14 @@ export type McpConnection = {
|
|||
transport: StdioClientTransport
|
||||
}
|
||||
|
||||
const AlwaysAllowSchema = z.array(z.string()).default([])
|
||||
|
||||
// StdioServerParameters
|
||||
const StdioConfigSchema = z.object({
|
||||
command: z.string(),
|
||||
args: z.array(z.string()).optional(),
|
||||
env: z.record(z.string()).optional(),
|
||||
alwaysAllow: AlwaysAllowSchema.optional(),
|
||||
})
|
||||
|
||||
const McpSettingsSchema = z.object({
|
||||
|
|
@ -275,7 +278,21 @@ export class McpHub {
|
|||
const response = await this.connections
|
||||
.find((conn) => conn.server.name === serverName)
|
||||
?.client.request({ method: "tools/list" }, ListToolsResultSchema)
|
||||
return response?.tools || []
|
||||
|
||||
// Get always allow settings
|
||||
const settingsPath = await this.getMcpSettingsFilePath()
|
||||
const content = await fs.readFile(settingsPath, "utf-8")
|
||||
const config = JSON.parse(content)
|
||||
const alwaysAllowConfig = config.mcpServers[serverName]?.alwaysAllow || []
|
||||
|
||||
// Mark tools as always allowed based on settings
|
||||
const tools = (response?.tools || []).map((tool) => ({
|
||||
...tool,
|
||||
alwaysAllow: alwaysAllowConfig.includes(tool.name),
|
||||
}))
|
||||
|
||||
// console.log(`[MCP] Fetched tools for ${serverName}:`, tools)
|
||||
return tools
|
||||
} catch (error) {
|
||||
// console.error(`Failed to fetch tools for ${serverName}:`, error)
|
||||
return []
|
||||
|
|
@ -476,6 +493,44 @@ export class McpHub {
|
|||
)
|
||||
}
|
||||
|
||||
async toggleToolAlwaysAllow(serverName: string, toolName: string, shouldAllow: boolean): Promise<void> {
|
||||
try {
|
||||
const settingsPath = await this.getMcpSettingsFilePath()
|
||||
const content = await fs.readFile(settingsPath, "utf-8")
|
||||
const config = JSON.parse(content)
|
||||
|
||||
// Initialize alwaysAllow if it doesn't exist
|
||||
if (!config.mcpServers[serverName].alwaysAllow) {
|
||||
config.mcpServers[serverName].alwaysAllow = []
|
||||
}
|
||||
|
||||
const alwaysAllow = config.mcpServers[serverName].alwaysAllow
|
||||
const toolIndex = alwaysAllow.indexOf(toolName)
|
||||
|
||||
if (shouldAllow && toolIndex === -1) {
|
||||
// Add tool to always allow list
|
||||
alwaysAllow.push(toolName)
|
||||
} else if (!shouldAllow && toolIndex !== -1) {
|
||||
// Remove tool from always allow list
|
||||
alwaysAllow.splice(toolIndex, 1)
|
||||
}
|
||||
|
||||
// Write updated config back to file
|
||||
await fs.writeFile(settingsPath, JSON.stringify(config, null, 2))
|
||||
|
||||
// Update the tools list to reflect the change
|
||||
const connection = this.connections.find((conn) => conn.server.name === serverName)
|
||||
if (connection) {
|
||||
connection.server.tools = await this.fetchToolsList(serverName)
|
||||
await this.notifyWebviewOfServerChanges()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to update always allow settings:", error)
|
||||
vscode.window.showErrorMessage("Failed to update always allow settings")
|
||||
throw error // Re-throw to ensure the error is properly handled
|
||||
}
|
||||
}
|
||||
|
||||
async dispose(): Promise<void> {
|
||||
this.removeAllFileWatchers()
|
||||
for (const connection of this.connections) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export interface WebviewMessage {
|
|||
| "taskCompletionViewChanges"
|
||||
| "openAdvisorModelSettings"
|
||||
| "requestVsCodeLmModels"
|
||||
| "toggleToolAlwaysAllow"
|
||||
// | "relaunchChromeDebugMode"
|
||||
text?: string
|
||||
askResponse?: ClineAskResponse
|
||||
|
|
@ -45,6 +46,11 @@ export interface WebviewMessage {
|
|||
autoApprovalSettings?: AutoApprovalSettings
|
||||
browserSettings?: BrowserSettings
|
||||
chatSettings?: ChatSettings
|
||||
|
||||
// For toggleToolAutoApprove
|
||||
serverName?: string
|
||||
toolName?: string
|
||||
alwaysAllow?: boolean
|
||||
}
|
||||
|
||||
export type ClineAskResponse = "yesButtonClicked" | "noButtonClicked" | "messageResponse"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export type McpTool = {
|
|||
name: string
|
||||
description?: string
|
||||
inputSchema?: object
|
||||
alwaysAllow?: boolean
|
||||
}
|
||||
|
||||
export type McpResource = {
|
||||
|
|
|
|||
|
|
@ -712,13 +712,19 @@ export const ChatRowContent = ({ message, isExpanded, onToggleExpand, lastModifi
|
|||
|
||||
{useMcpServer.type === "use_mcp_tool" && (
|
||||
<>
|
||||
<McpToolRow
|
||||
tool={{
|
||||
name: useMcpServer.toolName || "",
|
||||
description:
|
||||
server?.tools?.find((tool) => tool.name === useMcpServer.toolName)?.description || "",
|
||||
}}
|
||||
/>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<McpToolRow
|
||||
tool={{
|
||||
name: useMcpServer.toolName || "",
|
||||
description:
|
||||
server?.tools?.find((tool) => tool.name === useMcpServer.toolName)?.description || "",
|
||||
alwaysAllow:
|
||||
server?.tools?.find((tool) => tool.name === useMcpServer.toolName)?.alwaysAllow ||
|
||||
false,
|
||||
}}
|
||||
serverName={useMcpServer.serverName}
|
||||
/>
|
||||
</div>
|
||||
{useMcpServer.arguments && useMcpServer.arguments !== "{}" && (
|
||||
<div style={{ marginTop: "8px" }}>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,19 +1,45 @@
|
|||
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import { McpTool } from "../../../../src/shared/mcp"
|
||||
import { vscode } from "../../utils/vscode"
|
||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||
|
||||
type McpToolRowProps = {
|
||||
tool: McpTool
|
||||
serverName?: string
|
||||
}
|
||||
|
||||
const McpToolRow = ({ tool }: McpToolRowProps) => {
|
||||
const McpToolRow = ({ tool, serverName }: McpToolRowProps) => {
|
||||
const { autoApprovalSettings } = useExtensionState()
|
||||
|
||||
const handleAlwaysAllowChange = () => {
|
||||
if (!serverName) return
|
||||
|
||||
vscode.postMessage({
|
||||
type: "toggleToolAlwaysAllow",
|
||||
serverName,
|
||||
toolName: tool.name,
|
||||
alwaysAllow: !tool.alwaysAllow,
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div
|
||||
key={tool.name}
|
||||
style={{
|
||||
padding: "3px 0",
|
||||
}}>
|
||||
<div style={{ display: "flex" }}>
|
||||
<span className="codicon codicon-symbol-method" style={{ marginRight: "6px" }}></span>
|
||||
<span style={{ fontWeight: 500 }}>{tool.name}</span>
|
||||
<div
|
||||
data-testid="tool-row-container"
|
||||
style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}
|
||||
onClick={(e) => e.stopPropagation()}>
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<span className="codicon codicon-symbol-method" style={{ marginRight: "6px" }}></span>
|
||||
<span style={{ fontWeight: 500 }}>{tool.name}</span>
|
||||
</div>
|
||||
{serverName && autoApprovalSettings.enabled && autoApprovalSettings.actions.useMcp && (
|
||||
<VSCodeCheckbox checked={tool.alwaysAllow} onChange={handleAlwaysAllowChange} data-tool={tool.name}>
|
||||
Always allow
|
||||
</VSCodeCheckbox>
|
||||
)}
|
||||
</div>
|
||||
{tool.description && (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ const ServerRow = ({ server }: { server: McpServer }) => {
|
|||
width: "100%",
|
||||
}}>
|
||||
{server.tools.map((tool) => (
|
||||
<McpToolRow key={tool.name} tool={tool} />
|
||||
<McpToolRow key={tool.name} tool={tool} serverName={server.name} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue