Complete deployment configurations for all MCP clients
Claude Desktop, VS Code, Docker, and production deployments
# Clone repository
git clone https://github.com/Hack23/European-Parliament-MCP-Server.git
cd European-Parliament-MCP-Server
# Install dependencies
npm install
# Build project
npm run build
# Verify build
test -f dist/index.js && echo "Build successful"
cd /path/to/European-Parliament-MCP-Server
npm install
npm run build
Config Location:
~/Library/Application Support/Claude/claude_desktop_config.json~/.config/claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonConfiguration:
{
"mcpServers": {
"european-parliament": {
"command": "node",
"args": [
"/absolute/path/to/European-Parliament-MCP-Server/dist/index.js"
],
"env": {
"LOG_LEVEL": "info"
}
}
}
}
Important:
~ or relative paths)/ even on WindowsTools not appearing:
# Check file exists
test -f /path/to/dist/index.js && echo "OK" || echo "Missing"
# Check permissions
ls -la /path/to/dist/index.js
# Check Claude logs (macOS)
tail -f ~/Library/Logs/Claude/main.log
# Install from VS Code Marketplace
code --install-extension mcp-extension
cd ${workspaceFolder}/European-Parliament-MCP-Server
npm install
npm run build
Create .vscode/mcp.json in your workspace:
{
"servers": {
"european-parliament": {
"type": "stdio",
"command": "node",
"args": ["./dist/index.js"],
"cwd": "${workspaceFolder}/European-Parliament-MCP-Server",
"env": {
"LOG_LEVEL": "info"
}
}
}
}
Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)
> Developer: Reload Window
FROM node:22-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy built files
COPY dist/ ./dist/
# Expose WebSocket port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health')"
# Run server
CMD ["node", "dist/index.js", "--transport", "websocket", "--port", "3000"]
version: '3.8'
services:
ep-mcp-server:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- LOG_LEVEL=info
- CACHE_MAX_SIZE=500
- CACHE_TTL=900000
- RATE_LIMIT_REQUESTS=100
- RATE_LIMIT_WINDOW=900000
volumes:
- cache-data:/app/cache
- logs:/app/logs
restart: unless-stopped
networks:
- mcp-network
volumes:
cache-data:
logs:
networks:
mcp-network:
# Build image
docker-compose build
# Start service
docker-compose up -d
# Check logs
docker-compose logs -f
# Check health
curl http://localhost:3000/health
{
"mcpServers": {
"european-parliament": {
"type": "websocket",
"url": "ws://localhost:3000"
}
}
}
┌─────────────────┐
│ Load Balancer │
│ (nginx) │
└────────┬────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ MCP Server│ │ MCP Server│ │ MCP Server│
│ Instance 1│ │ Instance 2│ │ Instance 3│
└───────────┘ └───────────┘ └───────────┘
│ │ │
└────────────────────────┼────────────────────────┘
│
┌────────▼────────┐
│ Shared Cache │
│ (Redis) │
└─────────────────┘
/etc/nginx/sites-available/mcp-server:
upstream mcp_backend {
least_conn;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server {
listen 443 ssl http2;
server_name mcp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;
location / {
proxy_pass http://mcp_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket timeouts
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# Health check endpoint
location /health {
access_log off;
proxy_pass http://mcp_backend;
}
}
/etc/systemd/system/ep-mcp-server@.service:
[Unit]
Description=European Parliament MCP Server (instance %i)
After=network.target
[Service]
Type=simple
User=mcp
WorkingDirectory=/opt/european-parliament-mcp-server
ExecStart=/usr/bin/node dist/index.js --transport websocket --port 300%i
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=ep-mcp-server-%i
# Environment
Environment="NODE_ENV=production"
Environment="LOG_LEVEL=info"
Environment="PORT=300%i"
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/european-parliament-mcp-server/cache
ReadWritePaths=/opt/european-parliament-mcp-server/logs
# Resource limits
LimitNOFILE=65536
MemoryLimit=512M
[Install]
WantedBy=multi-user.target
Enable and start services:
# Enable 3 instances
sudo systemctl enable ep-mcp-server@{1..3}
# Start services
sudo systemctl start ep-mcp-server@{1..3}
# Check status
sudo systemctl status ep-mcp-server@*
# View logs
sudo journalctl -u ep-mcp-server@* -f
Prometheus metrics (if enabled):
# prometheus.yml
scrape_configs:
- job_name: 'ep-mcp-server'
static_configs:
- targets:
- 'localhost:3001'
- 'localhost:3002'
- 'localhost:3003'
Log aggregation with journald:
# View all server logs
sudo journalctl -u 'ep-mcp-server@*' --since "1 hour ago"
# Follow logs in real-time
sudo journalctl -u 'ep-mcp-server@*' -f
# Export logs
sudo journalctl -u 'ep-mcp-server@*' --since "24 hours ago" > server.log
#!/bin/bash
# backup.sh - Backup cache and logs
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/ep-mcp-server"
# Create backup directory
mkdir -p "$BACKUP_DIR/$DATE"
# Backup cache
tar -czf "$BACKUP_DIR/$DATE/cache.tar.gz" /opt/european-parliament-mcp-server/cache/
# Backup logs
tar -czf "$BACKUP_DIR/$DATE/logs.tar.gz" /opt/european-parliament-mcp-server/logs/
# Backup configuration
cp /etc/systemd/system/ep-mcp-server@.service "$BACKUP_DIR/$DATE/"
cp /etc/nginx/sites-available/mcp-server "$BACKUP_DIR/$DATE/"
# Keep only last 7 days
find "$BACKUP_DIR" -type d -mtime +7 -exec rm -rf {} +
echo "Backup completed: $BACKUP_DIR/$DATE"
| Variable | Default | Description |
|---|---|---|
NODE_ENV |
development |
Environment mode (development/production) |
LOG_LEVEL |
info |
Logging level (debug/info/warn/error) |
PORT |
3000 |
WebSocket server port |
CACHE_MAX_SIZE |
500 |
Maximum cache entries |
CACHE_TTL |
900000 |
Cache TTL in milliseconds (15 min) |
RATE_LIMIT_REQUESTS |
100 |
Maximum requests per window |
RATE_LIMIT_WINDOW |
900000 |
Rate limit window in ms (15 min) |
EP_API_BASE_URL |
(EP API) | European Parliament API base URL |
Development:
export NODE_ENV=development
export LOG_LEVEL=debug
export CACHE_TTL=60000 # 1 minute for testing
Production:
export NODE_ENV=production
export LOG_LEVEL=info
export CACHE_TTL=900000 # 15 minutes
export RATE_LIMIT_REQUESTS=100
# Check Node.js version
node --version # Must be v25.x+
# Check if port is in use
lsof -i :3000
# Check build
test -f dist/index.js && echo "OK" || echo "Run npm run build"
# Check dependencies
npm list --depth=0
# Monitor memory
watch -n 1 'ps aux | grep "node.*index.js"'
# Reduce cache size
export CACHE_MAX_SIZE=100
export CACHE_TTL=300000 # 5 minutes
# Enable debug logging
export LOG_LEVEL=debug
# Check EP API response time
time curl -s https://data.europarl.europa.eu/api/v2/meps > /dev/null
# Monitor with metrics
curl http://localhost:3000/metrics
Built with ❤️ by Hack23 AB
ISMS-compliant deployment demonstrating security excellence