@kolbo/mcp 1.90.2 → 1.91.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 +14 -0
- package/package.json +2 -2
- package/skill/SKILL.md +1 -0
- package/skill/references/workflows/adobe.md +41 -0
- package/src/apps/index.js +29 -6
- package/src/index.js +3 -0
- package/src/toolAnnotations.js +3 -0
- package/src/tools/adobe.js +175 -0
- package/src/tools/blender.js +1 -1
- package/src/tools/editor.js +1 -1
- package/src/tools/generate.js +4 -4
package/README.md
CHANGED
|
@@ -263,6 +263,20 @@ Every generation tool also accepts an optional `project_id` arg that routes the
|
|
|
263
263
|
| `blender_execute_python` | Execute explicitly reviewed Python plus a required plain-language purpose with full host authority; approval required unless trusted mode is visibly active |
|
|
264
264
|
| `blender_get_command_status` | Read bounded command status/result/error plus absolute `expires_at`; records and idempotency claims expire after 24 hours, and `awaiting_approval` means stop and wait for the user |
|
|
265
265
|
|
|
266
|
+
**Premiere Pro & After Effects Bridge**
|
|
267
|
+
Requires the Kolbo Studio panel open in Premiere Pro or After Effects with **AI agents** switched on in its header. Every edit is approved by the editor inside the panel; there is no raw ExtendScript tool.
|
|
268
|
+
|
|
269
|
+
| Tool | Description |
|
|
270
|
+
|------|-------------|
|
|
271
|
+
| `adobe_list_sessions` | List the caller's Premiere Pro / After Effects windows connected through the Kolbo panel |
|
|
272
|
+
| `adobe_get_project` | Queue a read-only project inspection (no approval) |
|
|
273
|
+
| `adobe_get_timeline` | Queue a read-only inspection of the active sequence or composition, bounded by `max_clips` |
|
|
274
|
+
| `adobe_import_media` | Import one Kolbo media id or Kolbo-owned HTTPS URL into the project bin |
|
|
275
|
+
| `adobe_place_on_timeline` | Import and place one Kolbo media item at the playhead of the work sequence / active comp (no time or track control in v1) |
|
|
276
|
+
| `adobe_create_sequence` | Create and open a Premiere Pro sequence (Premiere only) |
|
|
277
|
+
| `adobe_import_captions` | Import a Kolbo-hosted SRT onto the active Premiere sequence (Premiere only) |
|
|
278
|
+
| `adobe_get_command_status` | Read command status/result/error; `awaiting_approval` means stop and wait for the editor |
|
|
279
|
+
|
|
266
280
|
**Discovery & Account**
|
|
267
281
|
| Tool | Description |
|
|
268
282
|
|------|-------------|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolbo/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.91.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": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"smoke": "node scripts/smoke.js",
|
|
12
12
|
"check-skill-bundle": "node scripts/check-skill-bundle.js",
|
|
13
13
|
"check-parity": "node scripts/check-parity.js",
|
|
14
|
-
"prepublishOnly": "node scripts/smoke.js && node --test test/blender-tools.test.js && node scripts/check-skill-bundle.js && node scripts/check-parity.js && node scripts/check-widget-fields.js && node scripts/check-widget-render.js && node scripts/check-model-catalog.js && node scripts/check-skill-tools.js && node scripts/check-doctrine-parity.js && node scripts/check-submission-contract.js && node scripts/check-install.js",
|
|
14
|
+
"prepublishOnly": "node --test test/widget-resource-versions.test.js && node scripts/smoke.js && node --test test/blender-tools.test.js && node scripts/check-skill-bundle.js && node scripts/check-parity.js && node scripts/check-widget-fields.js && node scripts/check-widget-render.js && node scripts/check-model-catalog.js && node scripts/check-skill-tools.js && node scripts/check-doctrine-parity.js && node scripts/check-submission-contract.js && node scripts/check-install.js",
|
|
15
15
|
"check-model-catalog": "node scripts/check-model-catalog.js",
|
|
16
16
|
"check-widget-fields": "node scripts/check-widget-fields.js",
|
|
17
17
|
"check-widget-render": "node scripts/check-widget-render.js",
|
package/skill/SKILL.md
CHANGED
|
@@ -159,6 +159,7 @@ Font tools (when exposed by the installed MCP): `list_fonts`, `get_font`, `uploa
|
|
|
159
159
|
| `create_review_asset` / `add_review_version` / `set_review_status` / `create_review_comment` / `reply_review_comment` / `resolve_review_comment` / `unresolve_review_comment` / `create_review_collection` / `create_review_share_link` / `revoke_review_share_link` / `get_review_storage_usage` (+ list/get/update/delete siblings) | **Kolbo Review** — Frame.io-style client review: asset = media + appended versions (new cut = `add_review_version`, never delete+recreate), timecoded comments per version, approve/request-changes status, guest share links (no Kolbo account; comment-only unless `canSetStatus`). 5GB review storage cap. See `workflows/review-collections.md`. |
|
|
160
160
|
| `publish_html_artifact` | Publish HTML / SVG / Mermaid to `sites.kolbo.ai`. Server dedupes by content hash. Strict CSP. |
|
|
161
161
|
| `blender_list_sessions` / `blender_get_scene` / `blender_search_docs` / `blender_capture_viewport` / `blender_apply_operations` / `blender_import_media` / `blender_render` / `blender_undo` / `blender_file_operation` / `blender_execute_python` / `blender_get_command_status` | Connected Blender control through the Kolbo extension. Every tool crosses into an external desktop host; read `workflows/blender.md` before the first call. |
|
|
162
|
+
| `adobe_list_sessions` / `adobe_get_project` / `adobe_get_timeline` / `adobe_import_media` / `adobe_place_on_timeline` / `adobe_create_sequence` / `adobe_import_captions` / `adobe_get_command_status` | Connected Premiere Pro / After Effects control through the Kolbo panel. Every edit needs the editor's approval in the panel; read `workflows/adobe.md` before the first call. |
|
|
162
163
|
|
|
163
164
|
## ⚠️ Edit in place — never delete+recreate (HARD RULE — always on)
|
|
164
165
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Premiere Pro & After Effects Workflow
|
|
2
|
+
|
|
3
|
+
Use these rules whenever the user wants an agent to inspect or edit an open Premiere Pro or After Effects project through Kolbo. The Kolbo panel inside the Adobe app is a separate desktop authority boundary: a Kolbo account is necessary, but the editor's approval inside the panel is the final gate for every edit.
|
|
4
|
+
|
|
5
|
+
## Connect and target safely
|
|
6
|
+
|
|
7
|
+
1. Call `adobe_list_sessions` before the first Adobe action.
|
|
8
|
+
2. If no session is listed, ask the user to open **Window → Extensions → Kolbo Studio** in Premiere Pro or After Effects, sign in, and click the **AI agents** (robot) button in the panel header until its dot turns green. Do not substitute any other Kolbo tool for the panel relay.
|
|
9
|
+
3. If one session is active, `session_id` may be omitted. If several are active, show each session's `name` (Premiere Pro / After Effects), `adobe_version`, platform and id, and ask which to target. Never guess.
|
|
10
|
+
4. Keep the chosen `session_id` on every later Adobe call in the task. Re-list after a disconnect or app restart; ids are process-scoped.
|
|
11
|
+
|
|
12
|
+
There is no MCP logout tool. The editor disconnects from the panel header button.
|
|
13
|
+
|
|
14
|
+
## Inspect before changing
|
|
15
|
+
|
|
16
|
+
- Start with `adobe_get_project`, then `adobe_get_timeline` for the active Premiere sequence or After Effects composition. Both are read-only and run without approval.
|
|
17
|
+
- Timeline responses are bounded; pass `max_clips` when you only need the first clips.
|
|
18
|
+
|
|
19
|
+
## Command lifecycle and approval
|
|
20
|
+
|
|
21
|
+
Every Adobe tool except `adobe_list_sessions` and `adobe_get_command_status` returns a **command record**, not the result. Poll `adobe_get_command_status` with its `command_id` until the status is terminal: `succeeded`, `failed`, `denied` or `canceled`.
|
|
22
|
+
|
|
23
|
+
- `awaiting_approval` is not a polling state. Stop and tell the user to approve or deny the request in the Kolbo panel, then check once more after they answer.
|
|
24
|
+
- `denied` is final. Do not retry the same edit with cosmetic changes; ask the user what they want instead.
|
|
25
|
+
- "Allow for this session" lives only in the panel's memory and ends when the editor disconnects. Never tell the user it persists, and never ask them to enable it for you.
|
|
26
|
+
- Pass a stable `idempotency_key` when a timeout may cause you to retry the same command. A new intent needs a new key.
|
|
27
|
+
|
|
28
|
+
## Media, sequences and captions
|
|
29
|
+
|
|
30
|
+
- `adobe_import_media` and `adobe_place_on_timeline` accept exactly one Kolbo `media_id` (preferred) or a Kolbo-owned HTTPS `url`. Third-party hosts, HTTP, private network and guessed URLs are rejected; import third-party files into Kolbo first.
|
|
31
|
+
- To generate then edit: run the Kolbo generation tool, wait for its successful result, then pass the real media id. Never place a still-running generation.
|
|
32
|
+
- `adobe_place_on_timeline` drops the clip into a free track at the playhead of the Premiere work sequence, or into the active After Effects composition. There is no time, track, trim or transition control in v1; do not promise one. Ask the user to position the playhead first when placement matters.
|
|
33
|
+
- `adobe_create_sequence` and `adobe_import_captions` are Premiere Pro only. In After Effects they fail with `UNSUPPORTED_HOST`.
|
|
34
|
+
- For captions, create the SRT with `transcribe_audio`, then pass its Kolbo-hosted `.srt` URL to `adobe_import_captions`.
|
|
35
|
+
- There is no raw ExtendScript tool. If the user asks for an edit outside these commands, say it is not available through agents yet and suggest doing it in the panel or the app.
|
|
36
|
+
|
|
37
|
+
## Completion proof
|
|
38
|
+
|
|
39
|
+
1. Re-read with `adobe_get_timeline` or `adobe_get_project` after an edit.
|
|
40
|
+
2. Report what changed, which session was targeted, and that the editor approved it.
|
|
41
|
+
3. A command is complete only when `adobe_get_command_status` shows `succeeded`. An accepted enqueue is not proof the edit happened.
|
package/src/apps/index.js
CHANGED
|
@@ -24,7 +24,9 @@ const { uploadWidgetHtml } = require('./widgets/upload');
|
|
|
24
24
|
const { fontUploadWidgetHtml } = require('./widgets/fontUpload');
|
|
25
25
|
const { listWidgetHtml } = require('./widgets/list');
|
|
26
26
|
const { HOST_MAP } = require('../cdn');
|
|
27
|
-
const { plansWidgetHtml } = require('./widgets/plans');
|
|
27
|
+
const { plansWidgetHtml } = require('./widgets/plans');
|
|
28
|
+
const { ResourceTemplate } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
29
|
+
const { McpError, ErrorCode } = require('@modelcontextprotocol/sdk/types.js');
|
|
28
30
|
|
|
29
31
|
const UI = {
|
|
30
32
|
generation: 'ui://kolbo/generation.html',
|
|
@@ -164,7 +166,8 @@ function registerApps(server) {
|
|
|
164
166
|
[UI.mediaGrid, 'Kolbo Library Widget'],
|
|
165
167
|
[UI.catalog, 'Kolbo Model Catalog Widget'],
|
|
166
168
|
[UI.transcript, 'Kolbo Transcription Widget'],
|
|
167
|
-
[UI.upload, 'Kolbo Upload Widget'],
|
|
169
|
+
[UI.upload, 'Kolbo Upload Widget'],
|
|
170
|
+
[UI.fontUpload, 'Kolbo Font Upload Widget'],
|
|
168
171
|
[UI.list, 'Kolbo List Widget'],
|
|
169
172
|
[UI.plans, 'Kolbo Plans Widget'],
|
|
170
173
|
]) {
|
|
@@ -178,10 +181,30 @@ function registerApps(server) {
|
|
|
178
181
|
_meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } },
|
|
179
182
|
}],
|
|
180
183
|
})
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
// Published tool definitions and old conversations can retain any previous
|
|
187
|
+
// content hash. Keep those addresses readable after deploying new HTML.
|
|
188
|
+
// Match only this registered widget and the version format we publish.
|
|
189
|
+
registerAppResource(
|
|
190
|
+
server, name + ' (previous versions)',
|
|
191
|
+
new ResourceTemplate(uri + '{?v}', { list: undefined }),
|
|
192
|
+
{ mimeType: RESOURCE_MIME_TYPE, _meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } } },
|
|
193
|
+
async (requestedUri) => {
|
|
194
|
+
const requested = requestedUri.href;
|
|
195
|
+
if (!new RegExp('^' + uri.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\?v=[a-f0-9]{10}$').test(requested)) {
|
|
196
|
+
throw new McpError(ErrorCode.InvalidParams, 'Unknown widget version URI');
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
contents: [{
|
|
200
|
+
uri: requested, mimeType: RESOURCE_MIME_TYPE, text: widgetHtml(uri),
|
|
201
|
+
_meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } },
|
|
202
|
+
}],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
185
208
|
|
|
186
209
|
/** `_meta` for a tool RESULT (and optionally for tool registration). */
|
|
187
210
|
function uiMeta(uri) {
|
package/src/index.js
CHANGED
|
@@ -81,6 +81,7 @@ const { registerStockLibraryTools } = require('./tools/stock_library');
|
|
|
81
81
|
const { registerAudioStemTools } = require('./tools/audio_stems');
|
|
82
82
|
const { registerAnalyzeTools } = require('./tools/analyze');
|
|
83
83
|
const { registerBlenderTools } = require('./tools/blender');
|
|
84
|
+
const { registerAdobeTools } = require('./tools/adobe');
|
|
84
85
|
const { registerApps, attachToolWidgetMeta } = require('./apps');
|
|
85
86
|
const { attachToolAnnotations } = require('./toolAnnotations');
|
|
86
87
|
|
|
@@ -121,6 +122,7 @@ function createServer(opts = {}) {
|
|
|
121
122
|
'LOCAL FILES: never upload a user file with your own cloud credentials, an S3/Spaces script, or a third-party host — Kolbo owns this. ' + LOCAL_FILE_ROUTING,
|
|
122
123
|
'PROMPT CONVENTIONS (Kolbo-specific — these change the OUTPUT, not just the metadata):',
|
|
123
124
|
'A. Visual DNA: passing `visual_dna_ids` is not enough — every DNA in play must ALSO be tagged inside the prompt text as `@Name`, using the DNA name (e.g. "@Kobi walks into frame"). Moodboards are referenced the same way with `#Name`. Resolve names via `list_visual_dnas` / `list_moodboards`.',
|
|
125
|
+
'A2. NUMBERED REFERENCE TAGS: every attached reference must ALSO be tagged in the prompt text by its 1-based position in the array you passed — `@Image 1`, `@Image 2` for `reference_images` / `source_images`, `@Video 1` for `reference_videos`, `@Audio 1` for `reference_audio_urls`. Say what each one contributes ("@Image 1 is the character reference — preserve exact face", "@Video 2 defines the camera move"). An untagged attachment is silently ignored by the engine even though it was uploaded and billed. Order is the contract: position N is bound to `@ImageN`, so append new refs, never insert. `@Image\\d+` / `@Video\\d+` / `@Audio\\d+` are reserved — they are never looked up as Visual DNAs.',
|
|
124
126
|
'B. The full Kolbo skill is available to you as MCP RESOURCES under `kolbo://skill/`. Read `kolbo://skill/SKILL.md` first — it is the core rules plus a routing index — then read the matching `kolbo://skill/references/...` file before writing prompts for a specific model or workflow (per-model prompt rules, Visual DNA workflow, Creative Director, marketing, cost validation). Do this instead of guessing; the references exist precisely because the rules differ per model.',
|
|
125
127
|
'PROJECT CONTRACT (read this before generating anything):',
|
|
126
128
|
'Everything in Kolbo lives inside a PROJECT — sessions, generations, and media are all project-scoped.',
|
|
@@ -200,6 +202,7 @@ function createServer(opts = {}) {
|
|
|
200
202
|
registerStockLibraryTools(server, client, toolOptions);
|
|
201
203
|
registerAudioStemTools(server, client, toolOptions);
|
|
202
204
|
registerBlenderTools(server, client, toolOptions);
|
|
205
|
+
registerAdobeTools(server, client, toolOptions);
|
|
203
206
|
|
|
204
207
|
// MCP Apps widget resources (ui://kolbo/*). Registering resources is inert
|
|
205
208
|
// for text-only hosts — they never fetch them.
|
package/src/toolAnnotations.js
CHANGED
|
@@ -35,6 +35,7 @@ const READ_ONLY = [
|
|
|
35
35
|
const OPEN_WORLD_READ_ONLY = [
|
|
36
36
|
'blender_list_sessions', 'blender_get_scene', 'blender_search_docs',
|
|
37
37
|
'blender_get_command_status',
|
|
38
|
+
'adobe_list_sessions', 'adobe_get_project', 'adobe_get_timeline', 'adobe_get_command_status',
|
|
38
39
|
];
|
|
39
40
|
|
|
40
41
|
const PRIVATE_WRITE = [
|
|
@@ -102,6 +103,8 @@ const DESTRUCTIVE_WRITE = [
|
|
|
102
103
|
const OPEN_WORLD_WRITE = [
|
|
103
104
|
'import_music_audio',
|
|
104
105
|
'publish_html_artifact', 'create_review_share_link', 'blender_capture_viewport',
|
|
106
|
+
// Adobe edits add bins, clips, sequences or caption tracks; none delete or overwrite.
|
|
107
|
+
'adobe_import_media', 'adobe_place_on_timeline', 'adobe_create_sequence', 'adobe_import_captions',
|
|
105
108
|
];
|
|
106
109
|
|
|
107
110
|
const OPEN_WORLD_DESTRUCTIVE = [
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
const { isTrustedMediaUrl } = require('./blender');
|
|
5
|
+
|
|
6
|
+
// Adobe Premiere Pro / After Effects control through the Kolbo panel relay.
|
|
7
|
+
// Same relay contract as Blender (/v1/adobe mirrors /v1/blender): commands are
|
|
8
|
+
// queued on the server, delivered to the open Kolbo panel, approved there by the
|
|
9
|
+
// editor, and executed with the panel's fixed ExtendScript entry points. There
|
|
10
|
+
// is no raw ExtendScript tool by design.
|
|
11
|
+
|
|
12
|
+
const SAFE_ID = /^[A-Za-z0-9._:-]+$/;
|
|
13
|
+
|
|
14
|
+
const noControls = (max) => z.string().min(1).max(max).refine(
|
|
15
|
+
(value) => value.trim().length > 0 && !/[\x00-\x1f]/.test(value),
|
|
16
|
+
`Must be non-empty and contain no control characters (max ${max}).`,
|
|
17
|
+
);
|
|
18
|
+
const sessionId = z.string().min(1).max(128).regex(SAFE_ID).optional().describe(
|
|
19
|
+
'Target Adobe session id from adobe_list_sessions. Omit only when exactly one Premiere Pro or After Effects panel is connected.'
|
|
20
|
+
);
|
|
21
|
+
const idempotencyKey = z.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.max(128)
|
|
24
|
+
.regex(SAFE_ID)
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Optional replay-safe key. Reuse it only when retrying the same command.');
|
|
27
|
+
const mediaId = z.string().min(1).max(128).regex(SAFE_ID).optional()
|
|
28
|
+
.describe('Kolbo media library id (preferred). Provide exactly one of media_id or url.');
|
|
29
|
+
const mediaUrl = z.string().url().max(4096).optional()
|
|
30
|
+
.describe('Kolbo-owned HTTPS media URL. Third-party hosts are rejected; import them into Kolbo first.');
|
|
31
|
+
const mediaKind = z.enum(['video', 'image', 'audio']).optional()
|
|
32
|
+
.describe('Media kind. Inferred from the Kolbo record or file extension when omitted.');
|
|
33
|
+
|
|
34
|
+
function text(value) {
|
|
35
|
+
return { content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function envelope(type, args, payload) {
|
|
39
|
+
return {
|
|
40
|
+
...(args.session_id ? { session_id: args.session_id } : {}),
|
|
41
|
+
command_type: type,
|
|
42
|
+
payload,
|
|
43
|
+
...(args.idempotency_key ? { idempotency_key: args.idempotency_key } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function command(client, type, args, payload) {
|
|
48
|
+
return client.post('/v1/adobe/commands', envelope(type, args, payload)).then(text);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function mediaSource(args, toolName) {
|
|
52
|
+
if (Boolean(args.media_id) === Boolean(args.url)) {
|
|
53
|
+
throw new Error(`${toolName} requires exactly one of media_id or url.`);
|
|
54
|
+
}
|
|
55
|
+
if (args.url && !isTrustedMediaUrl(args.url)) {
|
|
56
|
+
throw new Error(`${toolName} accepts only Kolbo-owned HTTPS media URLs. Import third-party files into Kolbo first.`);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
...(args.media_id ? { media_id: args.media_id } : { url: args.url }),
|
|
60
|
+
...(args.kind ? { kind: args.kind } : {}),
|
|
61
|
+
...(args.name ? { name: args.name } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function registerAdobeTools(server, client) {
|
|
66
|
+
server.tool(
|
|
67
|
+
'adobe_list_sessions',
|
|
68
|
+
'List the caller\'s Premiere Pro and After Effects windows that have the Kolbo panel connected to AI agents. Call this before the first Adobe command. If none are listed, ask the user to open the Kolbo panel and click the AI agents button in its header.',
|
|
69
|
+
{
|
|
70
|
+
page: z.number().int().min(1).default(1),
|
|
71
|
+
page_size: z.number().int().min(1).max(100).default(25),
|
|
72
|
+
},
|
|
73
|
+
async ({ page, page_size }) => text(await client.get(`/v1/adobe/sessions?page=${page}&page_size=${page_size}`))
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
server.tool(
|
|
77
|
+
'adobe_get_project',
|
|
78
|
+
'Queue a read-only inspection of the open Premiere Pro or After Effects project. No approval is needed. Returns a command record; poll adobe_get_command_status for the result.',
|
|
79
|
+
{
|
|
80
|
+
session_id: sessionId,
|
|
81
|
+
include_items: z.boolean().optional().describe('Include project items when the host reports them.'),
|
|
82
|
+
idempotency_key: idempotencyKey,
|
|
83
|
+
},
|
|
84
|
+
async (args) => command(client, 'project.get', args, {
|
|
85
|
+
...(args.include_items !== undefined ? { include_items: args.include_items } : {}),
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
server.tool(
|
|
90
|
+
'adobe_get_timeline',
|
|
91
|
+
'Queue a read-only inspection of the active Premiere Pro sequence or After Effects composition. No approval is needed. Long clip lists are truncated to max_clips.',
|
|
92
|
+
{
|
|
93
|
+
session_id: sessionId,
|
|
94
|
+
max_clips: z.number().int().min(1).max(1000).optional(),
|
|
95
|
+
idempotency_key: idempotencyKey,
|
|
96
|
+
},
|
|
97
|
+
async (args) => command(client, 'timeline.get', args, {
|
|
98
|
+
...(args.max_clips ? { max_clips: args.max_clips } : {}),
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
server.tool(
|
|
103
|
+
'adobe_import_media',
|
|
104
|
+
'Import one Kolbo media item into the open Premiere Pro or After Effects project bin. The editor must approve it in the Kolbo panel. Returns a command record; poll adobe_get_command_status.',
|
|
105
|
+
{
|
|
106
|
+
session_id: sessionId,
|
|
107
|
+
media_id: mediaId,
|
|
108
|
+
url: mediaUrl,
|
|
109
|
+
kind: mediaKind,
|
|
110
|
+
name: noControls(128).optional().describe('Display/file name. Sanitized by the panel.'),
|
|
111
|
+
bin: noControls(128).optional(),
|
|
112
|
+
idempotency_key: idempotencyKey,
|
|
113
|
+
},
|
|
114
|
+
async (args) => command(client, 'media.import', args, {
|
|
115
|
+
...mediaSource(args, 'adobe_import_media'),
|
|
116
|
+
...(args.bin ? { bin: args.bin } : {}),
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
server.tool(
|
|
121
|
+
'adobe_place_on_timeline',
|
|
122
|
+
'Import one Kolbo media item and place it on the Premiere Pro work sequence (free track at the playhead) or the active After Effects composition. There is no time or track parameter. The editor must approve it in the Kolbo panel.',
|
|
123
|
+
{
|
|
124
|
+
session_id: sessionId,
|
|
125
|
+
media_id: mediaId,
|
|
126
|
+
url: mediaUrl,
|
|
127
|
+
kind: mediaKind,
|
|
128
|
+
name: noControls(128).optional(),
|
|
129
|
+
idempotency_key: idempotencyKey,
|
|
130
|
+
},
|
|
131
|
+
async (args) => command(client, 'timeline.place', args, mediaSource(args, 'adobe_place_on_timeline'))
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
server.tool(
|
|
135
|
+
'adobe_create_sequence',
|
|
136
|
+
'Create and open a new Premiere Pro sequence using the project default preset. Premiere Pro only; After Effects sessions fail with UNSUPPORTED_HOST. The editor must approve it in the Kolbo panel.',
|
|
137
|
+
{
|
|
138
|
+
session_id: sessionId,
|
|
139
|
+
name: noControls(128),
|
|
140
|
+
idempotency_key: idempotencyKey,
|
|
141
|
+
},
|
|
142
|
+
async (args) => command(client, 'sequence.create', args, { name: args.name })
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
server.tool(
|
|
146
|
+
'adobe_import_captions',
|
|
147
|
+
'Import an SRT caption file hosted on Kolbo storage onto the active Premiere Pro sequence. Premiere Pro only. The editor must approve it in the Kolbo panel. Create the SRT with transcribe_audio first when needed.',
|
|
148
|
+
{
|
|
149
|
+
session_id: sessionId,
|
|
150
|
+
url: z.string().url().max(4096).describe('Kolbo-owned HTTPS URL of the .srt file.'),
|
|
151
|
+
name: noControls(128).optional(),
|
|
152
|
+
idempotency_key: idempotencyKey,
|
|
153
|
+
},
|
|
154
|
+
async (args) => {
|
|
155
|
+
if (!isTrustedMediaUrl(args.url)) {
|
|
156
|
+
throw new Error('adobe_import_captions accepts only Kolbo-owned HTTPS caption URLs.');
|
|
157
|
+
}
|
|
158
|
+
return command(client, 'captions.import', args, {
|
|
159
|
+
url: args.url,
|
|
160
|
+
...(args.name ? { name: args.name } : {}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
server.tool(
|
|
166
|
+
'adobe_get_command_status',
|
|
167
|
+
'Read the state, expires_at and bounded result/error of one Adobe command owned by the caller. awaiting_approval is not a polling state: stop and ask the user to approve or deny it in the Kolbo panel.',
|
|
168
|
+
{
|
|
169
|
+
command_id: z.string().min(1).max(128).regex(SAFE_ID),
|
|
170
|
+
},
|
|
171
|
+
async ({ command_id: id }) => text(await client.get(`/v1/adobe/commands/${encodeURIComponent(id)}`))
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = { registerAdobeTools };
|
package/src/tools/blender.js
CHANGED
package/src/tools/editor.js
CHANGED
|
@@ -15,7 +15,7 @@ function registerEditorTools(server, client) {
|
|
|
15
15
|
{ session_id: z.string().min(1).max(100) },
|
|
16
16
|
async ({ session_id }) => output(await client.get(`/v1/editor/sessions/${encodeURIComponent(session_id)}`)));
|
|
17
17
|
server.tool('update_video_editor_session',
|
|
18
|
-
'Edit or rename a saved Video Editor session. First read get_video_editor_schema and get_video_editor_session. session_data patches settings (name, format, duration, fps, dimensions, background) or replaces tracks. operations support add/update/remove/move items and tracks, reorder_items and reorder_tracks. Full clip settings include source trims, speed, transforms, grading, audio, text and word-timed captions. Nested values replace rather than merge. All times are milliseconds. Requires the revision from the read; conflicts require re-reading. Changes save atomically without generation credits.
|
|
18
|
+
'Edit or rename a saved Video Editor session. First read get_video_editor_schema and get_video_editor_session. session_data patches settings (name, format, duration, fps, dimensions, background) or replaces tracks. operations support add/update/remove/move items and tracks, reorder_items and reorder_tracks. Full clip settings include source trims, speed, transforms, grading, audio, text and word-timed captions. Nested values replace rather than merge. All times are milliseconds. Requires the revision from the read; conflicts require re-reading. Changes save atomically without generation credits. Open editors receive saved changes automatically; unsaved manual edits require conflict resolution.',
|
|
19
19
|
{ session_id: z.string().min(1).max(100), expected_revision: z.string().min(1).max(100),
|
|
20
20
|
session_flags: z.object({ isPinned: z.boolean().optional(), isArchived: z.boolean().optional(), isLocked: z.boolean().optional() }).strict().optional(),
|
|
21
21
|
session_data: z.record(z.unknown()).optional(), operations: z.array(z.record(z.unknown())).min(1).max(200).optional() },
|
package/src/tools/generate.js
CHANGED
|
@@ -1428,11 +1428,11 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
1428
1428
|
'generate_elements',
|
|
1429
1429
|
'Generate a video from reference elements (images, videos, and/or audio) + a text prompt. Use when the user wants to animate specific uploaded/referenced assets — e.g. "animate this product", "put these 3 characters into a scene". PRIMARY ROUTE FOR A DNA-ANCHORED MULTI-SHOT FILM: one call can carry the whole sequence — seedance-2-5 takes 4-30s, up to 30 shots and 20 Visual DNAs in a SINGLE generation (seedance-2: 4-15s, 9 DNAs) — instead of a stack of separate clips. DIALOGUE IS PERFORMED NATIVELY: quoted dialogue in the prompt comes back as synced voices with lip movement, room tone and the SFX named in the AUDIO block — never route scene dialogue to generate_speech or generate_lipsync. Write dialogue in ENGLISH; other languages (Hebrew included) do not perform reliably. COST: resolution is a multiplier. When list_models publishes `video_input_credit` and this call carries videos, charge that rate against nominal input seconds + nominal output seconds; MP4 padding within 0.15s of an integer snaps to that integer and larger fractions round up. Otherwise use the normal output-second rate. PROMPT CONTRACT (Seedance / Elements): Locked Intro only — Total line, then [GLOBAL LOOK] / [CAST] / [LOCATION] / SHOT N. Do NOT write SCENE CONTEXT / OPTICS / ACTION department packs. Every Visual DNA in visual_dna_ids MUST also appear in the prompt as @ExactDNAName (e.g. "@Zohar walks…") — never "Zohar\'s" or "the man on the left" as a substitute. IMPORTANT: different models accept different numbers and durations of inputs — call list_models type="elements" and read elements_max_images / elements_max_videos / elements_max_audio plus min_video_duration / max_video_duration before generating. For text-only → video use generate_video instead. For animating a single still image use generate_video_from_image. Returns the final video URL when complete.',
|
|
1430
1430
|
{
|
|
1431
|
-
prompt: z.string().describe('Locked Intro prompt (Seedance/Elements): Total line, [GLOBAL LOOK], [CAST] with @ExactDNAName for every visual_dna_ids entry, [LOCATION], then SHOT N. Not SCENE CONTEXT/OPTICS/ACTION packs. Never substitute "the left man" or "Zohar\'s" for @Name.'),
|
|
1431
|
+
prompt: z.string().describe('Locked Intro prompt (Seedance/Elements): Total line, [GLOBAL LOOK], [CAST] with @ExactDNAName for every visual_dna_ids entry, [LOCATION], then SHOT N. Not SCENE CONTEXT/OPTICS/ACTION packs. Never substitute "the left man" or "Zohar\'s" for @Name. EVERY attached reference must also be tagged by its 1-based array position — `@Image 1`/`@Image 2` (reference_images), `@Video 1` (reference_videos), `@Audio 1` (reference_audio_urls) — and its job stated ("@Image 1 defines the character\'s face and wardrobe", "@Video 1 defines the camera move"). An untagged attachment is ignored by the engine even though it was uploaded and billed.'),
|
|
1432
1432
|
model: z.string().optional().describe('Model identifier. If the user already named a family (Grok / Kling / Veo / Seedance / …), pass THAT family — never default to Seedance because Elements often uses it. Use list_models type="elements" for exact ids and elements_max_* caps. Do NOT omit (omitting = Smart Select).'),
|
|
1433
|
-
reference_images: z.array(z.string()).optional().describe('Array of image references (product shots, character references, etc.). Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_images` URLs from list_models for the chosen model — exceeding it is a deterministic 400.**'),
|
|
1434
|
-
reference_videos: z.array(z.string()).optional().describe('Array of reference videos for models that accept video inputs. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_videos` URLs and keep every clip within `min_video_duration`-`max_video_duration` from list_models.** If `video_input_credit` is present, every attached video contributes its nominal duration to combined-second billing: encoder padding within 0.15s of an integer snaps to it; larger fractions round up.'),
|
|
1435
|
-
reference_audio_urls: z.array(z.string()).optional().describe('Array of reference audio tracks for models that accept audio inputs. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_audio` URLs from list_models.** `audio_url` remains supported as the legacy single-track form.'),
|
|
1433
|
+
reference_images: z.array(z.string()).optional().describe('Array of image references (product shots, character references, etc.). Tag each one in the prompt text by its 1-based position here — item 1 is `@Image 1`, item 2 is `@Image 2` — or the engine ignores it. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_images` URLs from list_models for the chosen model — exceeding it is a deterministic 400.**'),
|
|
1434
|
+
reference_videos: z.array(z.string()).optional().describe('Array of reference videos for models that accept video inputs. Tag each one in the prompt text by its 1-based position here — `@Video 1`, `@Video 2` — stating what it defines (motion, camera move, pacing), or the engine ignores it. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_videos` URLs and keep every clip within `min_video_duration`-`max_video_duration` from list_models.** If `video_input_credit` is present, every attached video contributes its nominal duration to combined-second billing: encoder padding within 0.15s of an integer snaps to it; larger fractions round up.'),
|
|
1435
|
+
reference_audio_urls: z.array(z.string()).optional().describe('Array of reference audio tracks for models that accept audio inputs. Tag each one in the prompt text by its 1-based position here — `@Audio 1`, `@Audio 2` — stating what it carries (dialogue, ambience, music), or the engine ignores it. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_audio` URLs from list_models.** `audio_url` remains supported as the legacy single-track form.'),
|
|
1436
1436
|
audio_url: z.string().optional().describe('A single reference audio track — legacy form of reference_audio_urls. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Audio constraints: `elements_max_audio` from list_models gates whether audio is accepted at all; audio duration must fall within `min_audio_duration`-`max_audio_duration`; format must be in `supported_audio_formats` (if specified).**'),
|
|
1437
1437
|
files: z.array(z.string()).optional().describe('Untyped catch-all for mixed media — images, videos AND audio, each a URL or an absolute local path. The kind is detected from the file extension and the item is routed to the matching reference list, so a local .mp4 is sent as a video and a local .mp3 as audio. Prefer the typed lists (reference_images / reference_videos / reference_audio_urls) when you already know the kind; they accept local paths too. URLs given here are forwarded as URLs, never re-uploaded. **Caps still apply per kind: `elements_max_images` / `elements_max_videos` / `elements_max_audio` from list_models. Local uploads are capped at 200MB each.**'),
|
|
1438
1438
|
duration: z.number().optional().describe('Output duration in seconds. Must be in `supported_durations` from list_models, OR within `min_output_duration`-`max_output_duration`. Default: 5'),
|