Skip to content

tomer-bdbd/soti-mcp

Repository files navigation

soti-mcp

Operate your SOTI MobiControl MDM fleet from any AI agent — Claude Code, Cursor, Cline, Continue. A Model Context Protocol (MCP) server that wraps the SOTI MobiControl REST API as a clean tool surface so an LLM can list, search, command, and reshape your Android / iOS / Windows / rugged device estate via natural language.

30-second demo

Note: A scripted GIF will be added in v0.2. In the meantime, here is the kind of dialogue this server enables:

You: "Show me devices in the field group with battery below 30% that haven't checked in for 6 hours."

Claude (calls soti_search_devices): Found 4 devices: device-a, device-b, …

You: "Lock down device-a in kiosk mode."

Claude (calls soti_lockdown_device): Dispatched EnableKioskMode to device-a.

Install

Per-project (recommended for MCP clients):

npm install --save-dev soti-mcp

Globally (for direct CLI use):

npm install -g soti-mcp

This package ships an executable soti-mcp binary that speaks MCP over stdio out of the box.

Configure your AI client

Claude Code

Add to your project's .mcp.json (or your user-level ~/.claude.json):

{
  "mcpServers": {
    "soti": {
      "command": "soti-mcp",
      "env": {
        "SOTI_MC_BASE_URL": "https://mc.example.com/MobiControl",
        "SOTI_MC_CLIENT_ID": "your-client-id",
        "SOTI_MC_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Cursor

~/.cursor/mcp.json (or workspace-level .cursor/mcp.json):

{
  "mcpServers": {
    "soti": {
      "command": "soti-mcp",
      "env": {
        "SOTI_MC_BASE_URL": "https://mc.example.com/MobiControl",
        "SOTI_MC_CLIENT_ID": "your-client-id",
        "SOTI_MC_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Cline

In your VS Code settings.json:

{
  "cline.mcpServers": {
    "soti": {
      "command": "soti-mcp",
      "env": {
        "SOTI_MC_BASE_URL": "https://mc.example.com/MobiControl",
        "SOTI_MC_CLIENT_ID": "your-client-id",
        "SOTI_MC_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Continue

~/.continue/config.json:

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "soti-mcp",
          "env": {
            "SOTI_MC_BASE_URL": "https://mc.example.com/MobiControl",
            "SOTI_MC_CLIENT_ID": "your-client-id",
            "SOTI_MC_CLIENT_SECRET": "your-client-secret"
          }
        }
      }
    ]
  }
}

HTTP / SSE transport (remote consumers)

Set SOTI_MCP_HTTP_HOST and SOTI_MCP_HTTP_PORT to expose the server over Streamable HTTP. Useful for hosting the MCP server in your platform stack.

SOTI_MCP_HTTP_HOST=0.0.0.0 SOTI_MCP_HTTP_PORT=8765 soti-mcp

Tool reference

Tool Kind Purpose
soti_list_devices Read Paginated device list, optionally filtered by group path or property filter.
soti_get_device Read Full details for a single device by ID, MAC, or IMEI.
soti_search_devices Read Advanced filter search (CONTAINS, =, !=, >, <, AND, OR).
soti_get_device_location Read Last known GPS / cellular fix for a device.
soti_get_device_apps Read Installed application list, paginated and orderable.
soti_list_groups Read Device group hierarchy.
soti_get_group_devices Read Members of a device group, recursing into subgroups.
soti_list_policies Read Configuration profiles (SOTI calls these profiles).
soti_list_alerts Read Active compliance / alert policies.
soti_get_compliance_report Read Compliance status for a device, group, or fleet.
soti_send_command Action Generic device action (CheckIn, Lock, Locate, RemoteRing, …).
soti_install_app Action Install a managed application on a device.
soti_uninstall_app Action Uninstall a managed application from a device.
soti_lockdown_device Action Enable kiosk lockdown.
soti_release_device Action Release kiosk lockdown.
soti_wipe_device DESTRUCTIVE Factory-reset / wipe. Requires confirm: true.
soti_assign_policy Action Assign a profile to groups, devices, or a filter expression.
soti_move_device Action Move a device to another group.

Resources

URI Template Returns
soti://device/{id} Full JSON snapshot of one device.
soti://group/{path}/devices Devices that belong to a group (recurses into subgroups).
soti://compliance/report/{date} Compliance roll-up snapshot.

Tool result envelope

Every tool returns a JSON object in this shape:

{
  "ok": true,
  "data": [ ],
  "nextCursor": "…optional opaque cursor…"
}

…or, on failure:

{
  "ok": false,
  "error": {
    "code": "DEVICE_NOT_FOUND",
    "message": "Device not found (GET /devices/abc)",
    "hint": "Verify the device ID, or use mac:/imei_meid_esn: prefix.",
    "upstreamStatus": 404
  }
}

Error codes form a stable taxonomy: AUTH_FAILED, DEVICE_NOT_FOUND, RATE_LIMITED, PERMISSION_DENIED, INVALID_PARAMS, UPSTREAM_ERROR, NETWORK_ERROR, NOT_SUPPORTED, MISSING_CONFIRM, TIMEOUT.

Example prompts

  • "Show me offline devices in the warehouse group."
  • "Lock down device A1B2 in kiosk mode."
  • "List the 5 most recent compliance violations on Android Plus devices."
  • "Move all devices in \\Stores\Old\Pilot into \\Stores\Production."
  • "Which devices are running the com.acme.pos app at version below 4.2?"
  • "Send a check-in command to every device that hasn't reported in 24 hours."

The LLM picks the right tools and chains them together; you stay in chat.

Security notes

  • Credentials — Store SOTI_MC_CLIENT_SECRET in your MCP client's secrets store, not in .mcp.json if you can avoid it. The client ID and secret should be created in the MobiControl console (Administration → API Clients) with the minimum group-scope permissions your workflows require.
  • Scope minimization — SOTI MC enforces permissions per device group. Create a dedicated API client for the LLM with read-only or limited-action rights, and grant write actions only on the groups you actually need to mutate.
  • Destructive operationssoti_wipe_device requires explicit confirm: true. The tool description marks it DESTRUCTIVE so MCP clients can highlight it. soti_send_command rejects Wipe / FactoryReset and forces callers through soti_wipe_device.
  • Audit logging — SOTI MC logs every API call against the API client identity. Use a dedicated client for the LLM so its activity is auditable separately from human operators.
  • Token storage — OAuth2 access tokens are held only in the running process memory; never written to disk. Logs redact Authorization headers and access tokens.
  • Rate limit — A token-bucket limiter (default 10 req/sec) prevents the LLM from accidentally hammering your MobiControl Server. Tune via SOTI_MC_RATE_LIMIT_RPS.
  • Network — All traffic to MobiControl is over HTTPS. Use a private network or reverse proxy if your MobiControl Server is exposed to the internet.

Compatibility matrix

MobiControl version Status Notes
16.x (cloud + on-prem) ✅ tested Full tool surface available.
15.x ✅ expected All endpoints used by this MCP exist since v14.
14.x ⚠️ partial soti_search_devices and soti_move_device require v14+.
13.x ⚠️ legacy Most read tools work; soti_search_devices falls back to soti_list_devices.
≤ 12.x ❌ unsupported API surface differs significantly.

When an endpoint is missing on an older version the server returns NOT_SUPPORTED rather than a raw 404 — your LLM can adapt its plan.

Environment variables

Variable Required Default Notes
SOTI_MC_BASE_URL yes e.g. https://mc.example.com/MobiControl. Token endpoint resolves to {BASE_URL}/api/token.
SOTI_MC_CLIENT_ID yes OAuth2 client ID.
SOTI_MC_CLIENT_SECRET yes OAuth2 client secret.
SOTI_MC_GRANT_TYPE no client_credentials Or password.
SOTI_MC_USERNAME when password Resource Owner Password grant only.
SOTI_MC_PASSWORD when password Resource Owner Password grant only.
SOTI_MC_RATE_LIMIT_RPS no 10 Per-server-instance request budget.
SOTI_MC_LOG_LEVEL no info trace / debug / info / warn / error. Logs go to stderr only.
SOTI_MCP_HTTP_HOST no If set with SOTI_MCP_HTTP_PORT, switches to Streamable HTTP transport.
SOTI_MCP_HTTP_PORT no TCP port for HTTP transport.

Local development

git clone https://github.com/tomer-bdbd/soti-mcp.git
cd soti-mcp
npm install
cp .env.example .env   # then edit with your sandbox credentials
npm run dev            # runs from src/ via tsx
npm test               # 40+ unit tests, no SOTI sandbox required
npm run test:coverage  # enforces ≥80% lines

A live smoke test against a real SOTI MobiControl deployment is gated behind SOTI_MC_INTEGRATION=1 and is not run in CI. To exercise it locally:

SOTI_MC_INTEGRATION=1 npm test

Roadmap

  • v0.2 — bulk operations (/devices/actions), webhook receiver for SOTI events, iOS APNS-aware command set, scripted demo GIF, OpenAPI-driven type generation.
  • v0.3 — multi-tenant config (multiple SOTI servers per process), retry budget surfaced as MCP progress events.

Contributing

Issues and PRs welcome. Please open an issue first for non-trivial changes so we can align on scope. Run npm run lint && npm run typecheck && npm test before opening the PR.

License

MIT — see LICENSE.


Trademark note. SOTI and MobiControl are trademarks of SOTI Inc. This project is not affiliated with or endorsed by SOTI Inc. The maintainer is an independent SOTI MobiControl operator who built this so AI agents could drive their fleet without re-implementing OAuth2 + REST glue.

About

Model Context Protocol server for SOTI MobiControl — operate Android/iOS/Windows/rugged MDM fleets with AI agents (Claude Code, Cursor, Cline, Continue).

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors