abm-mcp

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.

Category
Visit Server

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

  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.

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

  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.

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured