ninjaone-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ninjaone-mcpWhich devices are offline for Acme Corp?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ninjaone-mcp
NinjaOne RMM MCP server — exposes NinjaOne's Public API v2 (Organizations, Devices, Alerts, Ticketing, Automation/Scripting, Jobs) as MCP tools.
What is NinjaOne / when would an agent use this
NinjaOne is an RMM (remote monitoring and management) platform MSPs use to manage clients' IT fleets. An agent should reach for this MCP for requests like:
"How many devices does this customer have, and which are offline?" →
ninjaone_get_organization_devices/ninjaone_get_devices"Any active alerts for this device/org?" →
ninjaone_get_device_alerts/ninjaone_get_alerts"What tickets are open on the support board?" →
ninjaone_get_ticket_boardsthenninjaone_get_tickets"Run disk cleanup on this device and tell me when it's done" →
ninjaone_get_device_scripting_optionsto confirm what's runnable,ninjaone_run_script_on_device, thenninjaone_get_device_active_jobsto watch it finish"What automation scripts do we have available?" →
ninjaone_get_automation_scripts
Overview
This server implements the Model Context Protocol (Streamable HTTP transport) with 23 tools across 5 groups, following the MSPbots Vendor MCP Service SOP: stateless, no stored credentials, per-request header authentication.
This was built starting from the community wyre-technology/ninjaone-mcp project's tool surface (organizations/devices/alerts/tickets, reimplemented here directly against NinjaOne's REST API rather than its Node SDK) and extends it with 5 automation/scripting/jobs tools pulled from NinjaOne's own OpenAPI 3.0.1 spec — every endpoint below was checked against a real NinjaOne API spec, not guessed or copied from a secondary source.
The gateway does the OAuth2 exchange, not this server. NinjaOne authenticates via OAuth2 (client_credentials for a machine identity, refresh_token for a user identity — see below); this server takes only the already-exchanged bearer access token via header and calls NinjaOne's REST API directly with it. It never sees a client_id/client_secret/refresh_token, never talks to /oauth/token, and never caches anything — whoever operates the gateway is responsible for minting and refreshing tokens before they expire (NinjaOne's access tokens last 1 hour).
One tool needs a second identity. ninjaone_run_script_on_device is believed to be rejected by NinjaOne when called with a machine (API Services app) token regardless of scope, because NinjaOne ties script execution to a real user for its audit trail — this is the working hypothesis behind the design below, not yet independently confirmed against a real device/script by this repo. That tool alone takes a second, optional bearer token — one the gateway exchanged via the refresh_token grant against a NinjaOne "Web Application" app (which requires a one-time human browser authorization to obtain the refresh token in the first place). The other 22 tools are unaffected either way.
Quick Start
Docker (recommended)
docker compose up --buildThe server starts on http://localhost:8080.
Local (uv)
uv sync
python -m ninjaone_mcpHealth 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:
Header | 类型 | 是否必填 | 默认值 | 枚举值 | 字段描述 | Example |
| string | 必填 | 无 | 无(自由文本) | 已经换好的 NinjaOne OAuth2 bearer access token(网关侧用 |
|
| string | 可选 |
|
| NinjaOne 部署区域,决定实际请求的 base URL。 |
|
| string | 可选(仅 | 无 | 无(自由文本) | 已经换好的 NinjaOne OAuth2 bearer access token,但是网关用 |
|
Missing X-Ninja-Token returns 401 Unauthorized. Missing the optional X-Ninja-User-Token only affects ninjaone_run_script_on_device (returns a not_configured error) — every other tool works fine without it.
Environment Variables
Variable | Default | Description |
|
| Listening port |
|
| Listening host |
There is no base-URL env var — the base URL is derived per-request from the X-Ninja-Region header (see config.py's region table).
MCP Endpoint
POST http://localhost:8080/mcpConnect your MCP client with:
Transport:
http(Streamable HTTP)Headers:
X-Ninja-Token(required, an already-exchanged bearer access token),X-Ninja-Region(optional),X-Ninja-User-Token(optional, only forninjaone_run_script_on_device)
Tool List
Tool | 功能 | 参数 |
| 列出所有客户组织 |
|
| 按 ID 查单个组织详情 |
|
| 创建新组织 |
|
| 列出组织下的站点(location) |
|
| 列出组织下的设备 |
|
| 全局列出设备,支持 |
|
| 按 ID 查单个设备详情 |
|
| 查单个设备的活跃告警 |
|
| 查设备活动日志 |
|
| 查设备的 Windows 服务列表 |
|
| 重启设备(破坏性操作) |
|
| 全局列出活跃告警 |
|
| 重置/关闭一条告警(破坏性操作) |
|
| 列出所有工单看板 | 无 |
| 按看板列出工单,支持状态/组织/设备过滤 |
|
| 创建新工单 |
|
| 更新工单字段和/或添加评论 |
|
| 查工单日志(描述/评论/变更历史) |
|
| 列出可用的自动化脚本 | 无 |
| 查设备上可运行的脚本/内置动作/凭据选项 |
|
| 在设备上运行脚本或内置动作(破坏性操作,需要 |
|
| 全局列出正在运行/排队的任务 |
|
| 查单个设备正在运行/排队的任务 |
|
测试示例 (Test Example)
List ticket boards:
{
"method": "tools/call",
"params": { "name": "ninjaone_get_ticket_boards", "arguments": {} }
}Equivalent curl against the running server (streamable HTTP MCP endpoint):
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "X-Ninja-Token: <access_token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "ninjaone_get_ticket_boards", "arguments": {} }
}'Running a script on a device:
{
"method": "tools/call",
"params": {
"name": "ninjaone_run_script_on_device",
"arguments": { "device_id": 123, "type": "SCRIPT", "script_id": 456 }
}
}API Reference
Documentation:
https://app.ninjarmm.com/apidocs-beta/core-resources(per-region equivalents foreu/oc/ca/us2/fed)Auth: OAuth2 (the gateway's job, not this server's) —
client_credentialsgrant for the machine identity,refresh_tokengrant for the user identity, both atPOST /oauth/token; scopes for the machine identity:monitoring,management,control
Known Gaps / Implementation Notes
Endpoint provenance: 4 of the 5 automation/scripting/jobs endpoints (
requestScriptingOptions,runScriptOnDevice,getActiveJobs,getDeviceActiveJobs) were cross-checked against an independently obtained copy of NinjaOne's OpenAPI spec.getAutomationScriptswasn't present in that copy (it's newer than that spec revision) — its exact/apipath placement is inferred from the other 4's confirmed pattern, not independently verified. See the comment at the top oftools/automation.py.ninjaone_get_ticketsfilters client-side: NinjaOne's board-run endpoint's request schema definesfilters/searchCriteriaparams, but the community wyre-technology project reports these 400 in practice — this tool always requests an unfiltered page and filtersstatus/organization_id/device_idclient-side instead.No single-ticket-get or standalone add-comment endpoint: NinjaOne's ticketing API doesn't expose a
GET /ticketing/ticket/{id}— to look up one ticket, page throughninjaone_get_ticketson its board. Adding a comment isn't a separate endpoint either — it's folded intoninjaone_update_ticket'scomment/comment_publicparams, alongside aPUTon the ticket itself.ninjaone_get_devices'sdffilter can be silently dropped by NinjaOne when scoping by organization (a known issue in the community project) — preferninjaone_get_organization_devicesfor an org-scoped device list.Architecture history: this server originally did its own OAuth2 exchange (took
client_id/client_secretand called/oauth/tokenitself, per-request, never caching the result). That's since moved to the gateway — this server now only ever takes an already-exchanged bearer token (X-Ninja-Token) — matching the pattern MSPbots' gateway already uses forms-graph-mcp/connectwise-asio-mcp. The gateway is responsible for the OAuth2 exchange and for refreshing tokens before their 1-hour expiry; if it doesn't,X-Ninja-Token/X-Ninja-User-Tokenrequests will 401 against real NinjaOne endpoints (mapped tounauthorizedhere), not against this server's own logic.ninjaone_run_script_on_deviceuses a second, user-context token (X-Ninja-User-Token, gateway-exchanged via the refresh_token grant against a Web Application app) instead of the machine token every other tool uses — see the Overview section above for why. This is unverified against a real device/script so far; only the plumbing (missing-token error path, and a live call with a real machine-identity token reaching NinjaOne's real API and getting real data) has been checked.Verified against a live NinjaOne account:
tools/listreturns all 23 tools with clean schemas,pytest(17 tests) passes, and a realninjaone_get_organizationscall using a real, already-exchanged bearer token (viaX-Ninja-Token) returned real organization data.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/MSPbotsAI/ninjaone-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server