Skip to main content
Glama
MSPbotsAI

datto-rmm-mcp

by MSPbotsAI

datto-rmm-mcp

MCP server for Datto RMM — device inventory, the component (script) library, and Quick Job execution (run a component on a device right now), over the Model Context Protocol (Streamable HTTP/SSE transport).

Built for PRD-16562 (on-prem operations via Datto RMM, alongside self-host/NinjaOne) after a feasibility investigation confirmed the API surface — see Known Gaps for exactly what was and wasn't verified before this was written.

When would you use this

  • "What devices do we have in Datto?" / find a device before running something on it → dattormm_get_devices

  • "What scripts/components can we run?" → dattormm_get_components

  • "Run [component] on [device] now" → dattormm_run_component (⚠️ destructive, irreversible — see Known Gaps for what you can and can't confirm afterward)

  • "Did that job finish?" → dattormm_get_job_status

Related MCP server: Datadog MCP Server

Tools

授权需要 X-Datto-Api-Key / X-Datto-Api-Secret / X-Datto-Api-Url 三个请求头(见下方授权说明)。

Tool

功能

参数

dattormm_get_devices

列出该租户Datto RMM账号下的全部设备

page(可选)、max_results(可选)

dattormm_get_components

列出可运行的组件/脚本库

dattormm_run_component

立即在指定设备上运行指定组件——Datto的"Quick Job",破坏性、不可撤销

device_uid(必填)、component_uid(必填)、variables(可选)、confirm(必填,必须为true)

dattormm_get_job_status

查询某次job是否已到达终态

job_uid(必填)

dattormm_get_job_status只能确认job是否"completed",不能确认成败——见Known Gaps。

Quick Start

docker compose up --build

The server starts on http://localhost:8080.

Local (uv)

uv sync
python -m datto_rmm_mcp

Health Check

curl http://localhost:8080/health
# {"status": "ok"}

No credentials are required for the health endpoint.

授权参数说明 (Authentication)

Every request to /mcp must include the following HTTP headers (provided by the MCP caller/gateway):

Header

类型

是否必填

字段描述

X-Datto-Api-Key

string

必填

租户在Datto RMM里生成的API Key。用作OAuth2 password grant的username。

X-Datto-Api-Secret

string

必填

对应的API Secret Key。用作password。

X-Datto-Api-Url

string

必填

该租户账号所在的Datto RMM区域API host(Datto是多区域架构,每个租户账号固定绑在一个区域上,如zinfandel-api.centrastage.net)。裸host或带https://前缀均可,服务端会自动归一化。

Missing any of the three headers returns 401 Unauthorized

认证机制:本服务收到这三个凭据后,自己去调Datto的OAuth2 password grant(POST /auth/oauth/token,client_id/secret是Datto官方公开的固定值public-client/public,租户的API Key/Secret作为username/password),换出真正的bearer token再去调实际接口——不是网关代发token,是这个服务自己做的(因为Datto这套OAuth的client凭据本身就是公开常量,不存在需要网关代管的机密)。Token只在一次请求的生命周期内持有,从不缓存。

Environment Variables

Variable

Default

Description

MCP_HTTP_PORT

8080

Listening port

MCP_HTTP_HOST

0.0.0.0

Listening host

MCP Endpoint

POST http://localhost:8080/mcp

Connect your MCP client with:

  • Transport: http (Streamable HTTP / SSE)

  • Headers: X-Datto-Api-Key, X-Datto-Api-Secret, X-Datto-Api-Url (all required)

测试示例 (Test Example)

curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-Datto-Api-Key: <api-key>" \
  -H "X-Datto-Api-Secret: <api-secret>" \
  -H "X-Datto-Api-Url: zinfandel-api.centrastage.net" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": { "name": "dattormm_get_devices", "arguments": { "max_results": 10 } }
  }'

⚠️ 本仓库为公开仓库,请勿在任何提交的文件中写入真实的API Key/Secret, 上面的占位符仅为示意。

Known Gaps

  • What was actually verified live, and how. This server was written after a feasibility investigation on real customer Datto RMM accounts (read-only credentials, OAuth2 password grant against real tenant_integration records), not from documentation alone:

    • GET /api/v2/account/devices — called for real, returned real device records (1711 devices in one tested account).

    • GET /api/v2/account/components — called for real, returned 250 real components.

    • GET /api/v2/job/{jobUid} — called for real, twice, against two different real job UIDs on two different tenant accounts. Both returned only {id, dateCreated, name, uid, status}no exitCode, stdout, stderr, or success/failure field of any kind.

    • PUT /api/v2/device/{deviceUid}/quickjob (the tool that actually runs a script) has never been executed — by design, the investigation was read-only to stay invisible to customers. Its request/response contract in api_client.py/tools/jobs.py is taken from Datto's own current official documentation (rmm.datto.com/help/en/Content/2SETUP/APIv2.htm), not from a real call. Test this for real (a Datto trial/sandbox account, or an explicit customer-consented dry run) before treating this tool as production-ready.

  • No success/failure or stdout/stderr reporting, on purpose — and this is not a version artifact. Datto's own current API documentation states outright: "It is not possible from within the API to examine the success or failure result of a completed job schedule and access the StdOut/StdErr." Datto's v14.0.0 release notes separately claim "New API endpoints under v2/job now allow retrieval of job results, including StdOut and StdErr" — these two official Datto documents contradict each other, and this investigation could not resolve it: the "new endpoint" the release notes describe was never found (WebSearch results describing it could not be traced to a real, citable page), and there's no way to read a tested account's platform version from the API to know whether it should even have this capability. What's certain: the two real accounts tested, right now, do not return this data via GET /v2/job/{jobUid}. Given this, dattormm_get_job_status's docstring is deliberately conservative — it reports only "reached a terminal state," never success. Do not add a success/failure field to this tool without a fresh, real test proving the new endpoint (whatever it turns out to be) actually exists and works.

  • dattormm_run_component's request shape is desk-verified, not field-verified. {"componentUid": ..., "<variableName>": "<value>", ...} is what Datto's docs say to send; the docs also say a successful response contains a uid usable as dattormm_get_job_status's job_uid — this server is built to that contract, but no real call has confirmed it works as documented, whether variable names are validated, or what a validation error actually looks like from this specific endpoint (blind probing during this investigation got a generic {"detail":"Failed to read request"} for every guessed body shape, including ones matching the eventual documented shape — that response never got more specific no matter what was sent, so it's untested whether the documented shape actually parses).

  • componentUid discovery: dattormm_get_components is the intended way to find one (confirmed working), even though Datto's own docs say to copy it from the UI manually — the API path works in practice, use it.

  • No write/admin endpoints beyond quickjob are wrapped: device claim/unclaim, site management, alert management, and anything else in Datto's API are out of scope for this MCP; PRD-16562 only asked for deployment/execution + inventory.

  • Pagination parameters (page, max) are passed through, not independently verified beyond a max=2 smoke test — the exact upper bound Datto enforces, and whether page is 0- or 1-indexed, weren't confirmed field-by-field.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables integration with Datadog APIs to monitor and retrieve information about monitors, metrics, dashboards, logs, events, and incidents through the Model Context Protocol.
    1,293 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Fleet Device Management for device management, security monitoring, and compliance enforcement through the Model Context Protocol.
    120 PyPI
    5
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with ExoSense IoT devices, sensors, groups, and assets via GraphQL, supporting device management and data queries through a Model Context Protocol interface.
    MIT