About
Percepxion MCP Server
README
A Python FastMCP server that exposes the Percepxion REST API as MCP tools. Connect it to Claude Desktop, Claude Code, or any MCP-compatible client to manage out-of-band infrastructure through natural language.
What is Percepxion?
Percepxion is a SaaS platform for out-of-band (OOB) network device management. It connects to console servers, serial port aggregators, and remote access devices to provide fleet-wide visibility, configuration management, firmware updates, CLI access, and compliance reporting, independent of the primary network path.
This MCP server gives AI assistants direct access to Percepxion's management capabilities.
Use cases
- Inventory discovery, find all devices in an organization, filter by model or firmware version
- Remote CLI execution, run commands on a device and retrieve output through Percepxion
- Config management, push individual property changes or clone a full config from a reference device
- Firmware compliance, compare fleet firmware against a target and identify non-compliant devices
- Firmware updates, upload firmware and target a Smart Group for coordinated rollout
- Log retrieval, pull syslogs or access logs from devices on demand
- Audit investigation, search platform audit records by user, time range, or action
- Organization management, list organizations and scope operations to a specific one
How it works
The server runs locally and communicates with the Percepxion API over HTTPS. Authentication uses username/password; the server exchanges these for session tokens and holds them in memory for the lifetime of the process.
Many Percepxion operations are asynchronous. Tools that trigger device actions (CLI commands, config pushes, firmware updates, syslog requests) create a Percepxion job group and return the job record. Use search_job_groups or get_job_group to poll status and retrieve results.
Response envelope, all tools return this structure:
{ "ok": true, "data": { ... }, "status_code": 200 }
{ "ok": false, "error": "...", "status_code": 401, "details": { ... } }
Prerequisites
- Python 3.11 or later (3.12 recommended)
- Network access to your Percepxion API endpoint
- A Percepxion username and password with appropriate permissions
Quick start
Linux or WSL
git clone https://github.com/Lantronix/percepxion-mcp-server.git
cd percepxion-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
cp .env.example .env
# Edit .env, set PERCEPXION_USERNAME, PERCEPXION_PASSWORD
# Default API URL is https://api.percepxion.ai/api
# Lantronix employees: use https://api.gopercepxion.ai/api for the internal sandbox
Test the server starts:
python percepxion_mcp.py
The server blocks and waits for an MCP client connection. Connect a client, then call login_with_env to authenticate.
Docker
docker build -t percepxion-mcp-server .
docker run --rm -it --env-file .env percepxion-mcp-server
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
PERCEPXION_USERNAME |
Yes | , | Percepxion login username |
PERCEPXION_PASSWORD |
Yes | , | Percepxion login password |
PERCEPXION_API_URL |
No | https://api.percepxion.ai/api |
Percepxion API base URL. Use https://api.gopercepxion.ai/api for the Lantronix internal sandbox. |
PERCEPXION_DEFAULT_ORGANIZATION_ID |
No | , | Default organization ID used when callers omit organization_id. Useful for single-organization deployments. |
PERCEPXION_DEFAULT_TENANT_ID |
No | , | Deprecated alias for PERCEPXION_DEFAULT_ORGANIZATION_ID. Still works; if both are set, the new variable wins. |
PERCEPXION_REQUEST_TIMEOUT |
No | 45 |
HTTP timeout in seconds. Raise for large log downloads or slow links. |
PERCEPXION_FIRMWARE_DIR |
No | , | If set, firmware uploads are restricted to files in this directory. Recommended for shared or automated deployments. |
PERCEPXION_CREDENTIAL_PROVIDER |
No | env |
Credential backend: env (default), vault, aws, or cyberark. |
Keep .env out of version control. The repo includes .env.example as a starting point.
CLI command policy
send_direct_cli_command is read-only by default. Only show, get, ping, traceroute, and similar read commands are allowed. Configure write access and filtering in .env:
| Variable | Default | Description |
|---|---|---|
PERCEPXION_CLI_WRITE_ENABLED |
false |
Set to true to allow write commands (set, configure, etc.). |
PERCEPXION_CLI_YOLO |
false |
Set to true to disable all command filtering. Use with extreme caution. |
PERCEPXION_CLI_MAX_LENGTH |
512 |
Maximum command length in characters. |
PERCEPXION_CLI_DENY_COMMANDS |
, | Comma-separated commands to block in addition to built-in defaults (reload, factory-reset, write erase, etc.). |
PERCEPXION_CLI_PERMIT_COMMANDS |
, | Comma-separated explicit allowlist. If set, only matching commands (and their subcommands) are permitted. |
Credential providers
By default, credentials are read from environment variables. Three additional backends are available:
HashiCorp Vault:
PERCEPXION_CREDENTIAL_PROVIDER=vault
VAULT_ADDR=https://vault.example.com
VAULT_TOKEN=hvs.XXXX
VAULT_SECRET_PATH=secret/data/percepxion
AWS Secrets Manager:
PERCEPXION_CREDENTIAL_PROVIDER=aws
AWS_SECRET_NAME=percepxion/credentials
AWS_REGION=us-east-1
Install the AWS extra: pip install -e ".[aws]"
CyberArk Central Credential Provider (CCP):
Fetches Percepxion admin credentials from the CyberArk AIM Web Service at login time. No password stored in config files. Recommended for enterprises already running CyberArk.
PERCEPXION_CREDENTIAL_PROVIDER=cyberark
CYBERARK_URL=https://cyberark.internal
CYBERARK_APP_ID=PercepxionMCP
CYBERARK_SAFE=PercepxionSafe
CYBERARK_OBJECT=percepxion-admin-account
Optional mutual TLS (both vars required to enable):
CYBERARK_CERT_PATH=/path/to/client.pem
CYBERARK_KEY_PATH=/path/to/client.key
Set CYBERARK_VERIFY_SSL=false to skip server cert verification in lab environments. The AppID must be registered in CyberArk with access to the specified safe, and the host running this server must be an allowed machine for that AppID.
Full setup details in config/setup-instructions.md.
Connect an MCP client
Claude Code (recommended)
claude mcp add percepxion -- /path/to/percepxion-mcp-server/.venv/bin/python /path/to/percepxion-mcp-server/percepxion_mcp.py
Or add manually to ~/.claude/settings.json:
{
"mcpServers": {
"percepxion": {
"command": "/path/to/.venv/bin/python",
"args": ["/path/to/percepxion-mcp-server/percepxion_mcp.py"],
"env": {
"PYTHONUNBUFFERED": "1",
"PERCEPXION_USERNAME": "[email protected]",
"PERCEPXION_PASSWORD": "your-password"
}
}
}
}
Claude Desktop (Linux or macOS)
Copy config/claude_desktop_config.example.json, fill in your paths, and place it at:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Claude Desktop (Windows + WSL)
Use config/claude_desktop_config.wsl_windows.example.json. Replace the path placeholder with the WSL path to this repo.
First connection check
Once connected:
- Call
login_with_env - Call
get_device_listwithsearch_query: "*"
If get_device_list returns devices, the server is working.
Tool reference
Full reference in docs/tools.md. Summary below.
Call login_with_env before any other tool. The session persists for the lifetime of the process. On a 401 response, call login_with_env again.
Authentication and credentials
| Tool | Description |
|---|---|
login_with_env |
Authenticate using the configured credential provider. Call once per session. |
reconfigure_credentials |
Switch credential provider at runtime (env, vault, aws, cyberark) and clear the current session. |
Organization management
| Tool | Description |
|---|---|
list_organizations |
List organizations you have permission for. Use to discover organization_id values. |
list_tenants |
Deprecated alias for list_organizations, kept for backward compatibility. |
Most tools accept an organization_id parameter to scope the call. The older tenant_id name is still accepted everywhere as a deprecated alias (see Environment variables).
organization_id/tenant_id accept either a UUID or an exact (case-insensitive) organization name. Name resolution only works for organizations with at least one visible device (it's derived from device search results, there's no dedicated organization-lookup endpoint), and is always scoped to your own login-derived permissions, a name match for an organization you aren't permitted for is rejected, not returned. If a name matches zero or more than one permitted organization, the tool call fails with a clear error instead of guessing; use the organization_id (UUID) directly to disambiguate.
Device inventory
| Tool | Description |
|---|---|
get_device_list |
Search and paginate the device inventory. |
get_device_details |
Get full device properties by device_id or serial_num. |
get_devices_by_organization |
List all devices in a specific organization. |
Device lifecycle
| Tool | Description |
|---|---|
import_and_assign_devices |
Assign devices to an organization. |
unassign_devices |
Remove one or more devices from an organization. |
remove_device_from_platform |
Remove a single device (convenience wrapper). |
Smart Groups
| Tool | Description |
|---|---|
create_smart_group |
Create a Smart Group using a filter query or device ID list. Used to target bulk operations. |
list_smart_groups |
List Smart Groups by name. |
delete_smart_group |
Delete a Smart Group by ID. |
CLI commands
| Tool | Description | Async? |
|---|---|---|
send_direct_cli_command |
Send a CLI command to one device. Read-only by default (see CLI policy above). Commands are audit-logged. | Yes, use get_job_group |
Device configuration
| Tool | Description | Async? |
|---|---|---|
get_device_config |
Read current telemetry config before modifying it. | No |
update_device_config |
Save config properties and optionally apply them immediately. | Yes if apply_now=True |
clone_device_config |
Copy config from a source device to a target device via a template. | Yes, use get_job_group |
list_templates |
List saved config templates. | No |
delete_template |
Delete a config template by ID. | No |
Device operations
| Tool | Description | Async? |
|---|---|---|
reboot_device |
Reboot a device via Percepxion. | Yes, use get_job_group |
list_device_ports |
List serial and device ports on a device. Returns port names, numbers, and connection state. Does not include managed-device identity, use get_security_telemetry or get_port_telemetry for hostname, model, serial, and OS version. |
No |
Firmware management
| Tool | Description | Async? |
|---|---|---|
get_device_firmware_status |
Get firmware version and state for one device. | No |
firmware_compliance_report |
Compare fleet firmware against an expected version. | No |
list_firmware_content |
List firmware packages already uploaded to Percepxion storage. | No |
update_firmware_by_smart_group |
Upload firmware and apply to devices in one or more Smart Groups. | Yes, use get_job_group |
Logging
| Tool | Description | Async? |
|---|---|---|
request_device_syslog_upload |
Trigger devices to upload syslogs to Percepxion storage. | Yes, use get_job_group |
get_device_syslogs |
Query syslog files already uploaded. | No |
query_device_access_log |
Paginated query of device access log entries. | No |
download_device_access_log |
Download complete access log for one device. | No |
Security and audit
| Tool | Description |
|---|---|
get_security_telemetry |
Retrieve full device and per-port telemetry. Source of truth for managed-device inventory: returns per-port dp_info records with hostname, model, serial, IP, OS version, uptime, and CPU/memory/flash usage for every attached device. Also includes console manager info, firmware state, network probes, and audit records. |
get_port_telemetry |
Retrieve telemetry for a single port. Returns a structured managed-device object for that port only, faster and cheaper than get_security_telemetry when only one port is needed. |
investigate_audit_logs |
Search platform audit records by user, time range, or keyword. |
investigate_user_audit_logs |
Search user records with last recorded audit action per user. |
Job tracking
| Tool | Description |
|---|---|
search_job_groups |
Search and poll async job status by name prefix. |
get_job_group |
Get full job output and results by job group ID. |
Async job workflow
When a tool creates a job, it returns a job group record immediately:
1. Call the action tool (e.g. send_direct_cli_command)
→ Returns: { "ok": true, "data": { "id": "jg-abc123", "name": "CLI_dev001_1748000000" } }
2. Call get_job_group with the id
→ Returns: full job output, per-device results, and status
Job names include a Unix timestamp suffix to avoid collisions when multiple jobs run against the same device.
Security
This server executes operations on network infrastructure. Treat it accordingly.
Credentials:
- Keep
.envout of version control (it's in.gitignore). - Set file permissions:
chmod 600 .env - Use a dedicated Percepxion service account with minimum required permissions. Do not use an admin account for automated workflows.
- For team environments, use the Vault or AWS Secrets Manager providers instead of plaintext
.envfiles.
CLI command policy:
send_direct_cli_commandis read-only by default. Only recognized read commands (show,get,ping, etc.) pass through.- A built-in deny list blocks destructive operations (
reload,factory-reset,write erase,erase startup-config, etc.) even when write mode is enabled. - Set
PERCEPXION_CLI_WRITE_ENABLED=trueto allow write commands. All dispatched commands are logged to stderr with device ID and command string. - Set
PERCEPXION_CLI_DENY_COMMANDSto add custom blocked commands. SetPERCEPXION_CLI_PERMIT_COMMANDSfor an explicit allowlist. PERCEPXION_CLI_YOLO=truedisables all filtering. Use only in trusted, isolated environments.
Firmware uploads:
update_firmware_by_smart_groupreads a local file path and uploads it to Percepxion.- Set
PERCEPXION_FIRMWARE_DIRto restrict uploads to a specific directory. Without this, any file the server process can read can be uploaded.
Token handling:
- Auth tokens are stored in memory only and are never written to disk.
- On a 401 response, the session is cleared automatically. Call
login_with_envagain to restore. - There is no automatic token refresh. Long-running workflows should handle 401 responses and re-authenticate.
Network:
- The server communicates with Percepxion over HTTPS only.
- The default endpoint is
api.percepxion.ai. The Lantronix internal sandbox isapi.gopercepxion.ai. VerifyPERCEPXION_API_URLbefore running in any automated context.
Organization-name resolution:
organization_id/tenant_idaccept a name as a convenience, but resolution is hard-scoped to the authenticated session: candidate organizations come only fromsession.permitted_organization_ids, populated from your own/v2/user/loginresponse (user.group[].tenant_id) at login time.- A device-derived name match for an organization outside that permitted set is rejected, not returned. This is a real permission boundary, not just a UX filter, it prevents organization-name lookup from being used to discover or probe organizations you aren't already RBAC-entitled to.
- A UUID-shaped
organization_id/tenant_idalways skips name resolution entirely (no extra API call), identical to prior behavior.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "Not authenticated" | login_with_env not called or token expired |
Call login_with_env |
401 on any tool |
Token expired mid-session | Call login_with_env again |
| All calls fail or time out | Wrong PERCEPXION_API_URL |
Check .env, production is api.percepxion.ai, sandbox is api.gopercepxion.ai |
| Slow log downloads time out | Default 45s timeout too short | Set PERCEPXION_REQUEST_TIMEOUT=120 |
| Firmware upload rejected | File outside PERCEPXION_FIRMWARE_DIR |
Move file to allowed directory or unset the variable |
| "Write commands are disabled" | CLI policy in read-only mode | Set PERCEPXION_CLI_WRITE_ENABLED=true in .env |
| "Command is in the deny list" | Built-in deny list blocks the command | Set PERCEPXION_CLI_YOLO=true to bypass (use with caution) |
| Server exits immediately | Python path or venv issue | Run python percepxion_mcp.py directly to see the error |
| "No permitted organizations available" when resolving an organization name | Login response had no user.group entries, or login_with_env wasn't called |
Call login_with_env first; confirm the account has organization group membership in Percepxion |
| Organization name resolves to "0 matches" | The org has no visible devices (name resolution is device-derived), or the name doesn't match any organization you're permitted for | Use list_organizations to find the organization_id (UUID) directly and pass that instead |
| Organization name resolves to "ambiguous, multiple matches" | Two or more permitted organizations share the same name | Use list_organizations to disambiguate and pass the organization_id (UUID) directly |
Contributing
The project uses a feature branch workflow:
git checkout -b feat/your-feature
# make changes
git push -u origin feat/your-feature
# open a pull request to main
Run the test suite before submitting:
pip install -e ".[dev]"
pytest tests/ -v
See docs/adding-new-tools.md for conventions on adding new tools to the server.
Developer docs
- docs/tools.md, full tool reference with API endpoint mapping
- docs/adding-new-tools.md, conventions for adding tools to this server
- config/setup-instructions.md, detailed setup for all OS and credential provider combinations
- docs/claude-example.prompt, starter system prompt for Claude Desktop sessions
Changelog
See CHANGELOG.md.
License
See LICENSE.
Installing Percepxion
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/Lantronix/percepxion-mcp-serverFAQ
Is Percepxion MCP free?
Yes, Percepxion MCP is free — one-click install via Unyly at no cost.
Does Percepxion need an API key?
No, Percepxion runs without API keys or environment variables.
Is Percepxion hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Percepxion in Claude Desktop, Claude Code or Cursor?
Open Percepxion on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Percepxion with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
