mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-01-29 22:12:05 +00:00
feat: configurable MAX_SESSIONS via N8N_MCP_MAX_SESSIONS env var (v2.28.4) (#469)
* fix: n8n_test_workflow webhookId resolution and form handling (v2.28.2) ## Bug Fixes - **webhookId Resolution**: Fixed trigger handlers using `node.id` instead of `node.webhookId` for building webhook URLs. This caused 404 errors when nodes had custom IDs. - **Chat Trigger URL**: Fixed chat triggers using wrong URL pattern. Now correctly uses `/webhook/<webhookId>/chat` endpoint. - **Form Content-Type**: Fixed form triggers failing with "Expected multipart/form-data" error by switching to proper multipart encoding. ## Enhancements - **Form Field Types**: Added support for all n8n form field types (text, textarea, email, number, password, date, dropdown, checkbox, file, hidden) - **Checkbox Arrays**: Automatically converts arrays to `field[]` format - **Helpful Warnings**: Reports missing required fields with names and labels - **Error Hints**: Provides complete field structure on failure Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: address code review issues for form trigger improvements - Add form-data as direct dependency (was only in devDependencies) - Add TypeScript interfaces (FormFieldValue, FormFieldOption) replacing any types - Add FORM_FIELD_TYPES constants for type-safe switch statements - Add isValidBase64() validation for file uploads with size limits - Add MAX_FILE_SIZE_BYTES (10MB) constant with validation - Update form-handler.test.ts for FormData instead of JSON - Update trigger-detector.test.ts for chat URL /chat suffix Conceived by Romuald Członkowski - www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: configurable MAX_SESSIONS via N8N_MCP_MAX_SESSIONS env var (v2.28.3) (#468) Make MAX_SESSIONS limit configurable for multi-tenant SaaS deployments. - Add N8N_MCP_MAX_SESSIONS environment variable (default: 100) - Include safety floor with Math.max(1, ...) to prevent invalid configs - Update documentation in LIBRARY_USAGE.md, SESSION_PERSISTENCE.md - Update CLAUDE.md and CHANGELOG.md Fixes #468 Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add QEMU setup for multi-arch Docker builds Add docker/setup-qemu-action@v3 before Buildx setup to enable proper QEMU emulation for linux/arm64 builds on GitHub Actions. Fixes CI Docker build failure with "execve: No such file or directory" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Romuald Członkowski <romualdczlonkowski@MacBook-Pro-Romuald.local>
This commit is contained in:
committed by
GitHub
parent
527e9874ab
commit
c2dc7c9c51
3
.github/workflows/docker-build-n8n.yml
vendored
3
.github/workflows/docker-build-n8n.yml
vendored
@@ -52,6 +52,9 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
|||||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [2.28.4] - 2025-12-05
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
**Configurable MAX_SESSIONS Limit (#468)**
|
||||||
|
|
||||||
|
The `MAX_SESSIONS` limit is now configurable via the `N8N_MCP_MAX_SESSIONS` environment variable, addressing scalability issues for multi-tenant SaaS deployments.
|
||||||
|
|
||||||
|
- **Problem**: Hardcoded limit of 100 concurrent sessions caused "Session limit reached" errors during peak usage
|
||||||
|
- **Solution**: `MAX_SESSIONS` now reads from `N8N_MCP_MAX_SESSIONS` env var (default: 100)
|
||||||
|
- **Usage**: Set `N8N_MCP_MAX_SESSIONS=1000` for higher capacity deployments
|
||||||
|
- **Safety**: Includes `Math.max(1, ...)` floor to prevent invalid configurations
|
||||||
|
- **Files**: `src/http-server-single-session.ts:44`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example: Allow up to 1000 concurrent sessions
|
||||||
|
N8N_MCP_MAX_SESSIONS=1000
|
||||||
|
```
|
||||||
|
|
||||||
## [2.28.3] - 2025-12-02
|
## [2.28.3] - 2025-12-02
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@@ -596,7 +615,7 @@ Added export/restore functionality for MCP sessions to enable zero-downtime depl
|
|||||||
- `restoreSessionState(sessions)` method for session recovery
|
- `restoreSessionState(sessions)` method for session recovery
|
||||||
- Validates session structure using existing `validateInstanceContext()`
|
- Validates session structure using existing `validateInstanceContext()`
|
||||||
- Handles null/invalid sessions gracefully with warnings
|
- Handles null/invalid sessions gracefully with warnings
|
||||||
- Enforces MAX_SESSIONS limit (100 concurrent sessions)
|
- Enforces MAX_SESSIONS limit (default 100, configurable via N8N_MCP_MAX_SESSIONS env var)
|
||||||
- Skips expired sessions during restore
|
- Skips expired sessions during restore
|
||||||
|
|
||||||
**3. SessionState Type**
|
**3. SessionState Type**
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ The MCP server exposes tools in several categories:
|
|||||||
- **Security-first**: API keys exported as plaintext - downstream MUST encrypt
|
- **Security-first**: API keys exported as plaintext - downstream MUST encrypt
|
||||||
- **Dormant sessions**: Restored sessions recreate transports on first request
|
- **Dormant sessions**: Restored sessions recreate transports on first request
|
||||||
- **Automatic expiration**: Respects `sessionTimeout` setting (default 30 min)
|
- **Automatic expiration**: Respects `sessionTimeout` setting (default 30 min)
|
||||||
- **MAX_SESSIONS limit**: Caps at 100 concurrent sessions
|
- **MAX_SESSIONS limit**: Caps at 100 concurrent sessions (configurable via N8N_MCP_MAX_SESSIONS env var)
|
||||||
|
|
||||||
**Important Implementation Notes:**
|
**Important Implementation Notes:**
|
||||||
- Only exports sessions with valid n8nApiUrl and n8nApiKey in context
|
- Only exports sessions with valid n8nApiUrl and n8nApiKey in context
|
||||||
|
|||||||
@@ -558,7 +558,7 @@ DISABLE_CONSOLE_OUTPUT=false
|
|||||||
|
|
||||||
# Optional: Session configuration
|
# Optional: Session configuration
|
||||||
SESSION_TIMEOUT=1800000 # 30 minutes in milliseconds
|
SESSION_TIMEOUT=1800000 # 30 minutes in milliseconds
|
||||||
MAX_SESSIONS=100
|
N8N_MCP_MAX_SESSIONS=100 # Maximum concurrent sessions (default: 100)
|
||||||
|
|
||||||
# Optional: Performance
|
# Optional: Performance
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ console.log(`Restored ${count} sessions`);
|
|||||||
- Validates session metadata (timestamps, required fields)
|
- Validates session metadata (timestamps, required fields)
|
||||||
- Skips expired sessions (age > sessionTimeout)
|
- Skips expired sessions (age > sessionTimeout)
|
||||||
- Skips duplicate sessions (idempotent)
|
- Skips duplicate sessions (idempotent)
|
||||||
- Respects MAX_SESSIONS limit (100 per container)
|
- Respects MAX_SESSIONS limit (default 100, configurable via N8N_MCP_MAX_SESSIONS env var)
|
||||||
- Recreates transports/servers lazily on first request
|
- Recreates transports/servers lazily on first request
|
||||||
- Logs security events for restore success/failure
|
- Logs security events for restore success/failure
|
||||||
|
|
||||||
@@ -595,19 +595,19 @@ console.log(`Export size: ${sizeKB.toFixed(2)} KB`);
|
|||||||
|
|
||||||
### MAX_SESSIONS Limit
|
### MAX_SESSIONS Limit
|
||||||
|
|
||||||
Hard limit: 100 sessions per container
|
Default limit: 100 sessions per container (configurable via `N8N_MCP_MAX_SESSIONS` env var)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Restore respects limit
|
// Restore respects limit
|
||||||
const sessions = createSessions(150); // 150 sessions
|
const sessions = createSessions(150); // 150 sessions
|
||||||
const restored = engine.restoreSessionState(sessions);
|
const restored = engine.restoreSessionState(sessions);
|
||||||
// restored = 100 (only first 100 restored)
|
// restored = 100 (only first 100 restored, or N8N_MCP_MAX_SESSIONS value)
|
||||||
```
|
```
|
||||||
|
|
||||||
For >100 sessions per tenant:
|
For higher session limits:
|
||||||
- Deploy multiple containers
|
- Set `N8N_MCP_MAX_SESSIONS=1000` (or desired limit)
|
||||||
- Use session routing/sharding
|
- Monitor memory usage as sessions consume resources
|
||||||
- Implement session affinity
|
- Alternatively, deploy multiple containers with session routing/sharding
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
@@ -676,10 +676,11 @@ Reached MAX_SESSIONS limit (100), skipping remaining sessions
|
|||||||
|
|
||||||
**Solutions:**
|
**Solutions:**
|
||||||
|
|
||||||
1. Scale horizontally (more containers)
|
1. Increase limit: Set `N8N_MCP_MAX_SESSIONS=1000` (or desired value)
|
||||||
2. Implement session sharding
|
2. Scale horizontally (more containers)
|
||||||
3. Reduce sessionTimeout
|
3. Implement session sharding
|
||||||
4. Clean up inactive sessions
|
4. Reduce sessionTimeout
|
||||||
|
5. Clean up inactive sessions
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Pre-filter by activity
|
// Pre-filter by activity
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-mcp",
|
"name": "n8n-mcp",
|
||||||
"version": "2.28.2",
|
"version": "2.28.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "n8n-mcp",
|
"name": "n8n-mcp",
|
||||||
"version": "2.28.2",
|
"version": "2.28.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "1.20.1",
|
"@modelcontextprotocol/sdk": "1.20.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-mcp",
|
"name": "n8n-mcp",
|
||||||
"version": "2.28.3",
|
"version": "2.28.4",
|
||||||
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ interface MultiTenantHeaders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Session management constants
|
// Session management constants
|
||||||
const MAX_SESSIONS = 100;
|
const MAX_SESSIONS = Math.max(1, parseInt(process.env.N8N_MCP_MAX_SESSIONS || '100', 10));
|
||||||
const SESSION_CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
const SESSION_CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||||
|
|
||||||
interface Session {
|
interface Session {
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ describe('SingleSessionHTTPServer - Session Persistence', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should respect MAX_SESSIONS limit during restore', () => {
|
it('should respect MAX_SESSIONS limit during restore', () => {
|
||||||
// Create 99 existing sessions (MAX_SESSIONS is 100)
|
// Create 99 existing sessions (MAX_SESSIONS defaults to 100, configurable via N8N_MCP_MAX_SESSIONS env var)
|
||||||
const serverAny = server as any;
|
const serverAny = server as any;
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
for (let i = 0; i < 99; i++) {
|
for (let i = 0; i < 99; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user