Skip to content

Commit e5ed990

Browse files
committed
fix(mcp): resolve resource auto-approval issues
- Fix state persistence for MCP resource auto-approve checkbox - Refactor ChatRow to use live state from mcpServers instead of temporary objects - Fix auto-approval logic in ChatView to check alwaysAllow before pattern matching - Add proper type imports for McpResource and McpResourceTemplate - Ensure resource auto-approval works exactly like tool auto-approval Addresses review feedback from PR #5709
1 parent 87f7c70 commit e5ed990

File tree

2 files changed

+72
-24
lines changed

2 files changed

+72
-24
lines changed

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import deepEqual from "fast-deep-equal"
66
import { VSCodeBadge, VSCodeButton } from "@vscode/webview-ui-toolkit/react"
77

88
import type { ClineMessage } from "@roo-code/types"
9+
import type { McpResource, McpResourceTemplate } from "../../../../src/shared/mcp"
910

1011
import { ClineApiReqInfo, ClineAskUseMcpServer, ClineSayTool } from "@roo/ExtensionMessage"
1112
import { COMMAND_OUTPUT_STRING } from "@roo/combineCommandSequences"
@@ -14,7 +15,6 @@ import { FollowUpData, SuggestionItem } from "@roo-code/types"
1415

1516
import { useCopyToClipboard } from "@src/utils/clipboard"
1617
import { useExtensionState } from "@src/context/ExtensionStateContext"
17-
import { findMatchingResourceOrTemplate } from "@src/utils/mcp"
1818
import { vscode } from "@src/utils/vscode"
1919
import { removeLeadingNonAlphanumeric } from "@src/utils/removeLeadingNonAlphanumeric"
2020
import { getLanguageFromPath } from "@src/utils/getLanguageFromPath"
@@ -1233,26 +1233,68 @@ export const ChatRowContent = ({
12331233
{title}
12341234
</div>
12351235
<div className="w-full bg-vscode-editor-background border border-vscode-border rounded-xs p-2 mt-2">
1236-
{useMcpServer.type === "access_mcp_resource" && (
1237-
<McpResourceRow
1238-
item={{
1239-
// Use the matched resource/template details, with fallbacks
1240-
...(findMatchingResourceOrTemplate(
1241-
useMcpServer.uri || "",
1242-
server?.resources,
1243-
server?.resourceTemplates,
1244-
) || {
1245-
name: "",
1246-
mimeType: "",
1247-
description: "",
1248-
}),
1249-
// Always use the actual URI from the request
1250-
uri: useMcpServer.uri || "",
1251-
}}
1252-
serverName={useMcpServer.serverName}
1253-
alwaysAllowMcp={alwaysAllowMcp}
1254-
/>
1255-
)}
1236+
{useMcpServer.type === "access_mcp_resource" &&
1237+
(() => {
1238+
// Find the exact resource match first
1239+
const exactResource = server?.resources?.find(
1240+
(r: McpResource) => r.uri === useMcpServer.uri,
1241+
)
1242+
if (exactResource) {
1243+
return (
1244+
<McpResourceRow
1245+
item={exactResource}
1246+
serverName={useMcpServer.serverName}
1247+
serverSource={server?.source || "global"}
1248+
alwaysAllowMcp={alwaysAllowMcp}
1249+
/>
1250+
)
1251+
}
1252+
1253+
// If no exact match, check templates
1254+
const matchedTemplate = server?.resourceTemplates?.find(
1255+
(template: McpResourceTemplate) => {
1256+
try {
1257+
const pattern = template.uriTemplate
1258+
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
1259+
.replace(/\\\{[^}]+\\\}/g, "[^/]+")
1260+
const regex = new RegExp(`^${pattern}$`)
1261+
return regex.test(useMcpServer.uri || "")
1262+
} catch {
1263+
return false
1264+
}
1265+
},
1266+
)
1267+
1268+
if (matchedTemplate) {
1269+
return (
1270+
<McpResourceRow
1271+
item={{
1272+
...matchedTemplate,
1273+
uri: useMcpServer.uri || "",
1274+
}}
1275+
serverName={useMcpServer.serverName}
1276+
serverSource={server?.source || "global"}
1277+
alwaysAllowMcp={alwaysAllowMcp}
1278+
/>
1279+
)
1280+
}
1281+
1282+
// Fallback if no match found
1283+
return (
1284+
<McpResourceRow
1285+
item={{
1286+
uri: useMcpServer.uri || "",
1287+
name: "",
1288+
mimeType: "",
1289+
description: "",
1290+
alwaysAllow: false,
1291+
}}
1292+
serverName={useMcpServer.serverName}
1293+
serverSource={server?.source || "global"}
1294+
alwaysAllowMcp={alwaysAllowMcp}
1295+
/>
1296+
)
1297+
})()}
12561298
{useMcpServer.type === "use_mcp_tool" && (
12571299
<McpExecution
12581300
executionId={message.ts.toString()}

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,20 +1004,26 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10041004

10051005
if (mcpServerUse.type === "access_mcp_resource") {
10061006
const server = mcpServers?.find((s: McpServer) => s.name === mcpServerUse.serverName)
1007-
const resource = server?.resources?.find((r: McpResource) => r.uri === mcpServerUse.uri)
10081007

1008+
// First check exact resource match
1009+
const resource = server?.resources?.find((r: McpResource) => r.uri === mcpServerUse.uri)
10091010
if (resource?.alwaysAllow) {
10101011
return true
10111012
}
10121013

1013-
// Check resource templates
1014+
// Then check resource templates
10141015
if (server?.resourceTemplates && mcpServerUse.uri) {
10151016
// Validate URI format first
10161017
if (!isValidUriFormat(mcpServerUse.uri)) {
10171018
return false
10181019
}
10191020

10201021
for (const template of server.resourceTemplates) {
1022+
// Check if template has alwaysAllow set
1023+
if (!template.alwaysAllow) {
1024+
continue
1025+
}
1026+
10211027
try {
10221028
// Convert template pattern to regex with more restrictive matching
10231029
const pattern = template.uriTemplate
@@ -1035,7 +1041,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10351041
return false
10361042
}
10371043

1038-
if (matches && template.alwaysAllow) {
1044+
if (matches) {
10391045
return true
10401046
}
10411047
} catch (error) {

0 commit comments

Comments
 (0)