Microsoft Intune Devices Tool
Read Microsoft Intune enrolled devices, compliance state, configuration profiles and detected apps. For device compliance reporting, patch and sync-age checks, and unapproved-software sweeps.
Tool ID
msgraph-intune-devices
Credential Required
Yes — the shared msgraph credential, owned by the msgraph connector. Configure the tenant
once and all nine tools use it; rotating the client secret is one edit rather than nine.
It is a server-managed OAuth credential: InTouch mints and refreshes the access token itself and
the connector never sees the secret. For unattended work set grant_type to client_credentials
(the app-only grant) — an app-only token belongs to the application, so a 06:00 schedule does not
run as a person, see only what that person can see, and stop working the day they leave.
Credential Properties
| Property | Type | Default | Description |
|---|---|---|---|
client_id |
string | — | Required. The Entra app registration's Application (client) ID. |
client_secret |
string | — | Required for app-only. The secret's Value, not its Secret ID. |
token_url |
string | — | Required. https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token |
grant_type |
string | (blank) | client_credentials for unattended app-only use. Blank means the user-delegated refresh-token flow. |
scope |
string | — | https://graph.microsoft.com/.default — resolves to whatever application permissions an admin has consented to. |
access_token |
string | — | Machine-managed. Leave empty; the server mints and persists it. |
refresh_token |
string | — | Delegated credentials only. Not used by the app-only grant. |
expires_at |
string | 0 |
Machine-managed expiry, epoch seconds. |
Entra setup
- https://entra.microsoft.com → App registrations → your app → API permissions.
- Add a permission → Microsoft Graph → Application permissions — not Delegated. Picking Delegated is the most common failure: it consents cleanly and then 403s at runtime.
- Tick the permissions listed under Permissions below, then Grant admin consent. The Status column must read Granted.
- Permissions live in the token, not the portal. A token minted before the grant carries the old
claims for about an hour — blank
access_tokento force a fresh mint.
Permissions
DeviceManagementManagedDevices.Read.All and DeviceManagementConfiguration.Read.All.
Operations
1. list_managed_devices — List enrolled devices
Every device Intune manages, with compliance state and last sync time. Calls GET /deviceManagement/managedDevices.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. list_managed_devices |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
2. get_managed_device — Get one device
One managed device by id. Calls GET /deviceManagement/managedDevices/{id}.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. get_managed_device |
id |
string | — | Required. Intune managed-device id. Required by get_managed_device and get_device_compliance_states. |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
3. get_device_compliance_states — Get a device's compliance verdicts
Why one device passes or fails each policy — the "why is this non-compliant" answer. Calls GET /deviceManagement/managedDevices/{id}/deviceCompliancePolicyStates.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. get_device_compliance_states |
id |
string | — | Required. Intune managed-device id. Required by get_managed_device and get_device_compliance_states. |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
4. list_compliance_policies — List compliance policies
The compliance policies defined in the tenant. Calls GET /deviceManagement/deviceCompliancePolicies.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. list_compliance_policies |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
5. list_device_configurations — List configuration profiles
The device configuration profiles defined in the tenant. Calls GET /deviceManagement/deviceConfigurations.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. list_device_configurations |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
6. list_detected_apps — List detected apps
Software inventory as Intune observed it — the basis of an unapproved-software sweep. Calls GET /deviceManagement/detectedApps.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
operation |
string | — | Required. list_detected_apps |
query |
string | — | Optional. OData query params as a JSON object string. Filter server-side on a large estate — {"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}. |
Published Outputs:
- result — the JSON response body
- status — HTTP status code
Paging
Graph answers a collection with 100 rows and an @odata.nextLink, so a naive listing returns a
fraction of a large tenant with HTTP 200 and no sign anything is missing. This connector follows
the continuation link until the collection is exhausted. If it stops at the page cap it says so —
the result carries complete: false with a warning, and the step returns WARNING rather than
SUCCESS. A page cap must never look like the end of the data.
Notes — two things that are not bugs
Intune is a separately licensed product. Graph is the transport, not the entitlement. On a tenant without Intune — Plan 1, or the EMS / Microsoft 365 E3 and E5 bundles that include it — these endpoints answer 403 no matter how much consent is granted. Check the licence before debugging the connector.
An Entra device is not an Intune device. The directory registers devices; Intune enrols and manages them. A laptop can exist in Entra and be absent here, so "every device we own" answered from this connector alone is an undercount — which is exactly what a compliance report must not be.
The tool keeps its msgraph- prefix because that string is the credential family key the anchor
invites by name; the display name and this README carry the correction.
Filter server-side on any real estate:
{"$filter": "complianceState eq 'noncompliant'", "$select": "deviceName,userPrincipalName,operatingSystem,complianceState,lastSyncDateTime"}.
Self-Contained JAR
The jar bundles all runtime dependencies; only intouch-tool-api is provided by the server.
Publishes
The keys a later task may reference as {{taskName.key}}. Referencing anything not listed here resolves to nothing at run time.
completeoperationresultstatuswarning