@@ -27,6 +27,7 @@ import {
2727 ChatMention ,
2828 ChatMetadata ,
2929} from "app-types/chat" ;
30+ import { isMcpAuthRequiredToolResult } from "app-types/mcp" ;
3031
3132import { errorIf , safe } from "ts-safe" ;
3233
@@ -89,6 +90,31 @@ function isExistingAttachmentPart(part: unknown): part is ChatAttachmentPart {
8990 ) ;
9091}
9192
93+ function wrapToolsWithAuthAbort (
94+ tools : Record < string , Tool > ,
95+ abortController : AbortController ,
96+ ) : Record < string , Tool > {
97+ const wrapped : Record < string , Tool > = { } ;
98+ for ( const [ name , tool ] of Object . entries ( tools ) ) {
99+ if ( ! tool . execute ) {
100+ wrapped [ name ] = tool ;
101+ continue ;
102+ }
103+ const originalExecute = tool . execute . bind ( tool ) ;
104+ wrapped [ name ] = {
105+ ...tool ,
106+ execute : async ( input , options ) => {
107+ const result = await originalExecute ( input , options ) ;
108+ if ( isMcpAuthRequiredToolResult ( result ) ) {
109+ abortController . abort ( ) ;
110+ }
111+ return result ;
112+ } ,
113+ } ;
114+ }
115+ return wrapped ;
116+ }
117+
92118export async function POST ( request : Request ) {
93119 try {
94120 const json = await request . json ( ) ;
@@ -281,7 +307,7 @@ export async function POST(request: Request) {
281307 . orElse ( { } ) ;
282308 const inProgressToolParts = extractInProgressToolPart ( message ) ;
283309 if ( inProgressToolParts . length ) {
284- await Promise . all (
310+ const manualToolOutputs = await Promise . all (
285311 inProgressToolParts . map ( async ( part ) => {
286312 const output = await manualToolExecuteByLastMessage (
287313 part ,
@@ -299,6 +325,9 @@ export async function POST(request: Request) {
299325 return output ;
300326 } ) ,
301327 ) ;
328+ if ( manualToolOutputs . some ( isMcpAuthRequiredToolResult ) ) {
329+ return ;
330+ }
302331 }
303332
304333 const userPreferences = thread ?. userPreferences || undefined ;
@@ -365,16 +394,19 @@ export async function POST(request: Request) {
365394 }
366395 logger . info ( `model: ${ chatModel ?. provider } /${ chatModel ?. model } ` ) ;
367396
397+ const mcpAuthAbort = new AbortController ( ) ;
398+ request . signal . addEventListener ( "abort" , ( ) => mcpAuthAbort . abort ( ) ) ;
399+
368400 const result = streamText ( {
369401 model,
370402 system : systemPrompt ,
371403 messages : convertToModelMessages ( messages ) ,
372404 experimental_transform : smoothStream ( { chunking : "word" } ) ,
373405 maxRetries : 2 ,
374- tools : vercelAITooles ,
406+ tools : wrapToolsWithAuthAbort ( vercelAITooles , mcpAuthAbort ) ,
375407 stopWhen : stepCountIs ( 10 ) ,
376408 toolChoice : "auto" ,
377- abortSignal : request . signal ,
409+ abortSignal : mcpAuthAbort . signal ,
378410 } ) ;
379411 result . consumeStream ( ) ;
380412 dataStream . merge (
0 commit comments