HRJ n8n MCP
by hrjapp
README.md
# HRJ n8n MCP
Local stdio MCP bridge for managing n8n from HRJ Agent.
This is the sanitized public version of the bridge built for a production VPS. It gives HRJ n8n tools without exposing n8n over the public internet and without putting API keys in your HRJ config.
## What it does
Exposes these MCP tools:
### Health & Info (Safe — Read Only)
| Tool | Description | Risk |
|------|-------------|------|
| `health` | Check n8n API reachability and Docker status | 🟢 Safe |
| `container_status` | Get Docker container status | 🟢 Safe |
### Workflows — Read (Safe)
| Tool | Description | Risk |
|------|-------------|------|
| `list_workflows` | List workflows, optionally filtered by active state | 🟢 Safe |
| `get_workflow` | Inspect one workflow with secret-bearing fields redacted | 🟢 Safe |
| `find_workflows` | Search workflow metadata by name, ID, or tag | 🟢 Safe |
| `export_workflow` | Fetch redacted workflow JSON for backup/review | 🟢 Safe |
### Workflows — Write (PROTECTED)
| Tool | Description | Risk | Protection |
|------|-------------|------|------------|
| `create_workflow` | Create a new workflow with name, nodes, and connections | 🟠 Write | Disabled by default |
| `update_workflow` | Update an existing workflow (partial updates supported) | 🟠 Write | Disabled by default |
| `delete_workflow` | Delete a workflow (irreversible, backup first!) | 🔴 Destructive | **Env + Human Token** |
| `activate_workflow` | Activate a workflow by ID | 🔴 Production | **Env + Human Token** |
| `deactivate_workflow` | Deactivate a workflow by ID | 🔴 Production | **Env + Human Token** |
### Executions (Safe — Read Only)
| Tool | Description | Risk |
|------|-------------|------|
| `list_executions` | List recent executions | 🟢 Safe |
| `get_execution` | Inspect one execution; payload data is off by default | 🟢 Safe |
| `recent_failures` | Recent failed/error executions | 🟢 Safe |
### Docker (Safe — Read Only)
| Tool | Description | Risk |
|------|-------------|------|
| `container_logs` | Docker logs with line-level redaction | 🟢 Safe |
## Security posture
- Stdio only. No HTTP server. No public port.
- API key is loaded from environment or a local dotenv file.
- `.env` is gitignored.
- Example config uses `REPLACE_ME`, never a real key.
- Tool responses redact obvious credential, token, secret, password, and authorization fields.
- Execution payload data is disabled by default in `get_execution`.
- **Write tools are disabled by default** — only read tools are enabled unless you explicitly enable them.
- **Destructive operations require human CLI confirmation** — tokens are generated via interactive script, not by AI.
- **Audit logging** — all write operations are logged to `~/.config/n8n-mcp/logs/audit.log` (append-only).
- Automatic retry on transient 5xx errors and connection failures.
### Tool enablement (recommended)
By default, **only read-only tools are enabled**. This follows the principle of least privilege — write tools must be explicitly enabled.
| Category | Tools | Default | Protection |
|----------|-------|---------|------------|
| Read | `health`, `list_*`, `get_*`, `find_*`, `export_*`, `container_*` | ✅ Enabled | None needed |
| Write | `create_workflow`, `update_workflow` | ❌ Disabled | Env flag |
| Destructive | `delete_workflow` | ❌ Disabled | **Env + Human Token** |
| Production | `activate_workflow`, `deactivate_workflow` | ❌ Disabled | **Env + Human Token** |
To enable write tools, add them to your HRJ config:
```yaml
mcp_servers:
n8n:
# ... basic config ...
tools:
default_enabled:
- health
- list_workflows
- get_workflow
- find_workflows
- list_executions
- get_execution
- recent_failures
- export_workflow
- container_logs
- container_status
# Enable write tools only when needed:
# - create_workflow
# - update_workflow
# - delete_workflow
# - activate_workflow
# - deactivate_workflow
```
### Destructive operations protection
For `delete_workflow`, `activate_workflow`, and `deactivate_workflow`, **two layers of protection** are required:
#### Layer 1: Environment variable (server-side)
Set in your `~/.config/n8n-mcp/env`:
```bash
# For delete operations (KEEP FALSE UNLESS NEEDED)
N8N_MCP_ALLOW_DELETE=false
# For activate/deactivate operations (KEEP FALSE UNLESS NEEDED)
N8N_MCP_ALLOW_ACTIVATE=false
```
**Important:** Only set these to `true` temporarily when you need to perform the operation, then set them back to `false`.
#### Layer 2: Human confirmation token (CLI)
Even with the env flag enabled, you must generate a confirmation token via the interactive CLI script:
```bash
# For delete
./scripts/confirm-action.sh delete 123
# For activate
./scripts/confirm-action.sh activate 123
# For deactivate
./scripts/confirm-action.sh deactivate 123
```
The script will:
1. Display a clear warning about the action
2. Ask you to type `YES` to confirm
3. Generate a time-limited token (120 seconds)
4. The MCP server consumes this token when you call the tool
**Why this is secure:**
- The token is generated by a **separate CLI process**, not by the AI
- The AI cannot generate tokens — it requires **interactive human input**
- Tokens expire after 120 seconds
- Tokens are single-use (deleted after validation)
- Tokens are stored with restrictive permissions (600)
#### Example workflow
```bash
# 1. Enable delete temporarily
export N8N_MCP_ALLOW_DELETE=true
# 2. Generate confirmation token (interactive)
./scripts/confirm-action.sh delete 123
# Type: YES
# 3. Use the MCP tool (token is consumed automatically)
# The AI calls: delete_workflow(workflow_id="123")
# 4. Disable delete immediately
export N8N_MCP_ALLOW_DELETE=false
```
#### Audit logging
All operations are logged to `~/.config/n8n-mcp/logs/audit.log`:
```json
{"action": "DELETE_BLOCKED", "workflow_id": "123", "timestamp": "2026-07-28T21:30:00+00:00", "reason": "N8N_MCP_ALLOW_DELETE=false"}
{"action": "TOKEN_VALIDATED", "workflow_id": "123", "timestamp": "2026-07-28T21:35:00+00:00", "action": "delete"}
{"action": "DELETE_WORKFLOW", "workflow_id": "123", "timestamp": "2026-07-28T21:35:01+00:00", "status": "success"}
```
The log file is **append-only** — entries cannot be deleted or modified without root access.
## Requirements
- Python 3.10+
- HRJ Agent with native MCP enabled
- n8n API key
- n8n reachable from the machine running HRJ, usually `http://127.0.0.1:5678`
## Install
```bash
git clone https://github.com/hrjapp/hrj-n8n-mcp.git
cd hrj-n8n-mcp
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
```
## Store your n8n key
Interactive helper:
```bash
./scripts/set-key.sh
```
Default output path:
```text
~/.config/n8n-mcp/env
```
Expected permissions:
```bash
stat -c '%a %U:%G %n' ~/.config/n8n-mcp/env
# 600 youruser:yourgroup /home/youruser/.config/n8n-mcp/env
```
Manual version:
```bash
install -d -m 700 ~/.config/n8n-mcp
cat > ~/.config/n8n-mcp/env <<'EOF'
N8N_BASE_URL=http://127.0.0.1:5678
N8N_API_KEY=REPLAC...hmod 600 ~/.config/n8n-mcp/env
```
Replace `REPLACE_ME` locally. Do not commit the real file.
## HRJ config
Add this to `~/.hrj/config.yaml`:
```yaml
mcp_servers:
n8n:
command: "/absolute/path/to/hrj-n8n-mcp/.venv/bin/python"
args:
- "/absolute/path/to/hrj-n8n-mcp/server.py"
env:
N8N_MCP_ENV: "/absolute/path/to/.config/n8n-mcp/env"
timeout: 120
connect_timeout: 30
sampling:
enabled: false
tools:
default_enabled:
- health
- list_workflows
- get_workflow
- find_workflows
- list_executions
- get_execution
- recent_failures
- export_workflow
- container_logs
- container_status
```
Then reload MCP in HRJ:
```text
/reload-mcp
```
Or from shell:
```bash
hrj mcp test n8n
```
## Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| `N8N_BASE_URL` | `http://127.0.0.1:5678` | n8n API base URL |
| `N8N_API_KEY` | *(required)* | n8n API key |
| `N8N_MCP_TIMEOUT` | `30` | HTTP request timeout in seconds |
| `N8N_CONTAINER_NAME` | `n8n` | Docker container name for n8n |
| `N8N_MCP_ALLOW_DOCKER_LOGS` | `true` | Enable Docker log features |
| `N8N_MCP_MAX_RETRIES` | `2` | Max retries on transient errors |
| `N8N_MCP_RETRY_DELAY` | `1.0` | Base delay between retries (seconds) |
| `N8N_MCP_ALLOW_DELETE` | `false` | Enable delete operations (requires human token) |
| `N8N_MCP_ALLOW_ACTIVATE` | `false` | Enable activate/deactivate (requires human token) |
| `N8N_MCP_LOG_DIR` | `~/.config/n8n-mcp/logs/` | Audit log directory |
| `N8N_MCP_TOKEN_DIR` | `~/.config/n8n-mcp/tokens/` | Token directory for human confirmation |
| `N8N_MCP_TOKEN_TTL` | `120` | Token time-to-live in seconds |
## Smoke test outside HRJ
```bash
. .venv/bin/activate
python -m py_compile server.py
hrj mcp test n8n
```
## Docker logs
`container_logs` shells out to Docker. If the user running HRJ cannot access Docker, set:
```text
N8N_MCP_ALLOW_DOCKER_LOGS=false
```
The rest of the API tools will still work.
## Audit logs
Write operations are logged to `~/.config/n8n-mcp/logs/audit.log`. Check this file to review:
- Which workflows were created, updated, or deleted
- When activation/deactivation occurred
- Failed attempts (blocked by env flag or missing token)
- Token validation events
## Notes for production use
- Keep n8n bound to loopback behind your reverse proxy.
- Do not expose this MCP bridge over Caddy, nginx, or Docker ports.
- Rotate n8n API keys if they ever hit chat logs, terminals, CI output, screenshots, or issue trackers.
- **Back up workflows before mutating them** (`export_workflow` before `update_workflow`).
- **Use `delete_workflow` with caution** — it is irreversible.
- **Keep write tools disabled by default** — enable only when needed.
- **Keep `N8N_MCP_ALLOW_DELETE=false`** unless actively deleting.
- **Review audit logs** periodically.
## License
MIT. See `LICENSE`.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues