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
There are two supported ways to serve HTTPS: a TLS-terminating reverse proxy with automatic certificates (recommended when the server has a public hostname), or native TLS with your own certificate files (for private networks with a corporate CA).
### Reverse proxy with automatic certificates
The container serves plain HTTP by default and can sit behind a TLS-terminating reverse proxy. [`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.
### Native TLS (bring your own certificate)
When the server runs on a private network without public DNS (so Let's Encrypt cannot issue a certificate), the server can terminate TLS itself using a certificate and key you provide, for example one issued by your corporate CA:
```yaml
services:
litmus-mcp-server:
image: ghcr.io/litmusautomation/litmus-mcp-server:latest
ports:
- "8000:8000"
volumes:
- /opt/litmus-mcp/certs:/certs:ro
environment:
SSL_CERTFILE: /certs/server.crt
SSL_KEYFILE: /certs/server.key
```
MCP clients then connect to `https://<hostname>:8000/mcp`. Notes:
- `SSL_CERTFILE` and `SSL_KEYFILE` are plain environment variables (like `ENABLE_STDIO`), not `.env` settings. Setting only one of them, or pointing at a missing file, aborts startup with an error instead of silently serving plain HTTP.
- `SSL_KEYFILE_PASSWORD` is available for encrypted private keys.
- The certificate must be issued for the hostname clients use, and clients must trust its CA. Self-signed certificates are rejected by claude.ai and Claude Desktop, so use a CA your machines already trust.
- Unlike the Caddy pattern, renewal is manual: replace the files and restart the container before the certificate expires.
---
## 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. Pages are fetched as markdown (a few KB each) rather than rendered HTML (a few hundred KB, mostly navigation), falling back to HTML only where no markdown version is published. `litmus://docs/api` resolves to the API portal's agent router at [api.litmus.io/agents.md](https://api.litmus.io/agents.md), and the per-product routers it links to are exposed directly as `litmus://docs/api/edge`, `litmus://docs/api/edgemanager` and `litmus://docs/api/unify`, alongside `litmus://docs/cli` for the litmus-cli guide and `litmus://docs/workflows` for multi-step task recipes. `litmus://docs/api/index` indexes everything the API portal publishes, including per-component pages not served as resources here, and `litmus://docs/reference/message-format` documents the JSON shape the NATS topic tools return.
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
62 tools across 13 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** * | `list_nats_topics` | Discover which topics exist, merged from analytics, DeviceHub tags and digital twin instances. |
| | `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 (`list_nats_topics` needs no broker access, since it reads topic names from the REST/GraphQL APIs rather than subscribing):
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.
- The catalog's `unify.*` functions target Litmus Unify, which authenticates separately from Litmus Edge. Send `UNS_URL`, `UNS_USERNAME` and `UNS_PASSWORD` (plus `UNS_VALIDATE_CERTIFICATE: false` for a self-signed certificate) to use them. Without `UNS_URL` the namespace is hidden from `litmus_sdk_discover`, since every call would otherwise fail on missing credentials; no other namespace needs these headers.
- `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` (the LEM device id, as with `lem_device_id` below) 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 `lem_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.
`lem_device_id` is the LEM device id from `lem_list_devices`, not the DeviceHub device id that `get_devicehub_devices` returns; the two are different namespaces. The argument was called `device_id` before, which collided with that DeviceHub id, and the old name is still accepted so existing clients keep working.
**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
chrome-devtools-mcp
Chrome DevTools for coding agents
claude-plugins-official
A directory of trusted plugins for Claude Code, including internal and...
python-sdk
The official Python SDK for Model Context Protocol servers and clients