-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
Fix: Improve Custom MCP node performance by caching toolkits #4809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@HenryHengZJ, this is working very well for me now, very smooth.
I will definitely be keeping this change for my own use, as it is much better to have a minor memory leak (especially since the current MCP implementation has some leaks anyway) than to have the constant process churn overload my server and force me to spend 20 minutes filling in actions on a single MCP node. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Implements caching for MCPToolkit
instances to eliminate redundant process spawning on UI refresh, boosting performance.
- Introduces a static
toolkitCache
keyed by workspace, parsed config, and sandbox. - Parses and canonicalizes
mcpServerConfig
to generate consistent cache keys. - Clears out invalid
mcpActions
after loading a new toolkit to keep the UI in sync.
Comments suppressed due to low confidence (1)
packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts:161
- Add unit tests to verify that cached toolkits are returned correctly and that the stale-action clearing logic behaves as expected to prevent regressions.
if (Custom_MCP.toolkitCache.has(cacheKey)) {
// If parsing fails (e.g., invalid JSON), use the raw string as a fallback. | ||
canonicalConfig = mcpServerConfig | ||
} | ||
const cacheKey = JSON.stringify({ workspaceId, canonicalConfig, sandbox }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serializing the entire sandbox object for the cache key can be expensive and may fail on circular references. Consider restricting the key to only the relevant sandbox properties (e.g. $vars
), or use a lightweight hash of workspaceId
and canonicalConfig
instead.
const cacheKey = JSON.stringify({ workspaceId, canonicalConfig, sandbox }) | |
const sandboxVars = sandbox['$vars'] || {}; | |
const cacheKey = JSON.stringify({ workspaceId, canonicalConfig, sandboxVars }); |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@toi500 im quite concerned about stringify the whole canonicalConfig and sandboxVars because users can enter anything that could cause problem.
all we need is a unique key right?
how bout workspaceId_chatflowId_nodeId
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, I think the key must be unique depending on the mcpServerConfig
..
How do we clear the cache though?
does this takes care of tool availability changes ? when custom mcps are used via |
Not sure if I am following you here. Every time you add a version, it uses a new mcpServerConfig, and you will fetch whatever actions that version has. That version is then cached until Flowise restarts. If what you mean is that you will lose the convenience of using "@latest" in some cases, it is a trade-off I would definitely pay for not spinning up the same server 10 times to add 10 actions and spending 10 minutes on it. |
As discussed, this PR fixes a critical performance issue in the
Custom MCP
node caused by redundant process spawning. The STDIO transport is re-spawning a child process on every UI refresh, leading to significant overhead.Solution:
This is a single file solution implemented entirely within
customMCP.ts
.static toolkitCache
is used to store and reuseMCPToolkit
instances, preventing the expensive process creation on every refresh.mcpServerConfig
JSON. This makes the cache immune to formatting differences (spaces, newlines) and prevents spawning duplicate processes for the same logical configuration.Trade-off:
Since we are not modifyingcore.ts
and the node'sdestroy()
method has proven unreliable for cleanup (I have tried to implement it without any success), this solution will leak one process per unique server configuration. This is a necessary trade-off to fix the critical performance issue immediately while keeping the changes isolated to this single file.