← EnkioCONTENT HISTORY

Update to Enkio

Snapshot Oct 26, 2026 · 06:08 UTC · version 1.0.1

Collection source: downloaded plugin package.

WHAT CHANGED

Instructions updated for generate-image

Skill instructions — Now says: use separate tool groups, and their tools are `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Always poll with...

Observed in instructions or declared skills. Runtime behavior has not been tested.

Save Enkio and check future changes in Following.

Up to 10 plugins free · no card required.

All fields and original values.

Skill instructions

Before

Oct 24, 2026 · 13:32 UTC

are two different upstream pipelines, and their tools are `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Calling `i2v_get_task` / `t2v_get_task` with a `job_id` will never find the task.

After

Oct 26, 2026 · 06:08 UTC

use separate tool groups, and their tools are `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Always poll with `any2i_get_task`; a video query tool returns no `image_urls`. **Membership check (requ...

Supporting files

Before

Oct 24, 2026 · 13:32 UTC

[{"relative_path":"references/auth.md","size_in_bytes":4896},{"relative_path":"references/credits.md","size_in_bytes":4270},{"relative_path":"references/errors.md","size_in_bytes":8464},{"relative_path":"references/workflow.md","size_in_...

After

Oct 26, 2026 · 06:08 UTC

[{"relative_path":"references/auth.md","size_in_bytes":4896},{"relative_path":"references/credits.md","size_in_bytes":4743},{"relative_path":"references/errors.md","size_in_bytes":9384},{"relative_path":"references/workflow.md","size_in_...

Compare saved observations

Download comparison JSON

SKILL.md text changes

− removed · + added

--- before
+++ after
@@ -45,10 +45,10 @@
 
 ## Hard constraints
 
-- **Image generation and video generation are two different upstream pipelines, and their tools are
+- **Image generation and video generation use separate tool groups, and their tools are
   not interchangeable**. The image-generation task identifier is **`job_id`** (not the video's
-  `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Calling
-  `i2v_get_task` / `t2v_get_task` with a `job_id` will never find the task.
+  `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Always poll
+  with `any2i_get_task`; a video query tool returns no `image_urls`.
 - **Creating a task charges credits; before submitting, you must explain the cost to the user and get
   explicit confirmation**. All query tools are free.
 - **`prompt` is required**. An empty prompt, or one containing only whitespace, will be rejected
@@ -143,6 +143,13 @@
 The returned `credit` is the current credit balance. Record it and compare it with the estimated cost
 when quoting in step 2.
 
+**Membership check (required).** Creating tasks with `any2i_create_task` requires an active membership. If
+`get_user_profile()` returns an `is_member` value other than `true`, stop here: call `get_pricing_url`
+and give the user the returned `pricing_url` to open in a browser, signed in with the same Wondershare
+account used to authorize this MCP, to purchase a membership. Do not continue with model selection,
+uploads, quoting, or task creation; after the user says the purchase is complete, call
+`get_user_profile()` again and continue only when `is_member` is `true`.
+
 ## Step 1: Choose a model
 
 ```
Full technical diff · 2 changed fields

changed /included_files

BEFORE
[
  {
    "relative_path": "references/auth.md",
    "size_in_bytes": 4896
  },
  {
    "relative_path": "references/credits.md",
    "size_in_bytes": 4270
  },
  {
    "relative_path": "references/errors.md",
    "size_in_bytes": 8464
  },
  {
    "relative_path": "references/workflow.md",
    "size_in_bytes": 7197
  }
]
AFTER
[
  {
    "relative_path": "references/auth.md",
    "size_in_bytes": 4896
  },
  {
    "relative_path": "references/credits.md",
    "size_in_bytes": 4743
  },
  {
    "relative_path": "references/errors.md",
    "size_in_bytes": 9384
  },
  {
    "relative_path": "references/workflow.md",
    "size_in_bytes": 7269
  }
]

changed /skill_md_contents

BEFORE
"---\nname: generate-image\ndescription: Generate images with AI (Enkio / enkiomv.ai), supporting text-to-image and image-to-image. Use when the user wants to generate an image, turn a photo into a certain style, change a photo's background/outfit/art style, says text-to-image / image-to-image / AI drawing, or asks which image-generation models are supported, how many credits they cost, or what resolution they can produce. The output is images; to generate videos, use the enkio:image-to-video, enkio:first-end-frame-video, enkio:reference-to-video, or enkio:text-to-video skills instead. The entire flow is completed through the enkio MCP service.\n---\n\n# AI Image Generation\n\nCall enkiomv.ai's image-generation capability through the `enkio` MCP service: provide a prompt,\nand optionally several input images, to generate images. **The same `any2i_*` tool set covers both\ntext-to-image and image-to-image**--with no input images it is text-to-image; with input images it is\nimage-to-image. Whether a model needs images, and how many, is determined entirely by that model's\nown configuration.\n\n## Service binding\n\nAll capabilities in this skill come from the single `enkio` MCP server and **must not be replaced**:\n\n- Its tool namespace in Codex is **`mcp__enkio`**--Codex normalizes `-` in server names to `_`, and\n  tool names do not carry a prefix. Every tool name below (such as `get_user_profile`) refers to the\n  tool of the same name under the `mcp__enkio` namespace.\n- **If the `mcp__enkio` namespace is not visible, the first judgment is \"not logged in\", not \"plugin\n  not installed\"**: an MCP server that has not completed OAuth will not register its entire namespace.\n  In this case, run `codex mcp login enkio` yourself (not the user), extract the plain `https://`\n  authorization URL it prints, and give the user only that link to click -- do not lead with the\n  `codex://mcp/login?server=enkio` deep link, since it silently does nothing unless the client has\n  registered the `codex://` protocol handler. See `references/auth.md` for the full procedure, and\n  explain that after login they must open a new conversation for it to take effect.\n- **Under no circumstances may you substitute another brand's MCP** (`mcp__selfyz_ai` and\n  `mcp__enkio` are two services, two accounts, and two credit pools; cross-use will really charge the\n  wrong account). Do not mix in a `task_id` / `job_id`, credit balance, or artifact URL obtained\n  elsewhere.\n- When you need to explain which service this skill is connected to, rely on the `brand` /\n  `brand_website` returned by `get_user_profile` and the value of `mcpServers.enkio.url` in this\n  plugin's `.mcp.json`; do not answer from memory or guesswork. If `brand` is not Enkio, stop\n  immediately and report the error.\n\nTasks are **asynchronous**: `any2i_create_task` returns a `job_id` immediately, and you must poll\n`any2i_get_task` yourself.\n\n```\n0 Log in/check balance -> 1 Choose model -> 2 Set quality and quote (confirm before charging)\n-> 3 Only with input images: crop locally -> 4 Only with input images: upload each image to get URLs\n-> 5 Create task (charges credits) -> 6 Poll -> 7 Download, preview, and deliver\n```\n\n## Hard constraints\n\n- **Image generation and video generation are two different upstream pipelines, and their tools are\n  not interchangeable**. The image-generation task identifier is **`job_id`** (not the video's\n  `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Calling\n  `i2v_get_task` / `t2v_get_task` with a `job_id` will never find the task.\n- **Creating a task charges credits; before submitting, you must explain the cost to the user and get\n  explicit confirmation**. All query tools are free.\n- **`prompt` is required**. An empty prompt, or one containing only whitespace, will be rejected\n  directly.\n- **The number of input images is decided by the model**: `any2i_get_options` returns\n  `image_count = { min, max }`. `min` equal to 0 means images may be omitted (text-to-image);\n  `max` equal to 0 means the model **does not accept input images at all**, and forcing them in will\n  be rejected. Any count outside the interval is rejected.\n- **Credits vary only with quality**, not with aspect ratio, number of input images, or prompt\n  length. Therefore, within the image-count limit, adding another image or writing a longer prompt is\n  \"free\".\n- **When there are input images, every image must be cropped to the target ratio before uploading**.\n  The crop specification comes from `crop` in `any2i_get_options`; **the server does not accept image\n  binaries, and cropping is done locally**. When `ratio` is `free`, no cropping is needed.\n- **Do not construct or guess `user_id`, `example`, signatures, or similar parameters**. The server\n  already handles them, and they do not exist in the tool inputs.\n- The allowed values for `quality` / `ratio` **must come from `any2i_list_models`**.\n- Polling cadence: once every 5 seconds, with a limit of about 5 minutes. Image generation is usually\n  much faster than video generation, but still give the user brief progress updates; do not wait\n  silently for a long time.\n- When a task's `job_status` is `fail`, do not blindly retry. Tell the user the `job_reason`\n  first, then ask whether to retry or give up. Retrying re-submits the task at the normal\n  price--failed credits are refunded automatically, and this billing rule was already disclosed\n  when quoting the cost, so no new price confirmation is needed here.\n- **Before showing images, you must download them locally first**. Pasting a remote URL directly\n  cannot preview it; see \"Displaying artifacts\".\n\n## How to write prompts\n\n**Text-to-image** (no input images): the model has no visual reference, so describe the image\nclearly--subject + action/pose + scene + composition/viewpoint + lighting/style.\n\n```\n✅ A corgi wearing sunglasses sits on a vintage motorcycle, afternoon backlight, film grain, shallow-depth-of-field close-up\n❌ A dog                                <- The scene, style, and composition are all left for the model to guess\n```\n\n**Image-to-image** (with input images): the prompt describes **what you want this image to become**.\nYou do not need to repeat what is already in the image; focus on \"what to change and what to keep\".\n\n```\n✅ Replace the background with snowy mountains, keep the person and clothing unchanged, and make the overall tone cool\n✅ Convert it to a watercolor illustration style while preserving the original composition\n❌ A person standing in front of snowy mountains                        <- It does not say whether to \"modify\" or \"redraw\", so original-image features are easily lost\n```\n\nWhen there are multiple input images, refer to them in natural language by submission order (\"the\nperson in the first image\", \"the clothing in the second image\"). **Do not use reference syntax such\nas `@1` or `{img1}`**; the upstream does not support it and will treat it as plain text.\n\nDo not exceed `prompt_limit_length`. The model's `prompt_hint` is upstream guidance on writing\nprompts, and `prompt_guide_url` is the upstream prompt guide page. You may paraphrase them to the\nuser, but do not open the page on the user's behalf.\n\n## Displaying artifacts\n\nThe finished images are **temporary remote URLs** from Enkio. Codex **cannot embed-preview media\nfiles from these domains**, and users cannot open a bare pasted URL.\n\nUse a per-task isolated working directory (so the user's repository is not polluted):\n\n```bash\nWORKDIR=\"${TMPDIR:-/tmp}/enkio-any2i/<job_id>\"\nmkdir -p \"$WORKDIR\"\ncurl -sS -L -o \"$WORKDIR/result1.png\" \"<image_urls[0]>\"\n```\n\n`image_urls` may contain multiple images; **download every image** and name them in order. Images can\nbe shown directly to the user, and the original remote URLs should be included as well so the user can\nsave them manually. If download fails (non-200 / empty file), clearly say \"preview download failed\"\nand provide the remote URL; do not falsely claim it has been displayed.\n\n## Step 0: Confirm service binding, login, and credit balance\n\n**First confirm that the `mcp__enkio` namespace exists.** If it does not exist, do not continue and\ndo not switch to another MCP. Tell the user that `enkio` is not logged in, then run\n`codex mcp login enkio` yourself, extract the plain `https://` authorization URL from its output, and\nhand the user only that link to click (do not lead with the unreliable\n`codex://mcp/login?server=enkio` deep link). See `references/auth.md` for details, and explain that\n**after login they must open a new Codex conversation** for it to take effect (the tool table in the\ncurrent conversation will not hot-refresh).\n\nAfter the namespace is ready, call `get_user_profile()`:\n\n- **Returns 401 / not logged in**: the token is invalid. Run `codex mcp logout enkio` then\n  `codex mcp login enkio` yourself, relay the newly printed `https://` login URL to the user the same\n  way as above (not the `codex://` deep link), and again they need to open a new conversation. See\n  `references/auth.md`.\n- Validate that the returned `brand` must be **Enkio**; otherwise the call is connected to the wrong\n  service. Stop immediately and tell the user.\n\nThe returned `credit` is the current credit balance. Record it and compare it with the estimated cost\nwhen quoting in step 2.\n\n## Step 1: Choose a model\n\n```\nany2i_list_models()\n-> { count, models: [ { model, model_name, model_desc, qualities, ratios, default_ratio,\n                       min_image_count, max_image_count, accepts_images, requires_images,\n                       prompt_limit_length, prompt_hint, prompt_guide_url,\n                       credits: [{ quality, quality_display, credit }] } ] }\n```\n\n`models[].model` is the model identifier; use it for all subsequent calls.\n\n**First filter models based on whether the user has images**:\n- User only provided text -> choose a model with `min_image_count == 0`\n- User provided images to modify -> choose a model with `accepts_images == true` whose count interval\n  can accommodate the number of images\n\nBriefly list the available models for the user, including each model's supported qualities, ratios,\nand required number of images. If the user has no preference, choose the default quality from\n`credits` with a reasonable cost-performance tradeoff and explain why.\n\n## Step 2: Set quality and quote\n\n```\nany2i_get_options(model, quality?, ratio?)\n-> { model, model_name, quality, ratio, credit_cost,\n    image_count: { min, max }, accepts_images, requires_images, crop,\n    prompt_required, prompt_limit_length, prompt_hint, prompt_guide_url }\n```\n\nIf parameters are omitted, they fall back to the model defaults, and the response clearly states the\nfinal effective values.\n\n**Tell the user both `credit_cost` and the `credit` balance from step 0, then wait for\nconfirmation**. If the balance is insufficient, prompt the user to recharge first (see\nreferences/credits.md for the recharge link and steps); do not force submission. Quality is the only\ndimension that affects credits, so if the user thinks it is expensive, suggest lowering quality\nfirst.\n\n## Step 3: Crop input images locally (skip if there are no input images)\n\nThe `crop` field gives the target ratio and pixel dimensions:\n\n```\ncrop = { ratio, crop_required, target_width, target_height, strategy, hint }\n```\n\nWhen `crop_required` is `false` (the ratio is `free`), skip this step and upload the original images\ndirectly. Otherwise, **every input image** must first be center-cropped to the target aspect ratio and\nthen scaled to `target_width × target_height`:\n\n```bash\nW=<target_width>; H=<target_height>\ni=1\nfor SRC in \"<input image 1>\" \"<input image 2>\"; do\n  ffmpeg -y -i \"$SRC\" \\\n    -vf \"crop='min(iw,ih*$W/$H)':'min(ih,iw*$H/$W)',scale=$W:$H\" \\\n    \"$WORKDIR/src$i.jpg\"\n  i=$((i+1))\ndone\n```\n\nIf ffmpeg is unavailable, use the macOS built-in `sips` (note that `--cropToHeightWidth` is **height\nfirst, then width**):\n\n```bash\ncp \"<input image 1>\" \"$WORKDIR/src1.jpg\"\nsips --cropToHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\nsips --resampleHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\n```\n\nAfter cropping, confirm that every output file exists and has the correct dimensions\n(`sips -g pixelWidth -g pixelHeight`) before moving on. **Keep the order unchanged**; it is the order\nof `image_urls` when submitting.\n\n## Step 4: Upload each image to get URLs (skip if there are no input images)\n\nThe upload endpoint accepts only one file per request, so **call `create_upload_url` separately for\nevery image**:\n\n```\ncreate_upload_url() -> { upload_url, headers }\n```\n\n```bash\ncurl -sS -X POST \"<upload_url>\" -F \"file=@$WORKDIR/src1.jpg\" -H \"X-Client-Sn: <value from headers>\"\n# -> {\"c\":200,\"m\":\"Success\",\"d\":\"https://.../src1.jpg\"}\n```\n\nThe `d` in the response is the image URL. `c != 200` means failure; report `m` to the user.\n**Collect these URLs in order**. Uploaded files are **temporary storage and are cleaned up\nperiodically**; after getting the URLs, submit the task as soon as possible.\n\n## Step 5: Create the task (charges credits)\n\n```\nany2i_create_task(model, prompt, image_urls?, quality?, ratio?)\n-> { job_id, job_status, model, image_count, quality, ratio, credit_cost }\n```\n\n- `prompt` is **required**; see \"How to write prompts\".\n- Do **not pass** `image_urls` for text-to-image; for image-to-image, pass them in order, and ensure\n  the count falls within the `image_count` interval from step 2.\n- `ratio` must **match** the ratio used for cropping in step 3.\n- `quality` must match what was confirmed during the step-2 quote; otherwise the actual charge will\n  not match the quote.\n\n## Step 6: Poll\n\n```\nany2i_get_task(job_id) -> { job_status, job_reason, image_urls, image_count, finished }\n```\n\nNote that the input parameter name is **`job_id`**, not `task_id`.\n\n- `job_status == \"success\"`: `image_urls` are the finished images; proceed to step 7.\n- `job_status == \"fail\"`: pass `job_reason` to the user and ask whether to adjust the prompt\n  and retry or give up. Retrying re-bills at the normal price (failed credits are refunded\n  automatically); this was already disclosed up front, so you do not need to reconfirm the\n  price.\n- Other values: queued or generating; wait 5 seconds and check again, with a brief progress update to\n  the user.\n\n## Step 7: Download and deliver\n\nFollowing \"Displaying artifacts\", download **every image** in `image_urls` to `$WORKDIR`, show them\nto the user, and provide the local paths + original URLs. Remind the user: remote links point to\ntemporary storage and will be cleaned up; local files under the system temporary directory may also be\nreclaimed by the system, so they should save the images to their own directory as soon as possible.\n\nIt is normal for the same prompt to generate different results each time. If the user is unhappy,\nfirst suggest **making the prompt more specific** rather than directly switching models and retrying.\n\n## Error handling\n\nFor login, connection, and service-binding issues, see `references/auth.md` (**when not logged in, the\nentire MCP namespace will not appear**; do not misjudge this as the plugin not being installed, and\nespecially do not switch to another brand's MCP). See `references/errors.md` for common error codes\nand handling; `references/credits.md` for credits and billing rules; and `references/workflow.md` for\nthe return-field structures of each tool.\n"
AFTER
"---\nname: generate-image\ndescription: Generate images with AI (Enkio / enkiomv.ai), supporting text-to-image and image-to-image. Use when the user wants to generate an image, turn a photo into a certain style, change a photo's background/outfit/art style, says text-to-image / image-to-image / AI drawing, or asks which image-generation models are supported, how many credits they cost, or what resolution they can produce. The output is images; to generate videos, use the enkio:image-to-video, enkio:first-end-frame-video, enkio:reference-to-video, or enkio:text-to-video skills instead. The entire flow is completed through the enkio MCP service.\n---\n\n# AI Image Generation\n\nCall enkiomv.ai's image-generation capability through the `enkio` MCP service: provide a prompt,\nand optionally several input images, to generate images. **The same `any2i_*` tool set covers both\ntext-to-image and image-to-image**--with no input images it is text-to-image; with input images it is\nimage-to-image. Whether a model needs images, and how many, is determined entirely by that model's\nown configuration.\n\n## Service binding\n\nAll capabilities in this skill come from the single `enkio` MCP server and **must not be replaced**:\n\n- Its tool namespace in Codex is **`mcp__enkio`**--Codex normalizes `-` in server names to `_`, and\n  tool names do not carry a prefix. Every tool name below (such as `get_user_profile`) refers to the\n  tool of the same name under the `mcp__enkio` namespace.\n- **If the `mcp__enkio` namespace is not visible, the first judgment is \"not logged in\", not \"plugin\n  not installed\"**: an MCP server that has not completed OAuth will not register its entire namespace.\n  In this case, run `codex mcp login enkio` yourself (not the user), extract the plain `https://`\n  authorization URL it prints, and give the user only that link to click -- do not lead with the\n  `codex://mcp/login?server=enkio` deep link, since it silently does nothing unless the client has\n  registered the `codex://` protocol handler. See `references/auth.md` for the full procedure, and\n  explain that after login they must open a new conversation for it to take effect.\n- **Under no circumstances may you substitute another brand's MCP** (`mcp__selfyz_ai` and\n  `mcp__enkio` are two services, two accounts, and two credit pools; cross-use will really charge the\n  wrong account). Do not mix in a `task_id` / `job_id`, credit balance, or artifact URL obtained\n  elsewhere.\n- When you need to explain which service this skill is connected to, rely on the `brand` /\n  `brand_website` returned by `get_user_profile` and the value of `mcpServers.enkio.url` in this\n  plugin's `.mcp.json`; do not answer from memory or guesswork. If `brand` is not Enkio, stop\n  immediately and report the error.\n\nTasks are **asynchronous**: `any2i_create_task` returns a `job_id` immediately, and you must poll\n`any2i_get_task` yourself.\n\n```\n0 Log in/check balance -> 1 Choose model -> 2 Set quality and quote (confirm before charging)\n-> 3 Only with input images: crop locally -> 4 Only with input images: upload each image to get URLs\n-> 5 Create task (charges credits) -> 6 Poll -> 7 Download, preview, and deliver\n```\n\n## Hard constraints\n\n- **Image generation and video generation use separate tool groups, and their tools are\n  not interchangeable**. The image-generation task identifier is **`job_id`** (not the video's\n  `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Always poll\n  with `any2i_get_task`; a video query tool returns no `image_urls`.\n- **Creating a task charges credits; before submitting, you must explain the cost to the user and get\n  explicit confirmation**. All query tools are free.\n- **`prompt` is required**. An empty prompt, or one containing only whitespace, will be rejected\n  directly.\n- **The number of input images is decided by the model**: `any2i_get_options` returns\n  `image_count = { min, max }`. `min` equal to 0 means images may be omitted (text-to-image);\n  `max` equal to 0 means the model **does not accept input images at all**, and forcing them in will\n  be rejected. Any count outside the interval is rejected.\n- **Credits vary only with quality**, not with aspect ratio, number of input images, or prompt\n  length. Therefore, within the image-count limit, adding another image or writing a longer prompt is\n  \"free\".\n- **When there are input images, every image must be cropped to the target ratio before uploading**.\n  The crop specification comes from `crop` in `any2i_get_options`; **the server does not accept image\n  binaries, and cropping is done locally**. When `ratio` is `free`, no cropping is needed.\n- **Do not construct or guess `user_id`, `example`, signatures, or similar parameters**. The server\n  already handles them, and they do not exist in the tool inputs.\n- The allowed values for `quality` / `ratio` **must come from `any2i_list_models`**.\n- Polling cadence: once every 5 seconds, with a limit of about 5 minutes. Image generation is usually\n  much faster than video generation, but still give the user brief progress updates; do not wait\n  silently for a long time.\n- When a task's `job_status` is `fail`, do not blindly retry. Tell the user the `job_reason`\n  first, then ask whether to retry or give up. Retrying re-submits the task at the normal\n  price--failed credits are refunded automatically, and this billing rule was already disclosed\n  when quoting the cost, so no new price confirmation is needed here.\n- **Before showing images, you must download them locally first**. Pasting a remote URL directly\n  cannot preview it; see \"Displaying artifacts\".\n\n## How to write prompts\n\n**Text-to-image** (no input images): the model has no visual reference, so describe the image\nclearly--subject + action/pose + scene + composition/viewpoint + lighting/style.\n\n```\n✅ A corgi wearing sunglasses sits on a vintage motorcycle, afternoon backlight, film grain, shallow-depth-of-field close-up\n❌ A dog                                <- The scene, style, and composition are all left for the model to guess\n```\n\n**Image-to-image** (with input images): the prompt describes **what you want this image to become**.\nYou do not need to repeat what is already in the image; focus on \"what to change and what to keep\".\n\n```\n✅ Replace the background with snowy mountains, keep the person and clothing unchanged, and make the overall tone cool\n✅ Convert it to a watercolor illustration style while preserving the original composition\n❌ A person standing in front of snowy mountains                        <- It does not say whether to \"modify\" or \"redraw\", so original-image features are easily lost\n```\n\nWhen there are multiple input images, refer to them in natural language by submission order (\"the\nperson in the first image\", \"the clothing in the second image\"). **Do not use reference syntax such\nas `@1` or `{img1}`**; the upstream does not support it and will treat it as plain text.\n\nDo not exceed `prompt_limit_length`. The model's `prompt_hint` is upstream guidance on writing\nprompts, and `prompt_guide_url` is the upstream prompt guide page. You may paraphrase them to the\nuser, but do not open the page on the user's behalf.\n\n## Displaying artifacts\n\nThe finished images are **temporary remote URLs** from Enkio. Codex **cannot embed-preview media\nfiles from these domains**, and users cannot open a bare pasted URL.\n\nUse a per-task isolated working directory (so the user's repository is not polluted):\n\n```bash\nWORKDIR=\"${TMPDIR:-/tmp}/enkio-any2i/<job_id>\"\nmkdir -p \"$WORKDIR\"\ncurl -sS -L -o \"$WORKDIR/result1.png\" \"<image_urls[0]>\"\n```\n\n`image_urls` may contain multiple images; **download every image** and name them in order. Images can\nbe shown directly to the user, and the original remote URLs should be included as well so the user can\nsave them manually. If download fails (non-200 / empty file), clearly say \"preview download failed\"\nand provide the remote URL; do not falsely claim it has been displayed.\n\n## Step 0: Confirm service binding, login, and credit balance\n\n**First confirm that the `mcp__enkio` namespace exists.** If it does not exist, do not continue and\ndo not switch to another MCP. Tell the user that `enkio` is not logged in, then run\n`codex mcp login enkio` yourself, extract the plain `https://` authorization URL from its output, and\nhand the user only that link to click (do not lead with the unreliable\n`codex://mcp/login?server=enkio` deep link). See `references/auth.md` for details, and explain that\n**after login they must open a new Codex conversation** for it to take effect (the tool table in the\ncurrent conversation will not hot-refresh).\n\nAfter the namespace is ready, call `get_user_profile()`:\n\n- **Returns 401 / not logged in**: the token is invalid. Run `codex mcp logout enkio` then\n  `codex mcp login enkio` yourself, relay the newly printed `https://` login URL to the user the same\n  way as above (not the `codex://` deep link), and again they need to open a new conversation. See\n  `references/auth.md`.\n- Validate that the returned `brand` must be **Enkio**; otherwise the call is connected to the wrong\n  service. Stop immediately and tell the user.\n\nThe returned `credit` is the current credit balance. Record it and compare it with the estimated cost\nwhen quoting in step 2.\n\n**Membership check (required).** Creating tasks with `any2i_create_task` requires an active membership. If\n`get_user_profile()` returns an `is_member` value other than `true`, stop here: call `get_pricing_url`\nand give the user the returned `pricing_url` to open in a browser, signed in with the same Wondershare\naccount used to authorize this MCP, to purchase a membership. Do not continue with model selection,\nuploads, quoting, or task creation; after the user says the purchase is complete, call\n`get_user_profile()` again and continue only when `is_member` is `true`.\n\n## Step 1: Choose a model\n\n```\nany2i_list_models()\n-> { count, models: [ { model, model_name, model_desc, qualities, ratios, default_ratio,\n                       min_image_count, max_image_count, accepts_images, requires_images,\n                       prompt_limit_length, prompt_hint, prompt_guide_url,\n                       credits: [{ quality, quality_display, credit }] } ] }\n```\n\n`models[].model` is the model identifier; use it for all subsequent calls.\n\n**First filter models based on whether the user has images**:\n- User only provided text -> choose a model with `min_image_count == 0`\n- User provided images to modify -> choose a model with `accepts_images == true` whose count interval\n  can accommodate the number of images\n\nBriefly list the available models for the user, including each model's supported qualities, ratios,\nand required number of images. If the user has no preference, choose the default quality from\n`credits` with a reasonable cost-performance tradeoff and explain why.\n\n## Step 2: Set quality and quote\n\n```\nany2i_get_options(model, quality?, ratio?)\n-> { model, model_name, quality, ratio, credit_cost,\n    image_count: { min, max }, accepts_images, requires_images, crop,\n    prompt_required, prompt_limit_length, prompt_hint, prompt_guide_url }\n```\n\nIf parameters are omitted, they fall back to the model defaults, and the response clearly states the\nfinal effective values.\n\n**Tell the user both `credit_cost` and the `credit` balance from step 0, then wait for\nconfirmation**. If the balance is insufficient, prompt the user to recharge first (see\nreferences/credits.md for the recharge link and steps); do not force submission. Quality is the only\ndimension that affects credits, so if the user thinks it is expensive, suggest lowering quality\nfirst.\n\n## Step 3: Crop input images locally (skip if there are no input images)\n\nThe `crop` field gives the target ratio and pixel dimensions:\n\n```\ncrop = { ratio, crop_required, target_width, target_height, strategy, hint }\n```\n\nWhen `crop_required` is `false` (the ratio is `free`), skip this step and upload the original images\ndirectly. Otherwise, **every input image** must first be center-cropped to the target aspect ratio and\nthen scaled to `target_width × target_height`:\n\n```bash\nW=<target_width>; H=<target_height>\ni=1\nfor SRC in \"<input image 1>\" \"<input image 2>\"; do\n  ffmpeg -y -i \"$SRC\" \\\n    -vf \"crop='min(iw,ih*$W/$H)':'min(ih,iw*$H/$W)',scale=$W:$H\" \\\n    \"$WORKDIR/src$i.jpg\"\n  i=$((i+1))\ndone\n```\n\nIf ffmpeg is unavailable, use the macOS built-in `sips` (note that `--cropToHeightWidth` is **height\nfirst, then width**):\n\n```bash\ncp \"<input image 1>\" \"$WORKDIR/src1.jpg\"\nsips --cropToHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\nsips --resampleHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\n```\n\nAfter cropping, confirm that every output file exists and has the correct dimensions\n(`sips -g pixelWidth -g pixelHeight`) before moving on. **Keep the order unchanged**; it is the order\nof `image_urls` when submitting.\n\n## Step 4: Upload each image to get URLs (skip if there are no input images)\n\nThe upload endpoint accepts only one file per request, so **call `create_upload_url` separately for\nevery image**:\n\n```\ncreate_upload_url() -> { upload_url, headers }\n```\n\n```bash\ncurl -sS -X POST \"<upload_url>\" -F \"file=@$WORKDIR/src1.jpg\" -H \"X-Client-Sn: <value from headers>\"\n# -> {\"c\":200,\"m\":\"Success\",\"d\":\"https://.../src1.jpg\"}\n```\n\nThe `d` in the response is the image URL. `c != 200` means failure; report `m` to the user.\n**Collect these URLs in order**. Uploaded files are **temporary storage and are cleaned up\nperiodically**; after getting the URLs, submit the task as soon as possible.\n\n## Step 5: Create the task (charges credits)\n\n```\nany2i_create_task(model, prompt, image_urls?, quality?, ratio?)\n-> { job_id, job_status, model, image_count, quality, ratio, credit_cost }\n```\n\n- `prompt` is **required**; see \"How to write prompts\".\n- Do **not pass** `image_urls` for text-to-image; for image-to-image, pass them in order, and ensure\n  the count falls within the `image_count` interval from step 2.\n- `ratio` must **match** the ratio used for cropping in step 3.\n- `quality` must match what was confirmed during the step-2 quote; otherwise the actual charge will\n  not match the quote.\n\n## Step 6: Poll\n\n```\nany2i_get_task(job_id) -> { job_status, job_reason, image_urls, image_count, finished }\n```\n\nNote that the input parameter name is **`job_id`**, not `task_id`.\n\n- `job_status == \"success\"`: `image_urls` are the finished images; proceed to step 7.\n- `job_status == \"fail\"`: pass `job_reason` to the user and ask whether to adjust the prompt\n  and retry or give up. Retrying re-bills at the normal price (failed credits are refunded\n  automatically); this was already disclosed up front, so you do not need to reconfirm the\n  price.\n- Other values: queued or generating; wait 5 seconds and check again, with a brief progress update to\n  the user.\n\n## Step 7: Download and deliver\n\nFollowing \"Displaying artifacts\", download **every image** in `image_urls` to `$WORKDIR`, show them\nto the user, and provide the local paths + original URLs. Remind the user: remote links point to\ntemporary storage and will be cleaned up; local files under the system temporary directory may also be\nreclaimed by the system, so they should save the images to their own directory as soon as possible.\n\nIt is normal for the same prompt to generate different results each time. If the user is unhappy,\nfirst suggest **making the prompt more specific** rather than directly switching models and retrying.\n\n## Error handling\n\nFor login, connection, and service-binding issues, see `references/auth.md` (**when not logged in, the\nentire MCP namespace will not appear**; do not misjudge this as the plugin not being installed, and\nespecially do not switch to another brand's MCP). See `references/errors.md` for common error codes\nand handling; `references/credits.md` for credits and billing rules; and `references/workflow.md` for\nthe return-field structures of each tool.\n"
Full snapshot data
{
  "description": "Generate images with AI (Enkio / enkiomv.ai), supporting text-to-image and image-to-image. Use when the user wants to generate an image, turn a photo into a certain style, change a photo's background/outfit/art style, says text-to-image / image-to-image / AI drawing, or asks which image-generation models are supported, how many credits they cost, or what resolution they can produce. The output is images; to generate videos, use the enkio:image-to-video, enkio:first-end-frame-video, enkio:reference-to-video, or enkio:text-to-video skills instead. The entire flow is completed through the enkio MCP service.",
  "included_files": [
    {
      "relative_path": "references/auth.md",
      "size_in_bytes": 4896
    },
    {
      "relative_path": "references/credits.md",
      "size_in_bytes": 4743
    },
    {
      "relative_path": "references/errors.md",
      "size_in_bytes": 9384
    },
    {
      "relative_path": "references/workflow.md",
      "size_in_bytes": 7269
    }
  ],
  "name": "generate-image",
  "skill_md_contents": "---\nname: generate-image\ndescription: Generate images with AI (Enkio / enkiomv.ai), supporting text-to-image and image-to-image. Use when the user wants to generate an image, turn a photo into a certain style, change a photo's background/outfit/art style, says text-to-image / image-to-image / AI drawing, or asks which image-generation models are supported, how many credits they cost, or what resolution they can produce. The output is images; to generate videos, use the enkio:image-to-video, enkio:first-end-frame-video, enkio:reference-to-video, or enkio:text-to-video skills instead. The entire flow is completed through the enkio MCP service.\n---\n\n# AI Image Generation\n\nCall enkiomv.ai's image-generation capability through the `enkio` MCP service: provide a prompt,\nand optionally several input images, to generate images. **The same `any2i_*` tool set covers both\ntext-to-image and image-to-image**--with no input images it is text-to-image; with input images it is\nimage-to-image. Whether a model needs images, and how many, is determined entirely by that model's\nown configuration.\n\n## Service binding\n\nAll capabilities in this skill come from the single `enkio` MCP server and **must not be replaced**:\n\n- Its tool namespace in Codex is **`mcp__enkio`**--Codex normalizes `-` in server names to `_`, and\n  tool names do not carry a prefix. Every tool name below (such as `get_user_profile`) refers to the\n  tool of the same name under the `mcp__enkio` namespace.\n- **If the `mcp__enkio` namespace is not visible, the first judgment is \"not logged in\", not \"plugin\n  not installed\"**: an MCP server that has not completed OAuth will not register its entire namespace.\n  In this case, run `codex mcp login enkio` yourself (not the user), extract the plain `https://`\n  authorization URL it prints, and give the user only that link to click -- do not lead with the\n  `codex://mcp/login?server=enkio` deep link, since it silently does nothing unless the client has\n  registered the `codex://` protocol handler. See `references/auth.md` for the full procedure, and\n  explain that after login they must open a new conversation for it to take effect.\n- **Under no circumstances may you substitute another brand's MCP** (`mcp__selfyz_ai` and\n  `mcp__enkio` are two services, two accounts, and two credit pools; cross-use will really charge the\n  wrong account). Do not mix in a `task_id` / `job_id`, credit balance, or artifact URL obtained\n  elsewhere.\n- When you need to explain which service this skill is connected to, rely on the `brand` /\n  `brand_website` returned by `get_user_profile` and the value of `mcpServers.enkio.url` in this\n  plugin's `.mcp.json`; do not answer from memory or guesswork. If `brand` is not Enkio, stop\n  immediately and report the error.\n\nTasks are **asynchronous**: `any2i_create_task` returns a `job_id` immediately, and you must poll\n`any2i_get_task` yourself.\n\n```\n0 Log in/check balance -> 1 Choose model -> 2 Set quality and quote (confirm before charging)\n-> 3 Only with input images: crop locally -> 4 Only with input images: upload each image to get URLs\n-> 5 Create task (charges credits) -> 6 Poll -> 7 Download, preview, and deliver\n```\n\n## Hard constraints\n\n- **Image generation and video generation use separate tool groups, and their tools are\n  not interchangeable**. The image-generation task identifier is **`job_id`** (not the video's\n  `task_id`), and the result is an **`image_urls` array** (not a single `video_url`). Always poll\n  with `any2i_get_task`; a video query tool returns no `image_urls`.\n- **Creating a task charges credits; before submitting, you must explain the cost to the user and get\n  explicit confirmation**. All query tools are free.\n- **`prompt` is required**. An empty prompt, or one containing only whitespace, will be rejected\n  directly.\n- **The number of input images is decided by the model**: `any2i_get_options` returns\n  `image_count = { min, max }`. `min` equal to 0 means images may be omitted (text-to-image);\n  `max` equal to 0 means the model **does not accept input images at all**, and forcing them in will\n  be rejected. Any count outside the interval is rejected.\n- **Credits vary only with quality**, not with aspect ratio, number of input images, or prompt\n  length. Therefore, within the image-count limit, adding another image or writing a longer prompt is\n  \"free\".\n- **When there are input images, every image must be cropped to the target ratio before uploading**.\n  The crop specification comes from `crop` in `any2i_get_options`; **the server does not accept image\n  binaries, and cropping is done locally**. When `ratio` is `free`, no cropping is needed.\n- **Do not construct or guess `user_id`, `example`, signatures, or similar parameters**. The server\n  already handles them, and they do not exist in the tool inputs.\n- The allowed values for `quality` / `ratio` **must come from `any2i_list_models`**.\n- Polling cadence: once every 5 seconds, with a limit of about 5 minutes. Image generation is usually\n  much faster than video generation, but still give the user brief progress updates; do not wait\n  silently for a long time.\n- When a task's `job_status` is `fail`, do not blindly retry. Tell the user the `job_reason`\n  first, then ask whether to retry or give up. Retrying re-submits the task at the normal\n  price--failed credits are refunded automatically, and this billing rule was already disclosed\n  when quoting the cost, so no new price confirmation is needed here.\n- **Before showing images, you must download them locally first**. Pasting a remote URL directly\n  cannot preview it; see \"Displaying artifacts\".\n\n## How to write prompts\n\n**Text-to-image** (no input images): the model has no visual reference, so describe the image\nclearly--subject + action/pose + scene + composition/viewpoint + lighting/style.\n\n```\n✅ A corgi wearing sunglasses sits on a vintage motorcycle, afternoon backlight, film grain, shallow-depth-of-field close-up\n❌ A dog                                <- The scene, style, and composition are all left for the model to guess\n```\n\n**Image-to-image** (with input images): the prompt describes **what you want this image to become**.\nYou do not need to repeat what is already in the image; focus on \"what to change and what to keep\".\n\n```\n✅ Replace the background with snowy mountains, keep the person and clothing unchanged, and make the overall tone cool\n✅ Convert it to a watercolor illustration style while preserving the original composition\n❌ A person standing in front of snowy mountains                        <- It does not say whether to \"modify\" or \"redraw\", so original-image features are easily lost\n```\n\nWhen there are multiple input images, refer to them in natural language by submission order (\"the\nperson in the first image\", \"the clothing in the second image\"). **Do not use reference syntax such\nas `@1` or `{img1}`**; the upstream does not support it and will treat it as plain text.\n\nDo not exceed `prompt_limit_length`. The model's `prompt_hint` is upstream guidance on writing\nprompts, and `prompt_guide_url` is the upstream prompt guide page. You may paraphrase them to the\nuser, but do not open the page on the user's behalf.\n\n## Displaying artifacts\n\nThe finished images are **temporary remote URLs** from Enkio. Codex **cannot embed-preview media\nfiles from these domains**, and users cannot open a bare pasted URL.\n\nUse a per-task isolated working directory (so the user's repository is not polluted):\n\n```bash\nWORKDIR=\"${TMPDIR:-/tmp}/enkio-any2i/<job_id>\"\nmkdir -p \"$WORKDIR\"\ncurl -sS -L -o \"$WORKDIR/result1.png\" \"<image_urls[0]>\"\n```\n\n`image_urls` may contain multiple images; **download every image** and name them in order. Images can\nbe shown directly to the user, and the original remote URLs should be included as well so the user can\nsave them manually. If download fails (non-200 / empty file), clearly say \"preview download failed\"\nand provide the remote URL; do not falsely claim it has been displayed.\n\n## Step 0: Confirm service binding, login, and credit balance\n\n**First confirm that the `mcp__enkio` namespace exists.** If it does not exist, do not continue and\ndo not switch to another MCP. Tell the user that `enkio` is not logged in, then run\n`codex mcp login enkio` yourself, extract the plain `https://` authorization URL from its output, and\nhand the user only that link to click (do not lead with the unreliable\n`codex://mcp/login?server=enkio` deep link). See `references/auth.md` for details, and explain that\n**after login they must open a new Codex conversation** for it to take effect (the tool table in the\ncurrent conversation will not hot-refresh).\n\nAfter the namespace is ready, call `get_user_profile()`:\n\n- **Returns 401 / not logged in**: the token is invalid. Run `codex mcp logout enkio` then\n  `codex mcp login enkio` yourself, relay the newly printed `https://` login URL to the user the same\n  way as above (not the `codex://` deep link), and again they need to open a new conversation. See\n  `references/auth.md`.\n- Validate that the returned `brand` must be **Enkio**; otherwise the call is connected to the wrong\n  service. Stop immediately and tell the user.\n\nThe returned `credit` is the current credit balance. Record it and compare it with the estimated cost\nwhen quoting in step 2.\n\n**Membership check (required).** Creating tasks with `any2i_create_task` requires an active membership. If\n`get_user_profile()` returns an `is_member` value other than `true`, stop here: call `get_pricing_url`\nand give the user the returned `pricing_url` to open in a browser, signed in with the same Wondershare\naccount used to authorize this MCP, to purchase a membership. Do not continue with model selection,\nuploads, quoting, or task creation; after the user says the purchase is complete, call\n`get_user_profile()` again and continue only when `is_member` is `true`.\n\n## Step 1: Choose a model\n\n```\nany2i_list_models()\n-> { count, models: [ { model, model_name, model_desc, qualities, ratios, default_ratio,\n                       min_image_count, max_image_count, accepts_images, requires_images,\n                       prompt_limit_length, prompt_hint, prompt_guide_url,\n                       credits: [{ quality, quality_display, credit }] } ] }\n```\n\n`models[].model` is the model identifier; use it for all subsequent calls.\n\n**First filter models based on whether the user has images**:\n- User only provided text -> choose a model with `min_image_count == 0`\n- User provided images to modify -> choose a model with `accepts_images == true` whose count interval\n  can accommodate the number of images\n\nBriefly list the available models for the user, including each model's supported qualities, ratios,\nand required number of images. If the user has no preference, choose the default quality from\n`credits` with a reasonable cost-performance tradeoff and explain why.\n\n## Step 2: Set quality and quote\n\n```\nany2i_get_options(model, quality?, ratio?)\n-> { model, model_name, quality, ratio, credit_cost,\n    image_count: { min, max }, accepts_images, requires_images, crop,\n    prompt_required, prompt_limit_length, prompt_hint, prompt_guide_url }\n```\n\nIf parameters are omitted, they fall back to the model defaults, and the response clearly states the\nfinal effective values.\n\n**Tell the user both `credit_cost` and the `credit` balance from step 0, then wait for\nconfirmation**. If the balance is insufficient, prompt the user to recharge first (see\nreferences/credits.md for the recharge link and steps); do not force submission. Quality is the only\ndimension that affects credits, so if the user thinks it is expensive, suggest lowering quality\nfirst.\n\n## Step 3: Crop input images locally (skip if there are no input images)\n\nThe `crop` field gives the target ratio and pixel dimensions:\n\n```\ncrop = { ratio, crop_required, target_width, target_height, strategy, hint }\n```\n\nWhen `crop_required` is `false` (the ratio is `free`), skip this step and upload the original images\ndirectly. Otherwise, **every input image** must first be center-cropped to the target aspect ratio and\nthen scaled to `target_width × target_height`:\n\n```bash\nW=<target_width>; H=<target_height>\ni=1\nfor SRC in \"<input image 1>\" \"<input image 2>\"; do\n  ffmpeg -y -i \"$SRC\" \\\n    -vf \"crop='min(iw,ih*$W/$H)':'min(ih,iw*$H/$W)',scale=$W:$H\" \\\n    \"$WORKDIR/src$i.jpg\"\n  i=$((i+1))\ndone\n```\n\nIf ffmpeg is unavailable, use the macOS built-in `sips` (note that `--cropToHeightWidth` is **height\nfirst, then width**):\n\n```bash\ncp \"<input image 1>\" \"$WORKDIR/src1.jpg\"\nsips --cropToHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\nsips --resampleHeightWidth \"$H\" \"$W\" \"$WORKDIR/src1.jpg\" >/dev/null\n```\n\nAfter cropping, confirm that every output file exists and has the correct dimensions\n(`sips -g pixelWidth -g pixelHeight`) before moving on. **Keep the order unchanged**; it is the order\nof `image_urls` when submitting.\n\n## Step 4: Upload each image to get URLs (skip if there are no input images)\n\nThe upload endpoint accepts only one file per request, so **call `create_upload_url` separately for\nevery image**:\n\n```\ncreate_upload_url() -> { upload_url, headers }\n```\n\n```bash\ncurl -sS -X POST \"<upload_url>\" -F \"file=@$WORKDIR/src1.jpg\" -H \"X-Client-Sn: <value from headers>\"\n# -> {\"c\":200,\"m\":\"Success\",\"d\":\"https://.../src1.jpg\"}\n```\n\nThe `d` in the response is the image URL. `c != 200` means failure; report `m` to the user.\n**Collect these URLs in order**. Uploaded files are **temporary storage and are cleaned up\nperiodically**; after getting the URLs, submit the task as soon as possible.\n\n## Step 5: Create the task (charges credits)\n\n```\nany2i_create_task(model, prompt, image_urls?, quality?, ratio?)\n-> { job_id, job_status, model, image_count, quality, ratio, credit_cost }\n```\n\n- `prompt` is **required**; see \"How to write prompts\".\n- Do **not pass** `image_urls` for text-to-image; for image-to-image, pass them in order, and ensure\n  the count falls within the `image_count` interval from step 2.\n- `ratio` must **match** the ratio used for cropping in step 3.\n- `quality` must match what was confirmed during the step-2 quote; otherwise the actual charge will\n  not match the quote.\n\n## Step 6: Poll\n\n```\nany2i_get_task(job_id) -> { job_status, job_reason, image_urls, image_count, finished }\n```\n\nNote that the input parameter name is **`job_id`**, not `task_id`.\n\n- `job_status == \"success\"`: `image_urls` are the finished images; proceed to step 7.\n- `job_status == \"fail\"`: pass `job_reason` to the user and ask whether to adjust the prompt\n  and retry or give up. Retrying re-bills at the normal price (failed credits are refunded\n  automatically); this was already disclosed up front, so you do not need to reconfirm the\n  price.\n- Other values: queued or generating; wait 5 seconds and check again, with a brief progress update to\n  the user.\n\n## Step 7: Download and deliver\n\nFollowing \"Displaying artifacts\", download **every image** in `image_urls` to `$WORKDIR`, show them\nto the user, and provide the local paths + original URLs. Remind the user: remote links point to\ntemporary storage and will be cleaned up; local files under the system temporary directory may also be\nreclaimed by the system, so they should save the images to their own directory as soon as possible.\n\nIt is normal for the same prompt to generate different results each time. If the user is unhappy,\nfirst suggest **making the prompt more specific** rather than directly switching models and retrying.\n\n## Error handling\n\nFor login, connection, and service-binding issues, see `references/auth.md` (**when not logged in, the\nentire MCP namespace will not appear**; do not misjudge this as the plugin not being installed, and\nespecially do not switch to another brand's MCP). See `references/errors.md` for common error codes\nand handling; `references/credits.md` for credits and billing rules; and `references/workflow.md` for\nthe return-field structures of each tool.\n"
}

SHA-256 of public snapshot: 53edf40004a8c17c67257b73650e6e7c73b9ad0036d9bddff607ca49444cc14f