Skip to main content
Glama

n8n-MCP

by 88-888
docker-entrypoint.shβ€’6.98 kB
#!/bin/sh set -e # Load configuration from JSON file if it exists if [ -f "/app/config.json" ] && [ -f "/app/docker/parse-config.js" ]; then # Use Node.js to generate shell-safe export commands eval $(node /app/docker/parse-config.js /app/config.json) fi # Helper function for safe logging (prevents stdio mode corruption) log_message() { [ "$MCP_MODE" != "stdio" ] && echo "$@" } # Environment variable validation if [ "$MCP_MODE" = "http" ] && [ -z "$AUTH_TOKEN" ] && [ -z "$AUTH_TOKEN_FILE" ]; then log_message "ERROR: AUTH_TOKEN or AUTH_TOKEN_FILE is required for HTTP mode" >&2 exit 1 fi # Validate AUTH_TOKEN_FILE if provided if [ -n "$AUTH_TOKEN_FILE" ] && [ ! -f "$AUTH_TOKEN_FILE" ]; then log_message "ERROR: AUTH_TOKEN_FILE specified but file not found: $AUTH_TOKEN_FILE" >&2 exit 1 fi # Database path configuration - respect NODE_DB_PATH if set if [ -n "$NODE_DB_PATH" ]; then # Basic validation - must end with .db case "$NODE_DB_PATH" in *.db) ;; *) log_message "ERROR: NODE_DB_PATH must end with .db" >&2; exit 1 ;; esac # Use the path as-is (Docker paths should be absolute anyway) DB_PATH="$NODE_DB_PATH" else DB_PATH="/app/data/nodes.db" fi DB_DIR=$(dirname "$DB_PATH") # Ensure database directory exists with correct ownership if [ ! -d "$DB_DIR" ]; then log_message "Creating database directory: $DB_DIR" if [ "$(id -u)" = "0" ]; then # Create as root but immediately fix ownership mkdir -p "$DB_DIR" && chown nodejs:nodejs "$DB_DIR" else mkdir -p "$DB_DIR" fi fi # Database initialization with file locking to prevent race conditions if [ ! -f "$DB_PATH" ]; then log_message "Database not found at $DB_PATH. Initializing..." # Ensure lock directory exists before attempting to create lock mkdir -p "$DB_DIR" # Check if flock is available if command -v flock >/dev/null 2>&1; then # Use a lock file to prevent multiple containers from initializing simultaneously # Try to create lock file, handle permission errors gracefully LOCK_FILE="$DB_DIR/.db.lock" # Ensure we can create the lock file - fix permissions if running as root if [ "$(id -u)" = "0" ] && [ ! -w "$DB_DIR" ]; then chown nodejs:nodejs "$DB_DIR" 2>/dev/null || true chmod 755 "$DB_DIR" 2>/dev/null || true fi # Try to create lock file with proper error handling if touch "$LOCK_FILE" 2>/dev/null; then ( flock -x 200 # Double-check inside the lock if [ ! -f "$DB_PATH" ]; then log_message "Initializing database at $DB_PATH..." cd /app && NODE_DB_PATH="$DB_PATH" node dist/scripts/rebuild.js || { log_message "ERROR: Database initialization failed" >&2 exit 1 } fi ) 200>"$LOCK_FILE" else log_message "WARNING: Cannot create lock file at $LOCK_FILE, proceeding without file locking" # Fallback without locking if we can't create the lock file if [ ! -f "$DB_PATH" ]; then log_message "Initializing database at $DB_PATH..." cd /app && NODE_DB_PATH="$DB_PATH" node dist/scripts/rebuild.js || { log_message "ERROR: Database initialization failed" >&2 exit 1 } fi fi else # Fallback without locking (log warning) log_message "WARNING: flock not available, database initialization may have race conditions" if [ ! -f "$DB_PATH" ]; then log_message "Initializing database at $DB_PATH..." cd /app && NODE_DB_PATH="$DB_PATH" node dist/scripts/rebuild.js || { log_message "ERROR: Database initialization failed" >&2 exit 1 } fi fi fi # Fix permissions if running as root (for development) if [ "$(id -u)" = "0" ]; then log_message "Running as root, fixing permissions..." chown -R nodejs:nodejs "$DB_DIR" # Also ensure /app/data exists for backward compatibility if [ -d "/app/data" ]; then chown -R nodejs:nodejs /app/data fi # Switch to nodejs user with proper exec chain for signal propagation # Build the command to execute if [ $# -eq 0 ]; then # No arguments provided, use default CMD from Dockerfile set -- node /app/dist/mcp/index.js fi # Export all needed environment variables export MCP_MODE="$MCP_MODE" export NODE_DB_PATH="$NODE_DB_PATH" export AUTH_TOKEN="$AUTH_TOKEN" export AUTH_TOKEN_FILE="$AUTH_TOKEN_FILE" # Ensure AUTH_TOKEN_FILE has restricted permissions for security if [ -n "$AUTH_TOKEN_FILE" ] && [ -f "$AUTH_TOKEN_FILE" ]; then chmod 600 "$AUTH_TOKEN_FILE" 2>/dev/null || true chown nodejs:nodejs "$AUTH_TOKEN_FILE" 2>/dev/null || true fi # Use exec with su-exec for proper signal handling (Alpine Linux) # su-exec advantages: # - Proper signal forwarding (critical for container shutdown) # - No intermediate shell process # - Designed for privilege dropping in containers if command -v su-exec >/dev/null 2>&1; then exec su-exec nodejs "$@" else # Fallback to su with preserved environment # Use safer approach to prevent command injection exec su -p nodejs -s /bin/sh -c 'exec "$0" "$@"' -- sh -c 'exec "$@"' -- "$@" fi fi # Handle special commands if [ "$1" = "n8n-mcp" ] && [ "$2" = "serve" ]; then # Set HTTP mode for "n8n-mcp serve" command export MCP_MODE="http" shift 2 # Remove "n8n-mcp serve" from arguments set -- node /app/dist/mcp/index.js "$@" fi # Export NODE_DB_PATH so it's visible to child processes if [ -n "$DB_PATH" ]; then export NODE_DB_PATH="$DB_PATH" fi # Execute the main command directly with exec # This ensures our Node.js process becomes PID 1 and receives signals directly if [ "$MCP_MODE" = "stdio" ]; then # Debug: Log to stderr to check if wrapper exists if [ "$DEBUG_DOCKER" = "true" ]; then echo "MCP_MODE is stdio, checking for wrapper..." >&2 ls -la /app/dist/mcp/stdio-wrapper.js >&2 || echo "Wrapper not found!" >&2 fi if [ -f "/app/dist/mcp/stdio-wrapper.js" ]; then # Use the stdio wrapper for clean JSON-RPC output # exec replaces the shell with node process as PID 1 exec node /app/dist/mcp/stdio-wrapper.js else # Fallback: run with explicit environment exec env MCP_MODE=stdio DISABLE_CONSOLE_OUTPUT=true LOG_LEVEL=error node /app/dist/mcp/index.js fi else # HTTP mode or other if [ $# -eq 0 ]; then # No arguments provided, use default exec node /app/dist/mcp/index.js else exec "$@" fi fi

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/88-888/n8n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server