Skip to main content
Glama
README.md
# teltonika-rms-mcp

An **unofficial, community-built** [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that lets AI agents (Claude Desktop, Claude Code, or any MCP-compatible client) query and operate a fleet of Teltonika devices through the **RMS (Remote Management System) API**.

> [!IMPORTANT]
> **Not affiliated with, endorsed by, or supported by Teltonika.** This is a personal side project, shared as an example to inspire others to build better ones. "Teltonika" and "RMS" are trademarks of their respective owners. Use it at your own risk, and test it on a non-production company or a few test devices first.

## Why

RMS already has a well-documented REST API. MCP is the missing glue that lets an agent use it in plain language:

- *"Which devices in company X were offline today, and what was their signal?"*
- *"Give me a firmware summary of the fleet and list the devices that aren't on the latest version."*
- *"How much mobile data did Pump-02 use last month on each SIM?"*
- *"Reboot Gateway-A."* (the agent shows you the device and asks before doing it)

## Tools

| Tool | Type | What it does |
|---|---|---|
| `list_devices` | read | Search and paginate devices (free text, company, raw RMS filters) |
| `get_device` | read | Full details of one device |
| `get_device_status` | read | Whether devices are online in RMS right now (via `/devices/statistics`) |
| `get_data_usage` | read | Per-SIM TX/RX data usage over a date range |
| `list_alerts` | read | Recent RMS alerts |
| `list_companies` | read | Companies / sub-companies visible to the token |
| `list_tags` | read | Device tags |
| `fleet_summary` | read | Online/offline counts, devices per model and firmware, weak-signal list |
| `rms_get` | read | Read-only GET on any RMS API path, for endpoints without a dedicated tool |
| `reboot_device` | **write** | Reboots a device in two steps: a preview first, then the reboot only with `confirm=true` |

Read tools are annotated `readOnlyHint`, and `reboot_device` is annotated `destructiveHint`, so MCP clients can ask for approval before running it.

**Read-only mode:** set `RMS_READ_ONLY=true` and `reboot_device` is not registered at all.

## Quick start

### 1. Create an RMS API token

In RMS, go to **Account settings → Security** and enable two-factor authentication, which RMS requires before you can create tokens. Then go to **API → Access tokens → Add new access token**.

Grant only the scopes you need:

| Scope (as listed in RMS) | Needed for |
|---|---|
| `devices:read` | device tools, status, data usage, fleet summary |
| read scopes for alerts, companies and tags | `list_alerts`, `list_companies`, `list_tags` |
| the device write / commands scope | `reboot_device` only |

The token is shown only once, so store it safely. Exact scope names can vary between RMS releases; pick them from the list in the RMS UI. If a tool returns HTTP 403, the token is missing the scope for that call.

### 2. Install

```bash
git clone https://github.com/marceloiamunoz/Teltonika_RMS_MCP4IA_example.git
cd Teltonika_RMS_MCP4IA_example
pip install -e .        # or: uv pip install -e .
```

Requires Python 3.10+.

### 3. Connect it to Claude Desktop

Add this to `claude_desktop_config.json` (see [`examples/claude_desktop_config.json`](examples/claude_desktop_config.json)):

```json
{
  "mcpServers": {
    "teltonika-rms": {
      "command": "teltonika-rms-mcp",
      "env": {
        "RMS_API_TOKEN": "paste-your-token-here",
        "RMS_READ_ONLY": "true"
      }
    }
  }
}
```

Restart Claude Desktop and ask: *"Give me a summary of my RMS fleet."*

Using **Claude Code**:

```bash
claude mcp add teltonika-rms --env RMS_API_TOKEN=xxx --env RMS_READ_ONLY=true -- teltonika-rms-mcp
```

### Configuration

| Variable | Default | Description |
|---|---|---|
| `RMS_API_TOKEN` | — (required) | RMS Personal Access Token |
| `RMS_READ_ONLY` | `false` | `true` hides every write tool |
| `RMS_BASE_URL` | `https://rms.teltonika-networks.com/api` | Override the API endpoint |
| `RMS_TIMEOUT` | `30` | HTTP timeout in seconds |
| `MCP_TRANSPORT` | `stdio` | `stdio` or `streamable-http` |

## How it works

```
AI agent ──MCP──▶ teltonika-rms-mcp ──HTTPS + Bearer token──▶ RMS API
```

- **Pagination:** list tools take `limit`/`offset`, and `fleet_summary` walks all pages up to a safety cap.
- **Rate limits and transient errors:** HTTP 429 and 5xx responses are retried with backoff, honouring `Retry-After`.
- **Async operations:** some RMS actions return a `meta.channel` instead of a result. The client polls `/status/channel/{channel}` until the operation finishes, so the agent gets a single final answer.
- **Errors** are returned as readable messages with hints, for example a 403 that names the missing scope.

## Known limitations

This is a prototype. Contributions are welcome.

- Endpoint coverage is intentionally small. Use `rms_get` to explore more endpoints, then promote the useful ones to proper tools.
- `reboot_device` runs the `reboot` command through `POST /devices/{id}/command`. A timeout in the result is expected, because the device drops its connection while it reboots.
- Field names in device payloads vary across models and RMS versions. `fleet_summary` tries several candidate keys for model, firmware, status and signal.
- On a device, `connection_state` is the last known *mobile* connection state, not whether RMS can reach the device right now. Use `get_device_status` for that.
- So far the test suite runs only against a mocked RMS. Reports from real fleets are very welcome.

## Ideas for contributors

- More tools: device location, firmware update, config profiles, RMS Connect and remote-access links, hotspots, VPN hubs.
- OAuth2 support for multi-user and remote deployments.
- MCP *resources* for fleet snapshots, and *prompts* such as a "daily fleet health report".
- Batch actions with a dry-run preview and per-device confirmation.

## Development

```bash
pip install -e ".[dev]"
pytest
ruff check .
```

The tests run a real in-memory MCP client session against a fake RMS API, so no token is needed.

## Security notes

- Prefer a dedicated token with minimal scopes and, where possible, scoped to a single company.
- Start with `RMS_READ_ONLY=true`.
- Never commit your token. `.env` is git-ignored.
- An agent with write tools can affect real devices in the field. Keep a human in the loop.

## License

[MIT](LICENSE) © Marcelo Muñoz