@@ -19,6 +19,7 @@ export function RuntimeProvider({ children }) {
1919 const [ isRunning , setIsRunning ] = useState ( false ) ;
2020 const [ nodeStatuses , setNodeStatuses ] = useState ( { } ) ;
2121 const [ mcpStatus , setMcpStatus ] = useState ( 'disabled' ) ; // disabled, connecting, connected, error
22+ const mcpMessagesRef = useRef ( [ ] ) ; // Queue for mcp-output node messages
2223 const [ hasCanvasNodes , setHasCanvasNodes ] = useState ( false ) ;
2324 const [ hasButtonsNodes , setHasButtonsNodes ] = useState ( false )
2425 const { addMessage, addDownload, addError, clear, clearErrors, messages, errors } = useDebug ( ) ;
@@ -148,6 +149,19 @@ export function RuntimeProvider({ children }) {
148149 return ;
149150 }
150151
152+ // Handle MCP message queue action
153+ if ( action === 'mcpQueueMessage' ) {
154+ mcpMessagesRef . current . push ( params ) ;
155+ // Keep queue from growing unbounded (max 1000 messages)
156+ if ( mcpMessagesRef . current . length > 1000 ) {
157+ mcpMessagesRef . current = mcpMessagesRef . current . slice ( - 1000 ) ;
158+ }
159+ // Update status on the node with new count
160+ const count = mcpMessagesRef . current . filter ( m => m . nodeId === nodeId ) . length ;
161+ peerRef . current . methods . emitEvent ( nodeId , 'queueUpdate' , { count } ) ;
162+ return ;
163+ }
164+
151165 const nodeDef = nodeRegistry . get ( nodeType ) ;
152166 if ( ! nodeDef ?. mainThread ?. [ action ] ) {
153167 logger . warn ( `No mainThread handler for ${ nodeType } .${ action } ` ) ;
@@ -169,6 +183,11 @@ export function RuntimeProvider({ children }) {
169183 return await audioManager . handleMainThreadCall ( nodeId , action , params ) ;
170184 }
171185
186+ // Handle MCP queue count query
187+ if ( action === 'mcpGetQueueCount' ) {
188+ return mcpMessagesRef . current . filter ( m => m . nodeId === params . nodeId ) . length ;
189+ }
190+
172191 const nodeDef = nodeRegistry . get ( nodeType ) ;
173192 if ( ! nodeDef ?. mainThread ?. [ action ] ) {
174193 throw new Error ( `No mainThread handler for ${ nodeType } .${ action } ` ) ;
@@ -760,6 +779,47 @@ export function RuntimeProvider({ children }) {
760779 return nodeStatusesRef . current ;
761780 } ) ;
762781
782+ peerRef . current . addHandler ( 'mcpGetMessages' , ( limit = 100 , clear = true ) => {
783+ const messages = mcpMessagesRef . current . slice ( 0 , limit ) ;
784+ if ( clear && messages . length > 0 ) {
785+ // Remove returned messages from queue
786+ mcpMessagesRef . current = mcpMessagesRef . current . slice ( messages . length ) ;
787+
788+ // Notify mcp-output nodes that queue was cleared
789+ // Group remaining messages by nodeId to get counts
790+ const remainingByNode = { } ;
791+ for ( const msg of mcpMessagesRef . current ) {
792+ remainingByNode [ msg . nodeId ] = ( remainingByNode [ msg . nodeId ] || 0 ) + 1 ;
793+ }
794+
795+ // Find all mcp-output nodes and update their status
796+ const state = flowStateRef . current ;
797+ const mcpOutputNodes = Object . values ( state . nodes ) . filter ( n => n . _node . type === 'mcp-output' ) ;
798+ for ( const node of mcpOutputNodes ) {
799+ const count = remainingByNode [ node . _node . id ] || 0 ;
800+ peerRef . current . methods . emitEvent ( node . _node . id , 'queueUpdate' , { count } ) ;
801+ }
802+ }
803+ return messages ;
804+ } ) ;
805+
806+ peerRef . current . addHandler ( 'mcpSendMessage' , ( payload , topic = '' ) => {
807+ // Find all mcp-input nodes and send message to them
808+ const state = flowStateRef . current ;
809+ const mcpInputNodes = Object . values ( state . nodes ) . filter ( n => n . _node . type === 'mcp-input' ) ;
810+
811+ if ( mcpInputNodes . length === 0 ) {
812+ return { success : false , error : 'No mcp-input nodes found in flows' } ;
813+ }
814+
815+ // Emit message to each mcp-input node
816+ for ( const node of mcpInputNodes ) {
817+ peerRef . current . methods . emitEvent ( node . _node . id , 'mcpMessage' , { payload, topic } ) ;
818+ }
819+
820+ return { success : true , nodeCount : mcpInputNodes . length } ;
821+ } ) ;
822+
763823 peerRef . current . addHandler ( 'mcpGetCanvasSvg' , ( ) => {
764824 // Get the canvas SVG from the DOM
765825 const svgElement = document . querySelector ( '.canvas-svg' ) ;
0 commit comments