API Server · Mac
Your Mac Is Now an Image Generation API
Start the API Server in Private Diffusion and your Mac answers image requests from Claude, from scripts, and from any app that speaks the OpenAI image API. Every image is made on your Mac, with no cloud relay in between.
- Mac only
- Beta
OpenAI-Compatible Image Generation API, Served From Your Mac
Code reaches it through the OpenAI image API, and Claude reaches it through MCP. Either way, the API Server runs the models you have already downloaded and hands back finished images.
OpenAI-Compatible
Point an OpenAI SDK at your Mac and call images.generate. Most image code written for OpenAI changes in two places: the base URL and the key.
Claude Connects Over MCP
Add Private Diffusion to Claude Code or Claude Desktop, then ask Claude for a picture. It calls the generate_image tool, and your Mac makes the image and hands it back.
Made on Your Mac
Prompts and images travel between your client and your Mac, with no cloud relay. Any device that can reach your Mac can send it requests, and it answers only those that carry your key.
Set It Up in Three Steps
- 1
Download a Model
Open Private Diffusion on your Mac and download at least one model. The server generates with the models you have, and the one active in Studio is its default.
- 2
Start the API Server
Click Start API Server in the API Server tab, or use the Server menu (⇧⌘A). To serve every time the app opens, turn on "Start the API server at launch" in Settings › API Server.
- 3
Copy Your Address and Key
Click Details in the API Server tab. It lists your Mac's addresses, your key, and ready-made commands for
curl, Claude Code, and Claude Desktop with both filled in.
Know Before You Connect
- The server speaks plain HTTP. Your key, prompts, and images cross the network unencrypted, so run it on networks you trust and stop it on public Wi-Fi.
- Any device that can reach your Mac and holds the key can generate images.
- Treat the key like a password. If it leaks, regenerate it in Settings › API Server. Clients using the old key stop working until you give them the new one.
- Any web page you give the key to can call the server from your browser. Paste it only into tools you trust.
- With "Start the API server at launch" turned on, your Mac serves on every network it joins. Turn it off on a laptop that travels.
- While the server runs, Studio pauses, your Mac stays awake, and switching or deleting models waits until you stop it.
- Images made over the API land in your gallery. Turn on Incognito Mode, or turn off Save API images to gallery, to keep them out.
- Your Mac makes one image at a time. Up to 8 requests wait their turn, and the next one gets a
queue_fullerror.
Generate Images From curl, Python, and JavaScript
Each example makes one picture and saves it as a file. Put your key in an environment variable named PD_API_KEY, and replace your-mac.local with your Mac's address from Details in the API Server tab.
8963 is the default port. If you changed it in Settings › API Server, use yours.
curl
Sends the prompt and decodes the returned image with jq.
curl -sS http://your-mac.local:8963/v1/images/generations \
-H "Authorization: Bearer $PD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "a lighthouse at dusk, oil painting", "size": "1024x1024"}' \
| jq -r '.data[0].b64_json // error(.error.message)' | base64 --decode > lighthouse.pngPython (OpenAI SDK)
Uses the official openai package. Fields the OpenAI API does not define, such as seed, go in extra_body. The SDK retries a full queue twice by default, then raises the error.
import base64
import os
from openai import OpenAI
client = OpenAI(
base_url="http://your-mac.local:8963/v1",
api_key=os.environ["PD_API_KEY"],
)
result = client.images.generate(
prompt="a lighthouse at dusk, oil painting",
size="1024x1024",
extra_body={"seed": 42},
)
with open("lighthouse.png", "wb") as f:
f.write(base64.b64decode(result.data[0].b64_json))JavaScript (OpenAI SDK, Node.js)
Runs in Node.js with the openai package, which sends extra fields such as seed as they are. Never run it in a web page, where anyone could read the key.
import { writeFileSync } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://your-mac.local:8963/v1",
apiKey: process.env.PD_API_KEY,
});
const result = await client.images.generate({
prompt: "a lighthouse at dusk, oil painting",
size: "1024x1024",
seed: 42,
});
writeFileSync("lighthouse.png", Buffer.from(result.data[0].b64_json, "base64"));Claude Image Generation Over MCP: Claude Code and Claude Desktop
Private Diffusion speaks the Model Context Protocol at /mcp. Connect Claude once, then ask for images in plain language.
Claude Code
With PD_API_KEY set as above, run this once in your terminal to add the server to Claude Code.
claude mcp add --transport http private-diffusion http://your-mac.local:8963/mcp \
--header "Authorization: Bearer $PD_API_KEY"Do not add --scope project. It writes your key into a .mcp.json file meant to be shared.
Claude Desktop
Claude Desktop reaches the server through mcp-remote, a small bridge that runs on Node.js. In Claude Desktop, open Settings › Developer › Edit Config, add this entry, replace pd-your-key with your key, and restart Claude.
{
"mcpServers": {
"private-diffusion": {
"command": "npx",
"args": [
"-y",
"[email protected]",
"http://your-mac.local:8963/mcp",
"--allow-http",
"--transport",
"http-only",
"--header",
"Authorization:${PRIVATE_DIFFUSION_AUTH}"
],
"env": {
"PRIVATE_DIFFUSION_AUTH": "Bearer pd-your-key"
}
}
}
}Needs Node.js. The bridge version is pinned.
MCP Tools
| Tool | What it does |
|---|---|
generate_image | Makes one to 4 images from a prompt. Takes the HTTP fields except quality and streaming, and returns jpeg with compression set to 85 unless you ask for PNG. An explicit model that is not ready is an error, not a fallback. |
list_models | Lists the models ready on this Mac with the sizes, steps, and upscale factors each accepts here. |
get_image_chunk | Used by MCP clients that display full-size images. You never call it yourself. |
Authentication
Every request to /v1/* and /mcp carries your key in the Authorization: Bearer pd-… header. The app creates the key the first time the server starts. Reveal or regenerate it in Settings › API Server.
A missing or wrong key returns 401 with the code invalid_api_key.
Endpoints: /v1/images/generations, /v1/models, and /mcp
POST /v1/images/generations
Generates images from a text prompt. Requests and responses follow the OpenAI image API, with a few fields of its own.
| Parameter | Values | Default | Notes |
|---|---|---|---|
prompt | string | Required | What to draw. Must not be empty. |
model | string | Active model | A model id from the table below. An id that is unknown, not downloaded, or not supported on this Mac falls back to the active model, and the response's model names the one that ran. |
n | 1–4 | 1 | How many images. Each uses the next seed. |
size | "auto" | "WxH" | "auto" | Snaps to the nearest size the model supports, by shape first and then area. "auto" picks 1024×1024 when the model allows it. Extra large sizes need a Mac with more memory. |
quality | "auto" | "low" | "medium" | "high" | "auto" | Only "high" changes the result, trading speed for detail. |
output_format | "png" | "jpeg" | "png" | The image file format. |
output_compression | 0–100 | 100 | Compression for JPEG output. 100 compresses least. |
seed | integer | Random | Set it to repeat a result. |
negative_prompt | string | None | What to keep out of the image. Some models only; the rest return 400. |
steps | integer | Model default | Must sit inside the model's range. Fixed-step models accept only their own value. |
upscale | 1.5 | 2 | 4 | None | Enlarges the image after it is made. The model must offer the factor and its upscaler must be downloaded, or the request returns 400. On Macs with less memory, 4 becomes 2. |
stream | boolean | false | Sends the result as server-sent events, with optional previews. |
partial_images | 0–3 | 0 | How many previews to stream before the final image. Used only with stream. |
Response
Images come back as base64 in b64_json, never as a URL, each with its seed and whether it carries a watermark. model names the model that ran.
{
"created": 1767225600,
"model": "zit",
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA…",
"seed": 42,
"watermarked": false,
"sensitive": false
}
]
}Streaming Partial Images
Set stream to true and the server replies with server-sent events. Each frame names its event and carries a JSON object.
| Event | Data |
|---|---|
image_generation.partial_image | type, b64_json, partial_image_index, created_at, watermarkedA preview while the image forms. The index restarts at 0 for each image. |
image_generation.completed | type, b64_json, seed, watermarked, sensitive, created_atThe finished image with its seed. One per image when you ask for more than one. |
error | errorSomething failed after the stream opened. Errors before that arrive as a normal JSON response. |
The stream closes after the last image. There is no separate done event.
GET /v1/models
Lists the models that are downloaded, ready, and supported on this Mac. Send one of their ids as model.
Which Models Work Over the API
Every Private Diffusion model works over the API once it is downloaded and your Mac supports it. Send the id from the second column as model.
| Model | Id | Negative prompt | Steps | Upscale |
|---|---|---|---|---|
| Anima | anima | No | 8-12, default 8 | 2× |
| Flux.2 Klein 4B | klein | Yes | 4 | 1.5×, 2× |
| Mage Flow Turbo | mage-flow-turbo | No | 4 | 1.5×, 2× |
| Krea 2 Turbo | krea2-turbo | No | 8 | 2× |
| Kroma Turbo | kroma | Yes | 8-12, default 10 | 2× |
| Z-Image-Turbo | zit | Yes | 9 | 2×, 4× |
| Juggernaut Z Fast | juggernaut-z | Yes | 8 | 2×, 4× |
| ERNIE Image Turbo | ernie-turbo | No | 8 | 1.5×, 2× |
| Chroma1-Flash | chroma | Yes | 12 | 2×, 4× |
| Boogu Image Turbo | boogu | No | 4 | 2×, 4× |
Krea 2 Turbo always runs 8 steps over the API, even when Studio is set to its faster 4-step mode.
Sizes and upscale factors depend on your Mac's memory. The list_models MCP tool reports what your Mac accepts.
Errors and Limits
Errors follow the OpenAI shape: a JSON object with a message, a type, the parameter at fault, and a code.
{
"error": {
"message": "steps must be between 8 and 12 for Kroma Turbo.",
"type": "invalid_request_error",
"param": "steps",
"code": null
}
}| Status | Type and code | When |
|---|---|---|
| 400 | invalid_request_error | A field is missing or out of range, or the body is not valid JSON. When one field is at fault, param names it. |
| 401 | invalid_request_error · invalid_api_key | The key is missing or wrong. |
| 404 | invalid_request_error · not_found | The path or method does not exist. |
| 405 | — | A request other than POST was sent to /mcp. |
| 413 | invalid_request_error · request_too_large | The body is larger than 2 MiB. |
| 429 | rate_limit_error · queue_full | The queue already holds 8 requests. Try again shortly. |
| 500 | server_error · generation_failed · internal_error | Generation failed on the Mac. |
| 503 | server_error · server_stopping · runtime_unavailable · model_unavailable | The server is stopping, the engine needs a moment, or no model is active. Retry after the seconds in Retry-After. |
- Request bodies up to 2 MiB.
- One to 4 images per request.
- One image at a time, with up to 8 waiting.
- Every 503 carries
Retry-Afterof 10 seconds.
FAQ
Connect Claude Code or Claude Desktop to Private Diffusion over MCP with the address and key from Details in the app's API Server tab. Then ask Claude for a picture. Claude calls Private Diffusion, which makes the image on your Mac and hands it back.
Yes, for generating images. Point an OpenAI SDK at your Mac's address with your key, and the image generation call works as it does with OpenAI. The differences: images come back as base64, there is no editing or image input, and you get extra fields such as a seed and a negative prompt.
Yes. Any device that can reach your Mac can use it with your key. Use the address from Details in the app's API Server tab.
No. The server uses plain HTTP, so use it on networks you trust, keep the key private, and regenerate it if it leaks.
Every model you have downloaded on your Mac. Each keeps its own rules for steps, negative prompts, and upscaling, listed in the table on this page.
Your Mac makes one image at a time. Up to 8 requests wait in line, and the next one gets a 429 error until the line moves. The OpenAI SDKs retry that error twice by default before giving up.
No. The API Server is part of Private Diffusion for Mac. On iPhone and iPad, you generate images in the app itself.