Skip to content

Commit fd66f5c

Browse files
committed
feat: non blocking structured output
1 parent f8d499f commit fd66f5c

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

packages/mcp-use/src/agents/mcp_agent.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,9 +1175,54 @@ export class MCPAgent {
11751175
}
11761176

11771177
try {
1178-
const structuredResult = await structuredLlm.invoke(formatPrompt)
1178+
logger.info(`🔄 Structured output attempt ${attempt} - using streaming approach`)
1179+
1180+
// Use streaming to avoid blocking the event loop
1181+
const stream = await structuredLlm.stream(formatPrompt)
1182+
let structuredResult = null
1183+
let chunkCount = 0
1184+
1185+
for await (const chunk of stream) {
1186+
chunkCount++
1187+
1188+
// Handle different chunk types
1189+
if (typeof chunk === 'string') {
1190+
// If it's a string, try to parse it as JSON
1191+
try {
1192+
structuredResult = JSON.parse(chunk)
1193+
} catch (e) {
1194+
logger.warn(`🔄 Failed to parse string chunk as JSON: ${chunk}`)
1195+
}
1196+
} else if (chunk && typeof chunk === 'object') {
1197+
// If it's already an object, use it directly
1198+
structuredResult = chunk
1199+
} else {
1200+
// Convert other types to string and try to parse
1201+
try {
1202+
structuredResult = JSON.parse(String(chunk))
1203+
} catch (e) {
1204+
logger.warn(`🔄 Failed to parse chunk as JSON: ${chunk}`)
1205+
}
1206+
}
1207+
1208+
// Yield control to allow keepalive events during streaming
1209+
// This prevents the event loop from being blocked during long LLM processing,
1210+
// allowing keepalive events to fire and preventing inactivity timeouts
1211+
await new Promise(resolve => setTimeout(resolve, 0))
1212+
1213+
// Log progress every 10 chunks
1214+
if (chunkCount % 10 === 0) {
1215+
logger.info(`🔄 Structured output streaming: ${chunkCount} chunks`)
1216+
}
1217+
}
1218+
11791219
logger.info(`🔄 Structured result attempt ${attempt}: ${JSON.stringify(structuredResult, null, 2)}`)
11801220

1221+
// Use the structured result directly (no need to parse)
1222+
if (!structuredResult) {
1223+
throw new Error('No structured result received from stream')
1224+
}
1225+
11811226
// Validate the structured result
11821227
const validatedResult = this._validateStructuredResult(structuredResult, outputSchema)
11831228
logger.info(`✅ Structured output successful on attempt ${attempt}`)

0 commit comments

Comments
 (0)