Перейти к основному содержанию

Генерация изображений в Claude Code: скрипт, MCP или SVG

Claude Code сам не рисует: схемы и обложки с текстом он рендерит кодом из SVG, а фото и иллюстрации создаёт внешняя модель, вызванная скриптом или MCP-сервером.

LaoZhang AI TeamОпубликовано12 мин чтения
Содержание
Изображения в Claude Code: три пути — SVG-рендер для схем и обложек без ключа, скрипт с API для фото и иллюстраций, MCP-сервер для выбора из многих моделей

Картинку в сессии Claude Code создаёт не сам Claude. Она появляется одним из двух способов: либо Claude пишет код (SVG, HTML, скрипт на Python) и запускает его рендер, либо скрипт или MCP-сервер обращается к внешней модели генерации — GPT Image, Nano Banana, FLUX. Первый способ подходит для схем, графиков и обложек с текстом и не требует ни ключа, ни оплаты. Второй нужен для фотографий и иллюстраций и почти всегда тарифицируется за каждый вызов.

Отсюда и порядок действий: определите тип изображения, затем решите, готовы ли вы подключать платный API, и только после этого выбирайте между собственным скриптом в скилле и готовым MCP-сервером.

Claude Code не рисует сам: два источника изображений в сессии

Ни одна модель Claude и ни один тариф не выдают растровое изображение. В справке Anthropic это сформулировано прямо: «Claude doesn't generate photos or illustrations the way image-generation tools do», а в документации по Vision Claude назван моделью, которая только понимает изображения и не может их генерировать, редактировать или изменять. Общий разбор того, что это означает для чат-приложений, есть в материале «Может ли Claude генерировать изображения?».

В терминале это ограничение обходится за счёт того, что Claude Code умеет запускать команды:

  • Рендер кодом. Claude пишет SVG, HTML или скрипт, запускает конвертер и получает PNG или WebP. Пиксели создаёт программа-рендерер по описанию, которое написал Claude.
  • Внешняя модель. Скрипт отправляет запрос в API изображений и сохраняет ответ в файл, либо то же самое делает инструмент MCP-сервера. Пиксели создаёт модель OpenAI, Google или другого поставщика, а Claude Code только формулирует запрос и раскладывает файлы.

Собственного коннектора или скилла с моделью генерации у Anthropic нет. Коннекторы Adobe, Canva и Hugging Face в каталоге сделаны партнёрами, а скиллы canvas-design, algorithmic-art и slack-gif-creator из репозитория anthropics/skills рендерят изображение кодом и ни к какой модели генерации не обращаются.

Как выбрать путь: схема — кодом, фото — моделью генерации

Выбор определяют три условия: тип изображения, готовность платить за вызовы и то, работаете вы один или в общем репозитории.

Что нужноПутьЧто потребуетсяЧем платите
Схема, график, обложка с текстом, иконка из простых формSVG или HTML и рендер кодомrsvg-convert или браузерный рендер, cwebpТолько токены Claude
Фото или иллюстрация, один человек, нужен контроль над параметрамиСкрипт в скилле, вызов API изображенийКлюч OpenAI или Gemini с включённой оплатойЗа каждый вызов по тарифу поставщика
Фото или иллюстрация, хочется выбирать среди многих моделейMCP-сервер fal.ai или ReplicateАккаунт и ключ площадкиЗа каждый запуск модели
Несколько пробных картинок без оплатыMCP-сервер Hugging Face или Cloudflare Workers AIАккаунт; у обоих суточный лимитНичего в пределах лимита
Изображения нужны всей команде в одном репозиторииПроектный скилл в .claude/skills/Ключ у каждого в своём окруженииУ каждого свой счёт

Схема выбора пути в Claude Code: схемы и обложки рендерятся кодом, фото и иллюстрации идут через скрипт в скилле или MCP-сервер

Если сомневаетесь между скриптом и MCP, смотрите на то, куда попадает файл. Скрипт пишет картинку туда, куда указано в аргументе --out, то есть сразу в проект. Изображение, которое вернул инструмент MCP, Claude Code сохраняет в каталог tool-results текущей сессии внутри ~/.claude/projects/, и в проект его нужно копировать отдельной просьбой.

Схемы и обложки с текстом: SVG, rsvg-convert и cwebp без API

Для всего, что состоит из фигур, линий и надписей, модель генерации не нужна и даже вредна: текст на картинке будет точным только тогда, когда он набран шрифтом, а не нарисован. Попросите Claude Code написать SVG заданного размера и отрендерить его:

bash
rsvg-convert -w 2000 -h 1125 diagram.svg -o diagram.png
cwebp -q 90 diagram.png -o diagram.webp

Так устроен процесс в блоге LaoZhang AI: с сентября 2026 года иллюстрации к статьям делаются в Claude Code без модели генерации. Claude пишет SVG вручную, rsvg-convert рендерит PNG точного размера (обложки 2400×1350, иллюстрации 2000×1125), cwebp переводит его в WebP. Восемнадцать файлов WebP для материала, вышедшего 2 октября 2026 года, заняли от 136 до 192 КБ каждый. В отдельном замере 1 октября написанный вручную SVG размером 911 байт превратился в PNG 1600×600 за 135 мс. Это наблюдение с одного сайта и одной машины, но оно показывает порядок величин: рендер занимает доли секунды и не стоит ничего сверх токенов на сам SVG.

Граница у этого пути жёсткая. Новую фотографию или живописную иллюстрацию он не создаст. Обрезать, обесцветить, склеить и переконвертировать готовые файлы через Pillow или ImageMagick можно, сгенерировать содержимое — нет.

Скрипт generate.py для OpenAI Images: 66 строк без зависимостей

Для фото и иллюстраций самый прозрачный вариант — небольшой скрипт, который вызывает API изображений и сохраняет файл. По состоянию на 2 октября 2026 года актуальные графические модели OpenAI — gpt-image-2.5-flare (быстрая, для повседневных задач) и gpt-image-2.5-sunburst (точное редактирование), обе работают через POST /v1/images/generations (руководство OpenAI). Ответ приходит в base64 в поле data[0].b64_json, поэтому декодировать и записывать файл должен сам скрипт.

Скрипт ниже использует только стандартную библиотеку Python. Он читает ключ из OPENAI_API_KEY и нигде его не печатает, принимает только две модели из списка, отказывается перезаписывать существующий файл и выводит JSON с путём, размером и полем usage из ответа.

python
#!/usr/bin/env python3
"""Generate one image with the OpenAI Images API and save it to disk.

Standard library only. Reads the key from OPENAI_API_KEY; never prints it.
"""
import argparse
import base64
import json
import os
import pathlib
import sys
import urllib.error
import urllib.request

MODELS = ("gpt-image-2.5-flare", "gpt-image-2.5-sunburst")


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--prompt", required=True)
    parser.add_argument("--out", required=True, help="output file, e.g. assets/hero.png")
    parser.add_argument("--model", default="gpt-image-2.5-flare", choices=MODELS)
    parser.add_argument("--size", default="1536x1024")
    parser.add_argument("--quality", default="low")
    args = parser.parse_args()

    key = os.environ.get("OPENAI_API_KEY")
    if not key:
        print("OPENAI_API_KEY is not set. Export it in the shell before starting claude.", file=sys.stderr)
        return 2

    out = pathlib.Path(args.out)
    if out.exists():
        print(f"{out} already exists. Choose another --out so nothing is overwritten.", file=sys.stderr)
        return 2

    base = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1").rstrip("/")
    body = json.dumps({
        "model": args.model,
        "prompt": args.prompt,
        "size": args.size,
        "quality": args.quality,
    }).encode()
    request = urllib.request.Request(
        f"{base}/images/generations",
        data=body,
        headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
    )
    try:
        with urllib.request.urlopen(request, timeout=300) as response:
            payload = json.load(response)
    except urllib.error.HTTPError as error:
        print(f"HTTP {error.code}: {error.read().decode(errors='replace')[:600]}", file=sys.stderr)
        return 1
    except urllib.error.URLError as error:
        print(f"Request failed: {error.reason}", file=sys.stderr)
        return 1

    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_bytes(base64.b64decode(payload["data"][0]["b64_json"]))
    print(json.dumps({"saved": str(out), "bytes": out.stat().st_size, "usage": payload.get("usage")}))
    return 0


if __name__ == "__main__":
    sys.exit(main())

Запуск выглядит так:

bash
python3 generate.py --prompt "isometric illustration of a server room, soft light" --out assets/hero.png

Объём проверки этого скрипта ограничен отказными сценариями, прогнанными 2 октября 2026 года на macOS с Python 3.12.1:

УсловиеЧто произошло
OPENAI_API_KEY не заданСообщение в stderr, код выхода 2, запрос в сеть не уходит
Поддельный ключЗапрос дошёл до api.openai.com, ответ HTTP 401 с кодом invalid_api_key, код выхода 1, файл не создан
--model dall-e-3 (вне списка)argparse отвечает invalid choice и перечисляет две допустимые модели
Файл по пути --out уже существуетСообщение в stderr, код выхода 2, запрос в сеть не уходит

Успешная генерация с настоящим ключом на этом скрипте не запускалась. Значит, не подтверждены содержимое поля usage в реальном ответе, итоговая стоимость, время ответа и то, примет ли конкретный аккаунт значения по умолчанию. Сами значения взяты из документации OpenAI: размер 1536x1024 входит в рекомендованные наряду с 1024x1024 и 1024x1536, качество low — одно из значений low, medium, high, xhigh, max, auto. Таймаут в 300 секунд выставлен с запасом: по тому же руководству сложный запрос может обрабатываться до двух минут.

Перед первым запуском учтите условие доступа: OpenAI предупреждает, что для моделей GPT Image может потребоваться верификация организации. Для неё нужен государственный документ из поддерживаемой страны, и один человек может подтвердить только одну организацию.

Скилл image: как Claude Code находит и запускает скрипт

Чтобы не диктовать команду каждый раз, положите скрипт в скилл. Личный скилл живёт в ~/.claude/skills/image/, проектный — в .claude/skills/image/ внутри репозитория (документация по скиллам). Структура минимальная: файл SKILL.md и каталог scripts/ с generate.py.

markdown
---
name: image
description: Generate a photo or illustration with the OpenAI Images API and save it into the project. Use when the user asks to generate, draw or create a raster picture. Not for diagrams or charts.
allowed-tools: Bash(python3 ${CLAUDE_SKILL_DIR}/scripts/generate.py *)
---

Run exactly one command per image:

python3 ${CLAUDE_SKILL_DIR}/scripts/generate.py --prompt "PROMPT" --out PATH

- Write the prompt in English and describe subject, style, lighting and framing.
- Save under assets/ unless the user names another folder. Never reuse an existing file name.
- Keep the default model and quality unless the user asks for something else.
- After the script prints JSON, report the saved path and the usage field. Do not retry on HTTP errors; show the error instead.

Поле description решает, когда Claude сам подключит скилл: по нему он понимает, что просьба «сделай главную картинку для лендинга» относится сюда. Вручную скилл вызывается командой /image. Переменная ${CLAUDE_SKILL_DIR} подставляется и в тексте скилла, и в правиле allowed-tools, так что правило совпадает с командой, которую Claude реально выполняет; сам приём взят из официального примера allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *), а сочетание с generate.py — уже ваша сборка, которую стоит один раз проверить на запросе с несуществующим ключом.

Новый или изменённый скилл подхватывается в текущей сессии. Исключение одно: если каталога skills верхнего уровня не было в момент старта сессии, выполните /reload-skills. Личные скиллы не попадают в Cowork и облачные сессии. С каких ещё скиллов имеет смысл начинать, разобрано в обзоре лучших skills для Claude Code.

Тот же каркас подходит для Gemini. По состоянию на 2 октября 2026 года рабочие идентификаторы — gemini-3.1-flash-lite-image, gemini-3.1-flash-image и gemini-3-pro-image, а gemini-2.5-flash-image отключается именно 2 октября (список отключений). Готовый скрипт, папка скилла и MCP-расширение от Google описаны в отдельном руководстве «Nano Banana в Claude Code: подключение через скилл или MCP».

MCP-серверы Hugging Face, fal.ai и Replicate: команды подключения

MCP-сервер удобен, когда не хочется писать скрипт или нужно перебирать модели. Все три команды ниже взяты из документации площадок без пробного запуска, поэтому что именно каждый сервер возвращает в Claude Code (само изображение или ссылку на него), зависит от сервера и выясняется при первом вызове.

Hugging Face. В README официального сервера есть раздел для Claude Code (hf-mcp-server):

bash
claude mcp add hf-mcp-server -t http "https://huggingface.co/mcp?login"

В README адрес написан без кавычек; в zsh их лучше поставить из-за знака вопроса. После этого запустите claude и пройдите авторизацию. Генерация идёт через Spaces, которые вы добавляете на странице huggingface.co/settings/mcp; в примерах Hugging Face это Spaces с моделями FLUX и Qwen Image. Бесплатный объём здесь задаёт суточная квота GPU-времени ZeroGPU: 2 минуты без входа, 5 минут для бесплатного аккаунта, 40 минут для PRO (документация ZeroGPU).

fal.ai. Размещённый сервер подключается одной командой (документация fal):

bash
claude mcp add --transport http fal-ai https://mcp.fal.ai/mcp --header "Authorization: Bearer YOUR_FAL_KEY"

Сам сервер бесплатный, оплачиваются запуски моделей. Среди инструментов есть run_model и get_pricing: попросите Claude вызвать второй до первого, чтобы увидеть цену запуска заранее. Проверьте подключение командой /mcp.

Replicate. На странице mcp.replicate.com приведена команда:

bash
claude mcp add replicate https://mcp.replicate.com/sse --transport sse --scope user

Затем авторизация через /mcp. Учтите, что эта команда использует транспорт SSE, который в документации Claude Code помечен как устаревший.

Коннекторы из аккаунта claude.ai (в их числе Hugging Face) появляются в Claude Code только при входе через аккаунт claude.ai. При работе с ANTHROPIC_API_KEY их не будет, и останутся серверы, добавленные через claude mcp add.

Два технических условия относятся ко всем графическим MCP-серверам (раздел об изображениях в результатах инструментов):

  • Сохранение исходных байтов в файл работает начиная с Claude Code v2.1.283. В более старых версиях Claude получает только встроенную копию, возможно уменьшенную.
  • На ответ с изображением действует лимит токенов вывода MCP: предупреждение на 10 000 токенов, порог по умолчанию 25 000. Для инструментов, возвращающих картинки, единственный способ поднять порог — переменная MAX_MCP_OUTPUT_TOKENS.

Сколько стоит одно изображение: тарифы OpenAI, Gemini и Cloudflare

Каждый путь тарифицируется по-своему, и фиксированная цена за картинку есть не у всех. Данные ниже — по официальным страницам тарифов на 2 октября 2026 года.

ПоставщикКак считаетсяЦифрыБесплатный объём
OpenAI, gpt-image-2.5-flare и gpt-image-2.5-sunburstПо токенамВывод изображения $30 за 1 млн токенов, ввод изображения $8, ввод текста $5Нет
Gemini, gemini-3.1-flash-imageЗа изображение, по разрешению$0,045 (0.5K), $0,067 (1K), $0,101 (2K), $0,151 (4K)Нет: нужна включённая оплата
Gemini, gemini-3.1-flash-lite-imageЗа изображение$0,0336 (1K)Нет
Gemini, gemini-3-pro-imageЗа изображение$0,134 (1K и 2K), $0,24 (4K)Нет
Cloudflare Workers AI, @cf/black-forest-labs/flux-1-schnellВ нейронах4,80 нейрона за плитку 512×512 и 9,60 за шаг; сверх лимита $0,011 за 1 000 нейронов10 000 нейронов в сутки
Hugging Face ZeroGPUВ минутах GPU—5 минут в сутки на бесплатном аккаунте

Источники: тарифы OpenAI, тарифы Gemini API, тарифы Workers AI.

Как считается цена изображения: OpenAI по токенам, Gemini за изображение по разрешению, Cloudflare Workers AI в нейронах с расчётом 57,6 нейрона и около 173 изображений в сутки

OpenAI. Официальной цены за одно изображение нет, поэтому сумму считают из ответа: число выходных токенов из usage умножается на 30 и делится на 1 000 000. Скрипт выше печатает usage после каждого вызова именно для этого: сгенерируйте одну картинку с нужным размером и качеством, посчитайте по формуле и умножьте на планируемое количество. Подробный разбор оплаты по токенам — в материале «GPT Image 2.5 Sunburst: цена API и бюджет генерации». На уровне Tier 1 действует ещё и ограничение скорости: 5 изображений в минуту.

Cloudflare. Оценка по тарифной сетке: изображение 1024×1024 — это 4 плитки 512×512, при 4 шагах по умолчанию получается 4 × 4,80 + 4 × 9,60 = 57,6 нейрона. Суточные 10 000 нейронов дают 10 000 ÷ 57,6 ≈ 173 таких изображения, если на аккаунте больше ничего не расходует лимит. Лимит обнуляется в 00:00 UTC, а после его исчерпания запросы на бесплатном плане завершаются ошибкой. Официальный вызов:

bash
curl https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/ai/run/@cf/black-forest-labs/flux-1-schnell \
  -X POST \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -d '{ "prompt": "cyberpunk cat" }'

Модель возвращает JPEG в base64, так что декодирование в файл снова остаётся за скриптом, который Claude Code напишет по вашей просьбе.

Фиксированная цена за вызов у стороннего сервиса. Если расчёт по токенам неудобен или пройти верификацию организации OpenAI и включить оплату Gemini не получается, есть сторонний вариант: laozhang.ai, API-сервис владельца этого блога. В его документации по состоянию на 12 сентября 2026 года указаны gpt-image-2.5-sunburst-vip и gpt-image-2.5-flare-vip по $0,03 за вызов через совместимый с OpenAI адрес https://api2.laozhang.ai/v1, а по состоянию на 24 сентября — gemini-3.1-flash-image за $0,055 и gemini-3-pro-image за $0,09 за вызов независимо от разрешения. Это не OpenAI и не Google: их условия обработки данных и гарантии доступности на такой сервис не распространяются. В generate.py для него придётся добавить идентификаторы с суффиксом -vip в кортеж MODELS и задать OPENAI_BASE_URL; такая связка не запускалась, и её первой проверкой должен стать один вызов с просмотром ответа.

Где хранить ключ и что означает «больше не спрашивать»

Ключ должен жить в окружении, а не в репозитории и не в тексте запроса. Переменные оболочки Claude Code читает при запуске, поэтому после смены ключа сессию нужно перезапустить (настройки Claude Code). Вставлять ключ в диалог не стоит: он останется в истории сессии.

У MCP-серверов есть особенность: claude mcp add --header и claude mcp add --env KEY=value записывают значение в конфигурацию в открытом виде. Команда fal.ai выше поступает именно так. В общем репозитории используйте .mcp.json с подстановкой ${VAR}, чтобы в git попадало имя переменной, а не ключ. Файлы с ключами закройте правилом запрета, например Read(./.env) в permissions.deny (разрешения).

С автоматическим разрешением важно различать два уровня:

  • allowed-tools в скилле действует только в том ходе, где скилл вызван, и сбрасывается при вашем следующем сообщении. За один ход Claude может запустить скрипт несколько раз без вопросов, но не дольше.
  • Постоянное allow-правило появляется, когда на запрос подтверждения вы отвечаете «Yes, and don't ask again»: правило записывается в .claude/settings.local.json и действует во всех будущих сессиях в этом репозитории. Для скрипта генерации это означает платные вызовы без подтверждения, сколько бы их ни понадобилось Claude.

Для генерации изображений разумно оставить первый уровень и не выдавать второй, пока стоимость вызова не известна по usage. Ограничивать аргументы команды шаблоном в правиле не поможет: документация называет такие шаблоны хрупкими.

В чужом репозитории сначала прочитайте скиллы. Поле allowed-tools проектного скилла применяется даже в папке, которой вы ещё не доверяли, так что скилл из репозитория может сам выдать себе право запускать команды.

Посмотреть результат и исправить: Claude видит уменьшенную копию

Claude Code может открыть готовый файл инструментом Read и увидеть его как изображение, поэтому цикл «сгенерировать, посмотреть, поправить запрос, сгенерировать снова» работает без вашего участия на шаге проверки (справочник инструментов). Свой референс передаётся перетаскиванием в терминал, вставкой через Ctrl+V (Alt+V в Windows и WSL) или путём к файлу.

У этого цикла два ограничения. Первое: большие изображения перед отправкой модели уменьшаются и пережимаются, а начиная с v2.1.196 файл, который и после уменьшения весит больше 500 КБ, перекодируется в JPEG пониженного качества. Claude оценивает композицию и крупные ошибки, но мелкий текст и артефакты на большой картинке может не заметить; для проверки деталей попросите его сначала вырезать нужный фрагмент. Второе: каждая новая попытка у внешней модели — отдельный платный вызов. Ограничьте число попыток прямо в запросе, например «не больше двух вариантов, затем покажи оба пути».

Для рендера кодом тот же цикл бесплатен и особенно полезен: Claude правит координаты в SVG, перерендеривает и смотрит снова.

Когда менять путь: 401, верификация, лимит и токены MCP

Сменить путь стоит, когда препятствие лежит не в запросе, а в доступе или в устройстве самого пути.

ПризнакЧто это значитЧто делать
HTTP 401, invalid_api_keyКлюч не тот или сессия запущена до его экспортаЭкспортировать ключ и перезапустить claude
OpenAI требует верификацию организацииДоступ к GPT Image закрыт до подтвержденияПройти верификацию либо перейти на Gemini или MCP-площадку
Запрос к Gemini отклонён на бесплатном уровнеУ графических моделей бесплатного уровня нетВключить оплату в проекте Google
Запросы Cloudflare стали завершаться ошибкойИзрасходованы 10 000 нейронов за суткиДождаться 00:00 UTC или перейти на Workers Paid
Квота ZeroGPU исчерпанаЗакончились суточные минуты GPUКвота восстановится через 24 часа после первого использования
Файла из MCP нет в проектеОн лежит в tool-results сессииПопросить Claude скопировать его; проверить версию не ниже v2.1.283
Ответ MCP обрезан или с предупреждениемСработал лимит токенов выводаПоднять MAX_MCP_OUTPUT_TOKENS или перейти на скрипт, который пишет файл сам
На картинке искажён текстНадписи рисует модель генерацииСделать изображение кодом или наложить текст поверх через SVG

Частые вопросы

Можно ли генерировать изображения в Claude Code бесплатно?

Без оплаты работают рендер кодом и два варианта с суточным лимитом: 5 минут GPU ZeroGPU на бесплатном аккаунте Hugging Face и 10 000 нейронов в сутки у Cloudflare Workers AI. У графических моделей OpenAI и Gemini бесплатного уровня нет. Утверждения о неограниченной бесплатной генерации в документации этих площадок не подтверждаются.

Куда Claude Code сохраняет сгенерированную картинку?

Скрипт пишет файл по пути из аргумента --out, то есть в проект. Изображение из инструмента MCP сохраняется в каталог tool-results сессии внутри ~/.claude/projects/, и Claude получает путь к нему; это работает начиная с v2.1.283.

Можно ли оставить Claude Code генерировать картинки без присмотра?

Технически да, если выдать постоянное allow-правило на команду генерации, но тогда каждый запуск — платный вызов без подтверждения. Безопаснее держать разрешение в allowed-tools скилла, которое действует один ход, и ограничивать число попыток в самом запросе.

Работает ли генерация через Codex CLI и подписку ChatGPT?

Такую связку описывают в роликах и постах, но это отдельный путь через другой инструмент: изображение там создаёт Codex CLI в рамках подписки ChatGPT, а не API с оплатой за вызов, поэтому приведённые выше тарифы и расчёты к ней не применимы. Пути с описанием в документации Claude Code и поставщиков API — рендер кодом, скрипт с API-ключом и MCP-сервер.

Ещё по теме Claude Code
Claude Memory MCP: сначала встроенная память Claude Code, потом внешняя эскалация при реальном пороге
Claude Code

Claude Memory MCP в 2026: что это такое, что Claude Code уже помнит и когда действительно нужен внешний MCP

Практическое руководство по границе между встроенной памятью Claude Code и внешним memory MCP: что уже делают `CLAUDE.md` и auto memory, когда внешняя persistence реально добавляет ценность и какой setup surface оказывается самым легким и безопасным.

11 мин