Skip to main content

mlx-serve

Hook an app, game or script up to the local mlx-serve server for LLM chat, embeddings, image, speech, music, sound effect, video and 3D generation, and Laya/Kev/Clef typed decisions. Use when code should call mlx-serve.

Source facts

Repository
ddalcu/mlx-serve
Last source activity
October 10, 2026 at 22:39
Detected SKILL.md language
English
Stars
1,840
Forks
187

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
4 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
mlx-serve
description
Hook an app, game or script up to the local mlx-serve server for LLM chat, embeddings, image, speech, music, sound effect, video and 3D generation, and Laya/Kev/Clef typed decisions. Use when code should call mlx-serve.
# mlx-serve mlx-serve runs MLX models on this Mac behind one HTTP port: OpenAI, Anthropic and Ollama compatible chat, plus native endpoints for images, speech, music, sound effects, video, 3D and decisions. Everything below is plain HTTP + JSON, so any language works. ## Connect - Base URL: `$MLX_SERVE_URL` when set, else `http://127.0.0.1:11234`. Make it a config value or env var in the code you write, never a hardcoded LAN IP. - Auth: none from this Mac. A server started with `--api-key` wants `Authorization: Bearer <key>` from other machines; a 401 means that. - CORS is open (`Access-Control-Allow-Origin: *`): a browser game can call it directly. - Up? `curl -s "$MLX_SERVE_URL/health"` ## Pick models from `/v1/models`, never guess ids ```sh curl -s "${MLX_SERVE_URL:-http://127.0.0.1:11234}/v1/models" \ | jq -r '.data[] | "\(.id)\t\(.capabilities | join(","))\t\(.state)"' ``` Each row has `id` (like `org/name`), `capabilities`, `state` (`ready`, `unloaded`, `remote`) and `context_length`. Choose by capability: | capability | endpoint | details | |---|---|---| | `chat` | `POST /v1/chat/completions` (also `/v1/messages`, `/v1/responses`) | chat.md | | `embeddings` | `POST /v1/embeddings` | chat.md | | `image` | `POST /v1/images/generations`, `POST /v1/images/edits` | media.md | | `audio` without `music` or `sound` | `POST /v1/audio/speech` (TTS) | media.md | | `music` | `POST /v1/audio/music-generations` | media.md | | `sound` | `POST /v1/audio/sound-generations` (sound effects) | media.md | | `video` | `POST /v1/video/generations` | media.md | | `3d` | `POST /v1/3d/generations` | media.md | | `decisions` | `POST /v1/decisions`, `POST /v1/systemone` | decisions.md | Read the linked file (next to this one) before writing client code for that endpoint. If no model has the capability the user needs, say so and tell them to download one in the MLX Core app (Models). Do not invent an id. ## Loading and memory - Any request names its model with `"model": "<id>"`. An unloaded model loads on the first request, which can take seconds to minutes. `POST /v1/load-model {"model": "<id>"}` pre-warms one; `POST /v1/unload-model {"model": "<id>"}` frees it. - All models share one GPU memory budget. A 503 `out_of_memory` means unload something first (typically the media model when you are done with it). - Generation runs on one inference thread: a 3-minute video render stalls chat replies for 3 minutes. Decisions and embeddings are milliseconds. ## Rules for apps and games - Generate media AHEAD of time or in the background, never on the frame or input path. Cache results on disk keyed by model + prompt + seed + size, and ship the cache (or regenerate lazily) instead of calling on every run. - Rough cost on Apple Silicon: image 5-60 s, speech about real time or faster, sound effects about a second, music 30 s to minutes, 3D 1-5 min, video minutes. Set client timeouts to match (10+ minutes for video), and keep the game playable while waiting. - Send `"seed"` for reproducible assets. - Long jobs: send `"stream": true` and read the SSE `progress` events to drive a progress bar. See media.md. - Errors are JSON: `{"error": {"message": "..."}}` with a 4xx/5xx status. The message names the bad field. Show it; never retry a 400 unchanged. - Keep the server's own URL and model ids in one config module so the user can swap models without touching game code. ## Smoke test ```sh BASE="${MLX_SERVE_URL:-http://127.0.0.1:11234}" IMG=$(curl -s "$BASE/v1/models" | jq -r '[.data[] | select(.capabilities | index("image"))][0].id') curl -s "$BASE/v1/images/generations" -H 'content-type: application/json' \ -d "{\"model\":\"$IMG\",\"prompt\":\"pixel art treasure chest on a plain white background\",\"size\":\"512x512\",\"seed\":7}" \ | jq -r '.data[0].b64_json' | base64 -d > chest.png ```
View on GitHub