Content
<p align="center">
<a href="https://litmus.io">
<picture>
<source media="(prefers-color-scheme: light)" srcset="static/litmus-logo-light.svg" />
<source media="(prefers-color-scheme: dark)" srcset="static/litmus-logo-dark.svg" />
<img src="static/litmus-logo-light.svg" height="60" alt="Litmus logo" />
</picture>
</a>
</p>
<p align="center">
<a href="https://docs.litmus.io">
<img src="https://img.shields.io/badge/Litmus-Docs-2acfa6?style=flat-square" alt="Documentation" />
</a>
<a href="https://www.linkedin.com/company/litmus-automation/" >
<img src="https://img.shields.io/badge/LinkedIn-Follow-0a66c2?style=flat-square" alt="Follow on LinkedIn" />
</a>
</p>
# Litmus MCP Server
The official [Litmus Automation](https://litmus.io) **Model Context Protocol (MCP) Server** enables LLMs and intelligent systems to interact with [Litmus Edge](https://litmus.io/products/litmus-edge) for device configuration, monitoring, and management. It is built on top of the MCP SDK and adheres to the [Model Context Protocol spec](https://modelcontextprotocol.io/).
<div>
<picture>
<source media="(prefers-color-scheme: light)" srcset="static/MCP-server-arch-diagram.png" />
<img src="static/MCP-server-arch-diagram.png" alt="Litmus MCP Server Architecture Diagram" />
</picture>
</div>
## Table of Contents
- [Quick Launch](#quick-launch)
- [HTTPS Deployment](#https-deployment)
- [Web UI](#web-ui)
- [Persistent Configuration](#persistent-configuration)
- [Claude Code CLI](#claude-code-cli)
- [Cursor IDE](#cursor-ide)
- [VS Code / Copilot](#vs-code--github-copilot)
- [Windsurf](#windsurf)
- [STDIO - Claude Desktop](#stdio-with-claude-desktop)
- [Tips](#Tips)
- [Tools](#available-tools)
- [Litmus Central](#litmus-central)
---
## Quick Launch
### Start an HTTP MCP Server using Docker
Run the server in Docker (HTTP only)
```bash
docker run -d --name litmus-mcp-server -p 8000:8000 ghcr.io/litmusautomation/litmus-mcp-server:latest
```
The HTTP server exposes both MCP transports on port 8000:
- `http://<host>:8000/mcp` - Streamable HTTP (current MCP spec, recommended)
- `http://<host>:8000/sse` - HTTP+SSE (legacy transport, kept for older clients)
Clients that support Streamable HTTP should point at `/mcp` (e.g. `"type": "http"`, as in the Claude Code example below). The remaining client examples use the SSE endpoint; swap in `/mcp` if your client supports it, keeping the same headers.
NOTE: The Litmus MCP Server is built for linux/AMD64 platforms. If running in Docker on ARM64, specify the AMD64 platform type by including the --platform argument:
```bash
docker run -d --name litmus-mcp-server --platform linux/amd64 -p 8000:8000 ghcr.io/litmusautomation/litmus-mcp-server:main
```
---
## HTTPS Deployment
The container serves plain HTTP and is intended to sit behind a TLS-terminating reverse proxy in production. [`deploy/docker-compose.https.yml`](deploy/docker-compose.https.yml) ships that pattern using [Caddy](https://caddyserver.com/), which obtains and renews Let's Encrypt certificates automatically:
```bash
# DNS A/AAAA record for mcp.example.com must point at this machine
DOMAIN=mcp.example.com docker compose -f deploy/docker-compose.https.yml up -d
```
MCP clients then connect to `https://mcp.example.com/mcp` (no port) with the same headers as before. Notes:
- Only Caddy is published to the host (ports 80/443); the MCP server stays on the internal compose network, and the web UI (`:9000`) is deliberately not proxied.
- Certificates persist in the `caddy_data` volume across restarts.
- For private networks without public DNS, uncomment `tls internal` in [`deploy/Caddyfile`](deploy/Caddyfile) to use Caddy's internal CA instead (clients must trust that CA).
- Any other TLS-terminating proxy (Traefik, nginx, a cloud load balancer) works the same way: forward to port 8000 and keep SSE responses unbuffered.
---
## Web UI
The Docker image includes a built-in chat interface that lets you interact with Litmus Edge using natural language — no MCP client configuration required.
Start the server with both ports exposed:
```bash
docker run -d --name litmus-mcp-server \
-p 8000:8000 -p 9000:9000 \
-e ANTHROPIC_API_KEY=<key> \
ghcr.io/litmusautomation/litmus-mcp-server:latest
```
- **`:9000`** — Web UI (chat interface). Open `http://localhost:9000` in your browser, add a Litmus Edge instance via the config page, and start chatting.
- **`:8000`** — SSE endpoint for external MCP clients (Claude Desktop, Cursor, VS Code, etc.) — still available as normal.
> **Security note:** the Web UI is a local operator console. It has no login and it stores LLM API keys and Litmus Edge credentials, so only publish port 9000 on networks you trust; port 8000 (`/mcp`) is the only endpoint intended for MCP clients. Outside Docker, the UI binds to `127.0.0.1` unless you set `WEB_UI_HOST=0.0.0.0` (the Docker image sets this so the `-p 9000:9000` mapping works; simply omit the mapping to keep the UI private). Cross-origin browser access to the UI is disabled unless `WEB_UI_CORS_ORIGINS` is set to a comma-separated list of explicit origins.
**Supported LLM providers:** Anthropic Claude, OpenAI, and Google Gemini. Provide one or more keys at startup (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`) or enter them through the Web UI's setup screen. The active provider and model are switchable from the Web UI's config page at any time.
**Multiple Litmus Edge instances:** The Web UI lets you register and switch between multiple Litmus Edge devices from a single MCP server. Each instance keeps its own URL and OAuth2 credentials; the active instance's credentials are mirrored into `EDGE_URL` / `EDGE_API_CLIENT_ID` / `EDGE_API_CLIENT_SECRET` automatically. Manage instances under **Config → Litmus Edge Instances**, or check status per-instance from the **Health** page.
**Live Litmus documentation as MCP Resources:** The server exposes `litmus://docs/<section>` URIs that fetch live content from [docs.litmus.io](https://docs.litmus.io) on demand, so MCP-aware clients can pull current reference material directly into the model's context.
If you deploy the MCP server and web client on separate hosts, set `MCP_SSE_URL` to point the web client at the server:
```bash
-e MCP_SSE_URL=http://<mcp-server-host>:8000/sse
```
### Persistent Configuration
By default, configuration saved through the Web UI (API keys, Litmus Edge instances, model preferences, connection settings) is written to `.env` inside the container and is lost when the container is removed.
To retain configuration across container restarts and replacements, mount a host file over `/app/.env`:
```bash
# One-time setup — the host file must exist before docker run
mkdir -p /opt/litmus-mcp
touch /opt/litmus-mcp/.env
# Run with the volume mount
docker run -d --name litmus-mcp-server \
-p 8000:8000 -p 9000:9000 \
-v /opt/litmus-mcp/.env:/app/.env \
ghcr.io/litmusautomation/litmus-mcp-server:latest
```
Any configuration you save in the UI is written to `/opt/litmus-mcp/.env` on the host. A new container started with the same `-v` flag will pick it up automatically on startup.
> **Note:** The host-side file must be created with `touch` before running the container. If it does not exist, Docker creates a directory at that path and the application will fail to write configuration.
**Docker Compose equivalent:**
```yaml
services:
litmus-mcp-server:
image: ghcr.io/litmusautomation/litmus-mcp-server:latest
ports:
- "8000:8000"
- "9000:9000"
volumes:
- /opt/litmus-mcp/.env:/app/.env
```
---
> **Note:** `NATS_SOURCE`, `NATS_PORT`, `INFLUX_HOST`, and `INFLUX_PORT` are optional in all of the client configurations below. When omitted, the server derives the hosts from `EDGE_URL` (defaulting to `nats://<edge-host>:4222` and `http://<edge-host>:8086`) and mentions the fallback in tool responses. Set them only when the data plane is reachable at a different address or port than the Edge web UI.
### Claude Code CLI
Run Claude from a directory that includes a configuration file at `~/.claude/mcp.json`:
```json
{
"mcpServers": {
"litmus-mcp-server": {
"type": "http",
"url": "http://localhost:8000/mcp",
"headers": {
"EDGE_URL": "${EDGE_URL}",
"EDGE_API_CLIENT_ID": "${EDGE_API_CLIENT_ID}",
"EDGE_API_CLIENT_SECRET": "${EDGE_API_CLIENT_SECRET}",
"NATS_SOURCE": "${NATS_SOURCE}",
"NATS_PORT": "${NATS_PORT:-4222}",
"NATS_PASSWORD": "${NATS_PASSWORD}",
"INFLUX_HOST": "${INFLUX_HOST}",
"INFLUX_PORT": "${INFLUX_PORT:-8086}",
"INFLUX_DB_NAME": "${INFLUX_DB_NAME:-tsdata}",
"INFLUX_USERNAME": "${INFLUX_USERNAME}",
"INFLUX_PASSWORD": "${INFLUX_PASSWORD}"
}
}
}
}
```
[Anthropic Docs](https://docs.anthropic.com/en/docs/agents-and-tools/mcp)
---
### Cursor IDE
Add to `~/.cursor/mcp.json` or `.cursor/mcp.json`:
```json
{
"mcpServers": {
"litmus-mcp-server": {
"url": "http://<MCP_SERVER_IP>:8000/sse",
"headers": {
"EDGE_URL": "https://<LITMUSEDGE_IP>",
"EDGE_API_CLIENT_ID": "<oauth2_client_id>",
"EDGE_API_CLIENT_SECRET": "<oauth2_client_secret>",
"NATS_SOURCE": "<LITMUSEDGE_IP>",
"NATS_PORT": "4222",
"NATS_PASSWORD": "<access_token_from_litmusedge>",
"INFLUX_HOST": "<LITMUSEDGE_IP>",
"INFLUX_PORT": "8086",
"INFLUX_DB_NAME": "tsdata",
"INFLUX_USERNAME": "<datahub_username>",
"INFLUX_PASSWORD": "<datahub_password>"
}
}
}
}
```
[Cursor docs](https://docs.cursor.com/context/model-context-protocol)
---
### VS Code / GitHub Copilot
#### Manual Configuration
In VS Code:
Open User Settings (JSON) → Add:
```json
{
"mcpServers": {
"litmus-mcp-server": {
"url": "http://<MCP_SERVER_IP>:8000/sse",
"headers": {
"EDGE_URL": "https://<LITMUSEDGE_IP>",
"EDGE_API_CLIENT_ID": "<oauth2_client_id>",
"EDGE_API_CLIENT_SECRET": "<oauth2_client_secret>",
"NATS_SOURCE": "<LITMUSEDGE_IP>",
"NATS_PORT": "4222",
"NATS_PASSWORD": "<access_token_from_litmusedge>",
"INFLUX_HOST": "<LITMUSEDGE_IP>",
"INFLUX_PORT": "8086",
"INFLUX_DB_NAME": "tsdata",
"INFLUX_USERNAME": "<datahub_username>",
"INFLUX_PASSWORD": "<datahub_password>"
}
}
}
}
```
Or use `.vscode/mcp.json` in your project.
[VS Code MCP Docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
---
### Windsurf
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"litmus-mcp-server": {
"url": "http://<MCP_SERVER_IP>:8000/sse",
"headers": {
"EDGE_URL": "https://<LITMUSEDGE_IP>",
"EDGE_API_CLIENT_ID": "<oauth2_client_id>",
"EDGE_API_CLIENT_SECRET": "<oauth2_client_secret>",
"NATS_SOURCE": "<LITMUSEDGE_IP>",
"NATS_PORT": "4222",
"NATS_PASSWORD": "<access_token_from_litmusedge>",
"INFLUX_HOST": "<LITMUSEDGE_IP>",
"INFLUX_PORT": "8086",
"INFLUX_DB_NAME": "tsdata",
"INFLUX_USERNAME": "<datahub_username>",
"INFLUX_PASSWORD": "<datahub_password>"
}
}
}
}
```
[Windsurf MCP Docs](https://docs.windsurf.com/windsurf/mcp)
## STDIO with Claude Desktop
This MCP server supports local connections with Claude Desktop and other applications via Standard file Input/Output (STDIO): https://modelcontextprotocol.io/legacy/concepts/transports
To use STDIO: Clone, install dependencies, and add the server to the Claude Desktop configuration file with `ENABLE_STDIO` set to `true`. Claude Desktop launches the server process itself; without `ENABLE_STDIO` the server starts in HTTP mode, never answers on stdin/stdout, and Claude Desktop disconnects after its 60-second initialize timeout.
### Clone and install dependencies
```bash
git clone https://github.com/litmusautomation/litmus-mcp-server.git
cd litmus-mcp-server
# Using uv
uv sync
# Otherwise
pip install -e .
```
### Add json server definision to your Claude Desktop config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"litmus-mcp-server": {
"command": "/path/to/.venv/bin/python3",
"args": [
"/absolute/path/to/litmus-mcp-server/src/server.py"
],
"env": {
"ENABLE_STDIO": "true",
"PYTHONPATH": "/absolute/path/to/litmus-mcp-server/src",
"EDGE_URL": "https://<LITMUSEDGE_IP>",
"EDGE_API_CLIENT_ID": "<oauth2_client_id>",
"EDGE_API_CLIENT_SECRET": "<oauth2_client_secret>",
"NATS_SOURCE": "<LITMUSEDGE_IP>",
"NATS_PORT": "4222",
"NATS_PASSWORD": "<access_token_from_litmusedge>",
"INFLUX_HOST": "<LITMUSEDGE_IP>",
"INFLUX_PORT": "8086",
"INFLUX_DB_NAME": "tsdata",
"INFLUX_USERNAME": "<datahub_username>",
"INFLUX_PASSWORD": "<datahub_password>"
}
}
}
}
```
## Tips
For development, use Python **Virtual environments**, for example to bridge mcp lib version diffs between dev clients like 'npx @modelcontextprotocol/inspector' & litmus-mcp-server
```json
{
"mcpServers": {
"litmus-mcp-server": {
"command": "/absolute/path/to/litmus-mcp-server/.venv/bin/python",
"args": ["/absolute/path/to/litmus-mcp-server/src/server.py"],
"env": { /* same as above */ }
}
}
}
```
See [claude_desktop_config_venv.example.json](claude_desktop_config_venv.example.json) for the complete template.
**Header Configuration Guide:**
- `EDGE_URL`: Litmus Edge base URL (include https://)
- `EDGE_API_CLIENT_ID` / `EDGE_API_CLIENT_SECRET`: OAuth2 credentials from Litmus Edge
- `NATS_SOURCE`: Litmus Edge IP (no http/https); optional, derived from `EDGE_URL` when omitted
- `NATS_PASSWORD`: Access token from **System → Access Control → Tokens** (no username needed)
- `INFLUX_HOST`: Litmus Edge IP (no http/https)
- `INFLUX_USERNAME` / `INFLUX_PASSWORD`: DataHub user credentials
---
## Available Tools
59 tools across 12 categories. Tools accept structured arguments and return JSON.
| Category | Function Name | Description |
|---------------------------|----------------------------------------|-------------|
| **DeviceHub, Devices** | `get_litmusedge_driver_list` | List supported Litmus Edge drivers (e.g., ModbusTCP, OPCUA, BACnet). |
| | `get_devicehub_devices` | List all configured DeviceHub devices with connection settings and status. |
| | `create_devicehub_device` | Create a new device with specified driver and default configuration. |
| | `get_device_connection_status` ** | Check whether devices are actively publishing data via InfluxDB heartbeat (connected/stale/no_data). |
| **DeviceHub, Tags** | `get_devicehub_device_tags` | Retrieve tags (data points/registers) for a specific device or all devices, paginated via `limit`/`offset` so any tag count can be paged through. |
| | `get_current_value_of_devicehub_tag` | Read the current real-time value of a specific device tag. |
| | `create_devicehub_tag` | Create a new tag (register) on a device. Driver-required properties auto-fill from defaults. |
| | `update_devicehub_tag` | Update mutable fields of an existing tag (display name, description, properties). |
| | `delete_devicehub_tag` | Delete a tag from a device. Destructive. |
| | `get_tag_status` | Return runtime state (OK/Failed/Unknown) for tags on a specific device. Optionally filter to a single tag. |
| | `get_all_tags_status` | Return tag status across all devices. Defaults to non-OK only so issues surface first. |
| **Device Identity** | `get_litmusedge_friendly_name` | Get the human-readable name assigned to the Litmus Edge device. |
| | `set_litmusedge_friendly_name` | Update the friendly name of the Litmus Edge device. |
| **Cloud / LEM Activation**| `get_cloud_activation_status` | Check cloud registration and Litmus Edge Manager (LEM) connection status. |
| **Docker Management** | `get_all_containers_on_litmusedge` | List all Docker containers running on Litmus Edge Marketplace. |
| | `run_docker_container_on_litmusedge` | Deploy and run a new Docker container on Litmus Edge Marketplace. |
| **NATS Topics** * | `get_current_value_from_topic` | Subscribe to a NATS topic and return the next published message. |
| | `get_multiple_values_from_topic` | Collect multiple sequential values from a NATS topic for trend analysis. |
| **InfluxDB / Time Series** ** | `get_historical_data_from_influxdb` | Query historical time-series data from InfluxDB by measurement and time range. |
| | `list_influxdb_measurements` | List all measurement names in the `tsdata` database, discovery for downstream queries. |
| | `get_device_historical_data` | Fuzzy-match device names to InfluxDB measurements and pull historical data per match. |
| | `query_tag_data` | Query historical data for a specific tag by resolving its output topic. Newest-first. |
| | `get_tag_statistics` | Aggregate stats for a tag: mean, min, max, stddev, count, plus baseline range (mean +/- 2 sigma). |
| | `get_device_data_for_inference` | Composite payload for AI inference: device metadata, all tags, per-tag stats, and recent samples. |
| **System, Events** | `get_system_events` | Retrieve system events filtered by time range, component, and severity (INFO/WARN/ALERT/ERROR). |
| | `get_system_event_stats` | System and event health snapshot: event store size, last-hour event counts by severity, memory/storage usage, CPU count. |
| **Server** | `get_mcp_server_info` | Version info about the MCP server itself (server, litmussdk, litmus-cli, Python). Optional `check_updates` compares against the latest GitHub releases; `upgrade_cli` downloads and activates the newest litmus-cli. Needs no edge connection. |
| **System, Network** | `get_firewall_rules` | Return configured firewall rules: ports, protocols, ALLOW/DENY actions. |
| | `get_network_interface_info` | Network interface details: IP, MAC, gateway, link status, MTU, speed. Defaults to `eth0`. |
| | `get_packet_capture_interfaces` | List network interfaces available for packet capture. |
| | `get_packet_capture_status` | Current packet capture state and list of captured `.pcap` files with metadata. |
| | `start_packet_capture` | Start a packet capture on an interface. Duration 1-30 minutes. |
| | `stop_packet_capture` | Stop an in-progress packet capture. |
| **Digital Twins** | `list_digital_twin_models` | List all Digital Twin models with ID, name, description, and version. |
| | `create_digital_twin_model` | Create a new Digital Twin model. |
| | `list_digital_twin_instances` | List all Digital Twin instances or filter by model ID. |
| | `create_digital_twin_instance` | Create a new Digital Twin instance from an existing model. |
| | `list_static_attributes` | List static attributes (fixed key-value pairs) for a model, an instance (by id or name), or every instance at once (`all_instances`). |
| | `list_dynamic_attributes` | List dynamic attributes (real-time data points) for a model, an instance (by id or name), or every instance at once (`all_instances`). |
| | `list_transformations` | List data transformation rules configured for a Digital Twin model. |
| | `get_digital_twin_hierarchy` | Get the hierarchy configuration for a Digital Twin model. |
| | `save_digital_twin_hierarchy` | Save a new hierarchy configuration to a Digital Twin model. |
| **Litmus Edge Manager (LEM)** *** | `lem_list_devices` | List edge devices registered in a LEM project (paginated). |
| | `lem_get_device_details` | Full LEM-side record for a single edge device (versions, license, last seen, config). |
| | `lem_list_device_versions` | List Litmus Edge versions registered in a LEM project. |
| | `lem_list_device_groups` | List device group labels (project-level groupings) defined in a LEM project. |
| | `lem_get_license_expiry` | List devices whose license expires within the next N days. |
| | `lem_get_expired_licenses` | List devices in a LEM project whose license has already expired. |
| | `lem_dashboard_usage` | Project usage summary (device counts, license usage, deployment stats). |
| | `lem_get_project_alerts` | List active project-level alerts (device offline, license issues, etc.). |
| | `lem_list_companies` | List all companies on the LEM tenant with project/device/model counts. |
| | `lem_get_company_details` | Full details for a single company by name (teams, license, quotas). |
| | `lem_list_company_projects` | List all projects belonging to a given company. |
| | `lem_get_project_details` | Single-project details (timezone, data TTL, allocated slots, billing plan). |
| | `lem_deployment_info` | LEM tenant deployment info (version, build, release metadata). |
| | `lem_get_system_time` | LEM server clock; useful when comparing edge timestamps. |
| **LEM Bridge** *** | `lem_bridge_list_devicehub_devices` | List devicehub devices on a specific edge by tunneling through LEM (no active-instance switch). |
| | `lem_bridge_get_le_info` | Identity info (friendly name, cloud activation) for an edge via the LEM bridge. |
| **SDK Fallback (CLI)** ****| `litmus_sdk_discover` | Browse the full generated SDK catalog (~550 functions) by dotted-path prefix. |
| | `litmus_sdk_read` | Invoke a read-only SDK function (Get/List/Browse/...) by dotted path. |
| | `litmus_sdk_write` | Invoke a state-changing SDK function by dotted path. Approval-gated; potentially destructive. |
### Tool Use Notes
**\* NATS Topic Tools Requirements:**
To use `get_current_value_from_topic` and `get_multiple_values_from_topic`, you must configure access control on Litmus Edge:
1. Navigate to: **Litmus Edge → System → Access Control → Tokens**
2. Create or configure an access token with appropriate permissions
3. Provide the token in your MCP client configuration headers
**\*\* InfluxDB / Time Series Tools Requirements:**
To use any tool marked with `**` (`get_historical_data_from_influxdb`, `list_influxdb_measurements`, `get_device_historical_data`, `query_tag_data`, `get_tag_statistics`, `get_device_data_for_inference`, `get_device_connection_status`), you must allow InfluxDB port access:
1. Navigate to: **Litmus Edge -> System -> Network -> Firewall**
2. Add a firewall rule to allow port **8086** on **TCP**
3. Ensure InfluxDB is accessible from the MCP server host
4. Provide `INFLUX_HOST`, `INFLUX_PORT`, `INFLUX_DB_NAME`, `INFLUX_USERNAME`, `INFLUX_PASSWORD` in your MCP client headers
**\*\*\* LEM Tools Requirements:**
LEM tools talk to a Litmus Edge Manager (cloud) tenant rather than a single edge. To use any tool marked with `***`, provide these headers in your MCP client configuration:
- `EDGE_MANAGER_URL`: Litmus Edge Manager base URL (include `https://`)
- `EDGE_API_TOKEN`: API token issued by LEM
- `EDGE_MANAGER_PROJECT_ID` (optional): default project id, used when a tool's `project_id` argument is omitted
- `EDGE_MANAGER_ADMIN_URL` (optional): admin URL, defaults to the EDGE_MANAGER_URL host on port `8446`
**\*\*\*\* SDK Fallback Tools Requirements:**
`litmus_sdk_discover`, `litmus_sdk_read`, and `litmus_sdk_write` are backed by the standalone `litmus-cli` Go binary, as are the curated digital twin attribute and tag status tools. The Docker image installs it at build time, and `run.sh` installs or updates it automatically for local runs (checksum-verified into `.venv/bin`, pinned to the same version as the Docker image via the Dockerfile `ARG LITMUS_CLI_VERSION`). If the server is started without it (e.g. a bare `python src/server.py`), it self-installs the pinned release on first use: downloaded from the official releases, SHA256-verified, and cached under `~/.cache/litmus-mcp-server`. Air-gapped hosts without GitHub access should pre-install the binary instead. To use a different binary, set `LITMUS_CLI_PATH` (skips all bootstrapping), or install one from the `cli-v*` releases at https://github.com/litmusautomation/litmus-sdk-releases/releases and put it on PATH. They expose the full generated SDK surface beyond the curated tools above. Notes:
- Connection headers are forwarded to the CLI per call; no CLI profile is read or written.
- `litmus_sdk_read` accepts only read-only functions (final segment starting with Get, List, Browse, Describe, Read, Search, Find, Query, or Count); everything else goes through `litmus_sdk_write`.
- `litmus_sdk_write` can invoke destructive SDK functions (create/update/delete/restart). Every call requires explicit user approval via the `user_approved` argument, which the assistant may only set after you approve the exact function and arguments.
- Prefer the dedicated tools above when one covers the operation.
- `VALIDATE_CERTIFICATE` (optional): `true` to verify TLS certs on the LEM bridge (default `false`)
`lem_bridge_*` tools additionally tunnel through LEM to a specific edge and require both `project_id` and `device_id` as call arguments. The Web UI's **Config -> Litmus Edge Manager** page manages multiple LEM connections and writes these headers automatically.
**Per-call LEM bridge routing for edge tools:**
When `EDGE_MANAGER_URL` is configured, every edge-targeting tool (DeviceHub, Digital Twins, system, marketplace, and the SDK fallback tools) additionally accepts optional `project_id` and `device_id` arguments. Passing both routes that single call to the corresponding managed edge through the LEM bridge, so a LEM-only configuration (URL + token, no `EDGE_URL`) can still use the full Litmus Edge toolset: the assistant discovers ids with `lem_list_devices` and then calls edge tools directly against any device in the fleet. `EDGE_MANAGER_PROJECT_ID` and `EDGE_MANAGER_DEVICE_ID` headers remain supported as static defaults.
**CLI-backed curated tools:**
The digital twin attribute/transformation listing tools and the tag status tools are executed through the bundled `litmus-cli` binary (same connection layer as the SDK fallback tools) rather than the Python SDK, so devices or twins with unusual data no longer fail strict client-side validation, and LEM bridge routing applies uniformly.
---
## Litmus Central
Download or try Litmus Edge via [Litmus Central](https://central.litmus.io).
---
### MCP server registries
- [Glama](https://glama.ai/mcp/servers/@litmusautomation/litmus-mcp-server)
<a href="https://glama.ai/mcp/servers/@litmusautomation/litmus-mcp-server">
<img width="380" height="200" src="https://glama.ai/mcp/servers/@litmusautomation/litmus-mcp-server/badge" alt="Litmus MCP server" />
</a>
- [MCP.so](https://mcp.so/server/litmus-mcp-server/litmusautomation)
---
© 2026 Litmus Automation, Inc. All rights reserved.
Connection Info
You Might Also Like
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
git
A Model Context Protocol server for Git automation and interaction.
everything
Model Context Protocol Servers
ogham-mcp
Shared memory MCP server — persistent, searchable, cross-client
earl
Secure CLI proxy for AI agents — HCL-defined operation templates with OS...
opencode-mcp
MCP server for OpenCode AI — 70 tools, 10 resources, 5 prompts. Use npx...