Metadata-Version: 2.4
Name: bibliocommons-mcp-mosyle
Version: 1.0.0
Summary: MCP server for Mosyle Business MDM
Author-email: Cody Lusk <cody.lusk@bibliocommons.com>
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: fastmcp>=3.2.4
Requires-Dist: requests>=2.33.1
Requires-Dist: fastapi>=0.136.1
Requires-Dist: uvicorn>=0.46.0
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == "dev"
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
Requires-Dist: httpx>=0.28.1; extra == "dev"

# Mosyle MDM MCP Server

MCP server for interacting with Mosyle Business MDM instances. Provides 35 tools across device management, user/group management, custom attributes, lost mode, and log streaming. Supports JWT authentication and a `--read-only` mode for safe operation.

## Configuration

**Authentication**: Mosyle uses an API access token combined with email/password credentials to obtain a JWT bearer token. Create a dedicated API user in Mosyle Business rather than using a personal account.

### Option 1: config.json

```bash
cp config.json.example config.json
# Edit config.json with your API credentials
```

### Option 2: Environment Variables

```bash
export MOSYLE_HOST="businessapi.mosyle.com"
export MOSYLE_EMAIL="api-user@example.com"
export MOSYLE_PASSWORD="api-password"
export MOSYLE_ACCESS_TOKEN="your-access-token"
export MOSYLE_LOGS_HOST="businessapilogs.mosyle.com"
export MOSYLE_TIMEOUT="30"
```

## Installation

### Option 1: Using uv (Recommended)

[uv](https://github.com/astral-sh/uv) is a fast Python package manager. Install it first:

```bash
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
```

No additional installation needed - `uvx` will handle dependencies automatically.

### Option 2: Using pip

```bash
pip install bibliocommons-mcp-mosyle
# or for development
pip install -e ".[dev]"
```

## AI Client Setup

**Quick Links**: [Amazon Q](#amazon-q-developer-vs-code) | [Claude Desktop](#claude-desktop) | [VS Code](#vs-code-with-mcp-extension) | [GitHub Copilot](#github-copilot-vs-code) | [Cline](#cline-vs-code-extension) | [Zed](#zed-editor) | [Cursor](#cursor-ide) | [Kiro IDE](#kiro-ide) | [Kiro CLI](#kiro-cli)

### Amazon Q Developer (VS Code)

1. Install the Amazon Q extension in VS Code
2. Open VS Code Settings (JSON) and add:

```json
{
  "amazonQ.mcp.servers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "amazonQ.mcp.servers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Claude Desktop

1. Open Claude Desktop configuration:
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`

2. Add the server configuration:

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### VS Code (with MCP Extension)

1. Install an MCP-compatible extension in VS Code
2. Open VS Code Settings (JSON): `Cmd+Shift+P` → "Preferences: Open User Settings (JSON)"
3. Add the server configuration:

```json
{
  "mcp.servers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcp.servers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### GitHub Copilot (VS Code)

1. Install GitHub Copilot extension in VS Code
2. Open VS Code Settings (JSON) and add:

```json
{
  "github.copilot.chat.mcp.servers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "github.copilot.chat.mcp.servers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Cline (VS Code Extension)

1. Install the Cline extension in VS Code
2. Open VS Code Settings (JSON) and add:

```json
{
  "cline.mcpServers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "cline.mcpServers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Zed Editor

1. Open Zed settings: `Cmd+,` (macOS) or `Ctrl+,` (Linux/Windows)
2. Navigate to "Language Models" → "Configure MCP Servers"
3. Add the server configuration:

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Cursor IDE

1. Open Cursor Settings (JSON): `Cmd+Shift+P` → "Preferences: Open User Settings (JSON)"
2. Add the MCP server configuration:

```json
{
  "mcp.servers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcp.servers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Kiro IDE

1. Open Kiro IDE settings
2. Navigate to MCP Servers configuration
3. Add the server:

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Kiro CLI

1. Create or edit the MCP configuration file:
   - User level: `~/.kiro/settings/mcp.json`
   - Project level: `<project-root>/.kiro/settings/mcp.json`

2. Add the server configuration:

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mosyle", "bibliocommons-mcp-mosyle"]
    }
  }
}
```


**Alternative: Using python directly**

```json
{
  "mcpServers": {
    "mosyle": {
      "command": "python",
      "args": ["-m", "bibliocommons_mcp_mosyle"]
    }
  }
}
```



### Configuration Notes

- Replace `/absolute/path/to/mosyle/` with the actual path to your server directory
- **Using `uvx` (default)**: Automatically manages dependencies in isolated environments (like `npx` for Node.js)
- **Using `python` (alternative)**: Requires `pip install bibliocommons-mcp-mosyle` first
- Add `--config /path/to/config.json` to the args array to use a specific config file
- Add `--read-only` to the args array to disable destructive tools
- After adding the configuration, restart your AI client for changes to take effect

## Web UI with Swagger

A REST API with interactive Swagger documentation is available:

```bash
python -m bibliocommons_mcp_mosyle.webui
```

Access the Swagger UI at: [http://localhost:8000/docs]

The Web UI provides:

- Interactive API documentation
- Try-it-out functionality for all endpoints
- OpenAPI/Swagger specification
- REST API access to all MCP tools

## Standalone MCP Server

```bash
python -m bibliocommons_mcp_mosyle
```

## Available Tools

| Domain | Tools | Description |
|--------|-------|-------------|
| Devices | 9 | list_devices, update_device, shutdown_devices, restart_devices, wipe_devices, assign_device_user, unassign_device, enable_activation_lock, disable_activation_lock |
| Custom Attributes | 6 | list_custom_device_attributes, create_custom_device_attribute, assign_custom_device_attribute, update_custom_device_attribute, remove_custom_device_attribute, delete_custom_device_attribute |
| Variables | 3 | save_variable, delete_variable, lock_device |
| Users | 3 | list_users, create_user, update_user |
| User Groups | 5 | list_user_groups, create_user_group, update_user_group, add_users_to_group, remove_users_from_group |
| Device Groups | 3 | list_device_groups, get_device_group_info, update_device_group |
| Lost Mode | 4 | enable_lost_mode, disable_lost_mode, play_lost_mode_sound, request_device_location |
| Logs | 2 | list_action_logs, get_logs_stream |

See [docs/API-REFERENCE.md](docs/API-REFERENCE.md) for full parameter details.

## Read-Only Mode

Disable all destructive tools for safe, audit-only operation:

```bash
# CLI flag
python -m bibliocommons_mcp_mosyle --read-only

# Environment variable
export MOSYLE_READ_ONLY=true
```

In read-only mode, the following 26 tools are excluded:

- **Devices**: update_device, shutdown_devices, restart_devices, wipe_devices, assign_device_user, unassign_device, enable_activation_lock, disable_activation_lock
- **Custom Attributes**: create_custom_device_attribute, assign_custom_device_attribute, update_custom_device_attribute, remove_custom_device_attribute, delete_custom_device_attribute
- **Variables**: save_variable, delete_variable, lock_device
- **Users**: create_user, update_user
- **User Groups**: create_user_group, update_user_group, add_users_to_group, remove_users_from_group
- **Device Groups**: update_device_group
- **Lost Mode**: enable_lost_mode, disable_lost_mode, play_lost_mode_sound

The remaining 9 read-only tools are: list_devices, list_custom_device_attributes, list_users, list_user_groups, list_device_groups, get_device_group_info, request_device_location, list_action_logs, get_logs_stream.

## Security Notes

- Create a **dedicated API user** in Mosyle Business for MCP access rather than using a personal account
- The access token is a long-lived credential; store it securely and rotate periodically
- **Never commit `config.json`** with real credentials (it is excluded by `.gitignore`)
- Use `config.json.example` as a template
- Prefer environment variables for production and CI environments
- Use `--read-only` mode when write access is not needed
