krita-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| KRITA_MCP_HOME | No | Folder holding the bridge token. | ~/.krita-mcp |
| KRITA_MCP_HOST | No | Host of the Krita bridge. | 127.0.0.1 |
| KRITA_MCP_PORT | No | Port of the Krita bridge (not the MCP HTTP port). | 5679 |
| KRITA_MCP_TOKEN | No | Bridge token, used instead of reading it from KRITA_MCP_HOME. | |
| KRITA_MCP_HTTP_TOKEN | No | Bearer token HTTP clients must send via 'Authorization: Bearer …'. Defaults to a random token printed at server start. Required when binding the HTTP server to anything other than loopback. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Controls a running Krita instance. When the user asks for a picture from a prompt, start with create_artwork: it decides whether to GENERATE it with an image model (realistic / photographic results) or set it up for you to PAINT it with Krita's brushes, and you finish the work. Typical workflow:
krita_status (shows the workspace folder; all file paths must be inside it).
document_new or document_open, then work on separate layers: draw_shapes (crisp geometry), brush_stroke (Krita's real brushes), add_svg (editable vector shapes/text), import_image, filters.
LOOK at your work: canvas_snapshot (use grid=100 to read exact coordinates), and READ it: analyze_image (palette, light, contrast, layout), read_pixels (exact colours), find_color (where a colour is). Iterate until it looks right.
export_image / save_document to write files into the workspace. undo/redo revert whole AI edits (pixels, properties, layers). Use batch to run many steps in one call. Photos: adjust_image (levels, curves, hue/saturation, sharpen, denoise...), auto_enhance, add_vignette. Video/animation: import_video -> edit frames (animation_set frame=..., or for_each_frame) -> render_video; keyframe/list_keyframes, animation_contact_sheet to review motion. krita_action runs Krita's own commands. Generative AI (ai_backends shows what is connected: ComfyUI, AUTOMATIC1111/Forge, OpenAI, Gemini, Stability, Replicate, fal): generate_image (txt2img / img2img / inpaint the selection, count>1 = variations
comparison sheet -> pick_variation), outpaint, upscale_image, remove_background, match_colors (blend an element into the scene), generate_video (Sora, Veo, HeyGen avatars, ...), ask_vision (second opinion from Claude, GPT or Gemini). Results always land on new layers, cut to the selection, one undo step each. Free services (Pollinations, AI Horde) work without an account once the user turns them on. Skills: for bigger tasks, find_skills (a few words) and use_skill the one that fits - proven step-by-step workflows; they are loaded only when needed. Coordinates are pixels with the origin at the top-left. Colours are '#rrggbb' or '#rrggbbaa'. Layers can be referenced by id or (if unique) name.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| krita_statusB | Krita version, the sandboxed workspace folder, and the open documents (index, size, active). |
| document_newB | Create a new RGBA 8-bit sRGB document and make it active. background: colour or 'transparent'. |
| document_openB | Open a .kra/.ora/.psd or image file from the workspace and make it active. |
| document_activateB | Switch the active document (index from krita_status). |
| document_infoA | Active document details including the full layer tree (listed bottom-to-top) and selection bounds. |
| save_documentA | Save the active document as native .kra/.ora in the workspace (omit path to re-save in place). |
| export_imageA | Export the flattened image to png/jpg/webp/bmp/tiff/psd/ora in the workspace (format from extension). layer = export only that layer (cropped to its content unless full_canvas). quality = 0-100 for jpg/webp. x/y/width/height = export just that region (e.g. the area to send to an inpainting model). |
| document_closeA | Close the active document. Unsaved changes are discarded unless save=true. |
| resize_canvasB | Change the canvas size WITHOUT scaling content. Offsets shift existing content. |
| scale_imageB | Scale the whole image (all layers) to a new size. method: Bicubic, Bilinear, Lanczos3, Box, Hermite, Mitchell, BSpline or NearestNeighbor (pixel art). |
| crop_imageB | Crop the canvas to a rectangle, or to the current selection's bounds when no rectangle is given. |
| rotate_imageA | Rotate the whole image clockwise by any angle; the canvas grows to fit. |
| flipB | Mirror the whole image (target=image) or one layer (target=layer). direction: horizontal or vertical. |
| flatten_imageB | Merge all layers into one. |
| canvas_snapshotA | Return the current composite image so you can SEE the canvas. Optionally zoom into a region
(x, y, width, height in canvas pixels). max_size caps the longest side (64-4096).
layer = show only that layer (transparent elsewhere).
grid = draw labelled canvas-coordinate lines every |
| sample_colorB | Colour (rgba + '#rrggbbaa') of one pixel of the visible image, or of a single layer if given. |
| list_layersB | Layer tree of the active document (children bottom-to-top) and the active layer id. |
| create_layerA | Create a layer or mask; it becomes the active layer. type:
paintlayer (fill = optional solid colour), vectorlayer, grouplayer,
filllayer (fill = colour, or pattern = pattern resource name) - a non-destructive colour/pattern layer,
filterlayer (filter + filter_params) - non-destructive adjustment of everything below,
clonelayer (source = layer to mirror live),
filelayer (path = image in the workspace, kept as a live link),
filllayer with generator = seexpr | screentone | gradient | multigrid and generator_config, e.g.
seexpr {"script": "$c = noise(10*$u, 10*$v); [$c, $c*0.8, 1-$c]"} (procedural textures),
screentone {"pattern": 0, "shape": 0, "frequency_x": 30, "rotation": 45,
"foreground_color": "#000000", "background_color": "#ffffff"} (manga tones),
gradient {"shape": "radial", "start_position_x": 50, "start_position_y": 50,
"end_position_x": 100, "end_position_y": 50} (uses the user's fg/bg colours),
filtermask (filter + filter_params) / transparencymask - attached to |
| update_layerB | Change layer properties. layer = id or name (default: active layer). opacity is 0..1. blend_mode uses Krita ids such as normal, multiply, screen, overlay, add, color, hue. alpha_locked = only paint where the layer already has pixels; clipped = clip to the layers below in the group (Krita "inherit alpha"); color_label 0-8. x/y place the top-left of the layer's content (its "bounds"); dx/dy move it relative to where it is. |
| arrange_layerA | Restack a layer. to = top, bottom, up or down; or above = a sibling to sit directly over;
parent = a group to move the layer into (top of it unless |
| merge_downC | Merge a layer (default: active) into the layer below it. Returns the merged layer. |
| delete_layerC | Delete a layer (default: active layer). |
| duplicate_layerB | Duplicate a layer directly above the original. |
| transform_layerB | Scale (about the layer centre), rotate (degrees, clockwise) and/or shear a layer. |
| import_imageA | Put a raster image on a NEW paint layer. Provide |
| import_image_from_urlA | Download a PUBLIC http(s) image URL (no redirects, max 25 MB, private addresses blocked) and place it on a new layer. Same placement options as import_image. |
| draw_shapesA | Draw vector-style primitives (anti-aliased) onto a paint layer, in order (max 5000 per call).
Every shape has "type" and optional "opacity" (0..1). Types:
line {x1,y1,x2,y2,color,stroke_width}
polyline {points:[[x,y],...],color,stroke_width}
bezier {points:[start, c1,c2,end, c1,c2,end ...],color,stroke_width} (1+3n points)
rect {x,y,width,height,radius?,fill?,stroke?,stroke_width?,gradient?}
ellipse {cx,cy,rx,ry,fill?,stroke?,stroke_width?,gradient?}
polygon {points:[[x,y],...],fill?,stroke?,stroke_width?,gradient?}
text {x,y,text,size(px),font?,bold?,color} (x,y = baseline-left)
For closed shapes |
| brush_strokeA | Paint ONE stroke with Krita's real brush engine (texture, wet mixing, ... from the preset). points: [[x, y], ...] or [[x, y, pressure 0..1], ...] (pressure needs a pressure-sensitive preset). preset: brush preset name or unique part of it (see list_brush_presets; default: the current brush). size in px, opacity/flow 0..1, eraser=true erases with the brush. smooth=true curves through the points. closed/fill: close the path / fill it with the colour (outline=false for fill only). Painting respects the current selection. The user's own brush settings are restored afterwards. |
| list_brush_presetsC | Names of Krita's brush presets (optionally containing |
| set_selectionA | Select: kind=rect or ellipse (x, y, width, height), polygon (points [[x,y],...]),
layer (the opaque pixels of |
| modify_selectionC | operation: invert, grow, shrink, feather, border or smooth. amount in pixels. |
| fill_selectionA | Fill the current selection on a paint layer with a colour; omit colour to erase the selected pixels. |
| list_filtersA | Names of all Krita filters usable with apply_filter. |
| describe_filterB | Default parameters of a filter, so you know which |
| apply_filterB | Apply a Krita filter (blur, levels, invert, ...) to a paint layer, restricted to the selection if any. params: filter properties from describe_filter (string/number/bool values only). |
| undoA | Undo your last edit(s) (each tool call is one step: pixels, layer changes, selection...). native=true steps through Krita's own undo stack instead (also covers edits made by hand). |
| redoC | Redo edit(s) undone with undo. |
| historyC | Your undoable edits in the active document plus Krita's own undo stack (done=false = undone). |
| analyze_imageB | Numbers about the image (or a region / one layer): dominant palette with shares, mean colour, brightness, contrast, sharpness (0..1), coverage of non-transparent pixels, content bounds, and a grid x grid layout of mean colours (top row first). Use it to judge and match colours and lighting. |
| read_pixelsC | Exact colours of a small block (max 1024 pixels), rows top to bottom. |
| find_colorB | Where does a colour occur? Returns connected regions (bbox, share, centroid), largest first, plus total coverage. Good for locating objects before editing them. |
| view_imageA | Look at an image file in the workspace (reference, generated output, export) without importing it. |
| list_workspaceC | Files in the workspace folder (path relative to it, size, modified time). |
| export_selection_maskB | Save the current selection as a greyscale PNG mask (white = selected) for inpainting models. |
| add_svgA | Add SVG elements as EDITABLE vector shapes: , , , , , ,
, gradients in , groups. Bare elements use canvas pixel coordinates. Goes onto |
| list_vector_shapesC | Shapes on a vector layer: name, type, bbox in pixels (optionally each shape's SVG). |
| remove_vector_shapesB | Delete shapes by name from a vector layer (["all"] removes every shape). |
| list_resourcesC | Names of Krita resources: type = preset (brushes), pattern, gradient, palette, brush, workspace. |
| palette_colorsC | The colours (name + hex) of a Krita palette resource, for a coherent colour scheme. |
| set_guidesC | Set the document's guide lines (pixel positions), e.g. thirds or a layout grid the user can see. |
| animation_infoC | Frame rate, playback/clip range, current frame and animated layers. |
| animation_setC | Set frame rate, frame range (start..end) and/or go to |
| keyframeB | Keyframe operation on a paint layer at |
| list_keyframesC | Frames at which a layer has keyframes. |
| import_framesB | Load image files from the workspace (in order) as frames of a new animated layer. |
| animation_contact_sheetB | See many frames at once: a labelled grid of frames (max 48) to review motion and consistency. |
| video_infoC | Size, fps, duration, frame count, codec and audio presence of a video in the workspace. |
| import_videoA | Decode a video (mp4/mov/webm/mkv/avi/gif...) from the workspace into an animated layer so every frame can be painted, filtered or adjusted. Opens a new document sized to the video unless into_current. start/duration in seconds; fps resamples; width scales (keeps aspect). Max 1000 frames. |
| render_videoB | Render the animation (default: playback range) to .mp4 (H.264), .webm (VP9), .gif, .mov (ProRes), .mkv or .apng in the workspace, using the ffmpeg bundled with Krita. width scales the output. |
| adjust_imageA | Photo adjustment on a paint layer (limited to the selection if any). operation + settings: exact tone tools (pixel-precise, channel = rgb|r|g|b): levels {in_black, in_white, gamma, out_black, out_white} · curves {points: [[in,out],...] 0-255} brightness_contrast {brightness, contrast -100..100} · exposure {stops} · gamma {gamma} temperature {temperature -100..100 (warm+), tint -100..100 (magenta+)} Krita filters (non_destructive=true adds them as an editable filter mask instead): hue_saturation {hue -180..180, saturation, lightness -100..100, colorize} color_balance {shadows_|midtones_|highlights_ + cyan_red|magenta_green|yellow_blue: -100..100} sharpen {amount 0-10, radius, threshold} · blur {radius} · motion_blur {angle, length} lens_blur {radius} · denoise {strength} · denoise_gaussian {threshold, window} desaturate {method} · auto_contrast · normalize · invert · posterize {steps} threshold {level} · pixelize {size} · oil_paint {brush_size, smooth} · emboss {depth} edge_detect {radius} · high_pass {radius} · noise {amount, opacity, grayscale} color_to_alpha {color, threshold} · dodge / burn {exposure 0-1, range 0 shadows|1 mid|2 highlights} wave {amplitude, wavelength} · round_corners {radius} Any other Krita filter: apply_filter. |
| auto_enhanceC | One-click photo fix: stretch the tonal range (per channel also removes colour casts). |
| add_vignetteB | Darken (or tint) the edges on a new layer on top; adjust its opacity or delete it later. |
| convert_color_spaceB | Convert the image colour space, e.g. depth U16/F16/F32 for high-precision grading, back to RGBA/U8 for pixel tools. model: RGBA, GRAYA, CMYKA, LABA, XYZA. Profile defaults to sRGB. |
| colorize_lineartC | Flat-colour line art with Krita's Colourise Mask: regions = [{"color": "#e0b090", "points": [[x,y],...] (a scribble inside the area)} or {"color": ..., "rect": [x,y,w,h]}]. Krita floods each scribble's colour up to the lines. transparent_color marks areas to leave empty. |
| krita_actionB | Run one of Krita's own commands on the active document/layer (curated, no dialogs): selection: select_all, deselect, reselect, invert_selection, select_opaque(_add|_subtract|_intersect), copy_selection_to_new_layer, cut_selection_to_new_layer, clear_selection_pixels, fill_with_foreground, fill_with_background, fill_with_pattern, selection_to_vector_shape layers: convert_to_paint_layer, convert_to_animated_layer, convert_group_to_animated, convert_to_transparency_mask, convert_to_selection_mask, alpha_into_mask, flatten_layer, isolate_layer, isolate_group, rotate_layer_90_cw|90_ccw|180, mirror_all_layers_horizontally|vertically image: rotate_image_90_cw|90_ccw|180, trim_to_image, trim_to_layer, trim_to_selection, duplicate_image_as_new_document, create_snapshot animation: next_frame, previous_frame, next_keyframe, previous_keyframe, first_frame, last_frame, toggle_onion_skin, play_pause, stop_playback view: zoom_to_fit, zoom_to_100, zoom_in, zoom_out, mirror_view, rotate_view_left|right, reset_view, toggle_wrap_around, toggle_grid, toggle_pixel_grid, toggle_guides, toggle_rulers, toggle_selection_display, toggle_canvas_only |
| view_controlA | Move the user's view of the canvas (not the image): zoom (1.0 = 100%), rotation in degrees, mirror, fit to window, reset, or centre on a canvas point - e.g. to show the user what you changed. |
| notify_userB | Show a short floating message on the user's Krita canvas. |
| user_tool_stateC | Read (no arguments) or set the colours and brush the USER paints with next - e.g. hand them the palette colour or brush you used. Returns the current state. |
| export_animation_framesC | Render frames as numbered PNGs into a workspace folder. |
| batchA | Run several tool calls in one go, in order: [{"tool": "draw_shapes", "args": {...}}, ...] (max 200). Any tool except batch itself. Returns one result per operation; images (canvas_snapshot, view_image) are returned after the summary. Much faster than one call per step. |
| for_each_frameA | Apply the same tool calls to every frame of an animation / imported video, e.g. colour-grade a clip: [{"tool": "adjust_image", "args": {"operation": "temperature", "settings": {"temperature": 30}}}]. Frames default to the playback range (max 1000 frames, 20 operations). |
| ai_backendsA | Which generative-AI services are connected: image backends (ComfyUI, AUTOMATIC1111/Forge, OpenAI, Gemini, Stability, Replicate, fal) with their models/samplers/upscalers, video backends (HeyGen, Sora, Veo, Replicate, fal; details=true lists HeyGen avatars and voices), vision models for ask_vision, and the ComfyUI workflows saved in /workflows. Call this before generate_image. |
| generate_imageA | Generate pixels with an image model and place them as NEW layers (one undo step). mode: auto (inpaint if there is a selection, else txt2img), txt2img, img2img (rework the region; strength 0..1 = how much changes), inpaint (regenerate only the selected pixels; soft edges blend). The region is the selection's bounds + padding (or x/y/width/height, or region='canvas'); results are cut to the selection, so nothing outside it changes. count 1-8 = variations in a group plus a numbered comparison sheet (choose with pick_variation). backend: comfyui, a1111, openai, gemini, stability, replicate, fal (default: KRITA_MCP_IMAGE_BACKEND or the first available - see ai_backends). model = checkpoint / model id (Replicate 'owner/name', fal 'fal-ai/...'). size = longest side to generate at (default 1024). workflow = a ComfyUI API-format graph saved as /workflows/NAME.json using {{prompt}} {{negative}} {{seed}} {{image}} {{mask}} {{width}} {{height}} {{strength}} placeholders (ControlNet, IP-Adapter, Flux, ... anything ComfyUI can do). extra = provider-specific inputs. control = guide the composition with a layer, e.g. [{"layer": "Sketch", "type": "lineart", "strength": 0.8}] - paint a sketch / pose / depth layer and the model follows it. type: lineart, scribble, canny, softedge, depth, openpose, normal, seg, tile, ...; model = ControlNet model (default: the first installed whose name contains the type); preprocess = A1111 preprocessor (e.g. depth_midas when the layer is a photo); start/end 0..1; layer omitted = the whole picture. Real ControlNet on comfyui / a1111 (several guides at once; in workflows use {{control}} / {{control_1}}...); stability uses its sketch / structure control; openai and gemini receive the guide as the image to follow. style = a look recipe added to the prompt (with a matching negative prompt): photo, cinematic, portrait, product, fashion, street, landscape, macro, food, architecture, drone (realistic) or concept_art, illustration, anime, watercolor, oil_painting, 3d_render, pixel_art, comic, sketch. |
| outpaintB | Extend the picture beyond its edges: grows the canvas by left/right/top/bottom pixels, selects the
new border (reaching |
| pick_variationA | Show variant |
| upscale_imageA | AI super-resolution: scales the document by |
| remove_backgroundA | Cut the subject out of a layer. mode: mask (non-destructive transparency mask, default), erase, or
select (just select the subject). method: color (local, no AI: floods the plain background in from the
image border, within |
| match_colorsA | Make a layer's colours sit in the scene: transfers the mean and contrast of each channel from a reference (another layer, an image file in the workspace, or a region [x,y,w,h] of the picture - by default the whole picture). Use after pasting or generating an element. Respects the selection. |
| generate_videoA | Make a video with a video model, save it in the workspace and (by default) open it in Krita as an animation to paint over, grade or re-render. use_canvas=true sends the current picture as the start frame (image-to-video) or, for HeyGen, as the background behind the avatar. backend: heygen (talking avatar: script + avatar_id + voice_id; character='photo' makes the character painted on the canvas talk), openai (Sora), gemini (Veo), replicate / fal (any video model id). camera = a cinematic camera move written into the prompt: dolly_in, dolly_out, push_in, pull_back, crash_zoom, pan_left/right, tilt_up/down, orbit_left/right, crane_up/down, handheld, fpv_drone, whip_pan, bullet_time, ken_burns, static. style = a look (cinematic, photo, anime, ... as in generate_image). Generation can take several minutes. (No video model? camera_move animates the picture locally.) |
| ask_visionB | Ask another vision AI about the canvas and get its answer as text: a second opinion or critique, a caption, or a detailed prompt for an image model. provider: anthropic (Claude), openai (GPT, or any OpenAI-compatible server such as Ollama or LM Studio), gemini. Optionally a region or a single layer. |
| create_artworkA | START HERE when the user asks you to make a picture from a prompt. Creates the document and either GENERATES it with an image model (realistic photos, cinematic stills, anything photographic) or sets it up for you to PAINT it with Krita's own brushes. approach: auto (decides: realism or a connected image model -> generate; hand-made / graphic requests or no model -> paint), generate, paint, or hybrid (generate, then add layers for you to paint over and refine). style: photo, cinematic, portrait, product, fashion, street, landscape, macro, food, architecture, drone, concept_art, illustration, anime, watercolor, oil_painting, 3d_render, pixel_art, comic, sketch (default: guessed from the prompt). aspect: 1:1, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16, 21:9, 4:5, 5:4 (or width/height). count = variations to compare (generate; default 4 on a local GPU, 1 on paid cloud services, which charge per image). For painting it returns a plan; then use brush_stroke / draw_shapes / add_svg, look with canvas_snapshot, and iterate. To turn your painted sketch into a realistic image later: generate_image(control=[{"layer": "Sketch", "type": "scribble"}], style="photo"). |
| camera_moveA | Bring a still to life without any AI model: renders the current picture through a moving virtual camera into an animation (a new document by default). move: dolly_in, dolly_out, push_in, pull_back, zoom_in, zoom_out, crash_zoom, pan_left, pan_right, tilt_up, tilt_down, orbit_left, orbit_right, crane_up, crane_down, handheld, ken_burns, static. intensity 0.1-3. render_path = also render it, e.g. 'shot.mp4'. |
| search_assetsA | Find free real-world material to make work realistic. kind: textures - Poly Haven CC0 photo textures (rock, wood, bark, fabric, leather, skin, metal, ground, ...), hdris - Poly Haven CC0 HDRI panoramas as photographic skies and backdrops, photos - Openverse openly licensed photos for reference or compositing (licence: e.g. 'cc0,pdm' for no attribution, or 'by,by-sa'); results include the attribution text. Then import_asset(id, kind). |
| import_assetA | Put a search_assets result on a new layer. Textures tile across the canvas by default (tile_size = px per tile; texture_map: diffuse, normal, roughness, ao, displacement); hdris and photos cover the canvas (fit: cover, contain, stretch, tile, none). To texture a painted shape: import it, then update_layer(clipped=true, blend_mode='overlay' or 'multiply') above the shape in the same group. Returns the layer and the attribution to credit (photos). |
| find_skillsA | Find skills - step-by-step know-how for kinds of Krita work (photoreal images, hand painting, retouching, video, and any the user installed). Search with a few words about the task; then load the one that fits with use_skill. Cheap: returns names and one-line descriptions only. |
| use_skillA | Load a skill's instructions (from find_skills) and follow them. file = one of the extra text files the skill lists (references, templates). Skills are text only; nothing in them is executed. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| create | Make anything from a prompt: Krita decides whether to generate it (realistic) or paint it. |
| paint_scene | Plan and paint a scene with Krita's own tools, then critique and refine it. |
| generative_inpaint | Change part of the picture with an image model while keeping everything else. |
| concept_variations | Explore several design directions quickly, then develop the best. |
| retouch_photo | Retouch the open photo: tone, colour, cleanup, finish. |
| animate | Make a short frame-by-frame or AI-assisted animation. |
| product_shot | Cut out a product and stage it in a newly generated setting. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 86 tools
Most tools target distinct resources or actions, but the 86-tool surface has several overlapping clusters: adjust_image vs apply_filter vs auto_enhance, view_control vs krita_action view commands, set_selection vs krita_action selection commands, and the create_artwork/generate_image split. The detailed descriptions clarify these boundaries, but an agent still has a realistic chance of choosing a redundant or lower-level tool.
The set is overwhelmingly snake_case and follows a predictable verb_noun or noun_info pattern across documents, layers, selections, animation, and media. A few names are noun-only or verb-less (keyframe, history, batch, outpaint, palette_colors), but they remain readable and do not break the overall convention.
At 86 tools, the surface is far beyond the well-scoped 3-15 range and crosses the extreme-mismatch threshold of 50+. Krita is broad, but this many tools creates a sprawling interface where the agent must navigate many specialized and partially overlapping operations.
The surface covers document lifecycle, layer CRUD and arrangement, selections, filters, drawing, vector shapes, animation, video import/render, AI generation, asset search, skills, undo/history, and batching. Only minor gaps such as direct editing of existing vector shapes exist, and those have practical workarounds.