11import { type ToolName , toolNames , type FileEntry } from "@roo-code/types"
2- import { type ToolUse , type ToolParamName , toolParamNames , type NativeToolArgs } from "../../shared/tools"
2+ import {
3+ type ToolUse ,
4+ type McpToolUse ,
5+ type ToolParamName ,
6+ toolParamNames ,
7+ type NativeToolArgs ,
8+ } from "../../shared/tools"
39import { parseJSON } from "partial-json"
410import type {
511 ApiStreamToolCallStartChunk ,
@@ -41,11 +47,12 @@ export type ToolCallStreamEvent = ApiStreamToolCallStartChunk | ApiStreamToolCal
4147 */
4248export class NativeToolCallParser {
4349 // Streaming state management for argument accumulation (keyed by tool call id)
50+ // Note: name is string to accommodate dynamic MCP tools (mcp_serverName_toolName)
4451 private static streamingToolCalls = new Map <
4552 string ,
4653 {
4754 id : string
48- name : ToolName
55+ name : string
4956 argumentsAccumulator : string
5057 }
5158 > ( )
@@ -188,8 +195,9 @@ export class NativeToolCallParser {
188195 /**
189196 * Start streaming a new tool call.
190197 * Initializes tracking for incremental argument parsing.
198+ * Accepts string to support both ToolName and dynamic MCP tools (mcp_serverName_toolName).
191199 */
192- public static startStreamingToolCall ( id : string , name : ToolName ) : void {
200+ public static startStreamingToolCall ( id : string , name : string ) : void {
193201 this . streamingToolCalls . set ( id , {
194202 id,
195203 name,
@@ -229,6 +237,11 @@ export class NativeToolCallParser {
229237 // Accumulate the JSON string
230238 toolCall . argumentsAccumulator += chunk
231239
240+ // For dynamic MCP tools, we don't return partial updates - wait for final
241+ if ( toolCall . name . startsWith ( "mcp_" ) ) {
242+ return null
243+ }
244+
232245 // Parse whatever we can from the incomplete JSON!
233246 // partial-json-parser extracts partial values (strings, arrays, objects) immediately
234247 try {
@@ -237,7 +250,7 @@ export class NativeToolCallParser {
237250 // Create partial ToolUse with extracted values
238251 return this . createPartialToolUse (
239252 toolCall . id ,
240- toolCall . name ,
253+ toolCall . name as ToolName ,
241254 partialArgs || { } ,
242255 true , // partial
243256 )
@@ -250,19 +263,20 @@ export class NativeToolCallParser {
250263
251264 /**
252265 * Finalize a streaming tool call.
253- * Parses the complete JSON and returns the final ToolUse.
266+ * Parses the complete JSON and returns the final ToolUse or McpToolUse .
254267 */
255- public static finalizeStreamingToolCall ( id : string ) : ToolUse | null {
268+ public static finalizeStreamingToolCall ( id : string ) : ToolUse | McpToolUse | null {
256269 const toolCall = this . streamingToolCalls . get ( id )
257270 if ( ! toolCall ) {
258271 console . warn ( `[NativeToolCallParser] Attempting to finalize unknown tool call: ${ id } ` )
259272 return null
260273 }
261274
262275 // Parse the complete accumulated JSON
276+ // Cast to any for the name since parseToolCall handles both ToolName and dynamic MCP tools
263277 const finalToolUse = this . parseToolCall ( {
264278 id : toolCall . id ,
265- name : toolCall . name ,
279+ name : toolCall . name as ToolName ,
266280 arguments : toolCall . argumentsAccumulator ,
267281 } )
268282
@@ -490,10 +504,10 @@ export class NativeToolCallParser {
490504 id : string
491505 name : TName
492506 arguments : string
493- } ) : ToolUse < TName > | null {
507+ } ) : ToolUse < TName > | McpToolUse | null {
494508 // Check if this is a dynamic MCP tool (mcp_serverName_toolName)
495509 if ( typeof toolCall . name === "string" && toolCall . name . startsWith ( "mcp_" ) ) {
496- return this . parseDynamicMcpTool ( toolCall ) as ToolUse < TName > | null
510+ return this . parseDynamicMcpTool ( toolCall )
497511 }
498512
499513 // Validate tool name
@@ -697,6 +711,15 @@ export class NativeToolCallParser {
697711 }
698712 break
699713
714+ case "access_mcp_resource" :
715+ if ( args . server_name !== undefined && args . uri !== undefined ) {
716+ nativeArgs = {
717+ server_name : args . server_name ,
718+ uri : args . uri ,
719+ } as NativeArgsFor < TName >
720+ }
721+ break
722+
700723 default :
701724 break
702725 }
@@ -719,51 +742,44 @@ export class NativeToolCallParser {
719742
720743 /**
721744 * Parse dynamic MCP tools (named mcp_serverName_toolName).
722- * These are generated dynamically by getMcpServerTools() and need to be
723- * converted back to use_mcp_tool format.
745+ * These are generated dynamically by getMcpServerTools() and are returned
746+ * as McpToolUse objects that preserve the original tool name.
747+ *
748+ * In native mode, MCP tools are NOT converted to use_mcp_tool - they keep
749+ * their original name so it appears correctly in API conversation history.
750+ * The use_mcp_tool wrapper is only used in XML mode.
724751 */
725- private static parseDynamicMcpTool ( toolCall : {
726- id : string
727- name : string
728- arguments : string
729- } ) : ToolUse < "use_mcp_tool" > | null {
752+ public static parseDynamicMcpTool ( toolCall : { id : string ; name : string ; arguments : string } ) : McpToolUse | null {
730753 try {
731- const args = JSON . parse ( toolCall . arguments )
732-
733- // Extract server_name and tool_name from the arguments
734- // The dynamic tool schema includes these as const properties
735- const serverName = args . server_name
736- const toolName = args . tool_name
737- const toolInputProps = args . toolInputProps
738-
739- if ( ! serverName || ! toolName ) {
740- console . error ( `Missing server_name or tool_name in dynamic MCP tool` )
754+ // Parse the arguments - these are the actual tool arguments passed directly
755+ const args = JSON . parse ( toolCall . arguments || "{}" )
756+
757+ // Extract server_name and tool_name from the tool name itself
758+ // Format: mcp_serverName_toolName
759+ const nameParts = toolCall . name . split ( "_" )
760+ if ( nameParts . length < 3 || nameParts [ 0 ] !== "mcp" ) {
761+ console . error ( `Invalid dynamic MCP tool name format: ${ toolCall . name } ` )
741762 return null
742763 }
743764
744- // Build params for backward compatibility with XML protocol
745- const params : Partial < Record < string , string > > = {
746- server_name : serverName ,
747- tool_name : toolName ,
748- }
749-
750- if ( toolInputProps ) {
751- params . arguments = JSON . stringify ( toolInputProps )
752- }
765+ // Server name is the second part, tool name is everything after
766+ const serverName = nameParts [ 1 ]
767+ const toolName = nameParts . slice ( 2 ) . join ( "_" )
753768
754- // Build nativeArgs with properly typed structure
755- const nativeArgs : NativeToolArgs [ "use_mcp_tool" ] = {
756- server_name : serverName ,
757- tool_name : toolName ,
758- arguments : toolInputProps ,
769+ if ( ! serverName || ! toolName ) {
770+ console . error ( `Could not extract server_name or tool_name from: ${ toolCall . name } ` )
771+ return null
759772 }
760773
761- const result : ToolUse < "use_mcp_tool" > = {
762- type : "tool_use" as const ,
763- name : "use_mcp_tool" ,
764- params,
774+ const result : McpToolUse = {
775+ type : "mcp_tool_use" as const ,
776+ id : toolCall . id ,
777+ // Keep the original tool name (e.g., "mcp_serverName_toolName") for API history
778+ name : toolCall . name ,
779+ serverName,
780+ toolName,
781+ arguments : args ,
765782 partial : false ,
766- nativeArgs,
767783 }
768784
769785 return result
0 commit comments