dropsuite-mcp
by MSPbotsAI
README.md
# dropsuite-mcp
MCP server for **Dropsuite** (NinjaOne SaaS Backup) — a cloud backup
platform for Microsoft 365 / Google Workspace data. Exposes its reseller
REST API as MCP tools.
> Naming note: MSPbots' own integration is registered as "Dropsuite"
> (`subjectCode=DROPSUITE`); the vendor rebranded to "NinjaOne SaaS Backup"
> after being acquired by NinjaOne, but the API and credential fields are
> unchanged. This MCP covers exactly the 8 GET endpoints MSPbots itself has
> configured — see **Known Gaps** below for why the scope stops there.
## Overview
- Stateless HTTP service. No credentials are ever persisted — each request
supplies its own credentials via headers, used only for the lifetime of
that single request.
- Supports concurrent requests; per-request credential isolation is done via
Python `contextvars`, not a global/shared client instance.
- Entry points: `POST /mcp` (MCP protocol) and `GET /health` (health check).
- Default port: `8080` (configurable via `MCP_HTTP_PORT`).
## Authentication
Dropsuite authenticates with two static tokens (an **Access Token** and a
**Reseller Token**, both found on the "API Settings" page in the Dropsuite/
NinjaOne SaaS Backup dashboard). Since every reseller/partner has its own
site host, the base URL is also per-request rather than fixed.
Per the vendor's own documentation: **"Sub-partners and resellers can use
GET API calls to retrieve information about their organizations and
users"** — write access is restricted to Direct Partners/Distributors, so a
reseller-scoped credential (like MSPbots' own) is inherently read-only.
### HEADER 授权参数说明
| Header | 类型 | 是否必填 | 默认值 | 枚举值 | 字段描述 | Example |
|---|---|---|---|---|---|---|
| `X-Dropsuite-Access-Token` | string | 是 | 无 | 无 | Dropsuite Authentication Token,转发为上游 `X-Access-Token` 请求头 | `a1b2c3d4-e5f6-7890-abcd-ef1234567890` |
| `X-Dropsuite-Reseller-Token` | string | 是 | 无 | 无 | Dropsuite Reseller Token,转发为上游 `X-Reseller-Token` 请求头 | `12345678-90ab-cdef-1234-567890abcdef` |
| `X-Dropsuite-Site` | string | 是 | 无 | 无 | 该 reseller 的 API 主机地址(每个 reseller 独立) | `https://dropsuite.us` |
Missing any of the three headers returns `401`:
```json
{
"error": "Missing credentials",
"message": "This server requires the X-Dropsuite-Access-Token, X-Dropsuite-Reseller-Token, and X-Dropsuite-Site headers",
"required_headers": ["X-Dropsuite-Access-Token", "X-Dropsuite-Reseller-Token", "X-Dropsuite-Site"],
"optional_headers": []
}
```
## Environment Variables
| Variable | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `MCP_HTTP_PORT` | int | 否 | `8080` | HTTP 监听端口 |
| `MCP_HTTP_HOST` | string | 否 | `0.0.0.0` | HTTP 监听地址 |
(No `*_BASE_URL` env var — the site host is per-reseller and always
supplied via the `X-Dropsuite-Site` header, never a fixed default.)
## MCP Endpoint
- `POST /mcp` — MCP protocol (streamable HTTP transport)
- `GET /health` — health check, returns `{"status": "ok"}` (pure local probe, does not depend on the upstream Dropsuite API)
## Tool List
All 8 tools are plain `GET` calls with **no required parameters** — this
matches exactly how MSPbots itself calls this integration today. Each tool
accepts an optional `extra_params` pass-through dict for any additional
query-string filters, since Dropsuite's full filter reference is only
available through a partner-portal-gated PDF/Browsable API (see
**Known Gaps**).
| Tool | 功能 | 参数 |
|---|---|---|
| `dropsuite_get_accounts` | 列出该 reseller 下的备份账户(客户/组织) | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_users` | 列出被备份的邮箱/用户 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_contacts` | 列出被备份的联系人 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_calendars` | 列出被备份的日历 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_tasks` | 列出被备份的任务 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_onedrives` | 列出被备份的 OneDrive 账户 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_sharepoints_domains` | 列出被备份的 SharePoint 域 | `extra_params: dict[str,str] \| None` |
| `dropsuite_get_teams_and_groups_domains` | 列出被备份的 Teams/Groups 域 | `extra_params: dict[str,str] \| None` |
## 测试示例
```bash
# Health check
curl -s http://localhost:8080/health
# Call a tool via the MCP protocol (streamable HTTP) — requires an
# initialize handshake first per the MCP spec; abbreviated example below
# shows the tool-call request body only:
curl -s -X POST http://localhost:8080/mcp \
-H "X-Dropsuite-Access-Token: <your-access-token>" \
-H "X-Dropsuite-Reseller-Token: <your-reseller-token>" \
-H "X-Dropsuite-Site: https://dropsuite.us" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: <session-id-from-initialize>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "dropsuite_get_accounts",
"arguments": {}
}
}'
```
**Live-verified** (2026-07-29) against a real reseller test account: 6 of
the 8 tools (`get_accounts`, `get_users`, `get_contacts`, `get_calendars`,
`get_tasks`, `get_onedrives`) returned `200` with real data (an empty `[]`
list, since this test reseller currently has no linked accounts) called
through the actual running MCP server. See Known Gaps for the other 2.
## API Reference
- Vendor overview: https://help.dropsuite.com/hc/en-us/articles/20422080552855-API-Settings
- The full method/parameter reference ("REST API - for subreseller ver
1.00.pdf") is attached to a NinjaOne KB article
(https://www.ninjaone.com/docs/backup/saas-backup/getting-started/rest-api-reference/)
that redirects to a NinjaOne account login — not accessible without a
portal login, only an API token. The vendor's own "Browsable API" (a
live, self-documenting endpoint list) is likewise only reachable from
inside an authenticated Dropsuite/NinjaOne SaaS Backup dashboard session.
## Known Gaps
- **Scope is exactly MSPbots' 8 configured endpoints, not the vendor's full
API surface** — same situation as `bvoip-mcp`/`contactscience-mcp`
earlier in this program: the vendor's fuller API reference is gated
behind a portal login this session doesn't have, so there was no larger
accessible spec to weigh a broader scope against. The vendor's own docs
additionally confirm resellers are restricted to GET calls only, so a
reseller credential (like MSPbots' own) couldn't reach write endpoints
even if they were documented.
- **`dropsuite_get_sharepoints_domains` and
`dropsuite_get_teams_and_groups_domains` returned a generic vendor-side
`500 {"errors":{"System":["Internal Server Error"]}}`** in live testing
against the provided test account, while the other 6 endpoints returned
`200` (with empty `[]` results, since the test reseller has no linked
accounts). This looks like a vendor-side issue with enumerating
SharePoint/Teams domains when there's no linked data to return, rather
than a request-format problem on this server's side — both tools are
implemented identically to the other 6 working ones. Not independently
confirmed against an account that actually has SharePoint/Teams-enabled
backups.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues