MCP server
Let an AI assistant look up your device fleet and policies, and optionally lock a device or send it a message, using a Nomid API key.
What the MCP server does
The Model Context Protocol (MCP) is an open standard that lets AI assistants call tools in other systems. The Nomid MCP server lets an assistant such as Claude Code, Codex or Cursor answer questions about your fleet in plain language, for example how many devices use a policy or which devices have not been seen since a given date, without anyone opening the portal. A key with an extra permission can also lock a device, start or stop lost mode, or send a message to one device.
Endpoint and transport
POST https://api.nomid.tech/emm/api/mcp The server uses MCP Streamable HTTP in stateless mode. Every JSON-RPC call is an independent HTTPS request, so there is no session to keep alive and no event stream to hold open.
Send your API key as a bearer token or in the X-API-Key header. Most MCP clients only support the bearer form. A missing, invalid or expired key returns 401.
The key fixes the company. No tool accepts a tenant or company argument, and a key can only see its own company's devices and policies.
Create an API key
The MCP server uses the same API keys as the REST API. Create a dedicated key for each assistant so you can revoke it without affecting other integrations.
- 1
In the Nomid portal, open Settings and select the API tab.
- 2
Click Create API Key and enter a name that identifies the assistant, for example Claude Code read-only.
- 3
Choose the permissions described below. If you want the key to stop working on a given date, set an expiration date.
- 4
Copy the key when it is shown. It is displayed only once.
Read-only key
Enable the device and policy read permissions (DEVICES_READ and POLICIES_READ). This is enough for every read tool and is the recommended starting point.
Command key
To let the assistant lock a device, use lost mode or send a message, also enable the device command permission (DEVICES_COMMAND). A command key must also have DEVICES_READ. Only a portal user who is allowed to send device commands and has access to all policies can create a key with this permission.
Connect your assistant
Store the key in an environment variable named NOMID_API_KEY and never commit it to a repository. The URL in each example is the production endpoint.
Claude Code
Run this once in your shell. Your shell expands the variable when you run the command, and Claude Code then stores the resulting key in plain text in its own configuration file. Use a dedicated read-only key for this.
claude mcp add --transport http nomid-mdm https://api.nomid.tech/emm/api/mcp \
--header "Authorization: Bearer ${NOMID_API_KEY}" Codex
Add this to ~/.codex/config.toml. Codex reads the token from the named environment variable. It does not expand variables written inside the file.
[mcp_servers.nomid]
url = "https://api.nomid.tech/emm/api/mcp"
bearer_token_env_var = "NOMID_API_KEY" Cursor
Add this to .cursor/mcp.json. Cursor expands environment variables in the header value, as shown.
{
"mcpServers": {
"nomid-mdm": {
"url": "https://api.nomid.tech/emm/api/mcp",
"headers": {
"Authorization": "Bearer ${env:NOMID_API_KEY}"
}
}
}
} Other clients
Any MCP client that supports Streamable HTTP servers with custom headers can connect with the endpoint URL and an Authorization: Bearer header.
Available tools
Every tool is scoped to the key's company. A device is identified by its assetId, which is the pathName returned by search_devices and get_device. A policy is identified by its policyId, which is the pathName returned by list_policies.
Read tools
Read tools return the same data as the matching REST endpoints and never change anything.
| Tool | Required permission | What it does |
|---|---|---|
| search_devices | DEVICES_READ | Search devices with optional status, policy and lastSeenBefore filters. Results are paged: page starts at 0, and size defaults to 10 with a maximum of 25. |
| count_devices | DEVICES_READ | Count devices with the same optional status, policy and lastSeenBefore filters. |
| get_device | DEVICES_READ | Full detail for one device, including battery level, hardware memory and storage totals, and policy non-compliance reasons. |
| get_fleet_summary | DEVICES_READ | Aggregate fleet numbers: total devices, a breakdown by status and a security posture summary. It never returns a device list. |
| list_device_commands | DEVICES_READ | The most recent commands sent to a device, newest first, with type, status, timestamps and a short outcome code. limit defaults to 20 and is capped at 50. Command payloads are never returned. |
| list_policies | POLICIES_READ | List policies. Returns an overview only, without configuration detail. |
| get_policy | POLICIES_READ | Overview of one policy. |
Command tools
Command tools act on exactly one physical device per call. There is no bulk option. Each tool needs DEVICES_COMMAND.
| Tool | Required permission | What it does |
|---|---|---|
| lock_device | DEVICES_COMMAND + DEVICES_READ | Lock the device screen immediately. The user can unlock it normally. |
| start_lost_mode | DEVICES_COMMAND + DEVICES_READ | Lock the device and show a message, with optional contact details, on its lock screen. message is required and can be up to 4096 characters. phoneNumber, email, streetAddress and organization are optional. |
| stop_lost_mode | DEVICES_COMMAND + DEVICES_READ | End lost mode. Nothing happens, and no error is returned, if the device was not in lost mode. |
| send_device_message | DEVICES_COMMAND + DEVICES_READ | Show a plain-text push notification on the device. title (up to 60 characters) and body (up to 500 characters) are both required. Sending the same message again shows a second notification. |
Which devices can receive commands
- Only enrolled devices can receive commands (status ACTIVE, INACTIVE or SYNCHRONIZING). Deleted, reprovisioned and unenrolled assets are rejected.
- Lock and lost mode work only on Android Management (Google-managed) devices. Other device types are rejected.
- A message is a push notification to the Nomid agent on the device, so the device needs a registered push token.
- An asset that belongs to another company behaves exactly like an asset that does not exist.
Not available through MCP or the REST API: reboot, wipe or factory reset, remote access, enrollment tokens, policy changes and resetting the screen lock.
Safety and audit
A command changes something a person is holding. Treat each one as an action that needs a human decision.
- Always confirm with the user before any command. The tool descriptions ask the model to do this, but nothing on the server enforces it. Keep your client's per-tool approval turned on for command tools instead of auto-approving them.
- Never resend a command after an unconfirmed result. If the outcome is unknown, check list_device_commands after the device has had time to respond, and ask the user before sending again. A resend can duplicate a command that was already delivered, and a message shows a second notification.
- A result that says the command was not sent is safe to retry. The command never left Nomid.
- Every command is recorded in the device's command history in the Nomid portal and attributed to the API key that sent it, not to a person. The entry shows api-key, the key id and the key prefix. The history that list_device_commands returns contains only type, status, timestamps and outcome, not who sent the command.
- If a computer or configuration file is compromised, revoke the key from Settings, API. Revoked keys cannot be restored.
Rate limits
Limits are counted per API key in fixed one-minute windows. When you exceed the MCP request limit, the server answers HTTP 429 Too Many Requests with a Retry-After header that gives the seconds until the window resets.
| Limit | Allowed |
|---|---|
| All MCP requests, every tool | 60 per minute per key |
| Device commands, REST and MCP combined | 10 per minute per key |
A command tool call counts against both limits. When a command tool call exceeds the command limit, the server returns a tool error instead of an HTTP 429. It is a normal response flagged as an error, and its text says how many seconds to wait. The REST read endpoints do not use the MCP limit.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| 401 Unauthorized | The key is missing, invalid, expired or revoked. Check that the client sends Authorization: Bearer followed by the key, and that the environment variable was set when you ran the setup command. |
| Tool error saying the key lacks the required permission (HTTP 403 on the REST API) | The key was created without the permission this tool needs. Create a key that has it. Command tools need DEVICES_COMMAND and DEVICES_READ. |
| HTTP 429 Too Many Requests, or a tool error that says the rate limit was exceeded | You exceeded a rate limit. For an HTTP 429, wait the number of seconds in the Retry-After header. For a tool error, wait the number of seconds its message gives. |
| Tool error about a device that was not found or cannot take the command | Use the pathName from search_devices as assetId. Check that the device is enrolled and, for lock and lost mode, Google-managed. |
| Tool error saying the outcome is unknown | Do not resend. Check list_device_commands once the device has had time to respond, and ask the user before sending again. |
| The assistant does not list any Nomid tools | Confirm that your client supports Streamable HTTP servers with custom headers, and that the URL matches the endpoint above exactly. |