mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-01-30 06:22:04 +00:00
When SSE sessions are recreated every 5 minutes, the old session's MCP server was not being closed, causing: - SimpleCache cleanup timer continuing to run indefinitely - Database connections remaining open - Cached data (~50-100MB per session) persisting in memory Added server.close() call before transport.close() in resetSessionSSE(), mirroring the existing cleanup pattern in removeSession(). Fixes #542 Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
0f15b82f1e
commit
fad3437977
11
CHANGELOG.md
11
CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.33.4] - 2026-01-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Memory leak in SSE session reset** (Issue #542): Fixed memory leak when SSE sessions are recreated every 5 minutes
|
||||
- Root cause: `resetSessionSSE()` only closed the transport but not the MCP server
|
||||
- This left the SimpleCache cleanup timer (60-second interval) running indefinitely
|
||||
- Database connections and cached data (~50-100MB per session) persisted in memory
|
||||
- Fix: Added `server.close()` call before `transport.close()`, mirroring the existing cleanup pattern in `removeSession()`
|
||||
- Impact: Prevents ~288 leaked server instances per day in long-running HTTP deployments
|
||||
|
||||
## [2.33.3] - 2026-01-21
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "n8n-mcp",
|
||||
"version": "2.33.3",
|
||||
"version": "2.33.4",
|
||||
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -677,11 +677,25 @@ export class SingleSessionHTTPServer {
|
||||
private async resetSessionSSE(res: express.Response): Promise<void> {
|
||||
// Clean up old session if exists
|
||||
if (this.session) {
|
||||
const sessionId = this.session.sessionId;
|
||||
logger.info('Closing previous session for SSE', { sessionId });
|
||||
|
||||
// Close server first to free resources (database, cache timer, etc.)
|
||||
// This mirrors the cleanup pattern in removeSession() (issue #542)
|
||||
// Handle server close errors separately so transport close still runs
|
||||
if (this.session.server && typeof this.session.server.close === 'function') {
|
||||
try {
|
||||
await this.session.server.close();
|
||||
} catch (serverError) {
|
||||
logger.warn('Error closing server for SSE session', { sessionId, error: serverError });
|
||||
}
|
||||
}
|
||||
|
||||
// Close transport last - always attempt even if server.close() failed
|
||||
try {
|
||||
logger.info('Closing previous session for SSE', { sessionId: this.session.sessionId });
|
||||
await this.session.transport.close();
|
||||
} catch (error) {
|
||||
logger.warn('Error closing previous session:', error);
|
||||
} catch (transportError) {
|
||||
logger.warn('Error closing transport for SSE session', { sessionId, error: transportError });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user