ASCII Motion MCP
This MCP server enables creating, editing, animating, importing, and exporting ASCII art projects through an MCP host, with live browser bridge or local headless document editing.
Draw and edit canvas cells: get/set/clear cells, batch set, paste ASCII blocks, fill regions, resize/clear canvas.
Manage animation frames: list/add/delete/duplicate/navigate frames, set duration/name, shift/flip/copy content, interpolate, diff/compare/describe.
Work with layers, groups, content frames, keyframes, transforms, and timeline settings (FPS/duration).
Apply visual effects and procedural effect blocks with keyframes; run and preview generators.
Import media: images, videos, and ASCII text files into the canvas.
Export: text, JSON, native session, HTML, React, ANSI, Ink, Bubbletea, OpenTUI, plus PNG/JPG/SVG and MP4/WebM via browser.
Manage projects and files: new/save/load, list project files, set project name, undo/redo, history status.
Use palettes and colors: list character/color palettes, get active colors, set foreground/background/selected character, suggest palettes.
Perform selection operations: select rectangle/by color, get/clear selection, apply to selection, delete selection content.
Connect to the ASCII Motion app in live mode: get auth token, check connection status, refresh state from browser.
Batch and efficiency tools: apply_operations, bounded artifacts, revision checks, and scoped reads.
Enables GitHub Copilot to create, animate, and export ASCII art through the ASCII Motion MCP server.
Allows exporting ASCII art and animations as React components.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ASCII Motion MCP animate a bouncing ball with 8 frames"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ASCII Motion MCP
Create, animate and export ASCII art from an MCP-compatible assistant, using ASCII Motion as the authoritative editor.
Version 3 requires bridge v3.
ascii-motion-mcp@3pairs with ascii-motion.app 2.2.6 or later (bridge contracte76f9c34204f). Checkget_capabilitiesafter connecting. Useascii-motion-mcp@2.3.0only with older app builds that lack v3 negotiation.
Install and connect
Use Node.js 22 or 24. An MCP host starts the server; the browser connects to that same process. Do not start a second terminal instance to obtain a token.
For a published release:
npm install -g ascii-motion-mcpFrom a source checkout (for development):
npm ci
npm run build
node dist/index.js --helpConfigure the host with command: "node" and arguments
["/absolute/path/to/ascii-motion-mcp/dist/index.js", "--live", "--project-dir", "/absolute/path/to/projects"]. A source build must match the app's bridge contract.
GitHub Copilot app
Open Customize > MCP, add a custom stdio server, and enter the command and
arguments above. Manage it under Installed. For a published installation,
the command can instead be ascii-motion-mcp with --live --project-dir ....
In the same Copilot conversation, call get_auth_token and
get_connection_status. Open the app's MCP Connection dialog, enter that
instance's token and port, and connect. Treat the token as a secret.
The Copilot app starts a separate server for every conversation that has the
MCP enabled. A server binds its live port only when a tool is first used, so
idle conversations do not hold it. If another conversation already owns the
port, live tools return PORT_IN_USE instead of crashing; close that
conversation (or stop its server) and retry, and the server binds on the next
tool call.
GitHub Copilot CLI
Use the standalone copilot CLI, not the retired gh copilot extension:
copilot mcp add ascii-motion -- node /absolute/path/to/ascii-motion-mcp/dist/index.js --live --project-dir /absolute/path/to/projects --port 9876The CLI's configuration is ~/.copilot/mcp-config.json. Its mcpServers entries
are not the same schema as VS Code's servers entries.
VS Code with Copilot
Create .vscode/mcp.json:
{
"servers": {
"ascii-motion": {
"type": "stdio",
"command": "node",
"args": [
"/absolute/path/to/ascii-motion-mcp/dist/index.js",
"--live",
"--project-dir",
"${workspaceFolder}"
]
}
}
}For Claude Desktop, Cursor or Windsurf, add an equivalent stdio entry using the
host's MCP settings. Claude Desktop and Windsurf use a top-level mcpServers
object; Cursor uses its MCP configuration, not mcp.servers in generic editor
settings. Restart or reload the server after changing its command.
Related MCP server: ASCII & SVG Art Studio
Live and headless behavior
In live mode, inputs and acknowledged results are validated against the app-owned contract. Reads sample the actual compositor at an absolute timeline frame, including transforms, generators and procedural effects. Raster shaders apply to rendered image/video exports, not character-cell reads.
Mutations are ordered, revision-checked and applied by the app. A timeout, disconnect, invalid target or locked layer is an error, not a successful edit to a private server copy. Only one browser tab owns a connection. Reconnect and refresh after an indeterminate timeout before retrying a destructive action.
Without --live, compatible document tools edit and save a local document.
Headless mode does not recreate the app's compositor, shader renderer, media
pipeline or cloud authentication. Native saves preserve layers, groups,
typography, palettes, effects, shaders, generators and additive native fields.
Compatibility corrections include integer frame rates of 1..60 (the app's actual range), motion-trails in the effect-block enum, and bounded preview/diff pagination. Existing names are retained, but obsolete ranges are not advertised as working against the current editor.
Some old inputs cannot be represented by the current app. Connected groups
require two distinct, ungrouped layers. OpenTUI exports TypeScript/TSX, not
Python; use componentName, not className. The connected Bubble Tea exporter
uses modelName: "Model". HTML always includes controls and loops indefinitely,
and JSON exports are sparse. Unsupported requests fail explicitly rather than
silently dropping options.
Connected legacy image/video imports use the app conversion pipeline, with
top-left placement and the legacy dark-to-bright charset order preserved.
Exact source-color backgrounds and the old brightness-dither
options are not supported by this adapter. Use import_media and
get_catalog {family:"tools"} for native palette mapping, conversion settings
and video sampling windows. Legacy image import overlays non-empty cells,
preserving unrelated artwork. Canonical mode:"new_layer", "replace" and
image-only "overlay" make the placement policy explicit.
Discover and work efficiently
Start with get_capabilities and get_document_summary. Use get_catalog for
current effect, shader, generator, palette, font, drawing and export options.
tools/list is authoritative; there is no manually maintained tool-count table.
Full typed discovery is larger than the old partial toolset. Use host-side
progressive/tool-search discovery where available; response paging reduces
result tokens, not the size of the initial tool schemas.
Existing tool names remain compatibility entrypoints. Where a canonical app
operation has the same name but different inputs, it is exposed with an app_
prefix: for example, load_project reads a local file, while app_load_project
accepts a session object. Prefer the stable-ID, explicit-target operation for
new workflows.
All new
frame,startFrameanddurationFramesfields are zero-based timeline frames, not milliseconds or array indices.Address layers, content frames, effects, shaders and keyframes by their returned IDs. Compatibility content-frame indices are ordinals.
Pass the revision returned by an authoritative read as
expectedRevisionwhen a later canonical tool must not overwrite intervening UI edits.Use scoped
read_cells,get_canvas_asciiorget_canvas_previewbefore editing. Useget_canvas_renderfor a bounded ANSI terminal preview.Batch cells or independent mutations.
apply_operationsis atomic and produces one undo entry; it rejects nested batches, history/project resets and IO/cloud operations.Default responses are bounded to 16 KiB. Full results and exports are saved as artifacts instead of dumping large documents or base64 into the model. Follow
nextOffsetwithread_artifact; explicit artifact pages allow up to 8192 bytes and remain below the 64 KiB page-response ceiling.
Artifacts are saved under the project directory, by default in
.ascii-motion/artifacts/. Resource handles belong to the current server
session; saved file paths remain usable after restarting.
Supported workflows
The app contract covers drawing/brush/vector/Bezier/gradient/text/FIGlet/ASCII boxes; selection/clipboard/transforms; layer/group/content-frame editing; transform animation; effects and shaders; procedural generators; palettes; image/video import and trace overlays; native project files; and authenticated cloud project management.
Use live export catalogs for options and availability. Formats include PNG, JPG, SVG, WebM, MP4, image sequences, native sessions, text, JSON, ANSI, HTML, React, Ink, OpenTUI and Bubbletea. There is no GIF exporter. MP4 and other media codecs depend on the browser. Cloud operations use the browser's signed-in account and enforce its actual entitlements; account/billing/admin actions are not MCP authoring tools.
Examples:
Create a small project, inspect the active layer and content-frame IDs, and draw a character graphic using one cell batch.
Add an Animated Text generator with a typewriter reveal, preview timeline frame 12, then undo and redo the change.
Export a WebM artifact without triggering a browser download, and save the complete native project in my project directory.
CLI
ascii-motion-mcp [--live] [--project-dir PATH] [--port PORT]
--live Enable the loopback browser bridge
--project-dir PATH File-operation root (default: current directory)
--port PORT Bridge port, 1..65535 (default: 9876)
--help Show help
--version Show the installed package versionASCII_MOTION_PROJECT_DIR also sets the file root. Files must stay within it,
including through symlinks. A remote/cloud-hosted MCP process cannot reach your
local browser merely because both use a loopback address.
Development
See Contributing, bridge protocol, updating and release coordination. The SDK serves both legacy initialization and modern MCP discovery over stdio. MCP Apps, resumable tasks and remote hosting are not required by this bridge and are not advertised as supported integrations.
Published app documentation lives in
Ascii-Motion-Web/docs-site, mounted at packages/web in the app repository.
MIT License. See LICENSE.
Available Tools
96 toolsadd_content_frameB
Add a new content frame (canvas data segment) to a layer at a specific timeline position.
Inputs: layerId (required), startFrame (required), durationFrames (required), data.
add_effect_blockA
Add a non-destructive procedural effect to a layer, group, or global effects. Available types: levels, hue-saturation, remap-colors, remap-characters, scatter, wave-warp, wiggle.
Inputs: ownerId (required), effectType (required), startFrame, durationFrames, +1 more.
add_effect_keyframeA
Add a keyframe to a procedural effect property. Creates the property track if it doesn't exist.
Inputs: blockId (required), propertyPath (required), frame (required), value (required).
add_frameC
Add a new frame to the animation
Inputs: atIndex, duration, copyFromIndex, name.
add_keyframeA
Add a keyframe to a layer property track. Creates the property track if it doesn't exist.
Inputs: layerId (required), propertyPath (required), frame (required), value (required), +1 more.
add_layerA
Add a new layer to the project. If project is in legacy frame mode, this switches it to layer mode.
Inputs: name.
apply_effectC
Apply a visual effect to the current frame or selection. Effects modify colors and/or characters.
Inputs: effect (required), brightness, contrast, hue, +10 more.
apply_to_selectionC
Apply an operation to all cells in the current selection
Inputs: operation (required), char, color, bgColor.
batch_recolorB
Replace one color with another across the entire frame or selection.
Inputs: oldColor (required), newColor (required), target, frameIndex.
batch_replace_charA
Replace one character with another across the entire frame or selection.
Inputs: oldChar (required), newChar (required), frameIndex.
clear_canvasA
Clear all cells on the current frame, leaving it empty
Inputs: no named parameters.
clear_cellA
Clear a cell, resetting it to empty (space with transparent background)
Inputs: x (required), y (required).
clear_selectionA
Clear the current selection (deselect)
Inputs: no named parameters.
compare_framesB
Compare two frames and show what cells changed between them. Useful for understanding motion and edits in an animation.
Inputs: frameA (required), frameB (required), showUnchanged.
copy_frame_and_modifyA
Duplicate a frame and apply modifications in a single operation. Efficient for creating animation sequences.
Inputs: sourceIndex (required), modifications (required), insertAtIndex, name, +1 more.
copy_region_to_frameC
Copy a region of cells from one frame to another
Inputs: sourceFrame (required), targetFrame (required), sourceRegion (required), targetPosition, +1 more.
create_groupB
Create a layer group to organize layers together.
Inputs: name, layerIds.
delete_frameA
Delete a frame from the animation. Cannot delete the last remaining frame.
Inputs: index (required).
delete_selection_contentB
Delete all cell content within the current selection
Inputs: no named parameters.
describe_animationA
Get a high-level description of the animation: frame count, timing, and motion patterns.
Inputs: no named parameters.
duplicate_frameB
Duplicate a frame, inserting the copy immediately after the original
Inputs: index (required).
duplicate_layerA
Duplicate a layer with all its content frames and property tracks.
Inputs: layerId (required).
export_ansiB
Export the current frame with ANSI escape codes for terminal display.
Inputs: frameIndex, colorMode.
export_bubbleteaA
Export the current frame as a Bubbletea (Go TUI) component.
Inputs: filePath, frameIndex, packageName, modelName, +1 more.
export_htmlB
Export the animation as a self-contained HTML file with embedded animation player.
Inputs: filePath, backgroundColor, fontFamily, fontSize, +3 more.
export_imageA
Export the current frame as an image (PNG, JPG, or SVG). The browser renders the image at full quality. Requires live mode with a connected browser.
Inputs: filePath (required), format, sizeMultiplier, includeGrid, +2 more.
export_inkA
Export the current frame as an Ink (React CLI) component for Node.js terminal apps.
Inputs: filePath, frameIndex, componentName, includeAnimation.
export_jsonA
Export the project as structured JSON data. Good for programmatic processing.
Inputs: filePath, includeMetadata, humanReadable, includeEmptyCells.
export_opentuiB
Export the current frame as an OpenTUI (Python TUI) component.
Inputs: filePath, frameIndex, className, includeAnimation.
export_reactB
Export the animation as a React component (JSX or TSX).
Inputs: filePath, typescript, includeControls, componentName.
export_sessionA
Export the project as an .asciimtn session file (can be loaded by Ascii-Motion app).
Inputs: filePath (required).
export_textA
Export the current frame or all frames as plain text (.txt). Returns ASCII art as text.
Inputs: filePath, frameIndex, allFrames, trimEmpty, +1 more.
export_videoA
Export the animation as a video file (MP4 or WebM). The browser renders each frame and encodes the video. Requires live mode with a connected browser.
Inputs: filePath (required), format, sizeMultiplier, frameRate, +4 more.
fill_regionB
Fill a region with a character and colors. Can be contiguous (flood fill) or global (all matching cells).
Inputs: x (required), y (required), char (required), color, +5 more.
flip_regionB
Flip/mirror content horizontally or vertically
Inputs: direction (required), region, frameIndex.
get_active_colorsA
Get the currently active foreground and background colors.
Inputs: no named parameters.
get_auth_tokenA
Get the authentication token for browser connection.
Inputs: no named parameters.
get_canvas_asciiA
Get the canvas as raw ASCII text (characters only, no color info). Good for verifying visual appearance.
Inputs: frameIndex, region, trimEmpty, overlayPreviousFrame.
get_canvas_previewB
Get non-empty cells in a region. Use for inspecting specific areas.
Inputs: frameIndex, region, maxCells.
get_canvas_summaryA
Get a compact summary of the canvas (dimensions, fill count, bounding box). Use this first to understand the canvas before requesting more detail.
Inputs: frameIndex.
get_cellA
Get the character and colors at a specific canvas position
Inputs: x (required), y (required), frameIndex.
get_character_paletteA
Get all characters from a specific palette.
Inputs: paletteId (required).
get_color_paletteB
Get all colors from a specific palette.
Inputs: paletteId (required).
get_color_statsA
Get statistics about colors used in the current frame. Useful before applying color effects.
Inputs: frameIndex, includeBackground.
get_connection_statusA
Check browser connection status. Returns whether browser is connected and client count
Inputs: no named parameters.
get_effect_blocksA
List all procedural effect blocks across layers, groups, and global effects. Shows effect type, timing, enabled status, and keyframe count.
Inputs: ownerId.
get_frame_diffA
Get the cells that differ between two frames. Useful for understanding animation changes.
Inputs: frameA (required), frameB (required), maxCells.
get_history_statusA
Check if undo/redo is available and what actions can be undone/redone
Inputs: no named parameters.
get_layer_propertiesA
Get all transform property values for a layer at the current frame, including keyframe status.
Inputs: layerId (required).
get_layersA
Get all layers in the project with their metadata, content frame count, and property track info.
Inputs: no named parameters.
get_project_infoC
Get information about the current project
Inputs: no named parameters.
get_selectionB
Get the current selection bounds and contents
Inputs: includeCells, maxCells.
go_to_frameB
Navigate to a specific frame, making it the current/active frame
Inputs: index (required).
import_ascii_textC
Import ASCII art from a plain text file onto the canvas.
Inputs: filePath (required), frameIndex, offsetX, offsetY, +3 more.
import_imageB
Import an image file and convert it to ASCII art on the canvas. Requires optional "sharp" or "jimp" package for image processing.
Inputs: filePath (required), targetWidth, targetHeight, charset, +5 more.
import_videoB
Import a video file and convert each frame to ASCII art animation. Requires ffmpeg and optional image processing package.
Inputs: filePath (required), targetWidth, targetHeight, charset, +5 more.
interpolate_framesC
Generate intermediate frames between two keyframes. Creates smooth transitions.
Inputs: startFrame (required), endFrame (required), steps (required), method.
list_character_palettesA
List all available character palettes for ASCII art.
Inputs: no named parameters.
list_color_palettesB
List all available color palettes.
Inputs: no named parameters.
list_framesA
List all frames in the animation with their metadata
Inputs: no named parameters.
list_project_filesB
List all .asciimtn project files in the project directory
Inputs: recursive.
load_projectA
Load a project from a .asciimtn file
Inputs: filePath (required).
new_projectA
Create a new empty project, discarding any unsaved changes
Inputs: width, height, name, template.
paste_ascii_blockB
Paste a multi-line ASCII art block onto the canvas at a specified position. Great for pasting found ASCII art.
Inputs: text (required), x, y, color, +2 more.
preview_generatorA
Preview a single frame from a generator without applying to the project.
Inputs: generator (required), color, density, seed.
redoA
Redo the last undone action
Inputs: no named parameters.
refresh_state_from_browserA
Request the browser to send its current state. Use this before reading canvas data to ensure you have the latest state. Returns success if browser is connected and responded.
Inputs: no named parameters.
remove_content_frameB
Remove a content frame from a layer.
Inputs: layerId (required), contentFrameId (required).
remove_effect_blockB
Remove a procedural effect block from its owner (layer, group, or global).
Inputs: blockId (required).
remove_effect_keyframeB
Remove a keyframe from a procedural effect property track.
Inputs: blockId (required), keyframeId (required).
remove_keyframeC
Remove a keyframe from a property track.
Inputs: layerId (required), trackId (required), keyframeId (required).
remove_layerA
Remove a layer by ID. Cannot remove the last remaining layer.
Inputs: layerId (required).
rename_layerB
Rename a layer.
Inputs: layerId (required), name (required).
reorder_layersB
Move a layer from one z-order position to another. Index 0 = bottom layer.
Inputs: fromIndex (required), toIndex (required).
resize_canvasA
Resize the canvas. Content outside the new bounds will be clipped.
Inputs: width (required), height (required).
run_generatorC
Generate procedural animation frames. Creates new frames with animated patterns.
Inputs: generator (required), frameCount, frameDuration, color, +16 more.
save_projectB
Save the current project to a .asciimtn file
Inputs: filePath (required).
select_by_colorA
Select cells that match specific criteria (magic wand style)
Inputs: x (required), y (required), matchChar, matchColor, +2 more.
select_rectangleC
Select a rectangular region of the canvas
Inputs: x (required), y (required), width (required), height (required).
set_active_layerA
Set which layer is active for drawing and editing operations.
Inputs: layerId (required).
set_background_colorB
Set the active background color.
Inputs: color (required).
set_cellA
Set the character and/or colors at a specific canvas position
Inputs: x (required), y (required), char, color, +1 more.
set_cells_batchA
Set multiple cells in a single operation. More efficient than calling set_cell repeatedly.
Inputs: cells (required).
set_foreground_colorB
Set the active foreground (text) color.
Inputs: color (required).
set_frame_durationB
Set the duration of a frame in milliseconds
Inputs: index (required), duration (required).
set_frame_nameB
Set or change the name of a frame
Inputs: index (required), name (required).
set_frame_rateA
Set the timeline frame rate (FPS). Preserves frame count — only changes playback speed.
Inputs: fps (required).
set_layer_visibilityC
Set visibility, solo, lock, or opacity on a layer.
Inputs: layerId (required), visible, solo, locked, +1 more.
set_project_nameC
Set the project name
Inputs: name (required).
set_selected_characterB
Set the active character used for drawing.
Inputs: character (required).
set_timeline_durationA
Set the total timeline duration in frames.
Inputs: durationFrames (required).
shift_frame_contentA
Shift all content on the current frame by an x/y offset. Useful for creating scrolling or movement animations.
Inputs: dx (required), dy (required), wrap, frameIndex.
suggest_palette_for_styleC
Get palette recommendations for a specific style.
Inputs: style (required).
undoB
Undo the last action
Inputs: no named parameters.
ungroup_layersA
Dissolve a layer group, keeping the layers.
Inputs: groupId (required).
update_effect_blockB
Update a procedural effect block's settings, timing, or enabled state.
Inputs: blockId (required), startFrame, durationFrames, enabled, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 96 tools
Tools are generally distinct with clear descriptions, but the large number (96) and several overlapping operations (e.g., multiple add/export/get tools) may cause minor confusion for an agent. Most tools have unique purposes.
The majority follow a verb_noun pattern (e.g., add_, get_, set_, export_), but there are inconsistencies like 'remove' vs 'delete' and phrases like 'refresh_state_from_browser' or 'suggest_palette_for_style'.
With 96 tools, the server far exceeds the typical well-scoped range. While many features are justified, the sheer number makes the surface feel heavy and harder for an agent to navigate efficiently.
The tool surface is exceptionally complete, covering project management, frame and layer operations, cell editing, effects, imports/exports, selection, palettes, undo/redo, and browser connectivity. No obvious gaps.
Maintenance
Related MCP Connectors
Build, version, review, and export websites, web apps, and games from a conversation.
Create AI animations and export transparent sprite sheets, alpha video, frames, and game assets.
Generate AI images, videos, music, SFX & speech in any AI assistant. Results appear inline in chat.
Write, run and check natural-language browser tests of your web app from your AI assistant.
Related MCP Servers
- FlicenseAqualityCmaintenanceExposes ASCIIFlow drawing primitives as tools to enable AI assistants to generate ASCII wireframes and diagrams from natural language descriptions. It provides commands for creating canvases and drawing boxes, lines, arrows, and text using a character-grid coordinate system.82-
- AlicenseNot gradedqualityCmaintenanceEnables AI to create ASCII and SVG art through a character canvas, with tools for drawing, previewing, and exporting to multiple formats, as well as composing stop-motion animations with optional voice-over.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create loop-perfect generative ASCII animations headlessly, including defining custom animations and 3D shapes as expression strings.55 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to drive Aseprite for pixel-art creation, including sprite setup, grid-based drawing, layer/frame/tag management, reference image import, and export, with rendered previews after every mutation.MIT