MCP Integration
This document describes how to use the Model Context Protocol (MCP) integration in Virga, which enables AI/LLM tools to interact with the C2 framework through multiple transport protocols.
Overview
The Model Context Protocol (MCP) is an open standard that allows AI assistants and LLM tools to securely interact with external systems. Virga implements MCP to enable:
- AI-powered security analysis and automation
- Interactive session management through AI assistants
- Natural language command execution
- Intelligent data querying and analysis
Architecture
Virga's MCP implementation supports three transport protocols, each suited for different use cases:
Transport Comparison
| Feature | SSE | STDIO | Streamable |
|---|---|---|---|
| Tools | 9 tools | 9 tools | 14 tools |
| Resources | 7 (with templates) | 3 (static only) | 4 |
| Protocol | HTTP + SSE | Process I/O | HTTP Stateful |
| Real-time | Yes (events) | No (sync) | Yes (streaming) |
| Best for | Web clients | CLI tools | Custom apps |
| Interactive Mode | No | No | Yes |
| Port Required | Yes (8444) | No | Yes (50012) |
Transport Protocols
1. SSE (Server-Sent Events)
Best for web-based clients and real-time event streaming.
Features:
- HTTP-based with event streaming
- Suitable for browser integration
- Real-time updates
- Firewall-friendly
Default Configuration:
mcp:
sse_base_path: /mcp
sse_enabled: true
sse_port: :8444
remote_enabled: false
remote_base_url: http://localhost:84442. STDIO (Standard Input/Output)
Best for CLI tools and local integrations.
Features:
- JSON-RPC over standard I/O
- Process-based communication
- Synchronous request/response
- Ideal for scripting
Default Configuration:
mcp:
stdio_enabled: false3. Streamable
Best for high-performance, custom integrations.
Features:
- Binary protocol support
- Bidirectional streaming
- Low latency
- Custom protocol implementation
Default Configuration:
mcp:
streamable_enabled: true
streamable_port: :50012Configuration
Server Configuration
Add MCP settings to your configs/server.yaml:
# MCP Configuration
mcp:
enabled: true
# SSE transport settings
sse_enabled: true
sse_port: :8444
sse_base_path: /mcp
# STDIO transport settings
stdio_enabled: false # Enable for CLI usage
# Streamable transport settings
streamable_enabled: true
streamable_port: :50012
# Remote access settings (for SSE)
remote_enabled: false
remote_base_url: http://localhost:8444Starting MCP Servers
MCP servers start automatically with the main Virga server when enabled:
# Start Virga with MCP
./virga-server -config configs/server.yaml
# Output:
# [INFO] Starting MCP SSE server on :8444...
# [INFO] MCP SSE server startedAvailable Tools
The available tools vary by transport protocol:
SSE and STDIO Transports (9 tools)
Both SSE and STDIO transports provide the same comprehensive set of tools:
Session Management
session_list- List all active C2 sessionssession_command- Execute commands in a session- Supports shell commands, Llama AI prompts, and MemDB queries
- Use
use_llama: truefor AI interpretation - Prefix with
memdbfor database queries
File Operations
upload_file- Upload files to target systemsdownload_file- Download files from targets
System Operations
list_processes- List running processeskill_process- Terminate processes by PIDget_system_info- Gather system information
Network Operations
list_network_connections- List network connectionsport_forward- Set up port forwarding
Streamable Transport (14 tools)
The Streamable transport includes all the standard tools plus additional real-time capabilities:
Core Tools (Same as SSE/STDIO) - 9 tools
session_list- List all active C2 sessionssession_command- Execute commands (shell, Llama, MemDB)upload_file- Upload files to target systemsdownload_file- Download files from targetslist_processes- List running processeskill_process- Terminate processes by PIDget_system_info- Gather system informationlist_network_connections- List network connectionsport_forward- Set up port forwarding
Additional Streamable-Only Tools - 5 tools
get_system_status- Get Virga system statusinteract_beacon- Start interactive session (1-second check-ins)stop_interact- Stop interactive session (return to 30-second check-ins)shell- Direct shell command execution (alias for session_command)ls- List files (executesls -la)
Client Integration Examples
Claude Desktop Integration
- Install Claude Desktop
- Configure MCP in Claude's configuration:
{
"mcpServers": {
"virga": {
"command": "curl",
"args": ["-N", "http://localhost:8444/mcp/events"],
"env": {}
}
}
}- Claude can now interact with your C2 sessions:
"List all active sessions and show me their details"
"Execute 'whoami' on session-123"
"Find all PDF files on the target system"Python Client Example
import asyncio
from mcp import Client
from mcp.client.sse import SSEClientTransport
async def main():
# Create SSE transport
transport = SSEClientTransport("http://localhost:8444/mcp")
# Initialize client
async with Client("virga-client", "1.0.0") as client:
await client.connect(transport)
await client.initialize()
# List sessions
result = await client.call_tool("session_list", {})
print(f"Active sessions: {result}")
# Execute command with AI
result = await client.call_tool("session_command", {
"session_id": "session-123",
"command": "Find and analyze suspicious network connections",
"use_llama": True,
"temperature": 0.7
})
print(f"Task ID: {result['task_id']}")
# Use file operations
# Upload a file
result = await client.call_tool("upload_file", {
"session_id": "session-123",
"remote_path": "/tmp/test.txt",
"content": "SGVsbG8gV29ybGQ=" # Base64 encoded "Hello World"
})
print(f"Upload result: {result}")
# List processes
result = await client.call_tool("list_processes", {
"session_id": "session-123"
})
print(f"Processes: {result}")
# Get system info
result = await client.call_tool("get_system_info", {
"session_id": "session-123"
})
print(f"System Info: {result}")
asyncio.run(main())JavaScript/TypeScript Example
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
async function interactWithVirga() {
const transport = new SSEClientTransport(
new URL("http://localhost:8444/mcp")
);
const client = new Client({
name: "virga-js-client",
version: "1.0.0",
}, {
capabilities: { tools: {} }
});
await client.connect(transport);
// Execute AI-powered analysis
const result = await client.callTool({
name: "session_command",
arguments: {
session_id: "session-123",
command: "Analyze system for persistence mechanisms",
use_llama: true,
max_iterations: 5
}
});
console.log("Analysis started:", result.task_id);
}Use Cases
1. AI-Powered Security Analysis
# Use AI to analyze a compromised system
result = await client.call_tool("session_command", {
"session_id": session_id,
"command": """
Perform a comprehensive security analysis:
1. Check for suspicious processes
2. Identify unusual network connections
3. Find recently modified system files
4. Look for persistence mechanisms
5. Generate a summary report
""",
"use_llama": True,
"max_iterations": 20,
"temperature": 0.3
})
# Or use individual tools for specific tasks
processes = await client.call_tool("list_processes", {
"session_id": session_id
})
connections = await client.call_tool("list_network_connections", {
"session_id": session_id
})
# Query MemDB through session_command
history = await client.call_tool("session_command", {
"session_id": session_id,
"command": "memdb SELECT * FROM commands WHERE exit_code != 0 LIMIT 10"
})2. Automated Incident Response
# Automated response to detected threats
async def respond_to_threat(session_id, threat_info):
# Kill malicious process
await client.call_tool("kill_process", {
"session_id": session_id,
"pid": threat_info["pid"]
})
# Download suspicious files for analysis
await client.call_tool("download_file", {
"session_id": session_id,
"remote_path": threat_info.get("executable_path")
})
# Get process information
processes = await client.call_tool("list_processes", {
"session_id": session_id
})
# Query related data through MemDB
await client.call_tool("session_command", {
"session_id": session_id,
"command": f"memdb SELECT * FROM processes WHERE parent_pid = {threat_info['pid']}"
})3. Natural Language Operations
# Let AI handle complex multi-step operations
commands = [
"Find all user accounts created in the last 30 days",
"Check if any of these accounts have administrative privileges",
"List all files accessed by these accounts",
"Create a timeline of suspicious activities"
]
for cmd in commands:
result = await client.call_tool("session_command", {
"session_id": session_id,
"command": cmd,
"use_llama": True
})
task_ids.append(result["task_id"])Advanced Features
Llama Integration
Commands can leverage the embedded AI model through the session_command tool:
# AI interprets and executes the intent
result = await client.call_tool("session_command", {
"session_id": "session-123",
"command": "Check if this system has been compromised",
"use_llama": True,
"temperature": 0.5, # Lower = more focused
"max_iterations": 10 # Max reasoning steps
})MemDB Queries
Query the in-memory database directly or through session_command:
# Query MemDB via session_command with memdb prefix
result = await client.call_tool("session_command", {
"session_id": "session-123",
"command": "memdb SELECT * FROM commands WHERE module = 'shell' LIMIT 10"
})
# Another MemDB query example
result = await client.call_tool("session_command", {
"session_id": "session-123",
"command": "memdb SELECT * FROM processes WHERE name LIKE '%suspicious%'"
})
# Get MemDB status through session_command
status = await client.call_tool("session_command", {
"session_id": "session-123",
"command": "memdb status"
})Resource Access
MCP provides read-only resources that vary by transport:
SSE Transport Resources (7 total)
Static resources:
sessions://list- All active sessionsbeacons://list- All configured beaconssystem://status- System status
Dynamic resources (templates):
sessions://detail/{session_id}- Specific session detailsbeacons://detail/{beacon_id}- Specific beacon detailshistory://commands/{session_id}- Command execution historyfiles://session/{session_id}- File operation history
STDIO Transport Resources (3 total)
sessions-list- All active sessionsbeacons-list- All configured beaconssystem-status- System status
Streamable Transport Resources (4 total)
virga://sessions/overview- Sessions overviewvirga://session/{id}/info- Specific session informationvirga://beacons/overview- Beacons overviewvirga://system/stats- System statistics
Example usage:
# SSE/STDIO resource access
resource = await client.read_resource("sessions://list") # SSE
resource = await client.read_resource("sessions-list") # STDIO
# Streamable resource access
resource = await client.read_resource("virga://sessions/overview")
resource = await client.read_resource(f"virga://session/{session_id}/info")Security Considerations
Authentication: Currently, MCP servers have limited authentication. Use network-level security:
- Bind to localhost only for local integrations
- Use VPN or SSH tunnels for remote access
- Implement firewall rules
Authorization: All connected clients have full access. Future versions will add:
- Token-based authentication
- Role-based access control
- Session-level permissions
Encryption: For production use:
- Use HTTPS/TLS for SSE transport
- Tunnel STDIO through SSH
- Enable transport-level encryption
Input Validation: The server validates all inputs, but clients should also:
- Sanitize user inputs
- Validate session IDs
- Handle errors gracefully
Troubleshooting
SSE Connection Issues
# Test SSE endpoint
curl -N http://localhost:8444/mcp/events
# Check if events are flowing
# You should see:
# event: open
# data: {"id":"...","timestamp":"..."}STDIO Communication
# Test STDIO server
echo '{"jsonrpc":"2.0","id":1,"method":"system/info","params":{}}' | \
./virga-server -mcp-stdio
# Enable debug logging
export VIRGA_LOG_LEVEL=debugCommon Issues
"Session not found" errors
- Verify session ID is correct
- Check if session is still active
- Ensure proper connection to C2 server
Timeout errors
- Increase timeout for long operations
- Check network connectivity
- Verify target system is responsive
JSON parsing errors
- Validate JSON syntax
- Check character encoding (UTF-8)
- Ensure proper escaping
Tool not found errors
- Verify tool name is correct (e.g.,
upload_filenotfile_upload) - Check transport type (some tools are transport-specific)
- Ensure server has MCP enabled
- Verify tool name is correct (e.g.,
Tool naming
- Use exact tool names as documented
- Common mistakes:
file_uploadshould beupload_file - Check the specific transport's tool list
Best Practices
Use appropriate transports:
- SSE for web/real-time applications
- STDIO for scripts and automation
- Streamable for high-performance needs
Handle asynchronous operations:
- Store task IDs for long-running operations
- Implement proper polling for results
- Handle partial results gracefully
Optimize AI usage:
- Use lower temperatures (0.1-0.3) for precise tasks
- Increase iterations for complex analysis
- Cache results to avoid redundant processing
Monitor resource usage:
- MCP operations can be resource-intensive
- Monitor memory usage with AI operations
- Implement rate limiting for production
Future Enhancements
Planned improvements for MCP integration:
- WebSocket support for bidirectional streaming
- GraphQL API for flexible queries
- Batch operations for efficiency
- Event subscriptions for real-time updates
- Plugin system for custom tools
- Audit logging for compliance