Desktop Management MCP Server
MCP server for managing devices via JAMF Pro and Microsoft Intune APIs, enabling AI assistants to query and control device management tasks.
README
Desktop Management MCP Server
Standalone Model Context Protocol (MCP) servers for JAMF Pro and Microsoft Intune. AI assistants (Claude Code, Gemini CLI, OpenCode, etc.) connect over HTTP and call device-management tools.
Architecture
MCP Client ──HTTP──▶ jamf-server (port 3001) ──▶ JAMF Pro REST API
MCP Client ──HTTP──▶ intune-server (port 3002) ──▶ Microsoft Graph API
Each server is a stateless Express app using @modelcontextprotocol/sdk. Every POST to /mcp creates a fresh StreamableHTTPServerTransport. Secrets are injected at runtime by Bitwarden Secrets Manager — no credentials are stored in the repo.
Prerequisites
- Node.js 24+
- BWS CLI (
bwsin PATH) - A Bitwarden Secrets Manager project with the secrets listed in
bws-secrets.map - JAMF Pro API client credentials (OAuth2)
- Azure AD app registration with Microsoft Graph permissions (for Intune)
Quick Start
# Install dependencies and build
npm install && npm run build
# Set your BWS machine account access token
export BWS_ACCESS_TOKEN="<your-token>"
# Start whichever server(s) you need
./start-jamf.sh # JAMF MCP on http://localhost:3001/mcp
./start-intune.sh # Intune MCP on http://localhost:3002/mcp
See bws-secrets.map for the secret names to create in your BWS project.
Environment Variables
Injected by bws run from your BWS project (see bws-secrets.map):
JAMF Pro:
JAMF_URL— e.g.https://yourorg.jamfcloud.comJAMF_CLIENT_ID,JAMF_CLIENT_SECRET
Microsoft Intune:
AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRET
Azure AD Graph Permissions
The Intune app registration needs these Application permissions (with admin consent):
Device.Read.AllDeviceManagementManagedDevices.Read.AllDeviceManagementApps.Read.AllDeviceManagementConfiguration.Read.AllGroup.Read.AllUser.Read.All
Client Configuration
Claude Code (~/.claude/claude_desktop_config.json or MCP settings)
{
"mcpServers": {
"jamf": {
"type": "http",
"url": "http://localhost:3001/mcp"
},
"intune": {
"type": "http",
"url": "http://localhost:3002/mcp"
}
}
}
Gemini CLI (~/.gemini/settings.json)
{
"mcpServers": {
"jamf": { "httpUrl": "http://localhost:3001/mcp" },
"intune": { "httpUrl": "http://localhost:3002/mcp" }
}
}
OpenCode (~/.config/opencode/opencode.json)
{
"mcp": {
"jamf": { "type": "remote", "url": "http://localhost:3001/mcp", "enabled": true },
"intune": { "type": "remote", "url": "http://localhost:3002/mcp", "enabled": true }
}
}
MCP Tools Reference
JAMF Pro Tools
| Tool | Description | Parameters |
|---|---|---|
jamf_get_computer |
Computer details by name | computerName |
jamf_get_computer_by_serial |
Computer details by serial number | serialNumber |
jamf_get_computers_by_user |
Macs by username / name / email | userIdentifier |
jamf_get_mobile_device |
Mobile device details by name | deviceName |
jamf_list_smart_groups |
List smart groups | type ("computer" or "mobile_device") |
jamf_get_smart_group_members |
Members of a smart group | groupId |
jamf_list_sites |
All JAMF sites | — |
jamf_list_scripts |
Scripts (with optional filter/pagination) | name?, page?, pageSize? |
jamf_list_packages |
Packages (with optional filter/pagination) | name?, page?, pageSize? |
jamf_list_inventory_preload |
Inventory preload records | page?, pageSize? |
jamf_list_prestage_configs |
Computer prestage assignments | — |
jamf_list_static_groups |
Static computer groups | — |
jamf_list_policies |
Policies list | — |
jamf_get_policy |
Policy details | policyId |
jamf_list_configuration_profiles |
Configuration profiles | — |
jamf_list_patch_policies |
Patch policies | — |
jamf_list_categories |
Categories | — |
jamf_list_departments |
Departments | — |
jamf_get_filevault_status |
FileVault encryption status | computerName |
jamf_send_mdm_command |
Send MDM command to a device | deviceId, command |
jamf_update_computer |
Update computer inventory fields | computerId, fields |
jamf_flush_mdm_commands |
Flush pending MDM commands | deviceId |
Microsoft Intune Tools
| Tool | Description | Parameters |
|---|---|---|
intune_get_autopilot_status |
Autopilot profile & status | serialNumber?, deviceName? |
intune_get_device_by_name |
Managed device by name | deviceName |
intune_get_device_by_serial |
Managed device by serial number | serialNumber |
intune_get_devices_by_user |
All devices for a user | userIdentifier |
intune_get_device_groups |
Device group memberships | deviceName?, deviceId?, serialNumber? |
intune_get_device_apps |
Detected & assigned apps | deviceName?, deviceId?, serialNumber? |
intune_list_configuration_policies |
Configuration policies (classic + settings catalog) | policyName?, platform? |
intune_troubleshoot_device_policies |
Device-level policy deployment diagnostics | deviceName?, deviceId?, serialNumber? |
intune_get_policy_assignments |
Assignment targets for a policy | policyId, source? |
intune_troubleshoot_policy |
Correlates policy assignment + device state | policyId, deviceName?, deviceId?, serialNumber?, source? |
intune_list_app_deployments |
Intune app deployments | appName?, publisher?, platform? |
intune_get_app_assignments |
Assignment targets for an app | appId |
intune_troubleshoot_app |
Correlates app assignment + device app status | appId, deviceName?, deviceId?, serialNumber? |
Running Tests
Tests are live integration tests against a real JAMF Pro instance:
export BWS_ACCESS_TOKEN="<your-token>"
bws run --access-token "$BWS_ACCESS_TOKEN" -- \
TEST_COMPUTER_NAME="<name>" \
TEST_COMPUTER_SERIAL="<serial>" \
TEST_USER_EMAIL="<email>" \
npm test
Add JAMF_TEST_WRITE=1 to enable destructive write tests (MDM commands, inventory updates).
Project Structure
├── src/
│ ├── mcp/
│ │ ├── jamf-server.ts # JAMF standalone MCP server (port 3001)
│ │ └── intune-server.ts # Intune standalone MCP server (port 3002)
│ ├── jamf/
│ │ └── jamf-api.ts # JAMF Pro REST + Classic API client
│ ├── intune/
│ │ └── graph-api.ts # Microsoft Graph / Intune client
│ └── utils/
│ └── logger.ts # Output formatting helpers
├── start-jamf.sh # BWS-wrapped launcher for JAMF server
├── start-intune.sh # BWS-wrapped launcher for Intune server
└── bws-secrets.map # Required BWS secret names and descriptions
Additional Resources
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.