How MCP Server Integration Works in Roo Code: `use_mcp_tool` and `access_mcp_resource` Explained
Roo Code extends its AI coding capabilities by communicating with Model Context Protocol (MCP) servers through two native tools—use_mcp_tool for invoking remote server functions and access_mcp_resource for reading files—both following a validated, approval-based pipeline before delegating execution to the MCP hub.
Roo Code's MCP server integration bridges LLM reasoning with external, user-controlled services. The system mediates these interactions through dedicated tool classes that validate parameters, enforce user consent, and normalize responses from remote MCP servers.
MCP Integration Architecture Overview
Both use_mcp_tool and access_mcp_resource follow a uniform seven-step execution pipeline defined in the core tool implementations:
- Tool-use block creation – The LLM emits a
ToolUse<"use_mcp_tool">orToolUse<"access_mcp_resource">block. - Synthetic block handling –
presentAssistantMessage.tsconverts the block into a syntheticToolUsethat concrete tool classes process. - Parameter validation – Each tool validates required fields (
server_name,tool_nameoruri), incrementingtask.consecutiveMistakeCounton errors. - Auto-approval check – If the MCP server definition includes
alwaysAllow: true,src/core/auto-approval/mcp.tsbypasses user consent. - User approval – Otherwise, the tool calls
askApproval("use_mcp_server", …)to prompt the user with "Allow Roo to call this MCP tool/resource?". - MCP hub interaction – The tool obtains the MCP hub from the provider (
task.providerRef.deref()?.getMcpHub()) and invokesrunTool()orreadResource(). - Result formatting –
formatResponsebuilds markdown-compatible output and optional image blobs for the chat UI.
How use_mcp_tool Invokes Remote MCP Tools
The use_mcp_tool implementation resides in src/core/tools/UseMcpToolTool.ts. This class handles invocation of named tools exposed by connected MCP servers, such as "npm-search" or custom business logic functions.
Parameter Validation and Tool Discovery
The execute method first calls validateParams to ensure server_name and tool_name are present and that arguments is a plain object. Missing parameters trigger task.sayAndCreateMissingParamError and increment the mistake counter.
// Validation logic from UseMcpToolTool.ts
validateParams(params, task) {
if (!params.server_name) {
task.sayAndCreateMissingParamError("use_mcp_tool", "server_name");
return false;
}
if (!params.tool_name) {
task.sayAndCreateMissingParamError("use_mcp_tool", "tool_name");
return false;
}
// Additional validation for arguments object...
}
Next, validateToolExists queries the MCP hub to locate the specified server, then performs fuzzy matching on the tool name using toolNamesMatch from src/utils/mcp-name.ts. This helper handles hyphen-to-underscore normalization, ensuring npm-search matches npm_search if necessary.
The Approval Workflow
Before execution, Roo Code converts the request into a ClineAskUseMcpServer JSON object and passes it to askApproval("use_mcp_server", …). If the user approves—or if the tool is auto-approved via isMcpToolAlwaysAllowed in src/core/auto-approval/mcp.ts—execution proceeds.
Auto-approval occurs only when the tool definition in the MCP server configuration explicitly sets alwaysAllow: true. Otherwise, the UI blocks execution pending explicit user consent.
Execution via MCP Hub
Upon approval, executeToolAndProcessResult (inherited from BaseTool) forwards the call to:
provider.getMcpHub().runTool(serverName, resolvedToolName, parsedArguments)
The MCP hub handles the remote RPC, executes the tool on the external server, and returns results. The tool then formats the output using formatResponse.toolResult and pushes it to the chat interface.
Handling Partial Streams
When the LLM streams a partial tool request, handlePartial creates a partial approval message and sends it via task.ask("use_mcp_server", …, true), allowing the UI to display incomplete tool calls before final execution.
How access_mcp_resource Retrieves Server Resources
Located in src/core/tools/accessMcpResourceTool.ts, this tool enables Roo Code to read arbitrary resources—files, images, or data blobs—from an MCP server's workspace using URI-based addressing.
URI-Based Resource Reading
The execute method validates server_name and uri parameters. Unlike use_mcp_tool, which requires a tool name and arguments, resource access only needs the server identifier and resource path.
// From accessMcpResourceTool.ts
if (!params.server_name || !params.uri) {
task.sayAndCreateMissingParamError("access_mcp_resource",
!params.server_name ? "server_name" : "uri");
return;
}
After passing through the same approval workflow as tool execution, the method calls:
provider.getMcpHub().readResource(server_name, uri)
Handling Text and Image Responses
The MCP hub returns an array of contents objects containing either text or binary image data. The tool processes these by:
- Concatenating text parts into a single markdown document
- Normalizing image blobs to
data:URLs for inline rendering - Sending formatted results via
task.sayandformatResponse.toolResult
This allows Roo Code to display images retrieved from remote MCP servers directly within the chat interface.
Synthetic Tool Dispatching
The assistant message layer in src/core/assistant-message/presentAssistantMessage.ts creates synthetic tool-use objects to route MCP requests through the standard execution path:
// Creating a synthetic tool use block for MCP tools
const syntheticToolUse: ToolUse<"use_mcp_tool"> = {
name: "use_mcp_tool",
params: {
server_name: "my-mcp",
tool_name: "npm-search",
arguments: { query: "zod" }
},
};
await useMcpToolTool.handle(cline, syntheticToolUse, callbacks);
This pattern ensures that native MCP tools and custom user-defined tools share identical validation, approval, and error-handling infrastructure.
Practical Implementation Examples
Example A: Invoking an NPM Search Tool
When the LLM requests a package search, Roo Code processes:
// LLM output structure
const toolRequest = {
name: "use_mcp_tool",
params: {
server_name: "my-mcp",
tool_name: "npm-search",
arguments: { query: "zod" }
}
};
// Synthetic block creation in presentAssistantMessage.ts
const syntheticToolUse: ToolUse<"use_mcp_tool"> = {
name: "use_mcp_tool",
params: toolRequest.params,
};
await useMcpToolTool.handle(cline, syntheticToolUse, callbacks);
The system validates the request, asks "Allow Roo to run npm-search on server my-mcp?", then executes the remote search via the MCP hub.
Example B: Reading a TypeScript Source File
To access a file on an MCP server:
// Resource request
const resourceRequest = {
name: "access_mcp_resource",
params: { server_name: "my-mcp", uri: "/src/utils.ts" }
};
// Synthetic dispatch
const syntheticToolUse: ToolUse<"access_mcp_resource"> = {
name: "access_mcp_resource",
params: resourceRequest.params,
};
await accessMcpResourceTool.handle(cline, syntheticToolUse, callbacks);
After approval, the tool retrieves the file contents and any embedded images, formatting them for display in the chat UI.
Core Source Files and Responsibilities
src/core/tools/UseMcpToolTool.ts– Implements theuse_mcp_toolnative tool, including parameter validation, tool existence checks with fuzzy matching, user approval handling, and result formatting.src/core/tools/accessMcpResourceTool.ts– Implementsaccess_mcp_resourcefor URI-based file reading, including text concatenation and image blob normalization.src/core/auto-approval/mcp.ts– ProvidesisMcpToolAlwaysAllowedto determine when to bypass user consent based on server configuration.src/core/assistant-message/presentAssistantMessage.ts– Dispatches native MCP tool blocks as synthetic tool-use objects for standardized processing.src/utils/mcp-name.ts– ContainstoolNamesMatchhelper for fuzzy name matching between hyphens and underscores.src/shared/tools.ts– TypeScript type definitions for MCP tool parameters and response shapes.
Summary
- Unified architecture – Both MCP tools inherit from
BaseTool, sharing validation, approval, and error-handling logic while delegating remote communication to the MCP hub abstraction. - Safety controls – Mandatory parameter validation with mistake counting, explicit user approval (unless auto-approved), and structured error reporting keep interactions deterministic.
- Flexible discovery – Runtime tool lookup with fuzzy name matching allows MCP servers to expose custom tools without rigid naming conventions.
- Rich media support –
access_mcp_resourcenormalizes image responses to data-URIs, enabling inline display of remote resources alongside text content.
Frequently Asked Questions
What happens if an MCP tool is called with the wrong name?
Roo Code uses fuzzy matching via toolNamesMatch in src/utils/mcp-name.ts to handle common variations like hyphens versus underscores. If no matching tool is found after normalization, the validation fails and task.sayAndCreateMissingParamError reports the missing tool to the user, incrementing consecutiveMistakeCount to prevent infinite loops.
Can MCP tools execute without user approval?
Yes, if the MCP server configuration sets alwaysAllow: true for a specific tool, src/core/auto-approval/mcp.ts short-circuits the approval UI. Otherwise, Roo Code explicitly asks "Allow Roo to call this MCP tool/resource?" before proceeding with execution.
How does Roo Code handle binary files from MCP servers?
When access_mcp_resource retrieves binary image data from an MCP server, it normalizes the blobs to data: URLs during result processing in src/core/tools/accessMcpResourceTool.ts. This allows images to render inline within the markdown chat interface alongside text content.
What is the difference between use_mcp_tool and access_mcp_resource?
use_mcp_tool invokes named functions exposed by the MCP server with arguments (like "npm-search"), while access_mcp_resource reads static resources via URI (like "/src/utils.ts"). The former executes remote procedures; the latter retrieves file contents and supports image blob normalization.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →