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:
Romuald Członkowski
2025-12-05 11:17:51 +01:00
committed by GitHub
parent 527e9874ab
commit c2dc7c9c51
9 changed files with 42 additions and 19 deletions

View File

@@ -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

View File

@@ -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**

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

@@ -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",

View File

@@ -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",

View File

@@ -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 {

View File

@@ -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++) {