Skip to main content
Deploy MCP Watch to macOS devices managed by SimpleMDM.

Prerequisites

  • SimpleMDM admin access
  • Configured enrollment key from Runlayer (see below)
  • Devices enrolled via User-Approved MDM or Automated Device Enrollment (for Full Disk Access)
Enrollment keys allow devices to automatically register with Runlayer and obtain API credentials.Enrollment Keys List
1

Navigate to Enrollment Keys

Go to Settings in the Runlayer dashboard and select the Enrollment Keys tab
2

Create a New Key

Click + Create Enrollment KeyCreate Enrollment Key
3

Configure the Key

  • Name (required): Enter a descriptive name (e.g., “Production MDM”)
  • Description (optional): Add context about the key’s purpose
4

Copy the Key

Copy the generated key (starts with rl_enroll_) and store it securelyEnrollment Key Created
Enrollment keys are shown only once. Store them securely and treat them like passwords.

Deployment Steps

1

Deploy PPPC Profile

The PPPC (Privacy Preferences Policy Control) profile grants Full Disk Access to the Runlayer scan wrapper binary (/usr/local/bin/runlayer-scan). This wrapper is a signed macOS binary that spawns the scan process, which inherits FDA permissions. This scoped approach ensures only Runlayer scans receive FDA, not all uvx executions.
  1. Go to Profiles in SimpleMDM
  2. Click Create Profile > Custom Configuration Profile
  3. Download the PPPC profile below and upload it
  4. Assign to the same devices/groups that will run the script
  5. Push the profile to devices
The deployment script embeds the wrapper binary and installs it automatically. You only need to deploy this PPPC profile to grant it Full Disk Access.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadDescription</key>
            <string>Privacy Preferences Policy Control payload for Runlayer MCP Watch</string>
            <key>PayloadDisplayName</key>
            <string>Privacy Preferences Policy Control</string>
            <key>PayloadIdentifier</key>
            <string>com.runlayer.scan.pppc.fda</string>
            <key>PayloadType</key>
            <string>com.apple.TCC.configuration-profile-policy</string>
            <key>PayloadUUID</key>
            <string>A1B2C3D4-E5F6-4A7B-8C9D-0E1F2A3B4C5D</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>Services</key>
            <dict>
                <key>SystemPolicyAllFiles</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access all files for MCP Watch scanning</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyAppData</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access app data for MCP Watch scanning</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyMediaLibrary</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access Apple Music media library</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>Photos</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access Photos library</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyDesktopFolder</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access Desktop folder</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyDocumentsFolder</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access Documents folder</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyDownloadsFolder</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access Downloads folder</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyNetworkVolumes</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access network volumes</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
                <key>SystemPolicyRemovableVolumes</key>
                <array>
                    <dict>
                        <key>Authorization</key>
                        <string>Allow</string>
                        <key>CodeRequirement</key>
                        <string>identifier "com.runlayer.scan"</string>
                        <key>Comment</key>
                        <string>Allow Runlayer scan wrapper to access removable volumes</string>
                        <key>Identifier</key>
                        <string>/usr/local/bin/runlayer-scan</string>
                        <key>IdentifierType</key>
                        <string>path</string>
                        <key>StaticCode</key>
                        <false/>
                    </dict>
                </array>
            </dict>
        </dict>
    </array>
    <key>PayloadDescription</key>
    <string>Grants Full Disk Access for Runlayer MCP Watch scanning via the runlayer-scan wrapper binary. This enables scanning of TCC-protected directories (Desktop, Documents, Application Support) without user prompts.</string>
    <key>PayloadDisplayName</key>
    <string>Runlayer MCP Watch - Full Disk Access</string>
    <key>PayloadIdentifier</key>
    <string>com.runlayer.scan.pppc</string>
    <key>PayloadOrganization</key>
    <string>Runlayer</string>
    <key>PayloadRemovalDisallowed</key>
    <false/>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>B2C3D4E5-F6A7-4B8C-9D0E-1F2A3B4C5D6E</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>
2

Generate the Script

Fill in your organization’s settings below to generate a customized deployment script.SimpleMDM-specific configuration tips:
  • ENROLLMENT_USERNAME: Use an MDM variable or custom attribute that provides the user’s identity. Common variables: $EMAIL, $USER_PRINCIPAL_NAME, or a custom attribute.
  • ENROLLMENT_DEVICE_NAME: Use an MDM variable or custom attribute that identifies the device. Common variables: $DEVICE_NAME, $SERIAL_NUMBER, or a custom attribute.
3

Navigate to Scripts

Open the Scripts section in SimpleMDM admin console
4

Add the Script

  • Click Add Script
  • Paste the generated script contents
  • Give it a descriptive name (e.g., “Runlayer MCP Watch”)
5

Assign to Devices

  • Select the devices or device groups to deploy to
  • Configure execution schedule (daily recommended)
6

Deploy

Save and monitor script execution status in the SimpleMDM console

Verification

After deployment, verify on target devices and in the Runlayer dashboard:
1

Verify PPPC Profile

On a target device, verify the profile is installed:
profiles show -type configuration | grep -i runlayer
2

Verify Wrapper Binary

Check that the wrapper binary is installed and signed correctly:
# Check binary exists
ls -la /usr/local/bin/runlayer-scan

# Verify signature
codesign -dv /usr/local/bin/runlayer-scan
3

Check Analytics

Navigate to Analytics in the Runlayer dashboard
4

Verify Devices

Confirm that devices are appearing in MCP Watch data
5

Review Shadow Servers

Review any discovered shadow servers and take action as needed

Log Locations

PlatformLog Location
macOS/var/log/mcp-watch.log

Exit Codes

CodeMeaning
0Success
1General failure (missing config, enrollment failed)
2Network failure
3Installation failure