Production-Ready AlienVault OTX Endpoint Security Scanning MCP Server with VirusTotal Integration
// crafted for the security community β funding keeps it maintained
The AlienSec MCP Server is a production-grade Model Context Protocol (MCP) server that provides comprehensive endpoint security scanning capabilities using AlienVault OTX with optional VirusTotal integration.
This server enables AI agents and applications to perform security scans on various endpoint types (macOS PKG, Windows PowerShell, Debian APT, Redhat RPM) and retrieve threat intelligence from AlienVault OTX and VirusTotal APIs.
-
Multi-Platform Endpoint Scanning
- Scan macOS systems using PKG installer flavor
- Scan Windows endpoints via PowerShell
- Scan Debian/Ubuntu systems using APT
- Scan Redhat/CentOS systems using RPM
-
VirusTotal Integration
- Scan files and URLs using VirusTotal API
- Retrieve existing analysis results
- Automatic rate limiting and circuit breaker protection
- Multiple API key support (respects VirusTotal ToS)
-
Threat Intelligence
- Search AlienVault OTX pulses
- Retrieve pulse details and events
- Access indicators of compromise (IoCs)
-
Data Persistence
- SQLite database with optional encryption
- Scan result storage with timestamps
- API request logging
- Circuit breaker event tracking
-
Production-Ready Features
- Comprehensive error handling
- Structured logging with Pino
- Environment variable validation with Zod
- Type-safe API schemas
- Graceful shutdown handling
- Node.js: >= 22.0.0
- npm: >= 8.0.0
- Operating System: macOS, Linux, or Windows
- Disk Space: Minimum 100MB for dependencies
-
AlienVault OTX API Key (Required)
- Sign up at https://otx.alienvault.com
- Navigate to Settings > API Keys
- Generate a new API key
-
VirusTotal API Key (Optional, for enhanced functionality)
- Sign up at https://www.virustotal.com
- Navigate to API Console
- Generate API key(s)
- Note: Free tier allows 500 requests/day, 4 requests/minute
git clone https://github.com/VRIL-LABS/aliensec-mcp-server.git
cd aliensec-mcp-servernpm installThis will install all production and development dependencies.
Copy the example environment file and update with your API keys:
cp .env.example .envEdit .env with your API keys:
# Server Configuration
NAME=aliensec-mcp-server
VERSION=1.0.0
DEBUG=false
LOG_LEVEL=info
# AlienVault OTX Configuration (Required)
ALIENVAULT_API_KEY=your_alienvault_api_key_here
ALIENVAULT_BASE_URL=https://api.agent.otxb.io
ALIENVAULT_DEFAULT_REGION=us-east-1
# VirusTotal Configuration (Optional)
VIRUSTOTAL_API_KEYS=key1,key2,key3
VIRUSTOTAL_BASE_URL=https://www.virustotal.com/api/v3
VIRUSTOTAL_RATE_LIMIT_PER_MINUTE=4
VIRUSTOTAL_DAILY_LIMIT=500
VIRUSTOTAL_CIRCUIT_BREAKER_TIMEOUT=300
# Database Configuration
DATABASE_PATH=./data/aliensec.db
DATABASE_ENCRYPTION_KEY=your_encryption_key_here
DATABASE_TIMEOUT=5000Note: VirusTotal ToS prohibits using multiple API keys to bypass rate limits. This implementation respects those limits and uses multiple keys for redundancy only.
For encrypted database support on Linux/macOS:
# Ubuntu/Debian
sudo apt-get install build-essential
# macOS
xcode-select --installRun the server in development mode with automatic reloading:
npm run devBuild and run the server:
npm run build
npm startThe server communicates via stdio (standard input/output). To use it with an MCP client:
# Direct execution
node dist/index.js
# Or using the npm script
npm startimport { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
const client = new Client({ name: 'my-client', version: '1.0.0' });
const transport = new StdioClientTransport({
command: 'node',
args: ['dist/index.js'],
});
await client.connect(transport);
// Call a scan tool
const result = await client.callTool({
name: 'scan_macos_pkg',
arguments: {
target: '192.168.1.100',
useVirusTotal: true,
},
});
console.log(result.content);| Tool | Description | Parameters |
|---|---|---|
scan_endpoint |
Generic endpoint scanner | flavor, target, useVirusTotal, apiKeyIndex |
scan_macos_pkg |
Scan macOS PKG installer | target, useVirusTotal |
scan_windows |
Scan Windows endpoint | target, useVirusTotal |
scan_debian_apt |
Scan Debian/APT endpoint | target, useVirusTotal |
scan_redhat_rpm |
Scan Redhat/RPM endpoint | target, useVirusTotal |
| Tool | Description | Parameters |
|---|---|---|
use_virustotal |
Scan resource with VirusTotal | resource, apiKeyIndex, wait |
get_virustotal_analysis |
Get existing VirusTotal analysis | hash, apiKeyIndex |
| Tool | Description | Parameters |
|---|---|---|
get_bootstrap_command |
Get bootstrap command for flavor | flavor, target |
get_bootstrap_urls |
Get all bootstrap URLs | - |
search_pulses |
Search AlienVault OTX pulses | query, limit, offset |
| Tool | Description | Parameters |
|---|---|---|
get_scan_stats |
Get scan statistics | - |
get_recent_scans |
Get recent scans | limit |
get_circuit_breaker_stats |
Get circuit breaker stats | - |
get_api_stats |
Get API statistics | - |
| Tool | Description | Parameters |
|---|---|---|
get_health |
Get server health status | - |
The server provides pre-configured bootstrap commands for each endpoint flavor. <api-key> below is your resolved ALIENVAULT_API_KEY value, and TARGET=<target> is only included when a target is provided.
API_KEY=<api-key> [TARGET=<target>] bash -c "$(curl -s https://api.agent.otxb.io/osquery-api-otx/bootstrap?flavor=pkg)"[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; API_KEY=<api-key> (new-object Net.WebClient).DownloadString("https://api.agent.otxb.io/osquery-api-otx/bootstrap?flavor=powershell") | iex; install_agent -apikey <api-key> [-target <target>]API_KEY=<api-key> [TARGET=<target>] bash -c "$(curl -s https://api.agent.otxb.io/osquery-api-otx/bootstrap?flavor=apt)"API_KEY=<api-key> [TARGET=<target>] bash -c "$(curl -s https://api.agent.otxb.io/osquery-api-otx/bootstrap?flavor=rpm)"aliensec-mcp-server/
βββ src/
β βββ config/
β β βββ index.ts # Environment configuration & validation
β βββ core/
β β βββ alienVault.ts # AlienVault OTX API client
β β βββ virusTotal.ts # VirusTotal API client
β βββ database/
β β βββ index.ts # SQLite database with repositories
β βββ types/
β β βββ index.ts # TypeScript type definitions
β βββ index.ts # Main MCP server entry point
βββ package.json
βββ tsconfig.json
βββ .env.example
βββ .gitignore
βββ eslint.config.js
βββ .prettierrc
βββ README.md
βββββββββββββββββββββββββββββββββββββββ
β MCP Server Layer β β src/index.ts
βββββββββββββββββββββββββββββββββββββββ€
β Core Service Layer β β src/core/
βββββββββββββββββββββββββββββββββββββββ€
β Data Access Layer β β src/database/
βββββββββββββββββββββββββββββββββββββββ€
β Configuration Layer β β src/config/
βββββββββββββββββββββββββββββββββββββββ€
β Type Definitions β β src/types/
βββββββββββββββββββββββββββββββββββββββ
- Singleton Pattern: Database, AlienVault client, VirusTotal client
- Repository Pattern: ScanRepository, CircuitBreakerRepository, APILogRepository
- Circuit Breaker Pattern: Automatic API key rotation on failures
- Token Bucket Rate Limiter: Rate limiting for VirusTotal API
- Factory Pattern: MCP server creation with dependency injection
- Strategy Pattern: Different scan flavors with common interface
The server uses SQLite with the following tables:
Stores all scan results with findings, VirusTotal data, and timestamps.
Tracks circuit breaker state changes for API keys.
Logs all API requests with response times, status codes, and errors.
Tracks database schema version for migrations.
- AlienSecError: Base error class with code and statusCode
- AlienVaultAPIError: AlienVault-specific errors
- VirusTotalAPIError: VirusTotal-specific errors with rate limit detection
- DatabaseError: Database-related errors
- ConfigurationError: Configuration validation errors
Tool errors return the standard MCP result shape with isError: true. The human-readable message is the first content block; error carries the JSON-stringified context data (scan ID, flavor, target, etc.) that triggered the failure:
{
"content": [
{ "type": "text", "text": "Scan failed: <error message>" }
],
"isError": true,
"error": "{\n \"scanId\": \"...\",\n \"flavor\": \"pkg\",\n \"target\": \"...\",\n \"error\": \"<error message>\"\n}"
}The server uses Pino for structured logging with the following levels:
- error: Critical failures
- warn: Warnings and potential issues
- info: Normal operations and status updates
- debug: Detailed debugging information
- trace: Very verbose logging for development
Logs are automatically redacted to prevent sensitive data (API keys) from being logged.
- Token Bucket Algorithm: Smooth rate limiting
- Configurable Limits: Set via environment variables
- Automatic Wait: Option to wait when rate limited
- Circuit Breaker: Automatically blocks API keys that fail repeatedly
- Failure Threshold: 5 consecutive failures
- Reset Timeout: 300 seconds (5 minutes)
- Half-Open State: Test with 1 request before fully reopening
The implementation respects VirusTotal's Terms of Service:
- Multiple API keys are for redundancy, not for bypassing limits
- Each API key respects individual rate limits
- Circuit breaker prevents rapid retries on failures
- Daily request counting prevents quota exhaustion
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run with coverage
npx vitest run --coverage# Run linting
npm run lint
# Auto-fix linting issues
npm run lint:fix
# Format code
npm run formatnpm run typecheck# Clean build
npm run clean
npm run build
# Check build output
ls -la dist/| Variable | Required | Default | Description |
|---|---|---|---|
ALIENVAULT_API_KEY |
Yes | - | AlienVault OTX API key |
ALIENVAULT_BASE_URL |
No | https://api.agent.otxb.io |
AlienVault API base URL |
ALIENVAULT_DEFAULT_REGION |
No | us-east-1 |
Default region for agents |
VIRUSTOTAL_API_KEYS |
No | `` | Comma-separated VirusTotal API keys |
VIRUSTOTAL_BASE_URL |
No | https://www.virustotal.com/api/v3 |
VirusTotal API base URL |
VIRUSTOTAL_RATE_LIMIT_PER_MINUTE |
No | 4 |
Rate limit per minute |
VIRUSTOTAL_DAILY_LIMIT |
No | 500 |
Daily request limit |
VIRUSTOTAL_CIRCUIT_BREAKER_TIMEOUT |
No | 300 |
Circuit breaker timeout (seconds) |
DATABASE_PATH |
No | ./data/aliensec.db |
SQLite database path |
DATABASE_ENCRYPTION_KEY |
No | - | Database encryption key |
DATABASE_TIMEOUT |
No | 5000 |
Database connection timeout |
NAME |
No | aliensec-mcp-server |
Server name |
VERSION |
No | 1.0.0 |
Server version |
DEBUG |
No | false |
Enable debug mode |
LOG_LEVEL |
No | info |
Log level (error, warn, info, debug, trace) |
- Database Encryption: Use
DATABASE_ENCRYPTION_KEYfor encrypting sensitive data at rest - API Key Security: API keys are never logged; use environment variables or secure vaults
- Memory Safety: Sensitive strings are hashed with PBKDF2 (120,000 iterations) before storage in circuit breaker and API log tables
- HTTPS Only: All API communication uses HTTPS
- Certificate Validation: TLS certificate validation is enabled by default
- User-Agent: Custom user agent identifies the server version
- Client-Side Rate Limiting: Prevents overwhelming external APIs
- Circuit Breaker: Prevents cascading failures
- Backpressure: Automatic waiting when rate limited
- Connection Pooling: Database connections are reused
- Lazy Loading: Repositories are created on-demand
- Indexed Queries: Database tables have appropriate indexes
- Caching: API key hashes are cached for circuit breaker checks
- Async/Await: Non-blocking I/O operations
- Scan Request: ~100-500ms (simulated)
- VirusTotal Request: ~200-1000ms (network dependent)
- Database Operations: <10ms (local SQLite)
Error: Failed to connect to database
Solution: Ensure the data directory exists and has write permissions:
mkdir -p data
chmod 755 dataMissing required environment variables:
- ALIENVAULT_API_KEY
Solution: Set the environment variable:
export ALIENVAULT_API_KEY=your_api_key_here
# or add to .env fileError: Rate limit exceeded for API key 0
Solution:
- Wait for the rate limit to reset (default: 4 requests/minute)
- Add more API keys (comma-separated in VIRUSTOTAL_API_KEYS)
- Use
wait: trueparameter to automatically wait
Error: API key 0 is blocked by circuit breaker
Solution: Wait for the circuit breaker timeout to expire (default: 5 minutes). The circuit will automatically reopen after the timeout.
Enable debug logging for detailed troubleshooting:
DEBUG=true LOG_LEVEL=debug npm run dev- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Use Conventional Commits format
- Prefix with type:
feat:,fix:,docs:,style:,refactor:,test:,chore: - Keep subject line under 72 characters
- Provide detailed description in body if needed
- All PRs require approval from at least one maintainer
- CI/CD pipeline must pass (lint, typecheck, tests)
- Code must follow existing patterns and style
This project is licensed under the MIT License - see the LICENSE file for details.
- Model Context Protocol: https://modelcontextprotocol.io
- AlienVault OTX: https://otx.alienvault.com
- VirusTotal: https://www.virustotal.com
- TypeScript: https://www.typescriptlang.org
- Zod: https://github.com/colinhacks/zod
- Pino: https://github.com/pinojs/pino
- better-sqlite3-multiple-ciphers: https://github.com/m4heshd/better-sqlite3-multiple-ciphers
- AlienVault OTX Documentation
- VirusTotal API Documentation
- Model Context Protocol Specification
- MCP TypeScript SDK
Built with β€οΈ for the security community