11import type { BaseCallbackHandler } from '@langchain/core/callbacks/base'
2+ import type { CallbackManagerForChainRun } from '@langchain/core/callbacks/manager'
23import type { BaseLanguageModelInterface , LanguageModelLike } from '@langchain/core/language_models/base'
4+ import type { Serialized } from '@langchain/core/load/serializable'
35import type {
46 BaseMessage ,
57} from '@langchain/core/messages'
68import type { StructuredToolInterface , ToolInterface } from '@langchain/core/tools'
79import type { StreamEvent } from '@langchain/core/tracers/log_stream'
810import type { AgentFinish , AgentStep } from 'langchain/agents'
9-
1011import type { ZodSchema } from 'zod'
1112import type { MCPClient } from '../client.js'
1213import type { BaseConnector } from '../connectors/base.js'
1314import type { MCPSession } from '../session.js'
15+ import { CallbackManager } from '@langchain/core/callbacks/manager'
1416import {
1517 AIMessage ,
1618 HumanMessage ,
@@ -22,10 +24,7 @@ import {
2224 ChatPromptTemplate ,
2325 MessagesPlaceholder ,
2426} from '@langchain/core/prompts'
25- import {
26- AgentExecutor ,
27- createToolCallingAgent ,
28- } from 'langchain/agents'
27+ import { AgentExecutor , createToolCallingAgent } from 'langchain/agents'
2928import { zodToJsonSchema } from 'zod-to-json-schema'
3029import { LangChainAdapter } from '../adapters/langchain_adapter.js'
3130import { logger } from '../logging.js'
@@ -503,6 +502,20 @@ export class MCPAgent {
503502 let nameToToolMap : Record < string , StructuredToolInterface > = Object . fromEntries ( this . _tools . map ( t => [ t . name , t ] ) )
504503 logger . info ( `🏁 Starting agent execution with max_steps=${ steps } ` )
505504
505+ // Create a run manager with our callbacks if we have any - ONCE for the entire execution
506+ let runManager : CallbackManagerForChainRun | undefined
507+ if ( this . callbacks ?. length > 0 ) {
508+ // Create an async callback manager with our callbacks
509+ const callbackManager = new CallbackManager ( undefined , {
510+ handlers : this . callbacks ,
511+ inheritableHandlers : this . callbacks ,
512+ } )
513+ // Create a run manager for this chain execution
514+ runManager = await callbackManager . handleChainStart ( {
515+ name : 'MCPAgent (mcp-use)' ,
516+ } as Serialized , inputs )
517+ }
518+
506519 for ( let stepNum = 0 ; stepNum < steps ; stepNum ++ ) {
507520 stepsTaken = stepNum + 1
508521 if ( this . useServerManager && this . serverManager ) {
@@ -531,15 +544,17 @@ export class MCPAgent {
531544
532545 try {
533546 logger . debug ( 'Starting agent step execution' )
534- const nextStepOutput = await this . _agentExecutor . _takeNextStep (
547+ const nextStepOutput : AgentStep [ ] | AgentFinish = await this . _agentExecutor . _takeNextStep (
535548 nameToToolMap as Record < string , ToolInterface > ,
536549 inputs ,
537550 intermediateSteps ,
551+ runManager ,
538552 )
539- // Agent finish handling
540- if ( ( nextStepOutput as AgentFinish ) . returnValues ) {
553+ // Agent finish handling (AgentFinish contains returnValues property)
554+ if ( 'returnValues' in nextStepOutput ) {
541555 logger . info ( `✅ Agent finished at step ${ stepNum + 1 } ` )
542- result = ( nextStepOutput as AgentFinish ) . returnValues ?. output ?? 'No output generated'
556+ result = nextStepOutput . returnValues ?. output ?? 'No output generated'
557+ runManager ?. handleChainEnd ( { output : result } )
543558
544559 // If structured output is requested, attempt to create it
545560 if ( outputSchema && structuredLlm ) {
@@ -618,10 +633,10 @@ export class MCPAgent {
618633 // Detect direct return
619634 if ( stepArray . length ) {
620635 const lastStep = stepArray [ stepArray . length - 1 ]
621- const toolReturn = await this . _agentExecutor . _getToolReturn ( lastStep )
636+ const toolReturn : AgentFinish | null = await this . _agentExecutor . _getToolReturn ( lastStep )
622637 if ( toolReturn ) {
623638 logger . info ( `🏆 Tool returned directly at step ${ stepNum + 1 } ` )
624- result = ( toolReturn as unknown as AgentFinish ) . returnValues ?. output ?? 'No output generated'
639+ result = toolReturn . returnValues ?. output ?? 'No output generated'
625640 break
626641 }
627642 }
@@ -630,11 +645,13 @@ export class MCPAgent {
630645 if ( e instanceof OutputParserException ) {
631646 logger . error ( `❌ Output parsing error during step ${ stepNum + 1 } : ${ e } ` )
632647 result = `Agent stopped due to a parsing error: ${ e } `
648+ runManager ?. handleChainError ( result )
633649 break
634650 }
635651 logger . error ( `❌ Error during agent execution step ${ stepNum + 1 } : ${ e } ` )
636652 console . error ( e )
637653 result = `Agent stopped due to an error: ${ e } `
654+ runManager ?. handleChainError ( result )
638655 break
639656 }
640657 }
@@ -643,6 +660,7 @@ export class MCPAgent {
643660 if ( ! result ) {
644661 logger . warn ( `⚠️ Agent stopped after reaching max iterations (${ steps } )` )
645662 result = `Agent stopped after reaching the maximum number of steps (${ steps } ).`
663+ runManager ?. handleChainEnd ( { output : result } )
646664 }
647665
648666 logger . info ( '🎉 Agent execution complete' )
@@ -802,6 +820,8 @@ export class MCPAgent {
802820 // Prepare inputs
803821 const inputs = { input : query , chat_history : langchainHistory }
804822
823+ logger . info ( 'callbacks' , this . callbacks )
824+
805825 // Stream events from the agent executor
806826 const eventStream = agentExecutor . streamEvents (
807827 inputs ,
0 commit comments