Implement SQLite database with full-text search for n8n node documentation
Major features implemented: - SQLite storage service with FTS5 for fast node search - Database rebuild mechanism for bulk node extraction - MCP tools: search_nodes, extract_all_nodes, get_node_statistics - Production Docker deployment with persistent storage - Management scripts for database operations - Comprehensive test suite for all functionality Database capabilities: - Stores node source code and metadata - Full-text search by node name or content - No versioning (stores latest only as per requirements) - Supports complete database rebuilds - ~4.5MB database with 500+ nodes indexed Production features: - Automated deployment script - Docker Compose production configuration - Database initialization on first run - Volume persistence for data - Management utilities for operations Documentation: - Updated README with complete instructions - Production deployment guide - Clear troubleshooting section - API reference for all new tools 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
140
scripts/deploy-production.sh
Executable file
140
scripts/deploy-production.sh
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Production deployment script for n8n-MCP
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 n8n-MCP Production Deployment Script"
|
||||
echo "======================================"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to generate secure password
|
||||
generate_password() {
|
||||
openssl rand -base64 32 | tr -d "=+/" | cut -c1-25
|
||||
}
|
||||
|
||||
# Check prerequisites
|
||||
echo -e "\n${YELLOW}Checking prerequisites...${NC}"
|
||||
|
||||
if ! command_exists docker; then
|
||||
echo -e "${RED}❌ Docker is not installed. Please install Docker first.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists docker compose; then
|
||||
echo -e "${RED}❌ Docker Compose v2 is not installed. Please install Docker Compose v2.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists node; then
|
||||
echo -e "${RED}❌ Node.js is not installed. Please install Node.js first.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ All prerequisites met${NC}"
|
||||
|
||||
# Check for .env file
|
||||
if [ ! -f .env ]; then
|
||||
echo -e "\n${YELLOW}Creating .env file...${NC}"
|
||||
|
||||
# Generate secure passwords
|
||||
N8N_BASIC_AUTH_PASSWORD=$(generate_password)
|
||||
N8N_API_KEY=$(generate_password)
|
||||
|
||||
cat > .env << EOF
|
||||
# n8n Configuration
|
||||
N8N_BASIC_AUTH_USER=admin
|
||||
N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
|
||||
N8N_HOST=localhost
|
||||
N8N_API_KEY=${N8N_API_KEY}
|
||||
|
||||
# MCP Configuration
|
||||
MCP_LOG_LEVEL=info
|
||||
NODE_ENV=production
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}✅ Created .env file with secure defaults${NC}"
|
||||
echo -e "${YELLOW}⚠️ Please note your credentials:${NC}"
|
||||
echo -e " n8n Username: admin"
|
||||
echo -e " n8n Password: ${N8N_BASIC_AUTH_PASSWORD}"
|
||||
echo -e " API Key: ${N8N_API_KEY}"
|
||||
echo -e "${YELLOW} Save these credentials securely!${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✅ Using existing .env file${NC}"
|
||||
fi
|
||||
|
||||
# Build the project
|
||||
echo -e "\n${YELLOW}Building the project...${NC}"
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Build failed. Please fix the errors and try again.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Build completed successfully${NC}"
|
||||
|
||||
# Build Docker image
|
||||
echo -e "\n${YELLOW}Building Docker image...${NC}"
|
||||
docker compose -f docker-compose.prod.yml build
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Docker build failed. Please check the logs.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Docker image built successfully${NC}"
|
||||
|
||||
# Start services
|
||||
echo -e "\n${YELLOW}Starting services...${NC}"
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Failed to start services. Please check the logs.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Services started successfully${NC}"
|
||||
|
||||
# Wait for services to be healthy
|
||||
echo -e "\n${YELLOW}Waiting for services to be healthy...${NC}"
|
||||
sleep 10
|
||||
|
||||
# Check service health
|
||||
N8N_HEALTH=$(docker compose -f docker-compose.prod.yml ps n8n --format json | jq -r '.[0].Health // "unknown"')
|
||||
MCP_HEALTH=$(docker compose -f docker-compose.prod.yml ps n8n-mcp --format json | jq -r '.[0].Health // "unknown"')
|
||||
|
||||
if [ "$N8N_HEALTH" = "healthy" ] && [ "$MCP_HEALTH" = "healthy" ]; then
|
||||
echo -e "${GREEN}✅ All services are healthy${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Services might still be starting up...${NC}"
|
||||
echo -e " n8n status: $N8N_HEALTH"
|
||||
echo -e " MCP server status: $MCP_HEALTH"
|
||||
fi
|
||||
|
||||
# Display access information
|
||||
echo -e "\n${GREEN}🎉 Deployment completed successfully!${NC}"
|
||||
echo -e "\n${YELLOW}Access Information:${NC}"
|
||||
echo -e " n8n UI: http://localhost:5678"
|
||||
echo -e " MCP Server: Running internally (accessible by n8n)"
|
||||
echo -e "\n${YELLOW}Next Steps:${NC}"
|
||||
echo -e " 1. Access n8n at http://localhost:5678"
|
||||
echo -e " 2. Log in with the credentials from .env file"
|
||||
echo -e " 3. Create a new workflow and add the MCP node"
|
||||
echo -e " 4. Configure the MCP node to connect to the internal server"
|
||||
echo -e "\n${YELLOW}Useful Commands:${NC}"
|
||||
echo -e " View logs: docker compose -f docker-compose.prod.yml logs -f"
|
||||
echo -e " Stop services: docker compose -f docker-compose.prod.yml down"
|
||||
echo -e " Rebuild database: docker compose -f docker-compose.prod.yml exec n8n-mcp node dist/scripts/rebuild-database.js"
|
||||
echo -e " View database stats: docker compose -f docker-compose.prod.yml exec n8n-mcp sqlite3 /app/data/nodes.db 'SELECT COUNT(*) as total_nodes FROM nodes;'"
|
||||
178
scripts/manage-production.sh
Executable file
178
scripts/manage-production.sh
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Production management script for n8n-MCP
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Display usage
|
||||
usage() {
|
||||
echo -e "${BLUE}n8n-MCP Production Management Script${NC}"
|
||||
echo -e "${YELLOW}Usage:${NC} $0 [command]"
|
||||
echo
|
||||
echo -e "${YELLOW}Commands:${NC}"
|
||||
echo " status - Show service status"
|
||||
echo " logs - View service logs"
|
||||
echo " start - Start all services"
|
||||
echo " stop - Stop all services"
|
||||
echo " restart - Restart all services"
|
||||
echo " rebuild-db - Rebuild the node database"
|
||||
echo " db-stats - Show database statistics"
|
||||
echo " backup - Backup data volumes"
|
||||
echo " restore - Restore data volumes from backup"
|
||||
echo " update - Update services to latest versions"
|
||||
echo " shell - Open shell in MCP container"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if docker compose file exists
|
||||
if [ ! -f "docker-compose.prod.yml" ]; then
|
||||
echo -e "${RED}❌ docker-compose.prod.yml not found. Run this script from the project root.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Main command handling
|
||||
case "$1" in
|
||||
status)
|
||||
echo -e "${YELLOW}Service Status:${NC}"
|
||||
docker compose -f docker-compose.prod.yml ps
|
||||
;;
|
||||
|
||||
logs)
|
||||
if [ -z "$2" ]; then
|
||||
docker compose -f docker-compose.prod.yml logs -f --tail=100
|
||||
else
|
||||
docker compose -f docker-compose.prod.yml logs -f --tail=100 "$2"
|
||||
fi
|
||||
;;
|
||||
|
||||
start)
|
||||
echo -e "${YELLOW}Starting services...${NC}"
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
echo -e "${GREEN}✅ Services started${NC}"
|
||||
;;
|
||||
|
||||
stop)
|
||||
echo -e "${YELLOW}Stopping services...${NC}"
|
||||
docker compose -f docker-compose.prod.yml down
|
||||
echo -e "${GREEN}✅ Services stopped${NC}"
|
||||
;;
|
||||
|
||||
restart)
|
||||
echo -e "${YELLOW}Restarting services...${NC}"
|
||||
docker compose -f docker-compose.prod.yml restart
|
||||
echo -e "${GREEN}✅ Services restarted${NC}"
|
||||
;;
|
||||
|
||||
rebuild-db)
|
||||
echo -e "${YELLOW}Rebuilding node database...${NC}"
|
||||
docker compose -f docker-compose.prod.yml exec n8n-mcp node dist/scripts/rebuild-database.js
|
||||
;;
|
||||
|
||||
db-stats)
|
||||
echo -e "${YELLOW}Database Statistics:${NC}"
|
||||
docker compose -f docker-compose.prod.yml exec n8n-mcp sqlite3 /app/data/nodes.db << 'EOF'
|
||||
.headers on
|
||||
.mode column
|
||||
SELECT
|
||||
COUNT(*) as total_nodes,
|
||||
COUNT(DISTINCT package_name) as total_packages,
|
||||
ROUND(SUM(code_length) / 1024.0 / 1024.0, 2) as total_size_mb,
|
||||
ROUND(AVG(code_length) / 1024.0, 2) as avg_size_kb
|
||||
FROM nodes;
|
||||
|
||||
.print
|
||||
.print "Top 10 packages by node count:"
|
||||
SELECT package_name, COUNT(*) as node_count
|
||||
FROM nodes
|
||||
GROUP BY package_name
|
||||
ORDER BY node_count DESC
|
||||
LIMIT 10;
|
||||
EOF
|
||||
;;
|
||||
|
||||
backup)
|
||||
BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)"
|
||||
echo -e "${YELLOW}Creating backup in ${BACKUP_DIR}...${NC}"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Stop services for consistent backup
|
||||
docker compose -f docker-compose.prod.yml stop
|
||||
|
||||
# Backup volumes
|
||||
docker run --rm -v n8n-mcp_n8n-data:/source -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/n8n-data.tar.gz -C /source .
|
||||
docker run --rm -v n8n-mcp_mcp-data:/source -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/mcp-data.tar.gz -C /source .
|
||||
|
||||
# Copy .env file
|
||||
cp .env "$BACKUP_DIR/"
|
||||
|
||||
# Restart services
|
||||
docker compose -f docker-compose.prod.yml start
|
||||
|
||||
echo -e "${GREEN}✅ Backup completed in ${BACKUP_DIR}${NC}"
|
||||
;;
|
||||
|
||||
restore)
|
||||
if [ -z "$2" ]; then
|
||||
echo -e "${RED}❌ Please specify backup directory (e.g., backups/20240107_120000)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$2" ]; then
|
||||
echo -e "${RED}❌ Backup directory $2 not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}⚠️ This will replace all current data! Continue? (y/N)${NC}"
|
||||
read -r confirm
|
||||
if [ "$confirm" != "y" ]; then
|
||||
echo "Restore cancelled"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Restoring from $2...${NC}"
|
||||
|
||||
# Stop services
|
||||
docker compose -f docker-compose.prod.yml down
|
||||
|
||||
# Restore volumes
|
||||
docker run --rm -v n8n-mcp_n8n-data:/target -v $(pwd)/$2:/backup alpine tar xzf /backup/n8n-data.tar.gz -C /target
|
||||
docker run --rm -v n8n-mcp_mcp-data:/target -v $(pwd)/$2:/backup alpine tar xzf /backup/mcp-data.tar.gz -C /target
|
||||
|
||||
# Start services
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
|
||||
echo -e "${GREEN}✅ Restore completed${NC}"
|
||||
;;
|
||||
|
||||
update)
|
||||
echo -e "${YELLOW}Updating services...${NC}"
|
||||
|
||||
# Pull latest images
|
||||
docker compose -f docker-compose.prod.yml pull
|
||||
|
||||
# Rebuild MCP image
|
||||
docker compose -f docker-compose.prod.yml build
|
||||
|
||||
# Restart with new images
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
|
||||
echo -e "${GREEN}✅ Services updated${NC}"
|
||||
;;
|
||||
|
||||
shell)
|
||||
echo -e "${YELLOW}Opening shell in MCP container...${NC}"
|
||||
docker compose -f docker-compose.prod.yml exec n8n-mcp /bin/sh
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
@@ -23,11 +23,11 @@ npm run build
|
||||
|
||||
echo
|
||||
echo "2. Building Docker image..."
|
||||
docker-compose -f docker-compose.test.yml build
|
||||
docker compose -f docker-compose.test.yml build
|
||||
|
||||
echo
|
||||
echo "3. Starting test environment..."
|
||||
docker-compose -f docker-compose.test.yml up -d
|
||||
docker compose -f docker-compose.test.yml up -d
|
||||
|
||||
echo
|
||||
echo "4. Waiting for services to be ready..."
|
||||
@@ -36,7 +36,7 @@ sleep 10
|
||||
# Wait for n8n to be healthy
|
||||
echo " Waiting for n8n to be ready..."
|
||||
for i in {1..30}; do
|
||||
if docker-compose -f docker-compose.test.yml exec n8n wget --spider -q http://localhost:5678/healthz 2>/dev/null; then
|
||||
if docker compose -f docker-compose.test.yml exec n8n wget --spider -q http://localhost:5678/healthz 2>/dev/null; then
|
||||
echo -e " ${GREEN}✓ n8n is ready${NC}"
|
||||
break
|
||||
fi
|
||||
@@ -48,7 +48,7 @@ echo
|
||||
echo "5. Running MCP client test..."
|
||||
|
||||
# Create a simple test using the MCP server directly
|
||||
docker-compose -f docker-compose.test.yml exec n8n-mcp node -e "
|
||||
docker compose -f docker-compose.test.yml exec n8n-mcp node -e "
|
||||
const http = require('http');
|
||||
|
||||
// Test data
|
||||
@@ -107,12 +107,12 @@ if (!found) {
|
||||
|
||||
echo
|
||||
echo "6. Alternative test - Direct file system check..."
|
||||
docker-compose -f docker-compose.test.yml exec n8n find /usr/local/lib/node_modules -name "*Agent*.node.js" -type f 2>/dev/null | head -10 || true
|
||||
docker compose -f docker-compose.test.yml exec n8n find /usr/local/lib/node_modules -name "*Agent*.node.js" -type f 2>/dev/null | head -10 || true
|
||||
|
||||
echo
|
||||
echo "7. Test using curl to n8n API..."
|
||||
# Get available node types from n8n
|
||||
NODE_TYPES=$(docker-compose -f docker-compose.test.yml exec n8n curl -s http://localhost:5678/api/v1/node-types | jq -r '.data[].name' | grep -i agent | head -5) || true
|
||||
NODE_TYPES=$(docker compose -f docker-compose.test.yml exec n8n curl -s http://localhost:5678/api/v1/node-types | jq -r '.data[].name' | grep -i agent | head -5) || true
|
||||
|
||||
if [ -n "$NODE_TYPES" ]; then
|
||||
echo -e "${GREEN}✓ Found Agent nodes in n8n:${NC}"
|
||||
@@ -126,7 +126,7 @@ echo "8. Cleanup..."
|
||||
read -p "Stop test environment? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
docker-compose -f docker-compose.test.yml down
|
||||
docker compose -f docker-compose.test.yml down
|
||||
echo -e "${GREEN}✓ Test environment stopped${NC}"
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user