keyframe-mcp 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,9 @@ Version 0.2.1 adds ownership metadata for the official MCP Registry, where the s
22
22
 
23
23
  Version 0.3.0 adds 18 `puppeteer_*` tools for Sprite Puppeteer: sample and your own characters, camera sets and directions, contact sheets, keyframed moves, and sheet, Godot, Unity, GameMaker, PNG-frame, Spine, GIF and project exports.
24
24
 
25
- Version 0.4.0 adds 24 `meshforge_*` tools for MeshForge: rig a 3D model in the browser (template skeleton, joints read off a measuring grid, automatic skin weights), give held props their own rigid bone, animate from keyframe specs written in character space, judge motion from contact sheets and measurements, save to the library and export GLB.
25
+ Version 0.6.0 adds `meshforge_remesh` (29 `meshforge_*` tools in all): a free remesh that rebuilds the model as an even mesh with new UVs and its texture baked across. `meshforge_reduce` can also scale textures down (`maxTexture`), and the motion presets gain actions: punch, claw swipe, kick, hit reaction, jump, death and taunt. Through `meshforge_call` there are rig markers (`setRigMarkers`), a stretch check (`stretchCheck`) and a local weight smooth (`smoothWeightsAt`).
26
+
27
+ Version 0.5.0 adds four more `meshforge_*` tools (28 in all): a weight fix, a flex test, free walk/run/idle cycles and free polygon reduction; binding now uses bone heat, like Blender's automatic weights, and there is a humanoid-with-a-tail skeleton. Version 0.4.0 added the first 24: rig a 3D model in the browser (template skeleton, joints read off a measuring grid, automatic skin weights), give held props their own rigid bone, animate from keyframe specs written in character space, judge motion from contact sheets and measurements, save to the library and export GLB.
26
28
 
27
29
  ## Workflow
28
30
 
@@ -112,10 +114,12 @@ Animate a rigged model:
112
114
 
113
115
  Rig an unrigged model (free, no API key):
114
116
 
115
- 1. `meshforge_start_rig {template:"humanoid"}` (or quadruped, chain) fits a skeleton to the mesh.
117
+ 0. Over ~150k triangles? `meshforge_reduce {triangles:40000}` then `meshforge_save {asNew:true}` (free; UVs, textures and weights carry over). A messy generated surface? `meshforge_remesh {triangles:30000}` rebuilds it evenly with a baked texture.
118
+ 1. `meshforge_start_rig {template:"humanoid"}` (or humanoid_tail, quadruped, chain) fits a skeleton to the mesh.
116
119
  2. `meshforge_render_rig` shows the joints over a measuring grid from the front and side. Read the right coordinates off the grid and fix joints with `meshforge_set_joints {joints:{forearmR:[0.55,0.74,0.05]}}` (mirrored by default). Joints belong inside the body.
117
120
  3. Props: `meshforge_add_prop {name:"axe", parent:"handR", select:{capsule:{a:[…],b:[…],radius:0.08}}}`. Preview a selection first with `meshforge_render_rig {select:…}` (orange); added props show purple.
118
- 4. `meshforge_bind_rig`, then test with an animation and save.
121
+ 4. `meshforge_bind_rig` (bone heat, like Blender's automatic weights). If its weight check reports strays, `meshforge_fix_weights`. Then `meshforge_flex_test` and a contact sheet of "Flex test".
122
+ 5. `meshforge_preset_animation {kind:"walk"}` (or run, idle, punch, swipe, kick, hit, jump, death, taunt) adds free motion fitted to the rig; tune with speed, stride, arms, bounce, tail. Then save.
119
123
 
120
124
  Example (the example orc, `meshforge_open {model:"Orc"}` first):
121
125
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyframe-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "mcpName": "io.github.kendall8388/keyframe",
5
5
  "repository": { "type": "git", "url": "https://github.com/kendall8388/Keyframe-it.git", "directory": "mcp" },
6
6
  "description": "MCP server for Keyframe.it — let Claude (or any MCP client) rig, animate and export 2D skeletal animations in the free Keyframe.it editor, rig, animate, play-test and export pixel-art sprites in Sprite Puppeteer, and rig and animate 3D models in MeshForge, by driving them in your browser.",
package/server.mjs CHANGED
@@ -10,7 +10,7 @@ import { advertisedTools } from './tools.mjs'
10
10
 
11
11
  export function createServer(session = new EditorSession(chromium)) {
12
12
  const runner = new ToolRunner(session)
13
- const server = new Server({ name: 'keyframe-mcp', version: '0.4.0' }, { capabilities: { tools: {}, resources: {} } })
13
+ const server = new Server({ name: 'keyframe-mcp', version: '0.6.0' }, { capabilities: { tools: {}, resources: {} } })
14
14
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: advertisedTools }))
15
15
  server.setRequestHandler(CallToolRequestSchema, req => runner.call(req.params.name, req.params.arguments ?? {}))
16
16
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: runner.resources() }))
package/tools.mjs CHANGED
@@ -99,11 +99,16 @@ definitions.push(
99
99
  mf('meshforge_contact_sheet', 'Frames of an animation from the front and side (or other views) in one labelled image: the way to judge motion.', object({ animation: str, samples: integer(2, 16), views, size: integer(96, 384) }), 'renderContactSheet', a => [a]),
100
100
  mf('meshforge_render_frame', 'One picture of the open model, optionally at a time in an animation, from a view (default threeQuarter).', object({ animation: str, time: number(0, 60), view: { enum: ['front', 'threeQuarter', 'side', 'right', 'left', 'back', 'top'] }, size: integer(128, 1024) }), 'renderFrame', a => [a]),
101
101
  mf('meshforge_inspect', 'Numbers for an animation: feet vs floor, foot sliding, loop gap, which bones move, hips travel.', object({ animation: str, samples: integer(2, 120) }, ['animation']), 'inspectAnimation', a => [a.animation, { samples: a.samples }]),
102
- mf('meshforge_start_rig', 'Rig the open model in the browser (free): a template skeleton (humanoid, quadruped or chain) fitted to the mesh. facing: which way the model looks in its own space. Then meshforge_render_rig.', object({ template: { enum: ['humanoid', 'quadruped', 'chain'] }, facing: { enum: ['+z', '-z', '+x', '-x'] } }), 'startRig', a => [a]),
102
+ mf('meshforge_start_rig', 'Rig the open model in the browser (free): a template skeleton (humanoid, humanoid_tail for lizard/shark folk, quadruped or chain) fitted to the mesh. Over ~150k triangles, meshforge_reduce first. facing: which way the model looks in its own space. Then meshforge_render_rig.', object({ template: { enum: ['humanoid', 'humanoid_tail', 'quadruped', 'chain'] }, facing: { enum: ['+z', '-z', '+x', '-x'] } }), 'startRig', a => [a]),
103
103
  mf('meshforge_render_rig', 'The model from the front and side with the draft joints drawn on it over a measuring grid (read coordinates off it). Props show purple; pass select to preview a selection in orange.', object({ views, size: integer(256, 1024), select: shape }), 'renderRig', a => [a]),
104
104
  mf('meshforge_set_joints', 'Move draft joints: {jointName: [x, y, z]} in character space. mirror (default true) moves the left/right twin too. Joints belong INSIDE the body.', object({ joints: { type: 'object', minProperties: 1, additionalProperties: vec3 }, mirror: bool }, ['joints']), 'setRigJoints', a => [a.joints, { mirror: a.mirror }]),
105
105
  mf('meshforge_add_prop', 'Give a held prop (axe, sword, shield, staff) its own rigid bone under parent (usually a hand). Works on a rig draft or on a model already rigged (MeshForge or Meshy). The selection grows along the prop automatically; check with meshforge_render_rig (draft) or meshforge_contact_sheet.', object({ name: str, parent: str, select: shape, grow: bool }, ['parent', 'select']), 'addProp', a => [a]),
106
- mf('meshforge_bind_rig', 'Build the bones and automatic skin weights from the draft. Existing animations are retargeted where the skeletons can be matched. Then test with meshforge_build_animation.', object({ smooth: integer(0, 6) }), 'bindRig', a => [a]),
106
+ mf('meshforge_bind_rig', 'Build the bones and automatic skin weights from the draft: method "heat" (bone heat, as Blender\'s automatic weights; default) or "nearest" (quicker). Existing animations are retargeted where the skeletons can be matched. Returns a weight check; then meshforge_flex_test.', object({ method: { enum: ['heat', 'nearest'] } }), 'bindRig', a => [a]),
107
+ mf('meshforge_fix_weights', 'Find skin that follows the wrong limb (a hand moving part of a foot) and hand it to the bone it sits by. Returns what was fixed and a fresh check.', object(), 'fixWeights'),
108
+ mf('meshforge_flex_test', 'Add a temporary clip (not saved) bending each limb, the spine, head and tail in turn; then meshforge_contact_sheet {animation:"Flex test", samples:12} to spot bad weights.', object(), 'flexTest'),
109
+ mf('meshforge_preset_animation', 'Free ready-made motion fitted to the open rig: cycles walk | run | idle (bipeds, four-legged rigs, tails) and actions punch | swipe | kick | hit | jump | death | taunt (two-legged rigs). Multipliers speed, stride, arms (for actions: strength), bounce, tail (1 = default). Returns measurements.', object({ kind: { enum: ['walk', 'run', 'idle', 'punch', 'swipe', 'kick', 'hit', 'jump', 'death', 'taunt'] }, speed: number(0.25, 4), stride: number(0, 3), arms: number(0, 3), bounce: number(0, 3), tail: number(0, 3), name: str }), 'buildPresetAnimation', a => [a]),
110
+ mf('meshforge_reduce', 'Free polygon reduction in the browser to about `triangles` (UVs, textures, rig weights and animations carry over); maxTexture (e.g. 2048) also scales textures down. Then meshforge_save with asNew:true to keep it as a copy.', object({ triangles: integer(500, 2000000), maxTexture: integer(256, 8192) }, ['triangles']), 'reduceModel', a => [a]),
111
+ mf('meshforge_remesh', 'Free remesh: rebuild the open model as one clean, even mesh of about `triangles` (default 30000) with fresh UVs and its texture baked across (texSize 1024 | 2048 | 4096). Drops any rig: rig it again after. Then meshforge_save with asNew:true.', object({ triangles: integer(1000, 100000), texSize: { enum: [1024, 2048, 4096] } }), 'remeshModel', a => [a]),
107
112
  mf('meshforge_save', 'Save the open model (rig and animations) to the MeshForge library. A model saved from MeshForge before is updated; a generated or imported one gets a new entry.', object({ name: str, asNew: bool }), 'saveProject', a => [a]),
108
113
  mf('meshforge_export', 'Write the open model with every animation as a .glb to disk.', object({ format: { enum: ['glb'] } }), 'exportFile', a => [{ format: a.format || 'glb' }]),
109
114
  mf('meshforge_screenshot', 'Show the MeshForge page. Prefer meshforge_contact_sheet or meshforge_render_rig to judge work.'),