slc-mcp-server

August 12, 2026 ยท View on GitHub

An MCP (Model Context Protocol) server that exposes the Lantronix SLC9000 console server REST API as tools for AI agents. Agents can query port status, manage firmware, apply configuration, and control device sessions without touching the web UI or writing curl commands.

This server handles device-level operations against individual SLC9000 units. It's designed to work alongside percepxion-mcp-server, which handles fleet-level operations through the Percepxion cloud platform. There's no capability overlap by design: when both servers are configured, the agent routes device-specific calls here and fleet-wide calls to Percepxion.

Capability Split

Capabilityslc-mcp-serverpercepxion-mcp-server
Serial port status/configget_slc_port, get_slc_portslist_device_ports
CLI commands, sync output (single call)apply_config_commands,
CLI commands, async output (job + fetch),send_direct_cli_command + get_cli_command_output
Firmware updatefirmware_update, get_firmware_update_statusupdate_firmware_by_smart_group
Device config backupexport_config_commandsget_device_config
User/session managementget_sessions, terminate_session,
Rebootreboot_devicereboot_device (fleet)
Cellular statusget_cellular_status,
Fleet-wide ops,smart groups, templates
Audit logs,investigate_audit_logs

Prerequisites

  • Python 3.11+
  • Network access to the SLC9000 device (direct IP or via jump host)
  • Device credentials with permissions appropriate for the operations requested. The SLC's built-in authentication and role system applies: read-only accounts can use read-only tools, and the server returns informative errors when credentials are invalid or lack the permissions needed for a given operation.
pip install -e .

This installs all dependencies including pyotp, which is required for 2FA-enabled devices.

Configuration

Set environment variables before starting the server, or put them in a .env file in the project root.

Environment Variables

VariableDefaultDescription
SLC_DEFAULT_IP,Default device IP, used when device_id isn't in the registry
SLC_USERNAMEsysadminDefault username
SLC_PASSWORD,Default password
SLC_TOTP_SECRET,Default TOTP secret for 2FA-enabled devices
SLC_{KEY}_IP,Per-device IP where KEY is the device identifier (uppercased, non-alphanumeric replaced with _)
SLC_{KEY}_USERNAME,Per-device username
SLC_{KEY}_PASSWORD,Per-device password
SLC_{KEY}_TOTP_SECRET,Per-device TOTP secret
SLC_VERIFY_SSLtrueSet to false only for lab devices with self-signed certificates. Never disable in production.
SLC_CREDENTIAL_PROVIDERenvCredential backend: env, vault, aws, percepxion, cyberark
SLC_KNOWN_DEVICE_IDSunsetenv provider only. Comma-separated allow-list of device_ids. When set, rejects any device_id not in this list before attempting the default-credential fallback. Opt-in; leave unset for the default single-device lab workflow below.

Key derivation example: device_id slc9000-dc-a becomes key SLC9000_DC_A, so the IP var is SLC_SLC9000_DC_A_IP.

Minimal .env

SLC_DEFAULT_IP=192.168.100.76
SLC_USERNAME=sysadmin
SLC_PASSWORD=yourpassword
SLC_VERIFY_SSL=false

Docker

Build and run the server in a container. All configuration passes via environment variables or a .env file.

Build:

docker build -t slc-mcp-server .

Run with a .env file:

docker run --rm --env-file .env slc-mcp-server

Run with individual env vars (single device, lab):

docker run --rm \
  -e SLC_DEFAULT_IP=192.168.100.76 \
  -e SLC_USERNAME=sysadmin \
  -e SLC_PASSWORD=yourpassword \
  -e SLC_VERIFY_SSL=false \
  slc-mcp-server

For production deployments with HashiCorp Vault or CyberArk, pass the relevant env vars instead of embedding credentials in the image. The Dockerfile uses a non-root user by default.

CLI Policy

The server enforces a CLI policy layer on top of the SLC device's own permission system. By default, apply_config_commands and the Percepxion client write tools (start_px_client, stop_px_client, restart_px_client) reject write commands unless explicitly enabled.

VariableDefaultDescription
SLC_CLI_WRITE_ENABLEDfalseAllow write commands via apply_config_commands and px client tools
SLC_CLI_YOLOfalseDisable all CLI policy filtering. Never use in production.
SLC_CLI_MAX_LENGTH512Maximum command length in characters
SLC_CLI_DENY_COMMANDSbuilt-in listComma-separated additional commands to block
SLC_CLI_PERMIT_COMMANDSunsetComma-separated allowlist, if set, only these prefixes are permitted

Built-in deny list (always blocked unless SLC_CLI_YOLO=true): factory-reset, write erase, erase startup-config, erase flash, reload, reboot, format, shutdown, power off, reset system, init 0, halt.

Read-only commands (show, diag, ping, traceroute, etc.) are always permitted regardless of SLC_CLI_WRITE_ENABLED. The get_px_status tool is always permitted.

This policy layer sits in addition to the SLC device's own user role restrictions. A command that passes the MCP policy layer can still be rejected by the device if the configured account lacks the required role.

Credential Providers

env (default): Reads credentials from environment variables as described above. Per-device vars take priority over globals. Good for single-device or small lab setups.

vault: Reads from HashiCorp Vault KV v2 at path slc/{device_id}. Requires VAULT_ADDR and VAULT_TOKEN env vars. The Vault secret must contain ip, username, password, and optionally totp_secret. Good for production deployments where secrets are already in Vault.

aws: Reads from AWS Secrets Manager at secret name slc/{device_id}. Requires standard AWS credential configuration (IAM role, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, or instance profile). Secret JSON must contain ip, username, password, and optionally totp_secret.

percepxion: Looks up the device IP from the Percepxion device registry by device_id, using the Percepxion API. Requires PERCEPXION_API_URL (default https://api.percepxion.ai), PERCEPXION_USERNAME, PERCEPXION_PASSWORD. SLC credentials still come from SLC_{KEY}_* env vars. Use this when your device inventory is managed in Percepxion and IPs change.

cyberark: Retrieves credentials from CyberArk Central Credential Provider (CCP) REST API. Requires CYBERARK_URL, CYBERARK_APP_ID, CYBERARK_SAFE. Each SLC device must have an account stored in CyberArk with Object = device_id and Address = management IP. When CYBERARK_CERT_PATH and CYBERARK_KEY_PATH are set, mTLS is enabled automatically. See .env.example for all options.

Switch providers at runtime without restarting:

configure_provider("vault")

2FA Support

When a device has 2FA enabled with TOTP (time-based one-time passwords), the server handles the challenge-response flow automatically. The login endpoint returns a challenge, the server generates the current TOTP code, and submits it in a second request.

To configure this, generate a TOTP secret on the device web UI and set the corresponding env var:

SLC_MYDEVICE_TOTP_SECRET=JBSWY3DPEHPK3PXP

The value is the base32 secret string, not a numeric code. PIN setup challenges (first-time 2FA activation where the device asks you to set a PIN) must be completed through the device web UI before the MCP server can authenticate. Only TOTP (passcode/tokencode challenge types) are handled automatically.

CLI Command Routing

Two tools handle CLI commands and they behave differently. Pick based on reachability and whether synchronous output is worth the trade-off against fleet-wide dispatch.

apply_config_commands (this server, POST /config/batch) sends CLI configuration commands to the SLC device and returns synchronous output directly, in one call, no polling. Use this when you have direct network access to the device and want output immediately.

send_direct_cli_command (percepxion-mcp-server) dispatches CLI commands through Percepxion's async job system, useful for devices reachable only through Percepxion (no direct network path) or for fleet-wide dispatch. Output is retrievable, but not synchronously: poll search_job_groups/get_job_group until status reaches "Completed", then call get_cli_command_output (percepxion-mcp-server v1.1.0+) for the actual device response text. Before v1.1.0, only job status was reachable via the API at all, output text was believed unreachable; that's no longer the case, get_cli_command_output calls the same endpoint Percepxion's own WebUI console-editor uses to render command output.

When both servers are configured: prefer apply_config_commands for a directly-reachable device where you want output in one call with no polling. Use send_direct_cli_command + get_cli_command_output for devices without direct network access, or for fleet-wide/bulk dispatch where the extra async round trip is an acceptable trade-off.

Tool Reference

Auth & Sessions

ToolDescription
logout_device(device_id)Invalidate the current API session token
get_sessions(device_id)List all active sessions (web UI, API, WebTerm)
get_session(device_id, session_id)Get details for a specific session
terminate_session(device_id, session_id, confirm=True)Forcibly terminate a session

System

ToolDescription
get_system_status(device_id)System status (uptime, state, etc.)
get_system_version(device_id)Firmware and software version
get_system_identity(device_id)Hostname, description, contact, location
update_system_identity(device_id, hostname, description, confirm=True)Update hostname or description
get_ztp_status(device_id)Zero Touch Provisioning status
reboot_device(device_id, confirm=True)Reboot the device

Network

ToolDescription
get_network_interfaces(device_id)All interface configurations and status

Ports & Connections

ToolDescription
get_slc_ports(device_id)All serial port configurations and status
get_slc_port(device_id, port_id)Single port status (port_id is a string like "1")
get_connections(device_id)All active connections
get_managed_devices(device_id)Inventory of managed devices
get_managed_device(device_id, managed_device_id)Single managed device status
get_cellular_status(device_id)Cellular modem status (firmware_revision, signal_strength, imei, iccid, model, band, apn, state)

Firmware

ToolDescription
get_firmware_version(device_id)Installed firmware version
get_firmware_update_status(device_id)Status of in-progress or completed update
check_firmware_updates(device_id)Check for available updates
get_firmware_bootbank(device_id)Active boot bank (1 or 2)
set_firmware_bootbank(device_id, bank, confirm=True)Set boot bank for next reboot
firmware_update(device_id, preserveconfig=True, confirm=True)Trigger firmware update
get_firmware_log(device_id)Log from the most recent update

Config Management

ToolDescription
save_config(device_id, confirm=True)Save running config to non-volatile storage
export_config_commands(device_id)Export config as replayable CLI commands
apply_config_commands(device_id, commands, confirm=True)Apply CLI config commands, returns output. Read-only by default (SLC_CLI_WRITE_ENABLED=false).
restore_config_baseline(device_id, confirm=True)Restore saved baseline config
export_config_for_edit(device_id)Export full config blob for editing
factory_reset(device_id, confirm="FACTORY RESET")Reset to factory defaults (irreversible)

Users

ToolDescription
get_sysadmin_user(device_id)Sysadmin account configuration
update_sysadmin_user(device_id, new_password, allow_dialback, dialback_number, confirm=True)Update sysadmin settings

Percepxion Client

Tools for managing the Percepxion cloud client running on the SLC device. Status is always readable; start/stop/restart require SLC_CLI_WRITE_ENABLED=true.

ToolDescription
get_px_status(device_id)Percepxion client status: enable state, connection, server URL, last heartbeat
start_px_client(device_id, confirm=True)Enable the Percepxion client (registers with cloud in ~30s)
stop_px_client(device_id, confirm=True)Disable the Percepxion client (shutdown takes 60-120s)
restart_px_client(device_id, confirm=True, timeout_seconds=120)Disable, wait for stopped state, then enable

Admin

ToolDescription
configure_provider(provider)Switch credential provider (env, vault, aws, percepxion, cyberark)

Multi-Server Claude Desktop Config

Configure both servers together for full device + fleet coverage:

{
  "mcpServers": {
    "slc-mcp-server": {
      "command": "python3",
      "args": ["/path/to/slc-mcp-server/run_server.py"],
      "env": {
        "SLC_DEFAULT_IP": "192.168.100.76",
        "SLC_USERNAME": "sysadmin",
        "SLC_PASSWORD": "yourpassword",
        "SLC_VERIFY_SSL": "false"
      }
    },
    "percepxion-mcp-server": {
      "command": "python3",
      "args": ["/path/to/percepxion-mcp-server/percepxion_mcp.py"],
      "env": {
        "PERCEPXION_API_URL": "https://api.percepxion.ai/api",
        "PERCEPXION_USERNAME": "user@example.com",
        "PERCEPXION_PASSWORD": "yourpassword"
      }
    }
  }
}

Testing

cd /path/to/slc-mcp-server
python3 -m pytest tests/ -v

The test suite covers all 33 tools including confirm guards, 2FA challenge flows, error body parsing, and new HTTP methods (PUT, DELETE, PATCH). No live device is required; tests use mocked HTTP responses.