Chore/Close mcp connection (#4375)

* close mcp connection

* update file types
This commit is contained in:
Henry Heng 2025-05-06 10:28:18 +08:00 committed by GitHub
parent df26e8aef9
commit c3610ff3c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 47 deletions

View File

@ -19,44 +19,61 @@ export class MCPToolkit extends BaseToolkit {
this.serverParams = serverParams this.serverParams = serverParams
this.transportType = transportType this.transportType = transportType
} }
async initialize() {
if (this._tools === null) { // Method to create a new client with transport
this.client = new Client( async createClient(): Promise<Client> {
{ const client = new Client(
name: 'flowise-client', {
version: '1.0.0' name: 'flowise-client',
}, version: '1.0.0'
{ },
capabilities: {} {
} capabilities: {}
) }
if (this.transportType === 'stdio') { )
// Compatible with overridden PATH configuration
this.serverParams.env = { let transport: StdioClientTransport | SSEClientTransport | StreamableHTTPClientTransport
if (this.transportType === 'stdio') {
// Compatible with overridden PATH configuration
const params = {
...this.serverParams,
env: {
...(this.serverParams.env || {}), ...(this.serverParams.env || {}),
PATH: process.env.PATH 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')
}
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)
}
} }
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 {
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.client.request({ method: 'tools/list' }, ListToolsResultSchema)
this.tools = await this.get_tools() 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') throw new Error('Client is not initialized')
} }
return await MCPTool({ return await MCPTool({
client: this.client, toolkit: this,
name: tool.name, name: tool.name,
description: tool.description || '', description: tool.description || '',
argsSchema: createSchemaModel(tool.inputSchema) argsSchema: createSchemaModel(tool.inputSchema)
@ -80,23 +97,31 @@ export class MCPToolkit extends BaseToolkit {
} }
export async function MCPTool({ export async function MCPTool({
client, toolkit,
name, name,
description, description,
argsSchema argsSchema
}: { }: {
client: Client toolkit: MCPToolkit
name: string name: string
description: string description: string
argsSchema: any argsSchema: any
}): Promise<Tool> { }): Promise<Tool> {
return tool( return tool(
async (input): Promise<string> => { async (input): Promise<string> => {
const req: CallToolRequest = { method: 'tools/call', params: { name: name, arguments: input } } // Create a new client for this request
const res = await client.request(req, CallToolResultSchema) const client = await toolkit.createClient()
const content = res.content
const contentString = JSON.stringify(content) try {
return contentString 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, name: name,

View File

@ -238,25 +238,34 @@ export const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, preview
* {isImageUploadAllowed: boolean, imgUploadSizeAndTypes: Array<{ fileTypes: string[], maxUploadSize: number }>} * {isImageUploadAllowed: boolean, imgUploadSizeAndTypes: Array<{ fileTypes: string[], maxUploadSize: number }>}
*/ */
let acceptFile = false 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) { if (constraints.isImageUploadAllowed) {
const fileType = file.type const fileType = file.type
const sizeInMB = file.size / 1024 / 1024 const sizeInMB = file.size / 1024 / 1024
constraints.imgUploadSizeAndTypes.map((allowed) => { if (constraints.imgUploadSizeAndTypes && Array.isArray(constraints.imgUploadSizeAndTypes)) {
if (allowed.fileTypes.includes(fileType) && sizeInMB <= allowed.maxUploadSize) { constraints.imgUploadSizeAndTypes.forEach((allowed) => {
acceptFile = true if (allowed.fileTypes && allowed.fileTypes.includes(fileType) && sizeInMB <= allowed.maxUploadSize) {
} acceptFile = true
}) }
})
}
} }
if (fullFileUpload) { if (fullFileUpload) {
return true return true
} else if (constraints.isRAGFileUploadAllowed) { } else if (constraints.isRAGFileUploadAllowed) {
const fileExt = file.name.split('.').pop() const fileExt = file.name.split('.').pop()
if (fileExt) { if (fileExt && constraints.fileUploadSizeAndTypes && Array.isArray(constraints.fileUploadSizeAndTypes)) {
constraints.fileUploadSizeAndTypes.map((allowed) => { constraints.fileUploadSizeAndTypes.forEach((allowed) => {
if (allowed.fileTypes.length === 1 && allowed.fileTypes[0] === '*') { if (allowed.fileTypes && allowed.fileTypes.length === 1 && allowed.fileTypes[0] === '*') {
acceptFile = true acceptFile = true
} else if (allowed.fileTypes.includes(`.${fileExt}`)) { } else if (allowed.fileTypes && allowed.fileTypes.includes(`.${fileExt}`)) {
acceptFile = true acceptFile = true
} }
}) })