Skip to main content
Glama
README.md
# 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

A3.8/5.0

Scored across 12 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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.

Maintenance

ActivityInactive
ResponsivenessNo issues