Scanning Details
Advanced configuration and operation of MCP Discovery scanning.
Scan Modes
Single Scan
Perform one scan and exit:
wl-discover --config config.toml scan
Useful for:
- Testing configuration
- CI/CD pipelines
- Manual inventory updates
Continuous Daemon
Run as a background daemon:
wl-discover --config config.toml run
Features:
- Periodic scanning at configured intervals
- Health monitoring
- Automatic registration updates
- Graceful shutdown on SIGTERM
Dry Run
See what would be discovered without registering:
wl-discover --config config.toml scan --dry-run
Output:
[DRY RUN] Would register:
- web-search (new)
- filesystem (update: capabilities changed)
- slack (no change)
[DRY RUN] Would remove (stale):
- old-server (not found in scan)
Discovery Strategies
Filesystem Strategy
Scans directories for MCP configuration files:
[filesystem]
paths = [
"~/.config/mcp",
"/etc/mcp/servers.d",
"${MCP_CONFIG_DIR}"
]
# Glob patterns for config files
patterns = [
"*.json",
"*.toml",
"mcp-*.yaml",
"server.config"
]
# Recurse into subdirectories
recursive = true
max_depth = 3
# Follow symlinks
follow_symlinks = true
Configuration File Formats
JSON format:
{
"name": "my-server",
"command": "node",
"args": ["./server.js", "--port", "3000"],
"env": {
"API_KEY": "${MY_API_KEY}",
"DEBUG": "true"
},
"capabilities": {
"tools": ["tool1", "tool2"],
"resources": ["resource1"]
}
}
TOML format:
name = "my-server"
command = "python"
args = ["-m", "my_mcp_server"]
[env]
API_KEY = "${MY_API_KEY}"
[capabilities]
tools = ["analyze", "summarize"]
Claude Config Strategy
Reads from Claude Desktop/Code configuration:
[claude_config]
enabled = true
# Platform-specific paths
paths = [
# macOS
"~/Library/Application Support/Claude/claude_desktop_config.json",
# Linux
"~/.config/claude/claude_desktop_config.json",
# Windows (via WSL)
"/mnt/c/Users/${USER}/AppData/Roaming/Claude/claude_desktop_config.json"
]
Claude config structure:
{
"mcpServers": {
"server-name": {
"command": "command",
"args": ["arg1", "arg2"],
"env": {
"KEY": "value"
}
}
}
}
Network Strategy
Scans network for MCP servers:
[network]
enabled = true
# CIDR ranges to scan
ranges = [
"192.168.1.0/24",
"10.0.0.0/16"
]
# Ports to check
ports = [3000, 8080, 9000]
# Connection timeout
timeout_ms = 3000
# Concurrent connections
concurrency = 50
# Skip localhost
exclude_localhost = true
Process Strategy
Discovers running MCP server processes:
[process]
enabled = true
# Process name patterns
patterns = [
"mcp-server-*",
"node.*mcp",
"python.*mcp_server"
]
# Extract port from process arguments
extract_ports = true
Server Verification
After discovery, servers are verified:
[verification]
enabled = true
timeout_ms = 5000
# Verify by starting the server
start_verify = true
# Or verify by connection (for network servers)
connection_verify = true
# Extract capabilities by introspection
introspect_capabilities = true
Capability Introspection
The scanner can query servers for their capabilities:
[introspection]
enabled = true
# MCP introspection methods
methods = ["tools/list", "resources/list", "prompts/list"]
# Timeout for introspection
timeout_ms = 10000
Registration Behavior
New Servers
When a new server is discovered:
- Validate configuration
- Verify server can start (if enabled)
- Extract/introspect capabilities
- Register with registry
[registration]
# Automatically register new servers
auto_register = true
# Require manual approval for new servers
require_approval = false
# Default status for new servers
default_status = "active"
Updated Servers
When an existing server configuration changes:
[registration]
# Automatically update changed servers
auto_update = true
# Fields that trigger an update
update_on_change = [
"command",
"args",
"env",
"capabilities"
]
Stale Servers
When a server is no longer discovered:
[registration]
# Behavior for servers not found in scan
# Options: "mark_inactive", "delete", "ignore"
stale_action = "mark_inactive"
# Grace period before marking stale (scans)
stale_after_scans = 3
Filtering
Include Filters
Only register servers matching criteria:
[filters.include]
# Server name patterns
names = ["web-*", "api-*"]
# Required capabilities
capabilities = ["tools"]
# Minimum capability count
min_tools = 1
Exclude Filters
Skip servers matching criteria:
[filters.exclude]
# Server name patterns to skip
names = ["test-*", "dev-*"]
# Skip servers with these commands
commands = ["echo", "cat"]
# Skip by path
paths = ["*/test/*", "*/tmp/*"]
Scheduling
Scan Intervals
[scheduler]
# Main scan interval (seconds)
scan_interval = 300
# Health check interval (seconds)
health_interval = 60
# Stagger scans to avoid thundering herd
jitter_percent = 10
Maintenance Windows
[scheduler.maintenance]
# Skip scans during maintenance
enabled = true
# Maintenance window (UTC)
start_hour = 2
end_hour = 4
days = ["saturday", "sunday"]
Monitoring
Metrics
The scanner exposes Prometheus metrics:
[metrics]
enabled = true
port = 9090
path = "/metrics"
Available metrics:
mcp_discovery_scans_totalmcp_discovery_servers_foundmcp_discovery_servers_registeredmcp_discovery_errors_totalmcp_discovery_scan_duration_seconds
Alerting
[alerting]
enabled = true
# Alert on scan failures
on_scan_failure = true
# Alert when servers become unhealthy
on_unhealthy = true
# Webhook for alerts
webhook_url = "https://hooks.example.com/mcp-alerts"
CLI Reference
# Show help
mcp-discover --help
# Scan with verbose output
mcp-discover --config config.toml scan -v
# Dry run
mcp-discover --config config.toml scan --dry-run
# Run daemon with custom interval
mcp-discover --config config.toml run --interval 60
# Force re-registration of all servers
mcp-discover --config config.toml scan --force
# Export discovered servers to file
mcp-discover --config config.toml scan --export servers.json
Next Steps
- Registry Quickstart - Set up the registry
- API Reference - Registry API docs