@gripforgeai/mcp 0.1.25 → 0.1.26

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.
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ export function createPropGripSchema(factory = z) {
3
+ const Z = factory;
4
+ const vector = Z.tuple([Z.number().finite(), Z.number().finite(), Z.number().finite()]);
5
+ return Z.object({
6
+ position: vector.describe('Grip point in the prop scene local coordinates'),
7
+ axis: vector.describe('Handle direction / shield top (+Y of the grip frame)'),
8
+ normal: vector.describe('Blade flat / outward shield face (+Z of the grip frame)'),
9
+ }).describe('Exact prop grip frame; overrides geometric guesses. A gf_grip locator can supply the same frame.');
10
+ }
11
+ export const propGripSchema = createPropGripSchema();
package/dist/server.js CHANGED
@@ -12,6 +12,7 @@ import { basename, dirname, extname, join, resolve } from 'node:path';
12
12
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
14
  import { z } from 'zod';
15
+ import { propGripSchema } from './attach-options.js';
15
16
  import { registerVfxProjectTools } from './vfx-project-tools.js';
16
17
  import { registerSceneTools } from './scene-tools.js';
17
18
  import { registerServerTools } from './server-tools.js';
@@ -84,6 +85,10 @@ server.tool('gripforge_attach', 'Attach a prop (sword, shield, gun, staff/scythe
84
85
  style: z.enum(['melee', 'gun', 'shield', 'staff']).optional().describe('Grip style (default: guessed from the filename)'),
85
86
  hand: z.enum(['right', 'left']).optional().describe('Hand side (default right)'),
86
87
  height_ratio: z.number().min(0.05).max(1.5).optional().describe('Prop size as a fraction of body height'),
88
+ prop_grip: propGripSchema.optional(),
89
+ style_2: z.enum(['melee', 'gun', 'shield', 'staff']).optional().describe('Style of the second held item'),
90
+ height_ratio_2: z.number().min(0.05).max(1.5).optional(),
91
+ prop_grip_2: propGripSchema.optional(),
87
92
  fist: z.number().min(0).max(1).optional().describe('Fist closing amount, 0 open → 1 closed (default 1)'),
88
93
  grip_offset: z
89
94
  .array(z.number())
@@ -100,7 +105,7 @@ server.tool('gripforge_attach', 'Attach a prop (sword, shield, gun, staff/scythe
100
105
  .describe('Bake character + closed fist + prop into one attached.glb (requires out_dir; .glb/.gltf inputs only). ' +
101
106
  'Use this for mitten-hand rigs: the closed fist cannot travel in the bind JSON.'),
102
107
  out_dir: z.string().optional().describe('Write bind.json + engine snippets into this folder'),
103
- }, async ({ character_path, prop_path, character_id, attach_id, prop_id, prop_id_2, prop_path_2, style, hand, height_ratio, fist, grip_offset, ai_refine, export_glb, out_dir }) => {
108
+ }, async ({ character_path, prop_path, character_id, attach_id, prop_id, prop_id_2, prop_path_2, style, hand, height_ratio, prop_grip, style_2, height_ratio_2, prop_grip_2, fist, grip_offset, ai_refine, export_glb, out_dir }) => {
104
109
  if (!API_KEY) {
105
110
  return err('GRIPFORGE_API_KEY missing. Create a free account at ' +
106
111
  API_URL +
@@ -148,6 +153,8 @@ server.tool('gripforge_attach', 'Attach a prop (sword, shield, gun, staff/scythe
148
153
  form.append('hand', hand);
149
154
  if (height_ratio != null)
150
155
  form.append('ratio', String(height_ratio));
156
+ if (prop_grip)
157
+ form.append('prop_grip', JSON.stringify(prop_grip));
151
158
  if (fist != null)
152
159
  form.append('fist', String(fist));
153
160
  if (grip_offset)
@@ -195,6 +202,12 @@ server.tool('gripforge_attach', 'Attach a prop (sword, shield, gun, staff/scythe
195
202
  form2.append('export', 'glb');
196
203
  form2.append('fingers', '1');
197
204
  form2.append('hand', hand === 'left' ? 'right' : 'left');
205
+ if (style_2)
206
+ form2.append('style', style_2);
207
+ if (height_ratio_2 != null)
208
+ form2.append('ratio', String(height_ratio_2));
209
+ if (prop_grip_2)
210
+ form2.append('prop_grip', JSON.stringify(prop_grip_2));
198
211
  const res2 = await fetch(`${API_URL}/api/v1/attach`, {
199
212
  method: 'POST',
200
213
  headers: apiHeaders(),
@@ -1300,6 +1313,8 @@ server.tool('gripforge_loadout', 'Build a multi-weapon character in ONE call: at
1300
1313
  prop_id: z.string(),
1301
1314
  hand: z.enum(['left', 'right']).optional(),
1302
1315
  style: z.enum(['melee', 'gun', 'shield', 'staff']).optional(),
1316
+ height_ratio: z.number().min(.05).max(1.5).optional(),
1317
+ prop_grip: propGripSchema.optional(),
1303
1318
  })))
1304
1319
  .describe('set name → props to hold in that set'),
1305
1320
  default_set: z.string().optional().describe('Set visible by default (first set otherwise)'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gripforgeai/mcp",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "The tools your AI needs to make your games. Turn prompts into production-ready game assets \u2014 animated characters with their weapons attached, seamless textures, terrain, VFX, HUDs \u2014 and playable game kits Unity, Godot, Unreal or Three.js can load.",
5
5
  "license": "MIT",
6
6
  "type": "module",