launchd-mcp
# launchd-mcp
Manage macOS `launchd` jobs from MCP tools.
This project provides:
- An MCP server (`main.py`) that wraps `launchctl`
- Task management tools for Python-script jobs (`link.igtm.launchd-mcp.*`)
- Per-task log management and retrieval
- A reusable Agent Skill at `skills/launchctl/SKILL.md` for users who prefer raw CLI workflows (no MCP server implementation)
## Features
- Basic launchctl operations: `list`, `print`, `kickstart`, `bootstrap`, `bootout`, `enable`, `disable`
- Managed task lifecycle:
- `create_or_update_python_task`
- `list_python_tasks`
- `get_python_task_logs`
- `remove_python_task`
- Scheduling and event options:
- `StartInterval` (seconds)
- `StartCalendarInterval`
- `WatchPaths`
- `QueueDirectories`
- Runtime tuning options:
- `KeepAlive`, `ThrottleInterval`, `ProcessType`, `Nice`, `Umask`, `HardResourceLimits`
## Requirements
- macOS (Darwin) for launchctl execution
- Python 3.13+
- `uv`
## Install
```bash
git clone git@github.com:igtm/launchd-mcp.git
cd launchd-mcp
uv sync
```
## Run MCP Server
```bash
uv run main.py
```
## Claude Desktop Example
`~/Library/Application Support/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"launchd": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/launchd-mcp",
"run",
"main.py"
]
}
}
}
```
## Logs
Managed task logs are written to:
- `~/.local/share/launchd-mcp/logs/{label}.out.log`
- `~/.local/share/launchd-mcp/logs/{label}.err.log`
## Tests
```bash
uv run pytest
```
## Agent Skill (CLI-first)
If you prefer managing launchd directly with shell/`launchctl`/plist files (without MCP server implementation), use:
- `skills/launchctl/SKILL.md`
This Skill follows the same label, task, and log conventions as this repository.
## Safety Notes
- For stdio MCP servers, never print to stdout except protocol messages.
- Treat `python_script` input as untrusted unless validated.
- Validate generated plist files (`plutil -lint`) before `launchctl bootstrap`.
TDQS
Scored across 12 tools
The generic launchctl tools and the managed Python-task tools are clearly separated into distinct groups. There is minor potential confusion between bootstrap_service and create_or_update_python_task since both load a plist, but the descriptions clarify that one is a raw launchctl wrapper and the other is a higher-level task manager.
All tool names follow a consistent verb_noun snake_case pattern, such as list_services, kickstart_service, bootout_service, and create_or_update_python_task. The naming convention is uniform across both the generic launchctl operations and the managed Python-task operations.
With 12 tools, the server is well-scoped for its launchd administration purpose. The generic service lifecycle tools and the higher-level Python-task management tools each earn their place without unnecessary redundancy or bloat.
The server covers the full launchd lifecycle: listing, inspecting, loading, unloading, starting, enabling, and disabling services. The Python-task workflow adds create/update/remove/list/logs, providing complete coverage for both the low-level and high-level use cases.