diff --git a/packages/components/nodes/tools/MCP/core.ts b/packages/components/nodes/tools/MCP/core.ts index 226c70b60ac..7c894fcc479 100644 --- a/packages/components/nodes/tools/MCP/core.ts +++ b/packages/components/nodes/tools/MCP/core.ts @@ -19,44 +19,61 @@ export class MCPToolkit extends BaseToolkit { this.serverParams = serverParams this.transportType = transportType } - async initialize() { - if (this._tools === null) { - this.client = new Client( - { - name: 'flowise-client', - version: '1.0.0' - }, - { - capabilities: {} - } - ) - if (this.transportType === 'stdio') { - // Compatible with overridden PATH configuration - this.serverParams.env = { + + // Method to create a new client with transport + async createClient(): Promise { + const client = new Client( + { + name: 'flowise-client', + version: '1.0.0' + }, + { + capabilities: {} + } + ) + + let transport: StdioClientTransport | SSEClientTransport | StreamableHTTPClientTransport + + if (this.transportType === 'stdio') { + // Compatible with overridden PATH configuration + const params = { + ...this.serverParams, + env: { ...(this.serverParams.env || {}), PATH: process.env.PATH } + } - this.transport = new StdioClientTransport(this.serverParams as StdioServerParameters) - await this.client.connect(this.transport) - } else { - if (this.serverParams.url === undefined) { - throw new Error('URL is required for SSE transport') - } + transport = new StdioClientTransport(params as StdioServerParameters) + await client.connect(transport) + } else { + if (this.serverParams.url === undefined) { + throw new Error('URL is required for SSE transport') + } - const baseUrl = new URL(this.serverParams.url) - try { - this.transport = new StreamableHTTPClientTransport(baseUrl) - await this.client.connect(this.transport) - } catch (error) { - this.transport = new SSEClientTransport(baseUrl) - await this.client.connect(this.transport) - } + const baseUrl = new URL(this.serverParams.url) + try { + transport = new StreamableHTTPClientTransport(baseUrl) + await client.connect(transport) + } catch (error) { + transport = new SSEClientTransport(baseUrl) + await client.connect(transport) } + } + + return client + } + + async initialize() { + if (this._tools === null) { + this.client = await this.createClient() this._tools = await this.client.request({ method: 'tools/list' }, ListToolsResultSchema) this.tools = await this.get_tools() + + // Close the initial client after initialization + await this.client.close() } } @@ -69,7 +86,7 @@ export class MCPToolkit extends BaseToolkit { throw new Error('Client is not initialized') } return await MCPTool({ - client: this.client, + toolkit: this, name: tool.name, description: tool.description || '', argsSchema: createSchemaModel(tool.inputSchema) @@ -80,23 +97,31 @@ export class MCPToolkit extends BaseToolkit { } export async function MCPTool({ - client, + toolkit, name, description, argsSchema }: { - client: Client + toolkit: MCPToolkit name: string description: string argsSchema: any }): Promise { return tool( async (input): Promise => { - const req: CallToolRequest = { method: 'tools/call', params: { name: name, arguments: input } } - const res = await client.request(req, CallToolResultSchema) - const content = res.content - const contentString = JSON.stringify(content) - return contentString + // Create a new client for this request + const client = await toolkit.createClient() + + try { + const req: CallToolRequest = { method: 'tools/call', params: { name: name, arguments: input } } + const res = await client.request(req, CallToolResultSchema) + const content = res.content + const contentString = JSON.stringify(content) + return contentString + } finally { + // Always close the client after the request completes + await client.close() + } }, { name: name, diff --git a/packages/ui/src/views/chatmessage/ChatMessage.jsx b/packages/ui/src/views/chatmessage/ChatMessage.jsx index 11355599b57..a63f2a71e01 100644 --- a/packages/ui/src/views/chatmessage/ChatMessage.jsx +++ b/packages/ui/src/views/chatmessage/ChatMessage.jsx @@ -238,25 +238,34 @@ export const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, preview * {isImageUploadAllowed: boolean, imgUploadSizeAndTypes: Array<{ fileTypes: string[], maxUploadSize: number }>} */ let acceptFile = false + + // Early return if constraints are not available yet + if (!constraints) { + console.warn('Upload constraints not loaded yet') + return false + } + if (constraints.isImageUploadAllowed) { const fileType = file.type const sizeInMB = file.size / 1024 / 1024 - constraints.imgUploadSizeAndTypes.map((allowed) => { - if (allowed.fileTypes.includes(fileType) && sizeInMB <= allowed.maxUploadSize) { - acceptFile = true - } - }) + if (constraints.imgUploadSizeAndTypes && Array.isArray(constraints.imgUploadSizeAndTypes)) { + constraints.imgUploadSizeAndTypes.forEach((allowed) => { + if (allowed.fileTypes && allowed.fileTypes.includes(fileType) && sizeInMB <= allowed.maxUploadSize) { + acceptFile = true + } + }) + } } if (fullFileUpload) { return true } else if (constraints.isRAGFileUploadAllowed) { const fileExt = file.name.split('.').pop() - if (fileExt) { - constraints.fileUploadSizeAndTypes.map((allowed) => { - if (allowed.fileTypes.length === 1 && allowed.fileTypes[0] === '*') { + if (fileExt && constraints.fileUploadSizeAndTypes && Array.isArray(constraints.fileUploadSizeAndTypes)) { + constraints.fileUploadSizeAndTypes.forEach((allowed) => { + if (allowed.fileTypes && allowed.fileTypes.length === 1 && allowed.fileTypes[0] === '*') { acceptFile = true - } else if (allowed.fileTypes.includes(`.${fileExt}`)) { + } else if (allowed.fileTypes && allowed.fileTypes.includes(`.${fileExt}`)) { acceptFile = true } })