keyframe-mcp 0.5.0 → 0.7.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,6 +22,10 @@ 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.7.0 adds `meshforge_free_arm` (30 `meshforge_*` tools in all): on a rig draft it cuts an arm the model has fused to its body free along the crease and closes both sides, so the arm can be raised without dragging the body. `meshforge_add_prop` can move a prop that stands apart into the hand first (`hold: "hang"` for a lantern or a bag, or `holdAt`), and the skeleton is now fitted to the body alone, ignoring pieces standing beside it.
26
+
27
+ 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`).
28
+
25
29
  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
30
 
27
31
  ## Workflow
@@ -112,12 +116,13 @@ Animate a rigged model:
112
116
 
113
117
  Rig an unrigged model (free, no API key):
114
118
 
115
- 0. Over ~150k triangles? `meshforge_reduce {triangles:40000}` then `meshforge_save {asNew:true}` (free; UVs, textures and weights carry over).
119
+ 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.
116
120
  1. `meshforge_start_rig {template:"humanoid"}` (or humanoid_tail, quadruped, chain) fits a skeleton to the mesh.
117
121
  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.
118
- 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.
119
- 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".
120
- 5. `meshforge_preset_animation {kind:"walk"}` (or run, idle) adds a free cycle fitted to the rig; tune with speed, stride, arms, bounce, tail. Then save.
122
+ 3. An arm fused to the body (a sleeve grown into a robe)? `meshforge_free_arm {side:"R"}` cuts it free along the crease so it can be raised cleanly.
123
+ 4. Props: `meshforge_add_prop {name:"axe", parent:"handR", select:{capsule:{a:[…],b:[…],radius:0.08}}}`. A prop standing apart, like a lantern on the ground: `{name:"lantern", parent:"handL", select:{piece:[x,y,z]}, hold:"hang"}` moves it into the hand first. Preview a selection with `meshforge_render_rig {select:…}` (orange); added props show purple.
124
+ 5. `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".
125
+ 6. `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.
121
126
 
122
127
  Example (the example orc, `meshforge_open {model:"Orc"}` first):
123
128
 
@@ -136,7 +141,8 @@ Example (the example orc, `meshforge_open {model:"Orc"}` first):
136
141
  | `meshforge_build_animation` | Keyframe spec → animation, with measurements |
137
142
  | `meshforge_contact_sheet` / `meshforge_render_frame` / `meshforge_inspect` | Frames as images; numbers |
138
143
  | `meshforge_start_rig` / `meshforge_render_rig` / `meshforge_set_joints` / `meshforge_bind_rig` | Rigging in the browser |
139
- | `meshforge_add_prop` | A rigid bone for a held weapon or shield (draft or bound rig) |
144
+ | `meshforge_free_arm` | Cut an arm fused to the body free before binding |
145
+ | `meshforge_add_prop` | A rigid bone for a held weapon, shield or lantern (draft or bound rig); can move it into the hand |
140
146
  | `meshforge_save` / `meshforge_export` | Library entry; .glb file |
141
147
  | `meshforge_screenshot` / `meshforge_open_result` | The page, and handoff to visible Chrome |
142
148
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyframe-mcp",
3
- "version": "0.5.0",
3
+ "version": "0.7.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.5.0' }, { capabilities: { tools: {}, resources: {} } })
13
+ const server = new Server({ name: 'keyframe-mcp', version: '0.7.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
@@ -102,12 +102,14 @@ definitions.push(
102
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
- 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]),
105
+ mf('meshforge_free_arm', 'On a rig draft, before binding: cut an arm the model has fused to its body (a sleeve grown into a robe, an arm resting on the side) free along the crease, from the armpit down, and close both sides, so the arm can be raised without dragging the body\'s skin. side "L" | "R" (the character\'s own); from: where the cut starts, as a fraction down the upper arm (default 0.35). Leaves the model alone and says why if no clean cut exists. Undo with meshforge_call {method:"restoreArm", args:[{side}]}.', object({ side: { enum: ['L', 'R'] }, from: number(0, 0.9) }, ['side']), 'freeArm', a => [a]),
106
+ mf('meshforge_add_prop', 'Give a prop (axe, sword, shield, staff, lantern) 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. On a draft, hold:"hang" first moves a prop that stands apart (a lantern on the ground) into the hand, its top in the fist and the rest hanging below; holdAt:[x,y,z] names the point of the prop to put in the fist instead.', object({ name: str, parent: str, select: shape, grow: bool, hold: { enum: ['hang'] }, holdAt: vec3 }, ['parent', 'select']), 'addProp', a => [a]),
106
107
  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
108
  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
109
  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 cycle fitted to the open rig (bipeds, four-legged rigs, tails): kind walk | run | idle, with multipliers speed, stride, arms, bounce, tail (1 = default). Returns measurements.', object({ kind: { enum: ['walk', 'run', 'idle'] }, 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). Then meshforge_save with asNew:true to keep it as a copy.', object({ triangles: integer(500, 2000000) }, ['triangles']), 'reduceModel', a => [a]),
110
+ 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]),
111
+ 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]),
112
+ 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]),
111
113
  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]),
112
114
  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' }]),
113
115
  mf('meshforge_screenshot', 'Show the MeshForge page. Prefer meshforge_contact_sheet or meshforge_render_rig to judge work.'),