The repository is split into two layers:
src/macinput/keyboard.py,mouse.py,screenshot.py- low-level macOS automation primitives
src/macinput/server.py,cli.py,settings.py- MCP server surface, validation, defaults, and runtime policy
This separation is deliberate. The low-level layer should stay simple and close to system APIs. The server layer should own:
- tool naming
- input validation
- safe defaults
- operator-facing configuration
- MCP resources and prompts
uv sync --extra dev
uv run pytest
uv run ruff check .The repository includes:
.github/workflows/ci.yml- runs lint and tests on
pushandpull_request
- runs lint and tests on
.github/workflows/release.yml- builds
sdistandwheelartifacts on manual dispatch or version tags - publishes to PyPI on
v*tags if trusted publishing is configured
- builds
These workflows intentionally avoid GUI injection tests because GitHub-hosted runners do not provide a reliable, permissioned macOS desktop session for end-to-end input automation.
When adding a new MCP tool:
- Add or reuse a low-level primitive only if the system interaction is genuinely reusable.
- Keep the MCP tool small and composable.
- Validate all inputs in the server layer.
- Document the tool in
README.md. - Decide whether the capability also needs a resource or prompt update.
Prefer:
- explicit parameters
- small reversible actions
- outputs that help the agent decide the next step
Avoid:
- monolithic multi-step tools
- host-specific behavior hidden inside tools
- tools that guess UI state without observation
- import tests
- config validation
- metadata shape
- docs linting
- keyboard injection
- mouse movement and clicking
- screenshot capture
- permission-denied behavior
- Add
LICENSE. - Add
examples/for common MCP hosts. - Add smoke tests on a macOS runner.
- Add optional region screenshot support.
- Add optional audit logging for regulated environments.