# MacMini MCP A local Model Context Protocol server that exposes selected macOS app actions to an AI harness. It uses Apple's scripting interfaces through `/usr/bin/osascript` and stays on the local machine. ## Available tools | Tool | Action | | --- | --- | | `notes_list` | Search notes; returns titles and metadata unless previews are explicitly requested | | `notes_read` | Read a note by the ID returned by `notes_list` | | `notes_create` | Create a plaintext-backed note | | `mail_accounts` | List configured Apple Mail accounts (read-only) | | `mail_list_mailboxes` | List Apple Mail's top-level mailboxes (read-only) | | `mail_list_messages` | List metadata from one selected account and mailbox (read-only) | | `mail_read_message` | Read a selected Apple Mail message (read-only) | | `calendar_list_calendars` | List calendar indexes, names, and write capability | | `calendar_list_events` | List events in an ISO-8601 time window from the focused `Home` calendar | | `calendar_create_event` | Create an event in the focused `Home` calendar | | `reminders_list_lists` | List reminder lists with account context and assignment metadata availability | | `reminders_list` | List reminders, including assignment details or assignment hints for shared-list reminders | | `reminders_create` | Create a reminder | | `contacts_search` | Search contact names and organizations without disclosing contact methods | | `contacts_read` | Read phone and email details for one selected contact | | `contacts_create` | Create a contact with optional email and phone details | | `deco_get_config_status` | Show Deco connection config without revealing the password | | `deco_get_overview` | Read TP-Link Deco overview stats and firmware | | `deco_list_clients` | List online Deco clients, current traffic speeds, and linked mesh node when available | | `deco_get_ipv4_status` | Read WAN/LAN IPv4 status | | `deco_get_firmware` | Read Deco model and firmware version | | `system_get_info` | Get macOS version (sw_vers), hardware model, and SpeechAnalyzer availability | | `system_speech_api_status` | Full check for Apple SpeechAnalyzer/SpeechTranscriber (macOS 26+) | | `speech_kokoro_status` | Check the warm `ksay` Kokoro TTS daemon | | `speech_kokoro_synthesize` | Generate fast Kokoro speech to a local WAV file | | `speech_kokoro_synthesize_base64` | Generate fast Kokoro speech and return WAV base64 | | `codex_image_get_config_status` | Show local Codex CLI image generation config | | `codex_image_generate` | Generate an image with this Mac's Codex CLI and save it locally | | `gemini_image_get_config_status` | Show Gemini image generation config without revealing the API key | | `gemini_image_generate` | Generate an image with the Gemini API and save it locally | | `gemini_chrome_prompt_get_config_status` | Show config for the Codex Chrome-skill Gemini image prompt builder | | `gemini_chrome_prompt_build` | Build a ready-to-run Codex prompt for Gemini web-app image generation | There are no destructive tools in the initial server. Calendar names can repeat across accounts. This server is focused on the event-rich `Home` calendar discovered during setup (`calendarIndex: 2`) and verifies the selected index is still named `Home` before operating on it. Calendar selector parameters remain available as advanced overrides. Reminder assignment data is exposed on `reminders_list` as an `assignment` object. Apple Reminders automation does not currently publish shared-list participant metadata directly, so the tool first checks for any native assignee field macOS exposes and then falls back to assignment hints embedded in the reminder title or notes, such as `(Alicia)` or `Captured 2026-05-18, Alicia;`. **macOS 26 note:** This Mac is on macOS 26.5.2 (Mac16,10 M4) — so `system_speech_api_status` confirms SpeechAnalyzer/SpeechTranscriber is available. Apple's new engine beats Whisper Small 2.12% vs 3.74% WER per Inscribe benchmark (2026-07-13). ## Setup Requires macOS and Node.js 20 or newer. ```sh npm install npm run python:install npm run check npm run service:install npm run ksay:install ``` The service defaults to a same-Mac endpoint: ```text http://127.0.0.1:7331/mcp ``` Health check: ```sh curl -s http://127.0.0.1:7331/health ``` `launchd` runs `node --watch src/http.js`, so edits to the server or imported modules cause it to restart automatically while the agent remains installed. After changing installed dependencies or service configuration, run: ```sh npm install npm run service:install ``` Operational commands: ```sh npm run service:status npm run service:restart npm run service:uninstall npm run ksay:restart ``` Service logs are stored in `.logs/`. ## Fast Kokoro speech with `ksay` This repo includes a warm Kokoro TTS daemon backed by `mlx-audio`, plus `bin/ksay`, a console command intended as a neural replacement for macOS `say`. The launchd service preloads the model and keeps it resident, so normal calls only pay generation and playback time. Install Python dependencies and the warm service: ```sh npm run python:install npm run ksay:install ``` Add the repo's `bin` directory to your shell path: ```sh export PATH="/Users/adolforeyna/Projects/MacMiniMCP/bin:$PATH" ``` Examples: ```sh ksay "Hello from Kokoro." ksay -v af_bella --speed 1.15 "Fast, warm speech." echo "Piped text works too." | ksay ksay --no-play -o /tmp/hello.wav "Write a wav without playback." ksay --status ``` Defaults can be overridden with environment variables: ```text KSAY_MODEL=mlx-community/Kokoro-82M-8bit KSAY_VOICE=af_heart KSAY_LANG_CODE=a KSAY_PORT=7332 KSAY_OUTPUT_DIR=/Users/adolforeyna/Projects/MacMiniMCP/generated-audio ``` Useful Kokoro voices include `af_heart`, `af_bella`, `af_nova`, `af_sky`, `am_adam`, `am_echo`, `bf_alice`, `bf_emma`, `bm_daniel`, and `bm_george`. Use language code `a` for American English and `b` for British English. ## Harness configuration For a harness that supports Streamable HTTP, configure the local MCP URL as `http://127.0.0.1:7331/mcp`. For a trusted local-network harness such as a Raspberry Pi, set `MACMINI_MCP_HOST` in `.env` to the Mac's LAN IP and set a strong `MACMINI_MCP_TOKEN`. Then configure the remote MCP client with: ```text URL: http://:7331/mcp Authorization: Bearer ``` Restart after changing `.env`: ```sh npm run service:restart ``` For TP-Link Deco tools, install Python dependencies with `npm run python:install`, then set `DECO_HOST`, `DECO_USERNAME=admin`, `DECO_PASSWORD`, and optionally `DECO_VERIFY_SSL=false` in `.env`. For Codex image generation, make sure the Mac is logged in with `codex login`. Generated files are saved to `generated-images/` by default; override this with `CODEX_IMAGE_OUTPUT_DIR`. Set `CODEX_IMAGE_MODEL` or `CODEX_IMAGE_TIMEOUT_MS` or `CODEX_CLI_PATH` to the absolute `codex` path. For Gemini image generation, set `GEMINI_API_KEY` in `.env`. Generated files are saved to `generated-images/` by default; override this with `GEMINI_IMAGE_OUTPUT_DIR`. The Gemini image tool calls the Gemini API directly and does not expose browser navigation, page inspection, or screenshot tools. For Gemini image generation through the signed-in Chrome web app, use `gemini_chrome_prompt_build` to create a ready-to-run Codex prompt. The MCP service does not control Chrome directly; the Chrome skill is only available inside an active Codex session. The generated prompt verifies the Chrome profile name is `ReynaFamilyBot`, opens only `https://gemini.google.com/app`, submits the image prompt, downloads the generated image, and copies it to `generated-images/`. Override the expected Chrome profile with `GEMINI_CHROME_PROFILE_NAME` and the output directory with `GEMINI_CHROME_IMAGE_OUTPUT_DIR`. For a harness that launches stdio servers, use: ```json { "mcpServers": { "macmini": { "command": "/Users/adolforeyna/.nvm/versions/node/v22.22.0/bin/node", "args": ["/Users/adolforeyna/Projects/MacMiniMCP/src/stdio.js"] } } } ``` ## Permissions and security On first use of a Notes, Calendar, Reminders, or Contacts tool, macOS may ask for Automation access for Node. Permit only the applications you want the server to control under **System Settings > Privacy & Security > Automation**. The HTTP service binds to `127.0.0.1` by default. When configured to bind to a LAN address, it refuses to start without `MACMINI_MCP_TOKEN`; clients must send `Authorization: Bearer *** This is HTTP bearer authentication on your local network, not encrypted transport. Use it only on a trusted LAN or put it behind a private encrypted network such as a VPN. ## Development ```sh npm run check npm run dev ``` The MCP transport follows the official TypeScript SDK Streamable HTTP server approach: [Model Context Protocol TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk). ## Image generation This server exposes Codex-backed and Gemini-backed image generation tools. Gemini image generation uses the Gemini API directly, not browser automation. Image Playground was tried and removed because the macOS app does not expose a scriptable prompt-to-file action through AppleScript or Shortcuts/App Intents.