abm-mcp
A read-only MCP server that provides tools to list and read devices, MDM servers, blueprints, configurations, apps, packages, users, and other resources from Apple Business Manager and Apple School Manager.
README
Apple Business Manager MCP server
A FastMCP server that exposes the Apple School & Business Manager API as MCP tools. It is strictly read-only — it lists and reads devices, MDM servers, blueprints, configurations, apps, packages, users, user groups, organizational units, audit events, AppleCare coverage, and assignment/activity status. It never creates, updates, deletes, or reassigns anything.
Read coverage of the Apple Business API is complete (34 tools). The write operations (assign/unassign devices; create/update/delete for blueprints, configurations, MDM servers; blueprint membership changes) are intentionally not implemented.
Works with both Apple Business Manager (business.api) and Apple School
Manager (school.api).
Tools
Read — devices, MDM services, activities (always available):
| Tool | What it does |
|---|---|
list_mdm_servers |
List all MDM servers in the org (id, name, type, timestamps). |
get_mdm_server |
Details for one MDM server by id. |
list_devices_for_mdm_server |
Device ids/serials assigned to a given MDM server (bulk-friendly). |
list_org_devices |
Devices enrolled via Automated Device Enrollment. |
get_org_device |
Full details for one device by serial number. |
get_device_assigned_server |
Which MDM server a device is assigned to (full info). |
get_device_assigned_server_id |
Assigned MDM server id (linkage only). |
get_device_applecare_coverage |
AppleCare coverage for one device. |
get_device_activity |
Status of a device-management activity by id. |
list_mdm_enrolled_devices |
Devices enrolled in Apple device management services (mdmDevices). |
get_mdm_enrolled_device_details |
Details for one MDM-enrolled device. |
Read — blueprints (always available):
| Tool | What it does |
|---|---|
list_blueprints |
List device blueprints in the org. |
get_blueprint |
Details for one blueprint by id. |
list_blueprint_device_ids |
Org-device ids assigned to a blueprint. |
list_blueprint_app_ids |
App ids attached to a blueprint. |
list_blueprint_configuration_ids |
Configuration ids attached to a blueprint. |
list_blueprint_package_ids |
Package ids attached to a blueprint. |
list_blueprint_user_group_ids |
User-group ids attached to a blueprint. |
list_blueprint_user_ids |
User ids attached to a blueprint. |
Read — configurations, apps, packages (always available):
| Tool | What it does |
|---|---|
list_configurations |
List MDM configurations in the org. |
get_configuration |
Details for one configuration by id. |
list_apps |
List apps available in the org (Apps and Books / VPP). |
get_app |
Details for one app by id. |
list_packages |
List packages in the org. |
get_package |
Details for one package by id. |
Read — users, user groups, organizational units, audit (always available):
| Tool | What it does |
|---|---|
list_users |
List managed Apple Account users in the org. |
get_user |
Details for one user by id. |
list_user_groups |
List user groups in the org. |
get_user_group |
Details for one user group by id. |
list_user_group_user_ids |
User ids belonging to a user group. |
list_organizational_units |
List organizational units in the org. |
get_organizational_unit |
Details for one organizational unit by id. |
list_organizational_unit_user_ids |
User ids belonging to an organizational unit. |
get_audit_events |
Org audit events in a time window (start/end timestamps required). |
1. Create API credentials in ABM/ASM
- Sign in to Apple Business (or School) Manager.
- Click your name (bottom-left) → Preferences → API.
- Click + to create an API account, give it a label, Create.
- Click Generate Private Key — the
.pemdownloads once. Keep it safe; it cannot be re-downloaded (you can revoke and regenerate). - Click Manage on the account to copy the Client ID and Key ID.
2. Install
cd abm-mcp
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
3. Configure credentials
The server reads four settings from environment variables:
ABM_CLIENT_ID=BUSINESSAPI.9703f56c-....
ABM_KEY_ID=d136aa66-0c3b-....
ABM_PRIVATE_KEY_PATH=/absolute/path/to/private-key.pem
ABM_SCOPE=business.api # or school.api
There are two ways to supply them — pick one, you don't need both:
-
envblock in Claude Desktop's config — recommended when running inside the Claude Desktop app (see step 5, Option B). Claude Desktop injects these when it launches the server, so no.envfile is needed. -
.envfile — used when you run the server yourself from a terminal (python server.py) or with the one-command installer (step 5, Option A). Copy the template and fill it in:cp .env.example .envThe server loads
.envautomatically (viapython-dotenv).
You can inline the key with ABM_PRIVATE_KEY_PEM instead of a path in either
case. Whichever file holds your credentials, keep it readable only by your own
user account.
Credential field details
Copy the three identifiers from the ABM/ASM API account's Manage screen using the copy icons (avoid retyping — the Client ID wraps across lines in the UI and is easy to mistype):
| Setting | Where it comes from | Format / example |
|---|---|---|
ABM_CLIENT_ID |
Manage screen → "Client ID" | Starts with BUSINESSAPI. (or SCHOOLAPI.) + a UUID, ~48 chars, e.g. BUSINESSAPI.9703f56c-10ce-4876-8f59-e78e5e23a152 |
ABM_KEY_ID |
Manage screen → "Key ID" | A UUID, 36 chars, e.g. d136aa66-0c3b-4bd4-9892-c20e8db024ab |
ABM_PRIVATE_KEY_PATH |
The .pem downloaded when the key was generated |
Absolute path to a PKCS#8 EC P-256 key (see below) |
ABM_SCOPE |
Must match the client type | business.api for a BUSINESSAPI. client; school.api for SCHOOLAPI. |
The key must be an EC P-256 key (Apple's API signs with ES256). The curve is non-negotiable; the encoding is what needs attention.
Apple issues the key as SEC1 (-----BEGIN EC PRIVATE KEY-----) with explicit
EC parameters, and this does NOT load in Python's cryptography library — it
fails with an ASN.1 / "EC curves with explicit parameters" error. You must
convert the downloaded key once to a named-curve PKCS#8 key:
openssl pkcs8 -topk8 -nocrypt -in abm-api-private-key.pem -out private-key-pkcs8.pem
Then point ABM_PRIVATE_KEY_PATH at private-key-pkcs8.pem (-----BEGIN PRIVATE KEY-----). The conversion re-encodes the same key material to the
named-curve form the library accepts, so the Key ID registered in ABM stays
valid. (A named-curve SEC1 key would also load fine — but Apple's specific
download uses explicit parameters, so conversion is required in practice.)
Lock down whatever holds the secret, and don't sync the folder anywhere public:
chmod 600 .env private-key-pkcs8.pem
Verify credentials without Claude Desktop
test_token.py performs a live token request and prints a masked report
(field lengths, the decoded JWT claims, and Apple's exact response) so you can
confirm auth before wiring up the app:
python test_token.py # uses .env
# or pass inline:
ABM_CLIENT_ID='...' ABM_KEY_ID='...' \
ABM_PRIVATE_KEY_PATH='/abs/path/private-key-pkcs8.pem' ABM_SCOPE='business.api' \
python test_token.py
A ✅ SUCCESS line means the credentials and signing are correct.
Troubleshooting invalid_client
If Apple's token endpoint returns {"error":"invalid_client"}, check, in order:
- JWT audience must include
/v2/. Theaudclaim has to behttps://account.apple.com/auth/oauth2/v2/tokeneven though the token request is POSTed to the non-v2URLhttps://account.apple.com/auth/oauth2/token. This is set inabm_client.py(TOKEN_AUDIENCE) and is the single most common cause.test_token.pywarns if it's missing. - Client ID / Key ID match the key. Confirm all three come from the same
API account's Manage screen, with no stray whitespace or truncation (watch
the field lengths in
test_token.py). - Scope matches the client type (
business.api↔BUSINESSAPI.). - Key not revoked / freshly created — a brand-new key can take a few minutes to become active; a revoked key fails permanently.
4. Run (optional — to test standalone)
python server.py # stdio transport
# or
fastmcp run server.py:mcp # via the FastMCP CLI
5. Use it in the Claude Desktop app
Claude Desktop launches the server itself over stdio, so you don't run it by hand — you just register it once.
Option A — one command (recommended)
Requires uv and fastmcp installed as CLI
tools (brew install uv and uv tool install fastmcp). This path uses the
.env file, so create it first (step 3). With your .env filled in:
./install-claude-desktop.sh
This runs fastmcp install claude-desktop, which builds an isolated
environment for the server (installing requirements.txt), passes your .env
values through, and adds the entry to Claude Desktop's config automatically.
Fully quit and reopen Claude Desktop afterward.
Option B — edit the config by hand
Open Claude Desktop's config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add an entry under mcpServers, pointing command at the Python inside the
virtualenv you created in step 2 (so the dependencies are available):
{
"mcpServers": {
"apple-business-manager": {
"command": "/absolute/path/to/abm-mcp/.venv/bin/python",
"args": ["/absolute/path/to/abm-mcp/server.py"],
"env": {
"ABM_CLIENT_ID": "BUSINESSAPI.9703f56c-....",
"ABM_KEY_ID": "d136aa66-0c3b-....",
"ABM_PRIVATE_KEY_PATH": "/absolute/path/to/private-key.pem",
"ABM_SCOPE": "business.api"
}
}
}
}
Use absolute paths for command, args, and the key path — Claude Desktop
does not run inside your project folder. On Windows, the interpreter is
.venv\Scripts\python.exe and paths use \\. With the env block filled in
here, you do not need a .env file.
It's JSON: comma-separate multiple servers under mcpServers and don't leave a
trailing comma. Save, then fully quit and reopen Claude Desktop.
Verify
In a new chat, open the tools menu (the tools/hammer icon in the message box) — you should see Apple Business Manager with its 8 tools. Try asking: "List the MDM servers in Apple Business Manager." If nothing appears, check Claude Desktop's MCP logs:
- macOS:
~/Library/Logs/Claude/mcp*.log
How auth works
Apple uses a two-step OAuth flow (see Implementing OAuth for the AxM API):
- The server signs a client assertion JWT (ES256, using your EC P-256
private key) with the standard claims (
iss/sub= Client ID,aud= Apple's token endpoint). - It exchanges that assertion for a bearer token via the
client_credentialsgrant, then callshttps://api-business.apple.com/v1/...(orapi-school.apple.com).
The token lives ~1 hour and is cached and refreshed automatically.
abm_client.py holds all of this; server.py just wraps GET endpoints as
tools.
Test (offline)
python test_smoke.py
Verifies JWT signing/verification, scope→host resolution, and that all tools register — no live API calls.
Notes & limits
- Strictly read-only. No write tools are implemented, so the server cannot assign/unassign devices or create/update/delete any resource.
- AppleCare has no bulk endpoint — one serial per call — so avoid looping
get_device_applecare_coverageover a large fleet. - Pagination follows JSON:API
links.nextcursors; use thelimitargument on list tools to cap results for big orgs. - Behind a proxy, set
HTTPS_PROXY/NO_PROXYin the environment.
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.