@writepanda/mcp 1.276.0 → 1.285.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/bin/server.mjs +166 -15
- package/package.json +1 -1
package/bin/server.mjs
CHANGED
|
@@ -53,7 +53,6 @@ import {
|
|
|
53
53
|
IN_APP_UNAVAILABLE,
|
|
54
54
|
isInAppCaller,
|
|
55
55
|
} from "./appConnection.mjs";
|
|
56
|
-
import { frameUntrusted } from "./untrusted.mjs";
|
|
57
56
|
import {
|
|
58
57
|
APP_TOOLS,
|
|
59
58
|
clientSupportsUi,
|
|
@@ -63,6 +62,7 @@ import {
|
|
|
63
62
|
toolUiMeta,
|
|
64
63
|
} from "./apps/index.mjs";
|
|
65
64
|
import { portableSchema } from "./portableSchema.mjs";
|
|
65
|
+
import { frameUntrusted } from "./untrusted.mjs";
|
|
66
66
|
|
|
67
67
|
// ── Credentials + transport ───────────────────────────────────────────
|
|
68
68
|
//
|
|
@@ -1032,7 +1032,7 @@ const TOOLS = [
|
|
|
1032
1032
|
{
|
|
1033
1033
|
name: "connector_list",
|
|
1034
1034
|
description:
|
|
1035
|
-
'List MCP connectors and their state. If the one needed isn\'t connected, tell the user its howToConnect line; you cannot connect connectors. status "connected, last check failed" (connected:false, lastCheck with reason, host and fix) means PandaStudio\'s own last use of it failed. needsReconnect:true (state needs_auth, status "needs sign-in again", HTTP 401) = the service refused its sign-in (e.g. a stale Replicate API token): nothing on it runs until the user presses Reconnect in Settings; relay howToConnect, don\'t retry. auth "api-key" + needsKey: the user must paste a key in Settings (never ask for it in chat).',
|
|
1035
|
+
'List MCP connectors and their state. If the one needed isn\'t connected, tell the user its howToConnect line; you cannot connect connectors. status "connected, last check failed" (connected:false, lastCheck with reason, host and fix) means PandaStudio\'s own last use of it failed. needsReconnect:true (state needs_auth, status "needs sign-in again", HTTP 401) = the service refused its sign-in (e.g. a stale Replicate API token): nothing on it runs until the user presses Reconnect in Settings; relay howToConnect, don\'t retry. auth "api-key" + needsKey: the user must paste a key in Settings (never ask for it in chat). native:true (fal): no connector_tools/connector_call; use its usedThrough tools (fal: media_generate_video).',
|
|
1036
1036
|
inputSchema: {
|
|
1037
1037
|
type: "object",
|
|
1038
1038
|
properties: {
|
|
@@ -1648,6 +1648,34 @@ const TOOLS = [
|
|
|
1648
1648
|
},
|
|
1649
1649
|
command: "project.duplicate",
|
|
1650
1650
|
},
|
|
1651
|
+
{
|
|
1652
|
+
name: "project_versions",
|
|
1653
|
+
description:
|
|
1654
|
+
"A project's earlier versions, newest first (a snapshot about every 10 min of editing, kept up to 30 days). For lost edits or 'go back to how it was'. Then project_open_version.",
|
|
1655
|
+
inputSchema: {
|
|
1656
|
+
type: "object",
|
|
1657
|
+
properties: {
|
|
1658
|
+
id: { type: "string" },
|
|
1659
|
+
path: { type: "string" },
|
|
1660
|
+
},
|
|
1661
|
+
},
|
|
1662
|
+
command: "project.versions",
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
name: "project_open_version",
|
|
1666
|
+
description:
|
|
1667
|
+
"Bring back an earlier version (from project_versions) as a NEW project beside the original, named '<name> (<date, time>)'. Never changes the original. Returns { id, path, name, savedAt }.",
|
|
1668
|
+
inputSchema: {
|
|
1669
|
+
type: "object",
|
|
1670
|
+
properties: {
|
|
1671
|
+
id: { type: "string" },
|
|
1672
|
+
path: { type: "string" },
|
|
1673
|
+
versionId: { type: "string", description: "From project_versions" },
|
|
1674
|
+
},
|
|
1675
|
+
required: ["versionId"],
|
|
1676
|
+
},
|
|
1677
|
+
command: "project.open-version",
|
|
1678
|
+
},
|
|
1651
1679
|
{
|
|
1652
1680
|
name: "project_locate",
|
|
1653
1681
|
description:
|
|
@@ -3005,6 +3033,11 @@ const TOOLS = [
|
|
|
3005
3033
|
inputSchema: {
|
|
3006
3034
|
type: "object",
|
|
3007
3035
|
properties: {
|
|
3036
|
+
still: {
|
|
3037
|
+
type: "boolean",
|
|
3038
|
+
description:
|
|
3039
|
+
"The graphic is MEANT to hold still (no entrance, no motion): skip the frozen-render check, kept for re-renders. Never fake a slow drift instead.",
|
|
3040
|
+
},
|
|
3008
3041
|
id: { type: "string" },
|
|
3009
3042
|
path: { type: "string" },
|
|
3010
3043
|
overlayId: { type: "string" },
|
|
@@ -4107,10 +4140,31 @@ const TOOLS = [
|
|
|
4107
4140
|
},
|
|
4108
4141
|
command: "project.detect-face",
|
|
4109
4142
|
},
|
|
4143
|
+
{
|
|
4144
|
+
name: "project_review_moment",
|
|
4145
|
+
description:
|
|
4146
|
+
"LOOK AND LISTEN to a moment of the edit as the viewer gets it: a contact sheet of the frames around atMs (edited ms) or wordId, the EXPORTED mix of that stretch transcribed and compared with what the edit should play (extra = leftover of a cut word or line, missing = clipped word), whether each cut lands in quiet or speech, nearby edits and stutters, plus a plain verdict. Use after every cut / pause / insert fix BEFORE telling the user it's fixed, and when the user names a moment ('at 16 seconds'). ASYNC: { jobId }; job_wait.",
|
|
4147
|
+
inputSchema: {
|
|
4148
|
+
type: "object",
|
|
4149
|
+
properties: {
|
|
4150
|
+
id: { type: "string" },
|
|
4151
|
+
path: { type: "string" },
|
|
4152
|
+
atMs: { type: "number", description: "Edited ms at the centre. Or wordId." },
|
|
4153
|
+
wordId: { type: "string", description: "Centre on this word (transcript id or prefix)." },
|
|
4154
|
+
spanMs: {
|
|
4155
|
+
type: "number",
|
|
4156
|
+
description: "Each side of the centre, ms. Default 1500, max 5000.",
|
|
4157
|
+
},
|
|
4158
|
+
frames: { type: "number", description: "Frames on the sheet. Default 12, max 24." },
|
|
4159
|
+
listen: { type: "boolean", description: "Default true; false = frames and edits only." },
|
|
4160
|
+
},
|
|
4161
|
+
},
|
|
4162
|
+
command: "project.review-moment",
|
|
4163
|
+
},
|
|
4110
4164
|
{
|
|
4111
4165
|
name: "project_render_sheet",
|
|
4112
4166
|
description:
|
|
4113
|
-
"Render N frames across an edited-time range into one contact-sheet PNG (row-major). Returns { sheetPath, frames[{atMs, path}] }; sheetPath null = read frames[].path.",
|
|
4167
|
+
"Render N frames across an edited-time range into one contact-sheet PNG (row-major). Returns { sheetPath, frames[{atMs, path}] }; sheetPath null (see sheetWarning) = read frames[].path.",
|
|
4114
4168
|
inputSchema: {
|
|
4115
4169
|
type: "object",
|
|
4116
4170
|
properties: {
|
|
@@ -4128,7 +4182,7 @@ const TOOLS = [
|
|
|
4128
4182
|
{
|
|
4129
4183
|
name: "project_apply_edit_plan",
|
|
4130
4184
|
description:
|
|
4131
|
-
'Apply many trim / zoom / speed ops atomically (any invalid op aborts). Ops: {"op":"add-trim",startMs,endMs} | {"op":"add-zoom",atMs,durationMs,depth?,focusX?,focusY?,soundUrl?,anchorSourceMs?} | {"op":"add-speed",startMs,endMs,speed}.',
|
|
4185
|
+
'Apply many trim / zoom / speed ops atomically (any invalid op aborts). Ops: {"op":"add-trim",startMs,endMs} (SOURCE ms) or by word {"op":"add-trim",afterWordId|fromWordId,beforeWordId|throughWordId}, edges snapped to the audio like project_add_trim | {"op":"add-zoom",atMs,durationMs,depth?,focusX?,focusY?,soundUrl?,anchorSourceMs?} | {"op":"add-speed",startMs,endMs,speed}.',
|
|
4132
4186
|
inputSchema: {
|
|
4133
4187
|
type: "object",
|
|
4134
4188
|
properties: {
|
|
@@ -4348,17 +4402,32 @@ const TOOLS = [
|
|
|
4348
4402
|
},
|
|
4349
4403
|
{
|
|
4350
4404
|
name: "project_add_trim",
|
|
4351
|
-
description:
|
|
4405
|
+
description:
|
|
4406
|
+
"Cut a span the exporter skips. Name the edges by WORD (afterWordId / fromWordId for the start, beforeWordId / throughWordId for the end): no ms maths, no clock mix-ups. Or startMs/endMs in SOURCE ms (a transcript word's sourceStartMs). Every edge snaps to the quietest point nearby without clipping a kept word; result.edges says where each landed and notes say when an edge inside a word cut it. Check the spot with project_review_moment before telling the user it's fixed.",
|
|
4352
4407
|
inputSchema: {
|
|
4353
4408
|
type: "object",
|
|
4354
4409
|
properties: {
|
|
4355
4410
|
id: { type: "string" },
|
|
4356
4411
|
path: { type: "string" },
|
|
4357
|
-
startMs: { type: "number" },
|
|
4358
|
-
endMs: { type: "number" },
|
|
4412
|
+
startMs: { type: "number", description: "SOURCE ms. Or afterWordId / fromWordId." },
|
|
4413
|
+
endMs: { type: "number", description: "SOURCE ms. Or beforeWordId / throughWordId." },
|
|
4414
|
+
afterWordId: {
|
|
4415
|
+
type: "string",
|
|
4416
|
+
description: "Cut STARTS right after this word (kept). Instead of startMs.",
|
|
4417
|
+
},
|
|
4418
|
+
fromWordId: { type: "string", description: "Cut STARTS at this word (cut too)." },
|
|
4419
|
+
beforeWordId: {
|
|
4420
|
+
type: "string",
|
|
4421
|
+
description: "Cut ENDS right before this word (kept). Instead of endMs.",
|
|
4422
|
+
},
|
|
4423
|
+
throughWordId: { type: "string", description: "Cut ENDS after this word (cut too)." },
|
|
4424
|
+
snapToAudio: {
|
|
4425
|
+
type: "boolean",
|
|
4426
|
+
description:
|
|
4427
|
+
"Default true: edges snap to the quietest point nearby without clipping a kept word. false = exact ms.",
|
|
4428
|
+
},
|
|
4359
4429
|
expectedRevision: { type: "number" },
|
|
4360
4430
|
},
|
|
4361
|
-
required: ["startMs", "endMs"],
|
|
4362
4431
|
},
|
|
4363
4432
|
command: "project.add-trim",
|
|
4364
4433
|
},
|
|
@@ -4407,6 +4476,11 @@ const TOOLS = [
|
|
|
4407
4476
|
inputSchema: {
|
|
4408
4477
|
type: "object",
|
|
4409
4478
|
properties: {
|
|
4479
|
+
snapToAudio: {
|
|
4480
|
+
type: "boolean",
|
|
4481
|
+
description:
|
|
4482
|
+
"lane main: default true, each edge snaps to the quietest point nearby without clipping a kept word (result.edges). false = exact.",
|
|
4483
|
+
},
|
|
4410
4484
|
id: { type: "string", description: "Project id (or pass path)." },
|
|
4411
4485
|
path: { type: "string", description: "Project file path (or pass id)." },
|
|
4412
4486
|
startMs: { type: "number", description: "Gap start, edited ms." },
|
|
@@ -4838,10 +4912,25 @@ const TOOLS = [
|
|
|
4838
4912
|
{
|
|
4839
4913
|
name: "project_update_region",
|
|
4840
4914
|
description:
|
|
4841
|
-
"Patch a region; unspecified fields are kept. Put the fields in patch. Every type takes startMs, endMs (edited ms; trim and speed are source ms); a retimed region is re-anchored at its new place, so later cuts and editor reloads keep it there. Patchable: zoom (depth, focusX, focusY, followCursor, focusMode static|auto), trim (startMs, endMs), speed (speed, rampIn, rampOut, preservePitch, freezeMs, holdMs, reverse, reverseAudio), fx (opacity, blendMode, speed, zIndex), annotation (text = the words shown, content, textContent, x, y, width, height, fontSize, fontFamily, textColor, color, backgroundColor, fontWeight, fontStyle, textDecoration, textAlign, style, zIndex), overlay (x, y, width, height in canvas %, layer, opacity, blendMode, muted, volume, loop, motionBlur, zIndex), adjustment (blendMode, fadeIn, fadeOut), motion (motionBlur), clip-transform (preset, transitionMs, easing, bezier, cameraFit, backgroundColor), background-effect (mode, strength, backgroundImage, backgroundFit, outline, outlineWidth, outlineColor, outlineShadow, matteContract, matteFeather), audio-overlay (sourceStartMs, volume 0-2, fadeIn, fadeOut in ms, 0 or null removes; fadeInMs, fadeOutMs are aliases). A key the region type doesn't have is not applied: the result lists it in ignoredKeys with a warning, and the call fails when nothing in the patch applies.",
|
|
4915
|
+
"Patch a region; unspecified fields are kept. Put the fields in patch. Every type takes startMs, endMs (edited ms; trim and speed are source ms); a retimed region is re-anchored at its new place, so later cuts and editor reloads keep it there. Patchable: zoom (depth, focusX, focusY, followCursor, focusMode static|auto), trim (startMs, endMs, afterWordId, fromWordId, beforeWordId, throughWordId), speed (speed, rampIn, rampOut, preservePitch, freezeMs, holdMs, reverse, reverseAudio), fx (opacity, blendMode, speed, zIndex), annotation (text = the words shown, content, textContent, x, y, width, height, fontSize, fontFamily, textColor, color, backgroundColor, fontWeight, fontStyle, textDecoration, textAlign, style, zIndex), overlay (x, y, width, height in canvas %, layer, opacity, blendMode, muted, volume, loop, motionBlur, zIndex), adjustment (blendMode, fadeIn, fadeOut), motion (motionBlur), clip-transform (preset, transitionMs, easing, bezier, cameraFit, backgroundColor), background-effect (mode, strength, backgroundImage, backgroundFit, outline, outlineWidth, outlineColor, outlineShadow, matteContract, matteFeather), audio-overlay (sourceStartMs, volume 0-2, fadeIn, fadeOut in ms, 0 or null removes; fadeInMs, fadeOutMs are aliases). A key the region type doesn't have is not applied: the result lists it in ignoredKeys with a warning, and the call fails when nothing in the patch applies.",
|
|
4842
4916
|
inputSchema: {
|
|
4843
4917
|
type: "object",
|
|
4844
4918
|
properties: {
|
|
4919
|
+
afterWordId: {
|
|
4920
|
+
type: "string",
|
|
4921
|
+
description: "Cut STARTS right after this word (kept). Instead of startMs.",
|
|
4922
|
+
},
|
|
4923
|
+
fromWordId: { type: "string", description: "Cut STARTS at this word (cut too)." },
|
|
4924
|
+
beforeWordId: {
|
|
4925
|
+
type: "string",
|
|
4926
|
+
description: "Cut ENDS right before this word (kept). Instead of endMs.",
|
|
4927
|
+
},
|
|
4928
|
+
throughWordId: { type: "string", description: "Cut ENDS after this word (cut too)." },
|
|
4929
|
+
snapToAudio: {
|
|
4930
|
+
type: "boolean",
|
|
4931
|
+
description:
|
|
4932
|
+
"Default true: edges snap to the quietest point nearby without clipping a kept word. false = exact ms.",
|
|
4933
|
+
},
|
|
4845
4934
|
id: { type: "string" },
|
|
4846
4935
|
loop: { type: "boolean", description: "overlay: loop, or hold the last frame." },
|
|
4847
4936
|
path: { type: "string" },
|
|
@@ -5921,7 +6010,7 @@ const TOOLS = [
|
|
|
5921
6010
|
{
|
|
5922
6011
|
name: "transcript_get",
|
|
5923
6012
|
description:
|
|
5924
|
-
"Transcript (default: open project). compact: segments of [id, text,
|
|
6013
|
+
"Transcript (default: open project). compact: segments of [id, text, editedStartMs, editedEndMs, sourceStartMs] (edited = as it plays, the playhead's clock, null = cut; sourceStartMs for anchorSourceMs; cut by word id, not ms); ids are unique prefixes, accepted wherever word ids are. text: '[m:ss.s] line' per segment, cheapest to read. words: full ids, end times, speaker. full: legacy.",
|
|
5925
6014
|
inputSchema: {
|
|
5926
6015
|
type: "object",
|
|
5927
6016
|
properties: {
|
|
@@ -6906,6 +6995,54 @@ const TOOLS = [
|
|
|
6906
6995
|
},
|
|
6907
6996
|
command: "media.generate-presenter",
|
|
6908
6997
|
},
|
|
6998
|
+
{
|
|
6999
|
+
name: "media_generate_video",
|
|
7000
|
+
description:
|
|
7001
|
+
"Generate an AI video clip with MiniMax H3 on the user's OWN fal account (connect fal in Settings > Connectors; their credits). Text to video, or image to video from a first frame (image) and optional last frame (endImage). PAID: only after the user agreed; never retry a failed job yourself. ASYNC: { jobId, estimatedCostUsd }; job_wait timeoutMs 600000 for { videoPath, durationMs, width, height, model, requestId }. Place with project_add_motion_graphic (overlay, moving B-roll) or project_add_clip (main track). FAL_NOT_CONNECTED: ask the user to connect fal (never ask for the key in chat).",
|
|
7002
|
+
inputSchema: {
|
|
7003
|
+
type: "object",
|
|
7004
|
+
properties: {
|
|
7005
|
+
prompt: {
|
|
7006
|
+
type: "string",
|
|
7007
|
+
description:
|
|
7008
|
+
"The shot: subject, action, camera, light, mood. With an image, describe the motion.",
|
|
7009
|
+
},
|
|
7010
|
+
image: {
|
|
7011
|
+
type: "string",
|
|
7012
|
+
description: "First frame: absolute path (PNG/JPEG/WebP) or https URL.",
|
|
7013
|
+
},
|
|
7014
|
+
endImage: { type: "string", description: "Last frame, same forms. Image to video only." },
|
|
7015
|
+
model: {
|
|
7016
|
+
type: "string",
|
|
7017
|
+
enum: ["h3", "h3-max", "h3-max-turbo"],
|
|
7018
|
+
description: "Default h3. h3-max for 1080P; h3-max-turbo is faster and cheaper.",
|
|
7019
|
+
},
|
|
7020
|
+
durationSec: {
|
|
7021
|
+
type: "number",
|
|
7022
|
+
description: "Default 5. h3: whole seconds 5-15; h3-max/turbo: 0.92-15.",
|
|
7023
|
+
},
|
|
7024
|
+
resolution: {
|
|
7025
|
+
type: "string",
|
|
7026
|
+
enum: ["480P", "768P", "1080P", "2K", "4K"],
|
|
7027
|
+
description: "Default 768P. h3: 480P/768P/2K/4K; h3-max/turbo: 480P/768P/1080P.",
|
|
7028
|
+
},
|
|
7029
|
+
aspectRatio: {
|
|
7030
|
+
type: "string",
|
|
7031
|
+
enum: ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"],
|
|
7032
|
+
description: "Text to video only (default 16:9); image to video follows the image.",
|
|
7033
|
+
},
|
|
7034
|
+
promptExpansion: {
|
|
7035
|
+
type: "string",
|
|
7036
|
+
enum: ["balanced", "fast", "quality", "disabled"],
|
|
7037
|
+
description: "fal's prompt rewriting. Default balanced; disabled = word for word.",
|
|
7038
|
+
},
|
|
7039
|
+
seed: { type: "number" },
|
|
7040
|
+
outputDir: { type: "string", description: "Default <userData>/generated-videos." },
|
|
7041
|
+
},
|
|
7042
|
+
required: ["prompt"],
|
|
7043
|
+
},
|
|
7044
|
+
command: "media.generate-video",
|
|
7045
|
+
},
|
|
6909
7046
|
{
|
|
6910
7047
|
name: "project_inspect_footage",
|
|
6911
7048
|
description:
|
|
@@ -8179,6 +8316,11 @@ const TOOLS = [
|
|
|
8179
8316
|
inputSchema: {
|
|
8180
8317
|
type: "object",
|
|
8181
8318
|
properties: {
|
|
8319
|
+
still: {
|
|
8320
|
+
type: "boolean",
|
|
8321
|
+
description:
|
|
8322
|
+
"The graphic is MEANT to hold still (no entrance, no motion): skip the frozen-render check, kept for re-renders. Never fake a slow drift instead.",
|
|
8323
|
+
},
|
|
8182
8324
|
templateId: { type: "string" },
|
|
8183
8325
|
slots: { type: "object", description: "By key; image slots take a file path." },
|
|
8184
8326
|
variables: {
|
|
@@ -8328,6 +8470,11 @@ const TOOLS = [
|
|
|
8328
8470
|
inputSchema: {
|
|
8329
8471
|
type: "object",
|
|
8330
8472
|
properties: {
|
|
8473
|
+
still: {
|
|
8474
|
+
type: "boolean",
|
|
8475
|
+
description:
|
|
8476
|
+
"The graphic is MEANT to hold still (no entrance, no motion): skip the frozen-render check, kept for re-renders. Never fake a slow drift instead.",
|
|
8477
|
+
},
|
|
8331
8478
|
html: { type: "string", description: "Or htmlPath." },
|
|
8332
8479
|
htmlPath: { type: "string" },
|
|
8333
8480
|
aspectRatio: { type: "string", enum: ["16:9", "9:16", "1:1"] },
|
|
@@ -8528,7 +8675,8 @@ const TOOLS = [
|
|
|
8528
8675
|
// ── project-aware LLM ──────────────────────────────────────────
|
|
8529
8676
|
{
|
|
8530
8677
|
name: "llm_generate_title",
|
|
8531
|
-
description:
|
|
8678
|
+
description:
|
|
8679
|
+
"Generate a YouTube title from what the EDITED video says (cut words left out) with the local LLM. Returns { title }: one complete phrase within maxChars, never cut mid-word.",
|
|
8532
8680
|
inputSchema: {
|
|
8533
8681
|
type: "object",
|
|
8534
8682
|
properties: {
|
|
@@ -8541,7 +8689,8 @@ const TOOLS = [
|
|
|
8541
8689
|
},
|
|
8542
8690
|
{
|
|
8543
8691
|
name: "llm_generate_description",
|
|
8544
|
-
description:
|
|
8692
|
+
description:
|
|
8693
|
+
"Generate a 3-5 sentence YouTube description from what the EDITED video says, with the local LLM. Returns { description, warnings? }: a warning means it repeated the transcript, so write the description yourself.",
|
|
8545
8694
|
inputSchema: {
|
|
8546
8695
|
type: "object",
|
|
8547
8696
|
properties: {
|
|
@@ -8554,7 +8703,8 @@ const TOOLS = [
|
|
|
8554
8703
|
},
|
|
8555
8704
|
{
|
|
8556
8705
|
name: "llm_generate_caption",
|
|
8557
|
-
description:
|
|
8706
|
+
description:
|
|
8707
|
+
"Generate an Instagram Reel caption with hashtags from what the EDITED video says.",
|
|
8558
8708
|
inputSchema: {
|
|
8559
8709
|
type: "object",
|
|
8560
8710
|
properties: {
|
|
@@ -8568,7 +8718,7 @@ const TOOLS = [
|
|
|
8568
8718
|
{
|
|
8569
8719
|
name: "llm_generate_timestamps",
|
|
8570
8720
|
description:
|
|
8571
|
-
"Generate YouTube chapter timestamps for the edited video: edited-timeline times from the words that survive the cuts (first 0:00, each >=
|
|
8721
|
+
"Generate YouTube chapter timestamps for the edited video: edited-timeline times from the words that survive the cuts (first 0:00, each >= 30 s, starting where a sentence starts, all before the end); the local LLM only writes each label from its own chapter's words.",
|
|
8572
8722
|
inputSchema: {
|
|
8573
8723
|
type: "object",
|
|
8574
8724
|
properties: {
|
|
@@ -8856,7 +9006,7 @@ const TOOLS = [
|
|
|
8856
9006
|
{
|
|
8857
9007
|
name: "ideas_research",
|
|
8858
9008
|
description:
|
|
8859
|
-
"Find outliers (videos beating their own channel's median views) across a niche: searches YouTube for the topic (comma-separate several angles) and/or expands from a seed channel the target audience watches, reads every channel found and ranks their recent uploads by multiplier. For what's trending, pass period month and maxAgeDays 30. Async: returns { researchId, jobId }; job.wait the jobId (~20-40 s), then ideas.get.",
|
|
9009
|
+
"Find outliers (videos beating their own channel's median views) across a niche: searches YouTube for the topic (comma-separate several angles) and/or expands from a seed channel the target audience watches, reads every channel found and ranks their recent uploads by multiplier. For what's trending, pass period month and maxAgeDays 30. With maxAgeDays set, an outlier the listing left undated (Shorts, premieres) is kept only once its real publish date is under the limit; ones YouTube won't date are left out and counted in stats.undatedSkipped. Async: returns { researchId, jobId }; job.wait the jobId (~20-40 s), then ideas.get.",
|
|
8860
9010
|
inputSchema: {
|
|
8861
9011
|
type: "object",
|
|
8862
9012
|
properties: {
|
|
@@ -9708,6 +9858,7 @@ Publishing has daily limits (YouTube uploads and updates per license, social pos
|
|
|
9708
9858
|
|
|
9709
9859
|
PandaStudio problems (a capability gap like an imported font the export can't draw, a command failing unexpectedly, a render not matching the project): call system_report_issue yourself, then tell the user you reported it. Not for user mistakes, missing keys or taste.
|
|
9710
9860
|
|
|
9861
|
+
Fixing a cut, pause or insert the user points at ("at 16 s it's sloppy"): look and listen with project_review_moment (frames + the exported mix transcribed + whether each cut lands in quiet), fix by WORD (project_add_trim / project_update_region with afterWordId / beforeWordId, never ms worked out by hand; edges snap to the audio), then review again before saying it's fixed. A few frames off is quicker for the user to drag in the timeline: tell them. A stutter in a result's warnings (picture changes a few frames apart) means put them on one frame or keep one.
|
|
9711
9862
|
Views: in chat apps that show MCP views, preview_show, project_render_frame / _render_sheet and project_edit_summary also show the frames and what the edit contains, and clips_get / clips_make show the clips as cards the user can open, export or remove. Summarise in a line instead of describing each frame or clip; what the user does in a view arrives as context, don't redo it.
|
|
9712
9863
|
|
|
9713
9864
|
Share links: when the user asks to send a video for feedback, share_status then share_create on a finished export gives a link anyone can watch and comment on (async, job_wait; storage is capped per plan, quota_exceeded means ask which link to delete). share_comments brings viewer comments into the project as review pins: apply each, review_resolve it, and it shows as Done to viewers. Never share, delete a link or reply to viewers without the user asking.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.285.0",
|
|
4
4
|
"description": "Model Context Protocol server for PandaStudio. Exposes the desktop video editor's automation surface to Cursor, Continue, Cline, Claude Desktop, and any MCP-compliant client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pandastudio",
|