@kolbo/mcp 1.47.0 → 1.48.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.47.0",
3
+ "version": "1.48.0",
4
4
  "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -254,6 +254,14 @@ const projectIdField = z.string().optional().describe(
254
254
  'Project ObjectId to drop this generation into. Call `list_projects` to discover IDs (the API has no concept of project names — only ObjectIds). IMPORTANT: this is per-call, NOT sticky — once the user has named a working project, pass its id on EVERY generation call in the conversation; any call that omits it silently lands in the default "API Generations" project instead. Requires owner / edit / full permission on the project; view-only is rejected.'
255
255
  );
256
256
 
257
+ // Read-scope variant for list/get tools that can surface a SHARED project's
258
+ // assets (a teammate's Visual DNAs / moodboards). Pass a project id you have
259
+ // edit+ on to also see that project owner's shared assets; omit to see only your
260
+ // own + global/org. View-only members and non-members get nothing extra.
261
+ const projectScopeReadField = z.string().optional().describe(
262
+ "Project ObjectId (from `list_projects`) to ALSO surface that shared project's assets (a teammate's, when the project is shared with you). Requires edit / full / owner on the project — view-only members and non-members get only their own. Omit to see just your own + global/org."
263
+ );
264
+
257
265
  // ─── Optional inline-image content blocks ────────────────────────────────────
258
266
  // When a host opts in (the remote HTTP connector sets inlineImages:true), turn
259
267
  // generated IMAGE urls into MCP `image` content blocks so clients render them
@@ -440,6 +448,7 @@ module.exports = {
440
448
  resolveToBuffer,
441
449
  creditFields,
442
450
  projectIdField,
451
+ projectScopeReadField,
443
452
  inlineImageBlocks,
444
453
  buildOpenUrl,
445
454
  uiGenerating,
@@ -5,6 +5,7 @@
5
5
 
6
6
  const { z } = require('zod');
7
7
  const { UI, uiResult, appsEnabled } = require('../apps');
8
+ const { projectScopeReadField } = require('./_shared');
8
9
 
9
10
  function registerMoodboardTools(server, client, options = {}) {
10
11
  const ui = () => appsEnabled(server, options);
@@ -13,11 +14,13 @@ function registerMoodboardTools(server, client, options = {}) {
13
14
  'list_moodboards',
14
15
  'List moodboards. By default returns ALL (personal + system presets + organization). Use "scope" to filter: "personal" (user\'s own), "preset" or "global" (system presets), or "organization" (org-shared). Returns id, name, master_prompt, thumbnail, and image URLs for each.',
15
16
  {
16
- scope: z.enum(['all', 'personal', 'preset', 'global', 'organization']).optional().describe('Filter by scope. Default: "all" (everything accessible). "personal" = only your own. "preset"/"global" = system presets. "organization" = org-shared.')
17
+ scope: z.enum(['all', 'personal', 'preset', 'global', 'organization']).optional().describe('Filter by scope. Default: "all" (everything accessible). "personal" = only your own. "preset"/"global" = system presets. "organization" = org-shared.'),
18
+ project_id: projectScopeReadField
17
19
  },
18
- async ({ scope } = {}) => {
20
+ async ({ scope, project_id } = {}) => {
19
21
  const params = new URLSearchParams();
20
22
  if (scope && scope !== 'all') params.set('scope', scope);
23
+ if (project_id) params.set('project_id', project_id);
21
24
  const qs = params.toString();
22
25
  const result = await client.get(`/v1/moodboards${qs ? '?' + qs : ''}`);
23
26
  const moodboards = result.moodboards || [];
@@ -5,7 +5,7 @@
5
5
 
6
6
  const { z } = require('zod');
7
7
  const FormData = require('form-data');
8
- const { resolveToBuffer: sharedResolveToBuffer, VISUAL_DNA_MAX_BYTES } = require('./_shared');
8
+ const { resolveToBuffer: sharedResolveToBuffer, VISUAL_DNA_MAX_BYTES, projectScopeReadField } = require('./_shared');
9
9
  const { UI, uiResult, appsEnabled } = require('../apps');
10
10
 
11
11
  // Visual DNA caps reference media at 25MB per file (stricter than the
@@ -85,14 +85,16 @@ function registerVisualDnaTools(server, client, options = {}) {
85
85
  scope: z.enum(['all', 'personal', 'global', 'organization']).optional().describe('Filter by scope. Default: "all" (everything accessible). "personal" = only your own. "global" = system presets/cast. "organization" = org-shared.'),
86
86
  search: z.string().optional().describe('Search by name, tags, or description (case-insensitive)'),
87
87
  collection: z.string().optional().describe('Filter global presets by collection: cast, influencers, props, locations, styles, glamour, street'),
88
- tags: z.string().optional().describe('Comma-separated tags to filter by (OR logic)')
88
+ tags: z.string().optional().describe('Comma-separated tags to filter by (OR logic)'),
89
+ project_id: projectScopeReadField
89
90
  },
90
- async ({ scope, search, collection, tags } = {}) => {
91
+ async ({ scope, search, collection, tags, project_id } = {}) => {
91
92
  const params = new URLSearchParams();
92
93
  if (scope && scope !== 'all') params.set('scope', scope);
93
94
  if (search) params.set('search', search);
94
95
  if (collection) params.set('collection', collection);
95
96
  if (tags) params.set('tags', tags);
97
+ if (project_id) params.set('project_id', project_id);
96
98
  const qs = params.toString();
97
99
  const result = await client.get(`/v1/visual-dna${qs ? '?' + qs : ''}`);
98
100
  const dnas = result.visual_dnas || [];
@@ -125,12 +127,14 @@ function registerVisualDnaTools(server, client, options = {}) {
125
127
  // ─── get_visual_dna ────────────────────────────────────────
126
128
  server.tool(
127
129
  'get_visual_dna',
128
- 'Fetch a single Visual DNA profile by ID. Returns the full profile including system_prompt and all reference images.',
130
+ 'Fetch a single Visual DNA profile by ID. Returns the full profile including system_prompt and all reference images. To fetch a teammate\'s Visual DNA that lives in a shared project, pass project_id (you need edit+ on it).',
129
131
  {
130
- visual_dna_id: z.string().describe('The Visual DNA profile ID')
132
+ visual_dna_id: z.string().describe('The Visual DNA profile ID'),
133
+ project_id: projectScopeReadField
131
134
  },
132
- async ({ visual_dna_id }) => {
133
- const result = await client.get(`/v1/visual-dna/${encodeURIComponent(visual_dna_id)}`);
135
+ async ({ visual_dna_id, project_id }) => {
136
+ const suffix = project_id ? `?project_id=${encodeURIComponent(project_id)}` : '';
137
+ const result = await client.get(`/v1/visual-dna/${encodeURIComponent(visual_dna_id)}` + suffix);
134
138
  return {
135
139
  content: [{
136
140
  type: 'text',