@@ -15,14 +15,19 @@ export class MCPToolkit extends BaseToolkit {
1515 client : Client | null = null
1616 serverParams : StdioServerParameters | any
1717 transportType : 'stdio' | 'sse'
18+ /** Per-invocation HTTP headers injected at tools/call time; overrides static toolkit headers for the same names. */
19+ getToolCallHeaders ?: ( ) => Promise < Record < string , string > >
1820 constructor ( serverParams : StdioServerParameters | any , transportType : 'stdio' | 'sse' ) {
1921 super ( )
2022 this . serverParams = serverParams
2123 this . transportType = transportType
2224 }
2325
24- // Method to create a new client with transport
25- async createClient ( ) : Promise < Client > {
26+ /**
27+ * Creates a new MCP client and connects it via the configured transport.
28+ * @param injectHeaders - Additional HTTP headers merged over static `serverParams.headers` for this connection. Used to pass per-invocation headers (e.g. from {@link getToolCallHeaders}) into SSE/HTTP transports.
29+ */
30+ async createClient ( injectHeaders : Record < string , string > = { } ) : Promise < Client > {
2631 const client = new Client (
2732 {
2833 name : 'flowise-client' ,
@@ -54,28 +59,30 @@ export class MCPToolkit extends BaseToolkit {
5459
5560 const baseUrl = new URL ( this . serverParams . url )
5661 await checkDenyList ( this . serverParams . url )
62+ const mergedHeaders = { ...this . serverParams ?. headers , ...injectHeaders }
63+ const headers = Object . keys ( mergedHeaders ) . length > 0 ? mergedHeaders : undefined
5764 try {
58- if ( this . serverParams . headers ) {
65+ if ( headers ) {
5966 transport = new StreamableHTTPClientTransport ( baseUrl , {
6067 requestInit : {
61- headers : this . serverParams . headers
68+ headers
6269 }
6370 } )
6471 } else {
6572 transport = new StreamableHTTPClientTransport ( baseUrl )
6673 }
6774 await client . connect ( transport )
6875 } catch ( error ) {
69- if ( this . serverParams . headers ) {
76+ if ( headers ) {
7077 transport = new SSEClientTransport ( baseUrl , {
7178 requestInit : {
72- headers : this . serverParams . headers
79+ headers
7380 } ,
7481 eventSourceInit : {
7582 fetch : async ( url , init ) => {
7683 return secureFetch ( url . toString ( ) , {
7784 ...( init as any ) ,
78- headers : this . serverParams . headers
85+ headers
7986 } ) as any
8087 }
8188 }
@@ -148,7 +155,8 @@ export async function MCPTool({
148155 return tool (
149156 async ( input ) : Promise < string > => {
150157 // Create a new client for this request
151- const client = await toolkit . createClient ( )
158+ const toolCallHeaders = await toolkit . getToolCallHeaders ?.( )
159+ const client = await toolkit . createClient ( toolCallHeaders )
152160
153161 try {
154162 const req : CallToolRequest = { method : 'tools/call' , params : { name : name , arguments : input as any } }
@@ -190,7 +198,7 @@ function createSchemaModel(
190198export const validateArgsForLocalFileAccess = ( args : string [ ] ) : void => {
191199 const dangerousPatterns = [
192200 // Absolute paths
193- / ^ \/ [ ^ / ] / , // Unix absolute paths starting with /
201+ / ^ \/ / , // Unix absolute paths starting with /
194202 / ^ [ a - z A - Z ] : \\ / , // Windows absolute paths like C:\
195203
196204 // Relative paths that could escape current directory
@@ -286,7 +294,9 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
286294 '-c' , // Execute shell commands
287295 '--call' , // Execute shell commands
288296 '--shell-auto-fallback' , // Shell execution fallback
289- '-y' // Auto-confirms installation prompts
297+ '-y' , // Auto-confirms installation prompts
298+ '--yes' , // Auto-confirms installation prompts
299+ '--node-options' // Passes arbitrary Node flags to underlying process, bypassing node flag blocklist
290300 ] ,
291301 node : [
292302 '-e' , // Execute JavaScript code
@@ -295,7 +305,13 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
295305 '--print' , // Evaluate and print JavaScript code
296306 '--inspect' , // Enable remote debugging (security risk)
297307 '--inspect-brk' , // Enable remote debugging with breakpoint (security risk)
298- '--experimental-policy' // Could load malicious policies
308+ '--experimental-policy' , // Could load malicious policies
309+ '-r' , // Short alias for --require
310+ '--require' , // Preload a CommonJS module before script runs
311+ '--loader' , // Custom ES module loader hook (code execution)
312+ '--experimental-loader' , // Same as --loader, older Node alias
313+ '--import' , // Preload ESM module before entry script (Node 18+)
314+ '--env-file' // Read env vars from a local file (Node 20+, local file access)
299315 ] ,
300316 python : [
301317 '-c' , // Execute Python code
@@ -307,15 +323,22 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
307323 ] ,
308324 docker : [
309325 'run' , // Run containers (too powerful)
326+ 'build' , // Pulls a container and executes the run instructions
310327 'exec' , // Execute in containers
328+ 'compose' , // Subcommand that starts containers (same risk as run)
311329 '-v' , // Mount host filesystems
312330 '--volume' , // Mount host filesystems
331+ '--mount' , // Alternative to -v/--volume for mounting host paths
332+ '--volumes-from' , // Mount volumes from another container (filesystem access)
313333 '--privileged' , // Privileged mode
314334 '--cap-add' , // Add capabilities
315335 '--security-opt' , // Modify security options
336+ '--device' , // Add host device files to container (privilege escalation)
337+ '--entrypoint' , // Override container entrypoint (arbitrary code execution)
316338 '--network' , // Host network access (catches --network=host and --network host)
317339 '--pid' , // Host PID namespace (catches --pid=host and --pid host)
318- '--ipc' // Host IPC namespace (catches --ipc=host and --ipc host)
340+ '--ipc' , // Host IPC namespace (catches --ipc=host and --ipc host)
341+ '--env-file' // Read env vars from a local host file (local file access)
319342 ]
320343 }
321344
0 commit comments