fix: resolve TypeScript errors and enhance test script
- Fix TypeScript errors in session management tests - Add null checks for sessionInfo.sessions access - Use type assertion for delete operator on process.env - Ensure proper cleanup of NODE_ENV in tests - Enhance test-n8n-integration.sh script - Add Docker installation check and auto-install for multiple OS - Implement n8n API key flow for management tools - Fix misleading Bearer token instruction - Add colored output for better UX - Check for optional jq installation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ echo "🚀 Starting n8n integration test environment..."
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
@@ -19,6 +20,117 @@ AUTH_TOKEN="test-token-for-n8n-testing-minimum-32-chars"
|
||||
# n8n data directory for persistence
|
||||
N8N_DATA_DIR="$HOME/.n8n-mcp-test"
|
||||
|
||||
# Function to detect OS
|
||||
detect_os() {
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
echo "$ID"
|
||||
else
|
||||
echo "linux"
|
||||
fi
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macos"
|
||||
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||
echo "windows"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check if Docker is installed
|
||||
check_docker() {
|
||||
if command -v docker &> /dev/null; then
|
||||
echo -e "${GREEN}✅ Docker is installed${NC}"
|
||||
# Check if Docker daemon is running
|
||||
if ! docker info &> /dev/null; then
|
||||
echo -e "${YELLOW}⚠️ Docker is installed but not running${NC}"
|
||||
echo -e "${YELLOW}Please start Docker and run this script again${NC}"
|
||||
exit 1
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to install Docker based on OS
|
||||
install_docker() {
|
||||
local os=$(detect_os)
|
||||
echo -e "${YELLOW}📦 Docker is not installed. Attempting to install...${NC}"
|
||||
|
||||
case $os in
|
||||
"ubuntu"|"debian")
|
||||
echo -e "${BLUE}Installing Docker on Ubuntu/Debian...${NC}"
|
||||
echo "This requires sudo privileges."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl gnupg
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
sudo usermod -aG docker $USER
|
||||
echo -e "${GREEN}✅ Docker installed successfully${NC}"
|
||||
echo -e "${YELLOW}⚠️ Please log out and back in for group changes to take effect${NC}"
|
||||
;;
|
||||
"fedora"|"rhel"|"centos")
|
||||
echo -e "${BLUE}Installing Docker on Fedora/RHEL/CentOS...${NC}"
|
||||
echo "This requires sudo privileges."
|
||||
sudo dnf -y install dnf-plugins-core
|
||||
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
|
||||
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
sudo usermod -aG docker $USER
|
||||
echo -e "${GREEN}✅ Docker installed successfully${NC}"
|
||||
echo -e "${YELLOW}⚠️ Please log out and back in for group changes to take effect${NC}"
|
||||
;;
|
||||
"macos")
|
||||
echo -e "${BLUE}Installing Docker on macOS...${NC}"
|
||||
if command -v brew &> /dev/null; then
|
||||
echo "Installing Docker Desktop via Homebrew..."
|
||||
brew install --cask docker
|
||||
echo -e "${GREEN}✅ Docker Desktop installed${NC}"
|
||||
echo -e "${YELLOW}⚠️ Please start Docker Desktop from Applications${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Homebrew not found${NC}"
|
||||
echo "Please install Docker Desktop manually from:"
|
||||
echo "https://www.docker.com/products/docker-desktop/"
|
||||
fi
|
||||
;;
|
||||
"windows")
|
||||
echo -e "${RED}❌ Windows detected${NC}"
|
||||
echo "Please install Docker Desktop manually from:"
|
||||
echo "https://www.docker.com/products/docker-desktop/"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ Unknown operating system: $os${NC}"
|
||||
echo "Please install Docker manually from https://docs.docker.com/get-docker/"
|
||||
;;
|
||||
esac
|
||||
|
||||
# If we installed Docker on Linux, we need to restart for group changes
|
||||
if [[ "$os" == "ubuntu" ]] || [[ "$os" == "debian" ]] || [[ "$os" == "fedora" ]] || [[ "$os" == "rhel" ]] || [[ "$os" == "centos" ]]; then
|
||||
echo -e "${YELLOW}Please run 'newgrp docker' or log out and back in, then run this script again${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check for Docker
|
||||
if ! check_docker; then
|
||||
install_docker
|
||||
fi
|
||||
|
||||
# Check for jq (optional but recommended)
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo -e "${YELLOW}⚠️ jq is not installed (optional)${NC}"
|
||||
echo -e "${YELLOW} Install it for pretty JSON output in tests${NC}"
|
||||
fi
|
||||
|
||||
# Function to cleanup on exit
|
||||
cleanup() {
|
||||
echo -e "\n${YELLOW}🧹 Cleaning up...${NC}"
|
||||
@@ -87,12 +199,50 @@ for i in {1..30}; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Guide user to get API key
|
||||
echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${YELLOW}🔑 n8n API Key Setup${NC}"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "\nTo enable n8n management tools, you need to create an API key:"
|
||||
echo -e "\n${GREEN}Steps:${NC}"
|
||||
echo -e " 1. Open n8n in your browser: ${BLUE}http://localhost:${N8N_PORT}${NC}"
|
||||
echo -e " 2. Click on your user menu (top right)"
|
||||
echo -e " 3. Go to 'Settings'"
|
||||
echo -e " 4. Navigate to 'API'"
|
||||
echo -e " 5. Click 'Create API Key'"
|
||||
echo -e " 6. Give it a name (e.g., 'n8n-mcp')"
|
||||
echo -e " 7. Copy the generated API key"
|
||||
echo -e "\n${YELLOW}Note: If this is your first time, you'll need to create an account first.${NC}"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
|
||||
# Wait for API key input
|
||||
echo -e "\n${YELLOW}Please paste your n8n API key here (or press Enter to skip):${NC}"
|
||||
read -r N8N_API_KEY
|
||||
|
||||
# Check if API key was provided
|
||||
if [ -z "$N8N_API_KEY" ]; then
|
||||
echo -e "${YELLOW}⚠️ No API key provided. n8n management tools will not be available.${NC}"
|
||||
echo -e "${YELLOW} You can still use documentation and search tools.${NC}"
|
||||
N8N_API_KEY=""
|
||||
N8N_API_URL=""
|
||||
else
|
||||
echo -e "${GREEN}✅ API key received${NC}"
|
||||
# Set the API URL for localhost access (MCP server runs on host, not in Docker)
|
||||
N8N_API_URL="http://localhost:${N8N_PORT}/api/v1"
|
||||
fi
|
||||
|
||||
# Start MCP server
|
||||
echo -e "\n${GREEN}🚀 Starting MCP server in n8n mode...${NC}"
|
||||
if [ -n "$N8N_API_KEY" ]; then
|
||||
echo -e "${YELLOW} With n8n management tools enabled${NC}"
|
||||
fi
|
||||
|
||||
N8N_MODE=true \
|
||||
MCP_MODE=http \
|
||||
AUTH_TOKEN="${AUTH_TOKEN}" \
|
||||
PORT=${MCP_PORT} \
|
||||
N8N_API_KEY="${N8N_API_KEY}" \
|
||||
N8N_API_URL="${N8N_API_URL}" \
|
||||
node dist/mcp/index.js > /tmp/mcp-server.log 2>&1 &
|
||||
|
||||
MCP_PID=$!
|
||||
@@ -137,6 +287,30 @@ curl -s -X POST http://localhost:${MCP_PORT}/mcp \
|
||||
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}' \
|
||||
| jq '.' || echo "(Install jq for pretty JSON output)"
|
||||
|
||||
# Test available tools
|
||||
echo -e "\n${YELLOW}🧪 Checking available MCP tools...${NC}"
|
||||
if [ -n "$N8N_API_KEY" ]; then
|
||||
echo -e "${GREEN}✅ n8n Management Tools Available:${NC}"
|
||||
echo " • n8n_list_workflows - List all workflows"
|
||||
echo " • n8n_get_workflow - Get workflow details"
|
||||
echo " • n8n_create_workflow - Create new workflows"
|
||||
echo " • n8n_update_workflow - Update existing workflows"
|
||||
echo " • n8n_delete_workflow - Delete workflows"
|
||||
echo " • n8n_trigger_webhook_workflow - Trigger webhook workflows"
|
||||
echo " • n8n_list_executions - List workflow executions"
|
||||
echo " • And more..."
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ n8n Management Tools NOT Available${NC}"
|
||||
echo " To enable, restart with an n8n API key"
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}✅ Documentation Tools Always Available:${NC}"
|
||||
echo " • list_nodes - List available n8n nodes"
|
||||
echo " • search_nodes - Search for specific nodes"
|
||||
echo " • get_node_info - Get detailed node information"
|
||||
echo " • validate_node_operation - Validate node configurations"
|
||||
echo " • And many more..."
|
||||
|
||||
echo -e "\n${GREEN}✅ Setup complete!${NC}"
|
||||
echo -e "\n📝 Next steps:"
|
||||
echo -e " 1. Open n8n at http://localhost:${N8N_PORT}"
|
||||
@@ -145,7 +319,7 @@ echo -e " 3. Add MCP Client Tool node"
|
||||
echo -e " 4. Configure it with:"
|
||||
echo -e " • Transport: HTTP"
|
||||
echo -e " • URL: http://host.docker.internal:${MCP_PORT}/mcp"
|
||||
echo -e " • Auth: Bearer ${AUTH_TOKEN}"
|
||||
echo -e " • Auth Token: ${BLUE}${AUTH_TOKEN}${NC}"
|
||||
echo -e "\n${YELLOW}Press Ctrl+C to stop both services${NC}"
|
||||
echo -e "\n${YELLOW}📋 To monitor MCP logs: tail -f /tmp/mcp-server.log${NC}"
|
||||
echo -e "${YELLOW}📋 To monitor n8n logs: docker logs -f n8n-test${NC}"
|
||||
|
||||
@@ -518,12 +518,18 @@ describe('HTTP Server Session Management', () => {
|
||||
});
|
||||
|
||||
it('should allow default token when NODE_ENV is not set', () => {
|
||||
delete process.env.NODE_ENV;
|
||||
const originalNodeEnv = process.env.NODE_ENV;
|
||||
delete (process.env as any).NODE_ENV;
|
||||
process.env.AUTH_TOKEN = 'REPLACE_THIS_AUTH_TOKEN_32_CHARS_MIN_abcdefgh';
|
||||
|
||||
expect(() => {
|
||||
new SingleSessionHTTPServer();
|
||||
}).not.toThrow();
|
||||
|
||||
// Restore original value
|
||||
if (originalNodeEnv !== undefined) {
|
||||
process.env.NODE_ENV = originalNodeEnv;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1037,11 +1043,12 @@ describe('HTTP Server Session Management', () => {
|
||||
expect(sessionInfo.sessions).toHaveProperty('sessionIds');
|
||||
|
||||
expect(typeof sessionInfo.active).toBe('boolean');
|
||||
expect(typeof sessionInfo.sessions.total).toBe('number');
|
||||
expect(typeof sessionInfo.sessions.active).toBe('number');
|
||||
expect(typeof sessionInfo.sessions.expired).toBe('number');
|
||||
expect(sessionInfo.sessions.max).toBe(100);
|
||||
expect(Array.isArray(sessionInfo.sessions.sessionIds)).toBe(true);
|
||||
expect(sessionInfo.sessions).toBeDefined();
|
||||
expect(typeof sessionInfo.sessions!.total).toBe('number');
|
||||
expect(typeof sessionInfo.sessions!.active).toBe('number');
|
||||
expect(typeof sessionInfo.sessions!.expired).toBe('number');
|
||||
expect(sessionInfo.sessions!.max).toBe(100);
|
||||
expect(Array.isArray(sessionInfo.sessions!.sessionIds)).toBe(true);
|
||||
});
|
||||
|
||||
it('should show legacy SSE session when present', async () => {
|
||||
|
||||
Reference in New Issue
Block a user