diff options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/config.md | 290 | ||||
| -rw-r--r-- | doc/mcp.md | 302 |
2 files changed, 592 insertions, 0 deletions
diff --git a/doc/config.md b/doc/config.md new file mode 100644 index 0000000..f200cdc --- /dev/null +++ b/doc/config.md @@ -0,0 +1,290 @@ +# 設定ファイル仕様 + +## 1. 概要 + +`mcp-sd15`のモデル構成と生成設定はTOMLファイルで管理する。起動時に次のように指定する。 + +```powershell +uv run mcp-sd15 --config C:\path\to\config.toml +``` + +`--config`を省略した場合は、現在のworking directoryにある`config.toml`を読み込む。 +設定値をCLIやMCPツール入力で上書きすることはできない。 + +## 2. モデルディレクトリ + +`model.root`の下には次のディレクトリ構成が必要である。 + +```text +<model.root>/ +├─ checkpoints/ +│ └─ <model.checkpoint> +├─ vae/ +│ └─ <model.vae> +├─ lora/ +│ └─ <model.lora.file> +└─ controlnet/ + ├─ <controlnet.depth.model> + ├─ <controlnet.openpose.model> + └─ <controlnet.inpaint.model> +``` + +各モデル項目にはパスではなくファイル名だけを記述する。絶対パス、ディレクトリ名を含む +相対パス、`.`、`..`は拒否される。 + +## 3. 設定項目一覧 + +| TOML key | 型 | 必須 | 既定値 | +|---|---|---:|---| +| `model.root` | string | Yes | なし | +| `model.checkpoint` | string | Yes | なし | +| `model.vae` | string | No | 未使用 | +| `model.lora[].file` | string | LoRA使用時 | なし | +| `model.lora[].weight` | number | No | `1.0` | +| `generation.steps` | integer | No | `25` | +| `generation.cfg_scale` | number | No | `7.0` | +| `generation.scheduler` | string enum | No | `dpmpp_2m` | +| `generation.default_size` | string enum | No | `square_512` | +| `controlnet.depth.enabled` | boolean | No | `false` | +| `controlnet.depth.model` | string | 有効時 | なし | +| `controlnet.depth.preprocessor` | string | No | `midas` | +| `controlnet.openpose.enabled` | boolean | No | `false` | +| `controlnet.openpose.model` | string | 有効時 | なし | +| `controlnet.inpaint.enabled` | boolean | No | `false` | +| `controlnet.inpaint.model` | string | 有効時 | なし | +| `output.enabled` | boolean | No | `false` | +| `output.directory` | string | No | `./outputs` | + +## 4. `[model]` + +base checkpoint、VAE、LoRAを指定する必須tableである。 + +```toml +[model] +root = "D:/AI/models" +checkpoint = "model.safetensors" +vae = "vae.safetensors" +``` + +### `root` + +- 必須の空でない文字列 +- 絶対パスを推奨 +- 相対パスの場合はconfigファイルが置かれたディレクトリを基準に解決 +- 起動時にディレクトリの存在を確認 + +### `checkpoint` + +- 必須のファイル名 +- `<root>/checkpoints/<checkpoint>`として解決 +- 起動時にファイルの存在を確認 +- サーバ初期化時にSD1.x pipelineとしてロードできなければ起動失敗 + +### `vae` + +- 任意のファイル名 +- 指定した場合は`<root>/vae/<vae>`として解決し、base modelのVAEを置換 +- 指定時は起動時にファイルの存在を確認 +- 省略時はcheckpointに含まれるVAEを使用 + +## 5. `[[model.lora]]` + +LoRAごとにarray of tablesを追加する。0個以上指定でき、記述順にadapter名が割り当てられる。 + +```toml +[[model.lora]] +file = "detail.safetensors" +weight = 0.8 + +[[model.lora]] +file = "style.safetensors" +weight = 0.5 +``` + +| Key | 型 | 制約 | +|---|---|---| +| `file` | string | 必須のファイル名。`<root>/lora/<file>`に存在すること | +| `weight` | number | `-4.0`以上`4.0`以下。既定値`1.0` | + +同じ`file`を複数回指定することはできない。LoRAを使わない場合は +`[[model.lora]]`を記述しない。 + +## 6. `[generation]` + +全ツールに共通する推論パラメータを指定する。table自体を省略した場合はすべて既定値となる。 + +```toml +[generation] +steps = 25 +cfg_scale = 7.0 +scheduler = "dpmpp_2m" +default_size = "square_512" +``` + +### `steps` + +- integerのみ +- 範囲は`1`以上`150`以下 +- booleanや小数は不可 + +### `cfg_scale` + +- finiteなintegerまたはfloat +- 範囲は`0.0`以上`30.0`以下 +- `NaN`や無限大は不可 + +### `scheduler` + +次の値だけを指定できる。 + +| 値 | Diffusers scheduler | +|---|---| +| `dpmpp_2m` | DPM-Solver++、solver order 2 | +| `ddim` | DDIM | +| `euler` | Euler Discrete | +| `euler_a` | Euler Ancestral Discrete | + +### `default_size` + +MCPツールで`size`を省略した場合に使用するサイズIDである。 + +| 値 | 解像度 | +|---|---:| +| `square_512` | 512 x 512 | +| `landscape_512` | 512 x 384 | +| `portrait_512` | 384 x 512 | + +## 7. `[controlnet.*]` + +ControlNetは用途ごとに個別設定する。各tableを省略するとその機能は無効になる。 + +### Depth + +```toml +[controlnet.depth] +enabled = true +model = "control_v11f1p_sd15_depth.safetensors" +preprocessor = "midas" +``` + +| Key | 仕様 | +|---|---| +| `enabled` | boolean。既定値`false` | +| `model` | 有効時に必須。`<root>/controlnet/<model>`として解決 | +| `preprocessor` | `midas`のみ指定可能。省略時も`midas` | + +### OpenPose + +```toml +[controlnet.openpose] +enabled = true +model = "control_v11p_sd15_openpose.safetensors" +``` + +この設定はMCPの`openpose`と`openpose_full`の両方で使用する。前者はbody、後者は +body、hand、faceを抽出する。preprocessorをMCPや設定から切り替えることはできない。 + +### Inpaint + +```toml +[controlnet.inpaint] +enabled = true +model = "control_v11p_sd15_inpaint.safetensors" +``` + +元画像とmaskからControlNet Inpaint用conditionを生成する。maskの輝度が50%を超える領域が +再生成対象になる。 + +### Annotatorモデル + +MiDaSとOpenPoseのannotator重みは`controlnet_aux`のローカルcacheに事前配置する必要がある。 +サーバは推論時に外部ネットワークから自動取得せず、`local_files_only=true`でロードする。 +annotator重みの場所をこのTOMLから指定する項目はない。 + +## 8. `[output]` + +生成したPNGをMCPレスポンスに加えてローカル保存するかを指定する。 + +```toml +[output] +enabled = false +directory = "./outputs" +``` + +| Key | 仕様 | +|---|---| +| `enabled` | `true`で保存、`false`でMCP返却のみ。既定値`false` | +| `directory` | 保存先。既定値`./outputs` | + +相対`directory`はconfigファイルのディレクトリを基準に解決する。保存が有効な場合、 +ディレクトリは最初の保存時に作成され、ファイル名はランダムUUIDの`<uuid>.png`となる。 + +## 9. 最小設定例 + +Text-to-Imageだけを使用する最小構成は次のとおり。 + +```toml +[model] +root = "D:/AI/models" +checkpoint = "model.safetensors" +``` + +この場合、VAEとLoRAは使用せず、全ControlNetとローカル保存は無効になる。生成設定には +既定値が使用される。 + +## 10. 全設定例 + +```toml +[model] +root = "D:/AI/models" +checkpoint = "model.safetensors" +vae = "vae.safetensors" + +[[model.lora]] +file = "detail.safetensors" +weight = 0.8 + +[[model.lora]] +file = "style.safetensors" +weight = 0.5 + +[generation] +steps = 25 +cfg_scale = 7.0 +scheduler = "dpmpp_2m" +default_size = "square_512" + +[controlnet.depth] +enabled = true +model = "control_v11f1p_sd15_depth.safetensors" +preprocessor = "midas" + +[controlnet.openpose] +enabled = true +model = "control_v11p_sd15_openpose.safetensors" + +[controlnet.inpaint] +enabled = true +model = "control_v11p_sd15_inpaint.safetensors" + +[output] +enabled = false +directory = "./outputs" +``` + +## 11. 起動時validation + +次のいずれかに該当するとMCPサーバは起動しない。 + +- TOML syntaxが不正 +- 必須tableまたは必須値がない +- 値の型、列挙値、数値範囲が不正 +- モデル項目にファイル名以外のパスが指定されている +- LoRAファイル名が重複している +- `model.root`が存在しない +- checkpoint、指定VAE、LoRA、有効なControlNetのファイルが存在しない +- CUDAが利用できない +- base checkpoint、VAE、LoRAがDiffusersでロードできない + +未定義のkeyは現在の実装ではエラーにはならないが、処理には使用されない。タイプミスを +見逃さないため、この文書に記載したkeyだけを使用することを推奨する。 diff --git a/doc/mcp.md b/doc/mcp.md new file mode 100644 index 0000000..0c50f75 --- /dev/null +++ b/doc/mcp.md @@ -0,0 +1,302 @@ +# MCPツール仕様 + +## 1. 概要 + +`mcp-sd15` はstdio transportで動作し、Stable Diffusion 1.xによる画像生成を行う +次の3ツールを公開する。 + +| ツール | 用途 | +|---|---| +| `generate_image` | テキストから画像を生成する | +| `generate_guided_image` | DepthまたはOpenPoseで誘導して画像を生成する | +| `inpaint_image` | 元画像のmask指定領域を再生成する | + +全ツールの出力は1枚のPNGである。生成パラメータ、モデル、LoRA、ControlNet強度、seedは +ツール入力には公開しない。これらは設定ファイルまたはサーバ内部で管理する。 + +## 2. 共通仕様 + +### 2.1 Prompt + +| 項目 | 仕様 | +|---|---| +| `positive_prompt` | 必須の文字列。前後の空白を除去した結果が空の場合はエラー | +| `negative_prompt` | 任意の文字列。省略または`null`の場合は空文字列 | +| 最大長 | それぞれ10,000文字 | + +### 2.2 Image size + +`size`には次の列挙値だけを指定できる。省略または`null`の場合は +`generation.default_size`が使用される。 + +| 値 | 幅 | 高さ | +|---|---:|---:| +| `square_512` | 512 | 512 | +| `landscape_512` | 512 | 384 | +| `portrait_512` | 384 | 512 | + +任意の`width`や`height`は指定できない。 + +### 2.3 入力画像 + +`input_image`と`mask_image`は、次のいずれかの文字列で指定する。 + +- PNGまたはJPEGバイナリをBase64エンコードした文字列 +- `data:image/png;base64,...`形式のdata URI +- `data:image/jpeg;base64,...`または`data:image/jpg;base64,...`形式のdata URI + +画像入力には次の制限がある。 + +| 項目 | 制限 | +|---|---| +| 画像形式 | PNG、JPEGのみ | +| Base64文字列長 | 36,000,000文字以下 | +| pixel数 | 40,000,000 pixel以下 | +| Base64 | 改行やBase64以外の文字を含まない正規のBase64 | + +入力画像は生成サイズにリサイズされる。通常画像にはLanczos、maskにはnearest-neighborが +使用される。 + +### 2.4 出力 + +成功時はMCPの`ImageContent`を1件返す。 + +```json +{ + "type": "image", + "data": "iVBORw0KGgoAAA...", + "mimeType": "image/png" +} +``` + +`data`はMCP SDKによってBase64エンコードされる。PNGには次のtext metadataが埋め込まれる。 + +| Key | 内容 | +|---|---| +| `seed` | サーバが生成したseed | +| `size` | 使用したサイズID | +| `mode` | `text_to_image`、`guided_image`、`inpaint_image`のいずれか | +| `timestamp` | UTCのISO 8601生成日時 | +| `elapsed_seconds` | キュー待ちを含む処理時間(秒) | + +出力ファイルの保存が有効な場合も、MCPレスポンスには同じPNGが返される。 + +## 3. `generate_image` + +設定済みのbase checkpoint、VAE、LoRAを使ってText-to-Imageを実行する。 + +### 入力 + +| 名前 | 型 | 必須 | 既定値 | +|---|---|---:|---| +| `positive_prompt` | string | Yes | なし | +| `negative_prompt` | string \| null | No | `null`(内部では空文字列) | +| `size` | size enum \| null | No | `generation.default_size` | + +### 呼び出し例 + +```json +{ + "positive_prompt": "a small lighthouse on a rocky coast, sunset", + "negative_prompt": "low quality, blurry", + "size": "landscape_512" +} +``` + +### JSON Schema + +```json +{ + "type": "object", + "title": "generate_imageArguments", + "properties": { + "positive_prompt": { + "type": "string", + "title": "Positive Prompt" + }, + "negative_prompt": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "default": null, + "title": "Negative Prompt" + }, + "size": { + "anyOf": [ + { + "type": "string", + "enum": ["square_512", "landscape_512", "portrait_512"] + }, + {"type": "null"} + ], + "default": null, + "title": "Size" + } + }, + "required": ["positive_prompt"] +} +``` + +## 4. `generate_guided_image` + +入力画像を固定preprocessorに通し、対応するControlNetで画像生成を誘導する。 + +### 入力 + +| 名前 | 型 | 必須 | 既定値 | +|---|---|---:|---| +| `positive_prompt` | string | Yes | なし | +| `control_mode` | control mode enum | Yes | なし | +| `input_image` | string | Yes | なし | +| `negative_prompt` | string \| null | No | `null`(内部では空文字列) | +| `size` | size enum \| null | No | `generation.default_size` | + +`control_mode`の意味は次のとおり。 + +| 値 | ControlNet設定 | 前処理 | +|---|---|---| +| `depth` | `controlnet.depth` | MiDaS depth | +| `openpose` | `controlnet.openpose` | body pose | +| `openpose_full` | `controlnet.openpose` | body、hand、face pose | + +要求したControlNetが設定で無効の場合はツールエラーになる。`openpose`と +`openpose_full`は同じControlNetモデルを共有する。 + +### 呼び出し例 + +```json +{ + "positive_prompt": "a dancer wearing a red dress, studio lighting", + "control_mode": "openpose_full", + "input_image": "data:image/png;base64,iVBORw0KGgoAAA...", + "negative_prompt": "deformed hands", + "size": "portrait_512" +} +``` + +### JSON Schema + +```json +{ + "type": "object", + "title": "generate_guided_imageArguments", + "properties": { + "positive_prompt": { + "type": "string", + "title": "Positive Prompt" + }, + "control_mode": { + "type": "string", + "enum": ["depth", "openpose", "openpose_full"], + "title": "Control Mode" + }, + "input_image": { + "type": "string", + "title": "Input Image" + }, + "negative_prompt": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "default": null, + "title": "Negative Prompt" + }, + "size": { + "anyOf": [ + { + "type": "string", + "enum": ["square_512", "landscape_512", "portrait_512"] + }, + {"type": "null"} + ], + "default": null, + "title": "Size" + } + }, + "required": ["positive_prompt", "control_mode", "input_image"] +} +``` + +## 5. `inpaint_image` + +元画像とmask画像を使い、白い領域をControlNet Inpaintで再生成する。 + +### 入力 + +| 名前 | 型 | 必須 | 既定値 | +|---|---|---:|---| +| `positive_prompt` | string | Yes | なし | +| `input_image` | string | Yes | なし | +| `mask_image` | string | Yes | なし | +| `negative_prompt` | string \| null | No | `null`(内部では空文字列) | +| `size` | size enum \| null | No | `generation.default_size` | + +`mask_image`はgrayscaleに変換される。輝度が50%を超えるpixelが再生成対象で、黒い領域は +保持対象となる。 + +### 呼び出し例 + +```json +{ + "positive_prompt": "a wooden table with a ceramic vase", + "input_image": "data:image/png;base64,iVBORw0KGgoAAA...", + "mask_image": "data:image/png;base64,iVBORw0KGgoAAA...", + "negative_prompt": "artifacts", + "size": "square_512" +} +``` + +### JSON Schema + +```json +{ + "type": "object", + "title": "inpaint_imageArguments", + "properties": { + "positive_prompt": { + "type": "string", + "title": "Positive Prompt" + }, + "input_image": { + "type": "string", + "title": "Input Image" + }, + "mask_image": { + "type": "string", + "title": "Mask Image" + }, + "negative_prompt": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "default": null, + "title": "Negative Prompt" + }, + "size": { + "anyOf": [ + { + "type": "string", + "enum": ["square_512", "landscape_512", "portrait_512"] + }, + {"type": "null"} + ], + "default": null, + "title": "Size" + } + }, + "required": ["positive_prompt", "input_image", "mask_image"] +} +``` + +## 6. 実行制御とエラー + +生成処理はサーバ内の単一lockで直列化される。同時に複数の要求を受信した場合、GPU推論は +1件ずつ実行される。 + +主なツールエラーは次のとおり。 + +| 分類 | 例 | +|---|---| +| 入力エラー | 空のprompt、不正なsize、不正なcontrol mode | +| 画像エラー | Base64不正、未対応形式、画像破損、上限超過 | +| 設定エラー | 要求したControlNetが無効、モデルをロードできない | +| 推論エラー | Diffusers処理失敗、出力画像数不正 | +| CUDA OOM | VRAM不足。CUDA cacheの解放を試みた後にエラーを返す | +| 保存エラー | output directoryの作成またはPNG書込み失敗 | + +エラー時に画像は返されない。設定ファイル自体やbase modelが不正な場合は、MCPツールを +公開する前のサーバ起動処理が失敗する。 |
