Skip to main content
Glama

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).

Related MCP server: appd-mcp

1. Create API credentials in ABM/ASM

  1. Sign in to Apple Business (or School) Manager.

  2. Click your name (bottom-left) → PreferencesAPI.

  3. Click + to create an API account, give it a label, Create.

  4. Click Generate Private Key — the .pem downloads once. Keep it safe; it cannot be re-downloaded (you can revoke and regenerate).

  5. 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:

  • env block 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 .env file is needed.

  • .env file — 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 .env

    The server loads .env automatically (via python-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:

  1. JWT audience must include /v2/. The aud claim has to be https://account.apple.com/auth/oauth2/v2/token even though the token request is POSTed to the non-v2 URL https://account.apple.com/auth/oauth2/token. This is set in abm_client.py (TOKEN_AUDIENCE) and is the single most common cause. test_token.py warns if it's missing.

  2. 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).

  3. Scope matches the client type (business.apiBUSINESSAPI.).

  4. 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.

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):

  1. 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).

  2. It exchanges that assertion for a bearer token via the client_credentials grant, then calls https://api-business.apple.com/v1/... (or api-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_coverage over a large fleet.

  • Pagination follows JSON:API links.next cursors; use the limit argument on list tools to cap results for big orgs.

  • Behind a proxy, set HTTPS_PROXY / NO_PROXY in the environment.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

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/o-sokhan/abm-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server