@kolbo/mcp 1.84.0 → 1.84.1
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/package.json +1 -1
- package/src/tools/visual_dna.js +10 -6
package/package.json
CHANGED
package/src/tools/visual_dna.js
CHANGED
|
@@ -28,6 +28,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
28
28
|
name: z.string().describe('Name of the Visual DNA profile. **Pick a short, lowercase, no-space single token** (e.g. `maya`, `tokyo_neon`, `brand_red`, `esther_model`) — never names with spaces (`Sarah Johnson` ❌). The user/LLM types this as `@<name>` inside generation prompts, and the @ parser stops at the first space, so `@Sarah Johnson` matches only `Sarah` and the binding silently drops. Multi-word concepts should use underscores or be a single token. Names are case-insensitive on lookup, but **reserved** values rejected on creation: `Image1`, `Image2`, …, `Video1`, …, `Audio1`, … (any-language characters allowed; max 100 chars).'),
|
|
29
29
|
dna_type: z.string().optional().describe('Type: "character", "style", "product", "scene", "environment". Default: "character"'),
|
|
30
30
|
prompt_helper: z.string().optional().describe('Optional description/notes to guide DNA extraction'),
|
|
31
|
+
description: z.string().optional().describe('Alias for `prompt_helper`. Accepted because every tool here REPORTS this field as `description`, so callers round-trip that name back in; without the alias zod stripped it and the notes were silently lost. Ignored when `prompt_helper` is also given.'),
|
|
31
32
|
images: z.array(z.string()).optional().describe('Array of image sources (URLs or absolute local paths). Max 4. All of them can reach the model on later gens — same subject, same vibe only; no extra heroes on character DNAs, no main characters on environment DNAs.'),
|
|
32
33
|
video: z.string().optional().describe('Optional video source (URL or absolute local path)'),
|
|
33
34
|
audio: z.string().optional().describe('Optional audio source (URL or absolute local path) — the character\'s voice, 5-30s of clean speech. Stored on the DNA and used two ways: (1) as REFERENCE AUDIO in video generation — attaching this DNA to an image-to-video generation on a model with audio slots (Seedance 2.x, Wan 3.0) auto-attaches the clip and tells the model it is that character\'s voice; (2) as the source for a real speaking voice, but ONLY when you ask for one — see `voice_source`.'),
|
|
@@ -35,7 +36,8 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
35
36
|
assigned_voice_id: z.string().optional().describe('Voice to attach when voice_source="assign" — a `custom_<id>` from the user\'s clones or a voice_id from `list_voices`.'),
|
|
36
37
|
character_sheet_url: z.string().optional().describe('URL of a reference sheet (from `generate_character_sheet`, any sheet_type) to set as the DNA\'s primary reference. Works for ALL DNA types — character turnaround, product detail sheet, location sheet, or style board — and is the single biggest consistency booster. Omit only when the user declines.')
|
|
37
38
|
},
|
|
38
|
-
async ({ name, dna_type, prompt_helper, images, video, audio, voice_source, assigned_voice_id, character_sheet_url }) => {
|
|
39
|
+
async ({ name, dna_type, prompt_helper, description, images, video, audio, voice_source, assigned_voice_id, character_sheet_url }) => {
|
|
40
|
+
const helper = prompt_helper !== undefined ? prompt_helper : description;
|
|
39
41
|
if (!name || !name.trim()) {
|
|
40
42
|
throw new Error('name is required');
|
|
41
43
|
}
|
|
@@ -58,7 +60,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
58
60
|
const form = new FormData();
|
|
59
61
|
form.append('name', name);
|
|
60
62
|
if (dna_type) form.append('dnaType', dna_type);
|
|
61
|
-
if (
|
|
63
|
+
if (helper) form.append('promptHelper', helper);
|
|
62
64
|
if (character_sheet_url) form.append('characterSheetUrl', character_sheet_url);
|
|
63
65
|
// Omitted stays omitted: the server infers 'clone' from a present audio clip, which is the
|
|
64
66
|
// long-standing behaviour older installs depend on. Only an explicit choice is forwarded.
|
|
@@ -193,6 +195,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
193
195
|
name: z.string().optional().describe('New name. Same no-space single-token rule as create_visual_dna — @Name binding stops at the first space.'),
|
|
194
196
|
dna_type: z.string().optional().describe('Type: "character", "style", "product", "scene", "environment". Changing type re-analyzes the profile.'),
|
|
195
197
|
prompt_helper: z.string().optional().describe('New description / intent notes. Replaces the old ones and re-synthesizes the DNA analysis when the text actually changes. Pass "" to clear.'),
|
|
198
|
+
description: z.string().optional().describe('Alias for `prompt_helper`. Accepted because every tool here REPORTS this field as `description`, so callers round-trip that name back in; without the alias zod stripped it and the edit silently did nothing. Ignored when `prompt_helper` is also given.'),
|
|
196
199
|
images: z.array(z.string()).optional().describe('Full replacement still set (URLs or absolute local paths). Max 4. Omit to keep current stills. Same purity rules as create: one identity, one vibe.'),
|
|
197
200
|
video: z.string().optional().describe('Replacement video source (URL or absolute local path).'),
|
|
198
201
|
audio: z.string().optional().describe('Replacement audio source (URL or absolute local path).'),
|
|
@@ -208,14 +211,15 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
208
211
|
specific_age: z.number().optional().describe('Character attribute (character DNAs).')
|
|
209
212
|
},
|
|
210
213
|
async ({
|
|
211
|
-
visual_dna_id, name, dna_type, prompt_helper, images, video, audio,
|
|
214
|
+
visual_dna_id, name, dna_type, prompt_helper, description, images, video, audio,
|
|
212
215
|
character_sheet_url, remove_character_sheet,
|
|
213
216
|
gender, ethnicity, body_type, hair_color, eye_color, skin_tone, age_range, specific_age
|
|
214
217
|
}) => {
|
|
218
|
+
const helper = prompt_helper !== undefined ? prompt_helper : description;
|
|
215
219
|
const imageList = Array.isArray(images) ? images.filter(Boolean) : [];
|
|
216
220
|
if (imageList.length > 4) throw new Error('Maximum 4 images allowed');
|
|
217
221
|
const hasMedia = imageList.length > 0 || !!video || !!audio;
|
|
218
|
-
const hasMeta = name !== undefined || dna_type !== undefined ||
|
|
222
|
+
const hasMeta = name !== undefined || dna_type !== undefined || helper !== undefined
|
|
219
223
|
|| character_sheet_url !== undefined || remove_character_sheet !== undefined
|
|
220
224
|
|| gender !== undefined || ethnicity !== undefined || body_type !== undefined
|
|
221
225
|
|| hair_color !== undefined || eye_color !== undefined || skin_tone !== undefined
|
|
@@ -240,7 +244,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
240
244
|
const body = { ...attrs };
|
|
241
245
|
if (name !== undefined) body.name = name;
|
|
242
246
|
if (dna_type !== undefined) body.dna_type = dna_type;
|
|
243
|
-
if (
|
|
247
|
+
if (helper !== undefined) body.prompt_helper = helper;
|
|
244
248
|
if (character_sheet_url !== undefined) body.character_sheet_url = character_sheet_url;
|
|
245
249
|
if (remove_character_sheet !== undefined) body.remove_character_sheet = remove_character_sheet;
|
|
246
250
|
const result = await client.put(path, body);
|
|
@@ -264,7 +268,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
264
268
|
const form = new FormData();
|
|
265
269
|
if (name !== undefined) form.append('name', name);
|
|
266
270
|
if (dna_type) form.append('dnaType', dna_type);
|
|
267
|
-
if (
|
|
271
|
+
if (helper !== undefined) form.append('promptHelper', helper);
|
|
268
272
|
if (character_sheet_url) form.append('characterSheetUrl', character_sheet_url);
|
|
269
273
|
if (remove_character_sheet !== undefined) {
|
|
270
274
|
form.append('removeCharacterSheet', remove_character_sheet ? 'true' : 'false');
|