@writepanda/mcp 1.249.0 → 1.259.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 +802 -19
- package/package.json +1 -1
package/bin/server.mjs
CHANGED
|
@@ -1274,6 +1274,29 @@ const TOOLS = [
|
|
|
1274
1274
|
borderRadius: { type: "number" },
|
|
1275
1275
|
showBlur: { type: "boolean" },
|
|
1276
1276
|
motionBlurAmount: { type: "number" },
|
|
1277
|
+
wallpaperMotion: { type: "number", description: "mesh: background speed 0-2." },
|
|
1278
|
+
screenFrame: {
|
|
1279
|
+
type: "object",
|
|
1280
|
+
description: "Device frame for screen recordings.",
|
|
1281
|
+
properties: {
|
|
1282
|
+
kind: {
|
|
1283
|
+
type: "string",
|
|
1284
|
+
enum: ["browser", "window", "laptop", "phone", "tablet"],
|
|
1285
|
+
},
|
|
1286
|
+
theme: { type: "string", enum: ["light", "dark"] },
|
|
1287
|
+
url: { type: "string" },
|
|
1288
|
+
},
|
|
1289
|
+
},
|
|
1290
|
+
screenTilt: {
|
|
1291
|
+
type: "object",
|
|
1292
|
+
description: "3D tilt of screen recordings.",
|
|
1293
|
+
properties: {
|
|
1294
|
+
angle: { type: "string", enum: ["flat", "left", "right", "above"] },
|
|
1295
|
+
followCursor: { type: "boolean" },
|
|
1296
|
+
clickBounce: { type: "boolean" },
|
|
1297
|
+
strength: { type: "number", description: "0-1." },
|
|
1298
|
+
},
|
|
1299
|
+
},
|
|
1277
1300
|
},
|
|
1278
1301
|
},
|
|
1279
1302
|
graphicSound: {
|
|
@@ -2412,12 +2435,18 @@ const TOOLS = [
|
|
|
2412
2435
|
{
|
|
2413
2436
|
name: "podcast_draft_rundown",
|
|
2414
2437
|
description:
|
|
2415
|
-
"Have the studio's producer draft the run of show from a short brief: segments with questions, guest lower thirds, and a YouTube title, description and thumbnail idea, on the model the user picked for the assistant. Replaces the current run of show unless apply=false.",
|
|
2438
|
+
"Have the studio's producer draft the run of show from a short brief: segments with questions, guest lower thirds, and a YouTube title, description and thumbnail idea, on the model the user picked for the assistant. Pass the host's own questions as questions: each goes in word for word (on the prompter card) with a lower third. Replaces the current run of show unless apply=false.",
|
|
2416
2439
|
inputSchema: {
|
|
2417
2440
|
type: "object",
|
|
2418
2441
|
properties: {
|
|
2419
2442
|
brief: { type: "string" },
|
|
2420
2443
|
minutes: { type: "number", description: "Total show length (default 45)." },
|
|
2444
|
+
questions: {
|
|
2445
|
+
type: "array",
|
|
2446
|
+
items: { type: "string" },
|
|
2447
|
+
description:
|
|
2448
|
+
"The host's own questions, in order: kept word for word, each with a lower third.",
|
|
2449
|
+
},
|
|
2421
2450
|
guests: {
|
|
2422
2451
|
type: "array",
|
|
2423
2452
|
items: {
|
|
@@ -3770,7 +3799,7 @@ const TOOLS = [
|
|
|
3770
3799
|
{
|
|
3771
3800
|
name: "audio_describe",
|
|
3772
3801
|
description:
|
|
3773
|
-
"Numeric audio evidence for a local audio/video path OR project id/range: loudness, true peak, clipping, silence, speech/music estimate, tempo/beats, attacks, spectral brightness and summary. No song/sound identification. Async: job.wait; first 10 minutes maximum.",
|
|
3802
|
+
"Numeric audio evidence for a local audio/video path OR project id/range: loudness, true peak, clipping, silence, speech/music estimate, tempo/beats, attacks, spectral brightness and summary. A file with no audio track returns hasAudio:false (silent), not an error. No song/sound identification. Async: job.wait; first 10 minutes maximum.",
|
|
3774
3803
|
inputSchema: {
|
|
3775
3804
|
type: "object",
|
|
3776
3805
|
properties: {
|
|
@@ -4022,6 +4051,43 @@ const TOOLS = [
|
|
|
4022
4051
|
},
|
|
4023
4052
|
command: "project.close-gap",
|
|
4024
4053
|
},
|
|
4054
|
+
{
|
|
4055
|
+
name: "project_set_overlay_lane",
|
|
4056
|
+
description:
|
|
4057
|
+
'Pin media overlays (B-roll, graphics, transitions) or audio tracks to a row of their timeline lane so each keeps its own row, like one track per asset. Without a pin the timeline packs items that do not overlap into the fewest rows. Rows are zero based, top first. Shapes: overlayId + lane; ids + lane (one row for all, or "separate": ids[i] -> row i, in order); or assignments [{id, lane}]. lane null or "auto" unpins. Layout only: nothing moves in time, picture stacking stays zIndex / layer, main-track clips are one sequential track (not lanes). A pin onto a row another PINNED item holds at the same time is rejected; unpinned items make room. Returns timelineLanes {media, audio}: ids per row, the numbering project_close_gap uses ("media:1"); project_read reports the same. One undo step.',
|
|
4058
|
+
inputSchema: {
|
|
4059
|
+
type: "object",
|
|
4060
|
+
properties: {
|
|
4061
|
+
id: { type: "string", description: "Project id (or pass path)." },
|
|
4062
|
+
path: { type: "string", description: "Project file path (or pass id)." },
|
|
4063
|
+
overlayId: { type: "string", description: "One media overlay or audio track id." },
|
|
4064
|
+
ids: {
|
|
4065
|
+
type: "array",
|
|
4066
|
+
items: { type: "string" },
|
|
4067
|
+
description: "Several media overlay / audio track ids, with lane.",
|
|
4068
|
+
},
|
|
4069
|
+
lane: {
|
|
4070
|
+
type: ["number", "string", "null"],
|
|
4071
|
+
description:
|
|
4072
|
+
'Row 0-31 (top first); null or "auto" unpins; "separate" with ids puts ids[i] on row i.',
|
|
4073
|
+
},
|
|
4074
|
+
assignments: {
|
|
4075
|
+
type: "array",
|
|
4076
|
+
items: {
|
|
4077
|
+
type: "object",
|
|
4078
|
+
properties: {
|
|
4079
|
+
id: { type: "string" },
|
|
4080
|
+
lane: { type: ["number", "string", "null"] },
|
|
4081
|
+
},
|
|
4082
|
+
required: ["id", "lane"],
|
|
4083
|
+
},
|
|
4084
|
+
description: 'Per-item rows, e.g. [{"id": "a", "lane": 0}, {"id": "b", "lane": "auto"}].',
|
|
4085
|
+
},
|
|
4086
|
+
expectedRevision: { type: "number" },
|
|
4087
|
+
},
|
|
4088
|
+
},
|
|
4089
|
+
command: "project.set-overlay-lane",
|
|
4090
|
+
},
|
|
4025
4091
|
|
|
4026
4092
|
{
|
|
4027
4093
|
name: "project_remove_pause",
|
|
@@ -4671,7 +4737,7 @@ const TOOLS = [
|
|
|
4671
4737
|
{
|
|
4672
4738
|
name: "project_set_wallpaper",
|
|
4673
4739
|
description:
|
|
4674
|
-
"Set the background: a wallpaper value, or source=desktop (a kept still of the user's desktop wallpaper) / source=edges (Match video edges: a soft gradient from the video's border colours, slowly following the content; same in preview and export).",
|
|
4740
|
+
"Set the background: a wallpaper value, or source=desktop (a kept still of the user's desktop wallpaper) / source=edges (Match video edges: a soft gradient from the video's border colours, slowly following the content; same in preview and export). Animated: 'mesh:<id>' = a living mesh gradient (blobs drift in a seamless 24 s loop); motion = drift speed.",
|
|
4675
4741
|
inputSchema: {
|
|
4676
4742
|
type: "object",
|
|
4677
4743
|
properties: {
|
|
@@ -4680,9 +4746,13 @@ const TOOLS = [
|
|
|
4680
4746
|
wallpaper: {
|
|
4681
4747
|
type: "string",
|
|
4682
4748
|
description:
|
|
4683
|
-
"Bundled id (e.g. gradient-blue), color, CSS gradient
|
|
4749
|
+
"Bundled id (e.g. gradient-blue), color, CSS gradient, 'none', or an animated mesh:aurora | mesh:sunset | mesh:ocean | mesh:candy | mesh:forest | mesh:midnight | mesh:peach | mesh:graphite. Omit with source.",
|
|
4684
4750
|
},
|
|
4685
4751
|
source: { type: "string", enum: ["desktop", "edges"] },
|
|
4752
|
+
motion: {
|
|
4753
|
+
type: "number",
|
|
4754
|
+
description: "Animated (mesh:) drift speed 0-2: 0 still, 1 default. Kept when omitted.",
|
|
4755
|
+
},
|
|
4686
4756
|
expectedRevision: { type: "number" },
|
|
4687
4757
|
},
|
|
4688
4758
|
},
|
|
@@ -4742,7 +4812,7 @@ const TOOLS = [
|
|
|
4742
4812
|
{
|
|
4743
4813
|
name: "project_set_style",
|
|
4744
4814
|
description:
|
|
4745
|
-
"Framing style, main-video frame (shape, border ring; drawn when the video is a card)
|
|
4815
|
+
"Framing style, main-video frame (shape, border ring; drawn when the video is a card), drawn-cursor behaviour, and the screen's device frame + 3D tilt (screen recordings / images only). Only passed fields change. Camera tile of screen+camera: project_set_webcam_style.",
|
|
4746
4816
|
inputSchema: {
|
|
4747
4817
|
type: "object",
|
|
4748
4818
|
properties: {
|
|
@@ -4766,6 +4836,27 @@ const TOOLS = [
|
|
|
4766
4836
|
borderWidth: { type: "number", description: "px 0-40." },
|
|
4767
4837
|
borderColor: { type: "string" },
|
|
4768
4838
|
resetFrame: { type: "boolean", description: "Clear shape + border first." },
|
|
4839
|
+
deviceFrame: {
|
|
4840
|
+
type: "string",
|
|
4841
|
+
enum: ["browser", "window", "laptop", "phone", "tablet", "none"],
|
|
4842
|
+
description: "Frame around the screen; the video shrinks to fit inside it.",
|
|
4843
|
+
},
|
|
4844
|
+
deviceFrameTheme: { type: "string", enum: ["light", "dark"] },
|
|
4845
|
+
deviceFrameUrl: {
|
|
4846
|
+
type: "string",
|
|
4847
|
+
description: "Browser address / window title; '' clears.",
|
|
4848
|
+
},
|
|
4849
|
+
tilt: {
|
|
4850
|
+
type: "string",
|
|
4851
|
+
enum: ["flat", "left", "right", "above"],
|
|
4852
|
+
description: "3D angle (left / right: that edge goes back; above: seen from above).",
|
|
4853
|
+
},
|
|
4854
|
+
tiltFollowCursor: {
|
|
4855
|
+
type: "boolean",
|
|
4856
|
+
description: "Lean toward the cursor (needs cursor data).",
|
|
4857
|
+
},
|
|
4858
|
+
tiltClickBounce: { type: "boolean", description: "Rock slightly on each click." },
|
|
4859
|
+
tiltStrength: { type: "number", description: "0-100, default 100." },
|
|
4769
4860
|
expectedRevision: { type: "number" },
|
|
4770
4861
|
},
|
|
4771
4862
|
},
|
|
@@ -4916,7 +5007,7 @@ const TOOLS = [
|
|
|
4916
5007
|
{
|
|
4917
5008
|
name: "project_align_cursor",
|
|
4918
5009
|
description:
|
|
4919
|
-
"Fix a screen recording whose drawn cursor / cursor auto-zooms land in the wrong place (old recordings saved the pointer with the wrong mapping) without re-recording. Pins: at atMs the REAL pointer (or what was clicked) is at x,y, fractions 0-1 of the recorded frame. 1 pin = offset; 2+ pins far apart also fix scale per axis. Stored on the clip (non-destructive), used by preview, export and auto-zoom; cursor auto-zooms follow unless moveZooms false. reset removes it. Check with project_render_frame.",
|
|
5010
|
+
"Fix a screen recording whose drawn cursor / cursor auto-zooms land in the wrong place (old recordings saved the pointer with the wrong mapping) without re-recording. Pins: at atMs the REAL pointer (or what was clicked) is at x,y, fractions 0-1 of the recorded frame. 1 pin = offset; 2+ pins far apart also fix scale per axis; the LAST pin is matched exactly (earlier ones steer the scale). Stored on the clip (non-destructive), used by preview, export and auto-zoom; cursor auto-zooms follow unless moveZooms false. reset removes it. Check with project_render_frame.",
|
|
4920
5011
|
inputSchema: {
|
|
4921
5012
|
type: "object",
|
|
4922
5013
|
properties: {
|
|
@@ -4929,7 +5020,7 @@ const TOOLS = [
|
|
|
4929
5020
|
points: {
|
|
4930
5021
|
type: "array",
|
|
4931
5022
|
description:
|
|
4932
|
-
"[{atMs (edited timeline ms) or sourceMs (clip's own ms), x 0-1, y 0-1}] where the real pointer is.",
|
|
5023
|
+
"[{atMs (edited timeline ms) or sourceMs (clip's own ms), x 0-1, y 0-1}] where the real pointer is. Last pin is exact.",
|
|
4933
5024
|
items: {
|
|
4934
5025
|
type: "object",
|
|
4935
5026
|
properties: {
|
|
@@ -5601,7 +5692,7 @@ const TOOLS = [
|
|
|
5601
5692
|
{
|
|
5602
5693
|
name: "audio_enhance",
|
|
5603
5694
|
description:
|
|
5604
|
-
"Enhance voice: THE audio cleanup step (one call). Runs the studio chain on speech, per source (a podcast's host and each guest separately): noise removal, coughs/bumps out of pauses, mouth-click repair, broadcast tone, boom control, level riding (lifts very quiet speech too), de-esser, quieter pauses, -16 LUFS / -1 dBTP. strength:
|
|
5695
|
+
"Enhance voice: THE audio cleanup step (one call). Runs the studio chain on speech, per source (a podcast's host and each guest separately): noise removal, coughs/bumps out of pauses, mouth-click repair, broadcast tone, boom control, level riding (lifts very quiet speech too), de-esser, quieter pauses, -16 LUFS / -1 dBTP. strength: light (default, the best-sounding setup with Studio mic sound), natural (fuller processing), strong (assertive broadcast; only when the user asks, never by your own choice). keepBackground true for vlogs / ambience / gameplay where the room is part of the video (no noise removal, event remover or pause expander; level, EQ and loudness still run). A stereo source keeps its stereo (result channels: 2; else channels: 1 with monoReason one-channel / dual-mono / silent / studio-mic), and Studio mic sound stays off unless restore is true (it rebuilds the voice without the room). Enhance voice already removes room echo with the Studio AI model; only use echo when the result reports the model did not run (fallback) (denoiser deepfilternet3, or keepBackground); when the model runs, echo is skipped and the result says echoSkipped: ai-model-removes-echo (relay echoSkippedReason, do not retry). restore = Studio mic sound (the app's name): leave it unset and it is ON on Apple silicon with macOS 14+ (TF-Restormer; Light + Studio mic sound is the default there) and off on Windows and Intel Macs (AP-BWE; pass true there only for thin, muffled or call-quality mics); false only when the user asks. restored / restoreEngine in the result say what ran. reference = a clip id or file whose voice tone to match. off true restores the original audio. The noise-removal engine is automatic. Every run processes the original media, so running again replaces the result (never stacks). ASYNC: { jobId }, job_wait; the result reports before/after loudness (LUFS, LRA, true peak, speech over pauses, tone deviation) and the engine per source: tell the user.",
|
|
5605
5696
|
inputSchema: {
|
|
5606
5697
|
type: "object",
|
|
5607
5698
|
properties: {
|
|
@@ -5615,7 +5706,7 @@ const TOOLS = [
|
|
|
5615
5706
|
strength: {
|
|
5616
5707
|
type: "string",
|
|
5617
5708
|
enum: ["light", "natural", "strong"],
|
|
5618
|
-
default: "
|
|
5709
|
+
default: "light",
|
|
5619
5710
|
},
|
|
5620
5711
|
keepBackground: {
|
|
5621
5712
|
type: "boolean",
|
|
@@ -5630,9 +5721,8 @@ const TOOLS = [
|
|
|
5630
5721
|
},
|
|
5631
5722
|
restore: {
|
|
5632
5723
|
type: "boolean",
|
|
5633
|
-
default: false,
|
|
5634
5724
|
description:
|
|
5635
|
-
"Studio mic sound
|
|
5725
|
+
"Studio mic sound. Leave unset: ON on Apple silicon with macOS 14+ (TF-Restormer), off on Windows and Intel Macs (AP-BWE). false only when the user asks.",
|
|
5636
5726
|
},
|
|
5637
5727
|
reference: { type: "string", description: "Clip id or audio/video file to sound like." },
|
|
5638
5728
|
off: { type: "boolean", description: "Remove the enhancement (original audio)." },
|
|
@@ -5711,7 +5801,7 @@ const TOOLS = [
|
|
|
5711
5801
|
{
|
|
5712
5802
|
name: "caption_set_template",
|
|
5713
5803
|
description:
|
|
5714
|
-
"Pick a caption template (
|
|
5804
|
+
"Pick a caption template (new projects start with hormoziEmphasis when vertical, classic otherwise; use those when the user names no style, never glowStack unless asked); clears style overrides. Emphasis templates (hormoziEmphasis, tiltedBox, serifItalic, condensedCaps, scriptKeyword) style the IMPORTANT word of each phrase, not the spoken one; emphasis is detected on apply when missing (result.emphasis).",
|
|
5715
5805
|
inputSchema: {
|
|
5716
5806
|
type: "object",
|
|
5717
5807
|
properties: {
|
|
@@ -6044,10 +6134,55 @@ const TOOLS = [
|
|
|
6044
6134
|
description:
|
|
6045
6135
|
"Hide desktop icons for a whole-display recording (restored on stop/crash/quit). Default: the user's setting. Result tip = ask the user to turn on Do Not Disturb.",
|
|
6046
6136
|
},
|
|
6137
|
+
windowSize: {
|
|
6138
|
+
type: "string",
|
|
6139
|
+
enum: ["16:9", "16:10", "4:3", "1:1", "9:16", "21:9", "720p", "1080p", "1440p", "4K"],
|
|
6140
|
+
description:
|
|
6141
|
+
"Window sources only: resize the window first. Ratio = same area, new shape; resolution = exact recorded pixels (fails if the display is too small). macOS needs Accessibility access.",
|
|
6142
|
+
},
|
|
6143
|
+
centerWindow: {
|
|
6144
|
+
type: "boolean",
|
|
6145
|
+
description:
|
|
6146
|
+
"Window sources only: move the window to the middle of its display for the recording, back on stop/failure/crash/quit. Default: the user's setting.",
|
|
6147
|
+
},
|
|
6047
6148
|
},
|
|
6048
6149
|
},
|
|
6049
6150
|
command: "recording.start",
|
|
6050
6151
|
},
|
|
6152
|
+
{
|
|
6153
|
+
name: "recording_resize_window",
|
|
6154
|
+
description:
|
|
6155
|
+
"Resize a window before recording it (the picker's size chips): a ratio keeps its area in the new shape, a resolution makes the recording exactly that size (1080p on a 2x display = a 960 x 540 point window). macOS needs Accessibility access (the error says how). Returns { frame, pixels }.",
|
|
6156
|
+
inputSchema: {
|
|
6157
|
+
type: "object",
|
|
6158
|
+
properties: {
|
|
6159
|
+
source: { type: "string", description: "'window:N:0' from recording_list_sources." },
|
|
6160
|
+
size: {
|
|
6161
|
+
type: "string",
|
|
6162
|
+
enum: ["16:9", "16:10", "4:3", "1:1", "9:16", "21:9", "720p", "1080p", "1440p", "4K"],
|
|
6163
|
+
},
|
|
6164
|
+
},
|
|
6165
|
+
required: ["source", "size"],
|
|
6166
|
+
},
|
|
6167
|
+
command: "recording.resize-window",
|
|
6168
|
+
},
|
|
6169
|
+
{
|
|
6170
|
+
name: "recording_get_window_options",
|
|
6171
|
+
description: "Window-recording options: { centerWindow, supported }.",
|
|
6172
|
+
inputSchema: { type: "object", properties: {} },
|
|
6173
|
+
command: "recording.get-window-options",
|
|
6174
|
+
},
|
|
6175
|
+
{
|
|
6176
|
+
name: "recording_set_center_window",
|
|
6177
|
+
description:
|
|
6178
|
+
"Turn Center on screen on/off for window recordings (window moves to the middle of its display during the recording, back after). Off by default. Returns { centerWindow }.",
|
|
6179
|
+
inputSchema: {
|
|
6180
|
+
type: "object",
|
|
6181
|
+
properties: { enabled: { type: "boolean" } },
|
|
6182
|
+
required: ["enabled"],
|
|
6183
|
+
},
|
|
6184
|
+
command: "recording.set-center-window",
|
|
6185
|
+
},
|
|
6051
6186
|
{
|
|
6052
6187
|
name: "recording_get_clean_desktop",
|
|
6053
6188
|
description: "Clean-desktop recording setting. Returns { cleanDesktop, supported }.",
|
|
@@ -6602,16 +6737,409 @@ const TOOLS = [
|
|
|
6602
6737
|
{
|
|
6603
6738
|
name: "memory_save",
|
|
6604
6739
|
description:
|
|
6605
|
-
"Save a durable
|
|
6740
|
+
"Save a durable fact or preference the user STATED, for all future chats (not one-off requests). kind profile = who they are. Over budget it's refused with the current entries: merge (memory_replace) or forget first. Noticed but not stated: memory_suggest.",
|
|
6606
6741
|
inputSchema: {
|
|
6607
6742
|
type: "object",
|
|
6608
6743
|
properties: {
|
|
6609
6744
|
note: { type: "string", description: "One concise fact." },
|
|
6745
|
+
kind: {
|
|
6746
|
+
type: "string",
|
|
6747
|
+
enum: ["notes", "profile"],
|
|
6748
|
+
description: "notes (default): preferences. profile: who the creator is.",
|
|
6749
|
+
},
|
|
6610
6750
|
},
|
|
6611
6751
|
required: ["note"],
|
|
6612
6752
|
},
|
|
6613
6753
|
command: "memory.save",
|
|
6614
6754
|
},
|
|
6755
|
+
{
|
|
6756
|
+
name: "memory_replace",
|
|
6757
|
+
description: "Rewrite one memory entry by id: correct it, or merge two to stay under budget.",
|
|
6758
|
+
inputSchema: {
|
|
6759
|
+
type: "object",
|
|
6760
|
+
properties: {
|
|
6761
|
+
entryId: { type: "string", description: "Entry id from memory_list." },
|
|
6762
|
+
note: { type: "string", description: "The new text." },
|
|
6763
|
+
kind: {
|
|
6764
|
+
type: "string",
|
|
6765
|
+
enum: ["notes", "profile"],
|
|
6766
|
+
description: "notes (default): preferences. profile: who the creator is.",
|
|
6767
|
+
},
|
|
6768
|
+
},
|
|
6769
|
+
required: ["entryId", "note"],
|
|
6770
|
+
},
|
|
6771
|
+
command: "memory.replace",
|
|
6772
|
+
},
|
|
6773
|
+
{
|
|
6774
|
+
name: "memory_suggest",
|
|
6775
|
+
description:
|
|
6776
|
+
"PandaStudio's own chat only: a 'Remember this?' card for a preference you noticed but the user didn't state. Their Save writes it; don't save it yourself.",
|
|
6777
|
+
inputSchema: {
|
|
6778
|
+
type: "object",
|
|
6779
|
+
properties: {
|
|
6780
|
+
note: { type: "string", description: "The preference, worded as it would be saved." },
|
|
6781
|
+
reason: { type: "string", description: "One line on why you think so." },
|
|
6782
|
+
kind: {
|
|
6783
|
+
type: "string",
|
|
6784
|
+
enum: ["notes", "profile"],
|
|
6785
|
+
description: "notes (default): preferences. profile: who the creator is.",
|
|
6786
|
+
},
|
|
6787
|
+
},
|
|
6788
|
+
required: ["note"],
|
|
6789
|
+
},
|
|
6790
|
+
command: "memory.suggest",
|
|
6791
|
+
},
|
|
6792
|
+
{
|
|
6793
|
+
name: "chat_ask",
|
|
6794
|
+
description:
|
|
6795
|
+
"PandaStudio's own chat only: ask the user a multiple-choice question as a card with 2-5 buttons. Doesn't wait; END YOUR TURN after calling it and the choice arrives as the user's next message. For real decisions (light or heavy edit, which opening), not things you can decide yourself. Other agents get not_supported: ask in your own chat.",
|
|
6796
|
+
inputSchema: {
|
|
6797
|
+
type: "object",
|
|
6798
|
+
properties: {
|
|
6799
|
+
question: { type: "string", description: "One short sentence." },
|
|
6800
|
+
options: {
|
|
6801
|
+
type: "array",
|
|
6802
|
+
description: "2-5 choices: strings, or { label, detail } with detail one short line.",
|
|
6803
|
+
items: {
|
|
6804
|
+
anyOf: [
|
|
6805
|
+
{ type: "string" },
|
|
6806
|
+
{
|
|
6807
|
+
type: "object",
|
|
6808
|
+
properties: { label: { type: "string" }, detail: { type: "string" } },
|
|
6809
|
+
required: ["label"],
|
|
6810
|
+
},
|
|
6811
|
+
],
|
|
6812
|
+
},
|
|
6813
|
+
},
|
|
6814
|
+
recommended: { type: "string", description: "Label of the choice you'd pick." },
|
|
6815
|
+
allowOther: { type: "boolean", description: "Also allow a typed answer." },
|
|
6816
|
+
},
|
|
6817
|
+
required: ["question", "options"],
|
|
6818
|
+
},
|
|
6819
|
+
command: "chat.ask",
|
|
6820
|
+
},
|
|
6821
|
+
{
|
|
6822
|
+
name: "motion_propose",
|
|
6823
|
+
description:
|
|
6824
|
+
"PandaStudio's own chat: show a rendered graphic playing in the chat with Add to timeline / Try another before placing it. Render first (motion_generate or motion_render_html, job_wait), then pass the jobId and where it goes. For graphic ideas and judgment calls; a graphic the user asked for goes straight in with project_add_motion_graphic.",
|
|
6825
|
+
inputSchema: {
|
|
6826
|
+
type: "object",
|
|
6827
|
+
properties: {
|
|
6828
|
+
id: { type: "string", description: "Project id" },
|
|
6829
|
+
path: { type: "string" },
|
|
6830
|
+
fromJob: { type: "string", description: "Finished render job (preferred)." },
|
|
6831
|
+
file: { type: "string", description: "Rendered MP4/WebM when there's no job." },
|
|
6832
|
+
atMs: { type: "number", description: "Edited timeline start." },
|
|
6833
|
+
durationMs: { type: "number", description: "Default: the render's length." },
|
|
6834
|
+
title: { type: "string", description: "What it shows, a few words." },
|
|
6835
|
+
reason: { type: "string", description: "Why at this moment." },
|
|
6836
|
+
},
|
|
6837
|
+
required: ["atMs", "title"],
|
|
6838
|
+
},
|
|
6839
|
+
command: "motion.propose",
|
|
6840
|
+
},
|
|
6841
|
+
{
|
|
6842
|
+
name: "post_plan",
|
|
6843
|
+
description:
|
|
6844
|
+
"PandaStudio's own chat: suggest where and when to post finished exports, a caption each, as an editable schedule card. Nothing posts until the user approves; then each row is queued via export_publish_social and you get the job ids. Export ids from export_list, accounts from social_channels.",
|
|
6845
|
+
inputSchema: {
|
|
6846
|
+
type: "object",
|
|
6847
|
+
properties: {
|
|
6848
|
+
summary: { type: "string", description: "One line on the plan." },
|
|
6849
|
+
rows: {
|
|
6850
|
+
type: "array",
|
|
6851
|
+
items: {
|
|
6852
|
+
type: "object",
|
|
6853
|
+
properties: {
|
|
6854
|
+
exportId: { type: "string" },
|
|
6855
|
+
channelIds: { type: "array", items: { type: "string" } },
|
|
6856
|
+
networks: {
|
|
6857
|
+
type: "array",
|
|
6858
|
+
items: {
|
|
6859
|
+
type: "string",
|
|
6860
|
+
enum: ["instagram", "tiktok", "facebook", "linkedin", "x"],
|
|
6861
|
+
},
|
|
6862
|
+
},
|
|
6863
|
+
caption: { type: "string" },
|
|
6864
|
+
when: {
|
|
6865
|
+
type: "string",
|
|
6866
|
+
description: "now, or ISO with offset (e.g. 2026-11-03T18:30:00+00:00).",
|
|
6867
|
+
},
|
|
6868
|
+
},
|
|
6869
|
+
required: ["exportId", "caption"],
|
|
6870
|
+
},
|
|
6871
|
+
},
|
|
6872
|
+
},
|
|
6873
|
+
required: ["rows"],
|
|
6874
|
+
},
|
|
6875
|
+
command: "post.plan",
|
|
6876
|
+
},
|
|
6877
|
+
{
|
|
6878
|
+
name: "plan_propose",
|
|
6879
|
+
description:
|
|
6880
|
+
"Write an editing plan for the user to approve BEFORE editing (summary, up to 3 questions, up to 20 steps). Shown as a plan card with Start editing; nothing changes yet. End your turn after proposing; when they press Start you get the planId and answers, then do the steps with plan_update_step after each. Mark needsApproval on steps that spend money, publish or reach outside the app.",
|
|
6881
|
+
inputSchema: {
|
|
6882
|
+
type: "object",
|
|
6883
|
+
properties: {
|
|
6884
|
+
id: { type: "string", description: "Project id" },
|
|
6885
|
+
path: { type: "string", description: "Absolute .pandastudio path (alternative to id)" },
|
|
6886
|
+
summary: { type: "string", description: "One line: what the footage is and the angle." },
|
|
6887
|
+
steps: {
|
|
6888
|
+
type: "array",
|
|
6889
|
+
description: "Steps in order.",
|
|
6890
|
+
items: {
|
|
6891
|
+
type: "object",
|
|
6892
|
+
properties: {
|
|
6893
|
+
title: { type: "string" },
|
|
6894
|
+
stage: { type: "string", enum: ["prep", "edit", "clip", "post"] },
|
|
6895
|
+
detail: { type: "string" },
|
|
6896
|
+
needsApproval: { type: "boolean" },
|
|
6897
|
+
},
|
|
6898
|
+
required: ["title"],
|
|
6899
|
+
},
|
|
6900
|
+
},
|
|
6901
|
+
questions: {
|
|
6902
|
+
type: "array",
|
|
6903
|
+
description: "Decisions only the user can make (max 3).",
|
|
6904
|
+
items: {
|
|
6905
|
+
type: "object",
|
|
6906
|
+
properties: {
|
|
6907
|
+
text: { type: "string" },
|
|
6908
|
+
options: { type: "array", items: { type: "string" } },
|
|
6909
|
+
recommended: { type: "string" },
|
|
6910
|
+
},
|
|
6911
|
+
required: ["text", "options"],
|
|
6912
|
+
},
|
|
6913
|
+
},
|
|
6914
|
+
recipeId: { type: "string", description: "Recipe the plan follows (recipe_pick)." },
|
|
6915
|
+
source: { type: "string", enum: ["chat", "recording-finished", "routine"] },
|
|
6916
|
+
},
|
|
6917
|
+
required: ["summary", "steps"],
|
|
6918
|
+
},
|
|
6919
|
+
command: "plan.propose",
|
|
6920
|
+
},
|
|
6921
|
+
{
|
|
6922
|
+
name: "plan_get",
|
|
6923
|
+
description:
|
|
6924
|
+
"The project's open plan (proposed or running) with step statuses and the next step; plan: null when none.",
|
|
6925
|
+
inputSchema: {
|
|
6926
|
+
type: "object",
|
|
6927
|
+
properties: {
|
|
6928
|
+
id: { type: "string" },
|
|
6929
|
+
path: { type: "string" },
|
|
6930
|
+
includeHistory: {
|
|
6931
|
+
type: "boolean",
|
|
6932
|
+
description: "Also return finished and dismissed plans.",
|
|
6933
|
+
},
|
|
6934
|
+
},
|
|
6935
|
+
},
|
|
6936
|
+
command: "plan.get",
|
|
6937
|
+
},
|
|
6938
|
+
{
|
|
6939
|
+
name: "plan_answer",
|
|
6940
|
+
description:
|
|
6941
|
+
"Record the user's answer to a plan question (option id or label). Only before the plan starts.",
|
|
6942
|
+
inputSchema: {
|
|
6943
|
+
type: "object",
|
|
6944
|
+
properties: {
|
|
6945
|
+
id: { type: "string" },
|
|
6946
|
+
path: { type: "string" },
|
|
6947
|
+
planId: { type: "string" },
|
|
6948
|
+
questionId: { type: "string" },
|
|
6949
|
+
optionId: { type: "string" },
|
|
6950
|
+
},
|
|
6951
|
+
required: ["questionId", "optionId"],
|
|
6952
|
+
},
|
|
6953
|
+
command: "plan.answer",
|
|
6954
|
+
},
|
|
6955
|
+
{
|
|
6956
|
+
name: "plan_start",
|
|
6957
|
+
description:
|
|
6958
|
+
"Start a proposed plan (unanswered questions take the recommended choice). The card's Start editing does this; call it only when the user told you to go ahead.",
|
|
6959
|
+
inputSchema: {
|
|
6960
|
+
type: "object",
|
|
6961
|
+
properties: { id: { type: "string" }, path: { type: "string" }, planId: { type: "string" } },
|
|
6962
|
+
},
|
|
6963
|
+
command: "plan.start",
|
|
6964
|
+
},
|
|
6965
|
+
{
|
|
6966
|
+
name: "plan_update_step",
|
|
6967
|
+
description:
|
|
6968
|
+
"Mark a step of the running plan: running, then done (result with the real counts), skipped or failed (say why).",
|
|
6969
|
+
inputSchema: {
|
|
6970
|
+
type: "object",
|
|
6971
|
+
properties: {
|
|
6972
|
+
id: { type: "string" },
|
|
6973
|
+
path: { type: "string" },
|
|
6974
|
+
planId: { type: "string" },
|
|
6975
|
+
stepId: { type: "string" },
|
|
6976
|
+
status: { type: "string", enum: ["running", "done", "skipped", "failed"] },
|
|
6977
|
+
result: { type: "string" },
|
|
6978
|
+
},
|
|
6979
|
+
required: ["stepId", "status"],
|
|
6980
|
+
},
|
|
6981
|
+
command: "plan.update-step",
|
|
6982
|
+
},
|
|
6983
|
+
{
|
|
6984
|
+
name: "plan_finish",
|
|
6985
|
+
description: "Close a plan: done (unreached steps become skipped) or dismissed.",
|
|
6986
|
+
inputSchema: {
|
|
6987
|
+
type: "object",
|
|
6988
|
+
properties: {
|
|
6989
|
+
id: { type: "string" },
|
|
6990
|
+
path: { type: "string" },
|
|
6991
|
+
planId: { type: "string" },
|
|
6992
|
+
status: { type: "string", enum: ["done", "dismissed"] },
|
|
6993
|
+
},
|
|
6994
|
+
required: ["status"],
|
|
6995
|
+
},
|
|
6996
|
+
command: "plan.finish",
|
|
6997
|
+
},
|
|
6998
|
+
{
|
|
6999
|
+
name: "routine_templates",
|
|
7000
|
+
description: "Ready-made routines with the exact settings for routine_propose.",
|
|
7001
|
+
inputSchema: { type: "object", properties: {} },
|
|
7002
|
+
command: "routine.templates",
|
|
7003
|
+
},
|
|
7004
|
+
{
|
|
7005
|
+
name: "routine_list",
|
|
7006
|
+
description:
|
|
7007
|
+
"This workspace's routines (proposed / on / paused), triggers in plain words, next run and recent runs with reports.",
|
|
7008
|
+
inputSchema: { type: "object", properties: {} },
|
|
7009
|
+
command: "routine.list",
|
|
7010
|
+
},
|
|
7011
|
+
{
|
|
7012
|
+
name: "routine_propose",
|
|
7013
|
+
description:
|
|
7014
|
+
"Propose a routine: recurring or event-triggered work done on its own. Created OFF; the user turns it on from a routine card. Say what it does, how often, and that it runs on their AI account.",
|
|
7015
|
+
inputSchema: {
|
|
7016
|
+
type: "object",
|
|
7017
|
+
properties: {
|
|
7018
|
+
name: { type: "string", description: "A few words, e.g. 'Monday competitor scan'." },
|
|
7019
|
+
prompt: {
|
|
7020
|
+
type: "string",
|
|
7021
|
+
description: "What the agent does each run (unattended: no questions, read-only shell).",
|
|
7022
|
+
},
|
|
7023
|
+
schedule: {
|
|
7024
|
+
type: "string",
|
|
7025
|
+
description:
|
|
7026
|
+
"'every 2h', 'daily 09:00', 'weekdays 09:00', 'mon,thu 18:30', 'monthly 1 09:00' or an ISO time. Schedule OR event; min every 15 min.",
|
|
7027
|
+
},
|
|
7028
|
+
timezone: { type: "string", description: "IANA zone; default this Mac's." },
|
|
7029
|
+
event: {
|
|
7030
|
+
type: "string",
|
|
7031
|
+
enum: ["recording.finished", "import.finished", "podcast.ended", "export.finished"],
|
|
7032
|
+
description: "Run when this happens instead of on a schedule.",
|
|
7033
|
+
},
|
|
7034
|
+
precheck: {
|
|
7035
|
+
type: "object",
|
|
7036
|
+
description:
|
|
7037
|
+
"Free check before the AI turn; nothing found = run skipped. {kind:'ideas-breakouts',minMultiplier} | {kind:'new-exports'} | {kind:'connector-connected',connector}.",
|
|
7038
|
+
},
|
|
7039
|
+
autonomy: {
|
|
7040
|
+
type: "string",
|
|
7041
|
+
enum: ["suggest", "act"],
|
|
7042
|
+
description: "suggest (default): no edits. act: edits that need no approval.",
|
|
7043
|
+
},
|
|
7044
|
+
notify: { type: "string", enum: ["desktop", "none"] },
|
|
7045
|
+
template: { type: "string", description: "Start from a routine_templates id." },
|
|
7046
|
+
},
|
|
7047
|
+
required: ["name", "prompt"],
|
|
7048
|
+
},
|
|
7049
|
+
command: "routine.propose",
|
|
7050
|
+
},
|
|
7051
|
+
{
|
|
7052
|
+
name: "routine_update",
|
|
7053
|
+
description:
|
|
7054
|
+
"Change a routine. name/notify apply now; prompt, schedule/event, precheck or autonomy become a pending change the user approves on the card.",
|
|
7055
|
+
inputSchema: {
|
|
7056
|
+
type: "object",
|
|
7057
|
+
properties: {
|
|
7058
|
+
routineId: { type: "string" },
|
|
7059
|
+
name: { type: "string", description: "A few words, e.g. 'Monday competitor scan'." },
|
|
7060
|
+
prompt: {
|
|
7061
|
+
type: "string",
|
|
7062
|
+
description: "What the agent does each run (unattended: no questions, read-only shell).",
|
|
7063
|
+
},
|
|
7064
|
+
schedule: {
|
|
7065
|
+
type: "string",
|
|
7066
|
+
description:
|
|
7067
|
+
"'every 2h', 'daily 09:00', 'weekdays 09:00', 'mon,thu 18:30', 'monthly 1 09:00' or an ISO time. Schedule OR event; min every 15 min.",
|
|
7068
|
+
},
|
|
7069
|
+
timezone: { type: "string", description: "IANA zone; default this Mac's." },
|
|
7070
|
+
event: {
|
|
7071
|
+
type: "string",
|
|
7072
|
+
enum: ["recording.finished", "import.finished", "podcast.ended", "export.finished"],
|
|
7073
|
+
description: "Run when this happens instead of on a schedule.",
|
|
7074
|
+
},
|
|
7075
|
+
precheck: {
|
|
7076
|
+
type: "object",
|
|
7077
|
+
description:
|
|
7078
|
+
"Free check before the AI turn; nothing found = run skipped. {kind:'ideas-breakouts',minMultiplier} | {kind:'new-exports'} | {kind:'connector-connected',connector}.",
|
|
7079
|
+
},
|
|
7080
|
+
autonomy: {
|
|
7081
|
+
type: "string",
|
|
7082
|
+
enum: ["suggest", "act"],
|
|
7083
|
+
description: "suggest (default): no edits. act: edits that need no approval.",
|
|
7084
|
+
},
|
|
7085
|
+
notify: { type: "string", enum: ["desktop", "none"] },
|
|
7086
|
+
},
|
|
7087
|
+
required: ["routineId"],
|
|
7088
|
+
},
|
|
7089
|
+
command: "routine.update",
|
|
7090
|
+
},
|
|
7091
|
+
{
|
|
7092
|
+
name: "routine_pause",
|
|
7093
|
+
description: "Pause a routine.",
|
|
7094
|
+
inputSchema: {
|
|
7095
|
+
type: "object",
|
|
7096
|
+
properties: { routineId: { type: "string" } },
|
|
7097
|
+
required: ["routineId"],
|
|
7098
|
+
},
|
|
7099
|
+
command: "routine.pause",
|
|
7100
|
+
},
|
|
7101
|
+
{
|
|
7102
|
+
name: "routine_resume",
|
|
7103
|
+
description: "Resume a paused routine (not a proposal).",
|
|
7104
|
+
inputSchema: {
|
|
7105
|
+
type: "object",
|
|
7106
|
+
properties: { routineId: { type: "string" } },
|
|
7107
|
+
required: ["routineId"],
|
|
7108
|
+
},
|
|
7109
|
+
command: "routine.resume",
|
|
7110
|
+
},
|
|
7111
|
+
{
|
|
7112
|
+
name: "routine_run",
|
|
7113
|
+
description:
|
|
7114
|
+
"Run a routine now in the background; the report lands in the Routines thread and routine_runs.",
|
|
7115
|
+
inputSchema: {
|
|
7116
|
+
type: "object",
|
|
7117
|
+
properties: { routineId: { type: "string" } },
|
|
7118
|
+
required: ["routineId"],
|
|
7119
|
+
},
|
|
7120
|
+
command: "routine.run",
|
|
7121
|
+
},
|
|
7122
|
+
{
|
|
7123
|
+
name: "routine_runs",
|
|
7124
|
+
description:
|
|
7125
|
+
"A routine's runs, newest first: done, silent, skipped, failed, missed, interrupted; with reports.",
|
|
7126
|
+
inputSchema: {
|
|
7127
|
+
type: "object",
|
|
7128
|
+
properties: { routineId: { type: "string" }, limit: { type: "number" } },
|
|
7129
|
+
required: ["routineId"],
|
|
7130
|
+
},
|
|
7131
|
+
command: "routine.runs",
|
|
7132
|
+
},
|
|
7133
|
+
{
|
|
7134
|
+
name: "routine_delete",
|
|
7135
|
+
description: "Delete a routine and its history (asks the user on a confirm card).",
|
|
7136
|
+
inputSchema: {
|
|
7137
|
+
type: "object",
|
|
7138
|
+
properties: { routineId: { type: "string" } },
|
|
7139
|
+
required: ["routineId"],
|
|
7140
|
+
},
|
|
7141
|
+
command: "routine.delete",
|
|
7142
|
+
},
|
|
6615
7143
|
{
|
|
6616
7144
|
name: "recipe_list",
|
|
6617
7145
|
description: "List edit recipes (proven styles): the user's saved ones first, then starters.",
|
|
@@ -6754,6 +7282,11 @@ const TOOLS = [
|
|
|
6754
7282
|
type: "object",
|
|
6755
7283
|
properties: {
|
|
6756
7284
|
query: { type: "string", description: "Entry id, or text removing every match." },
|
|
7285
|
+
kind: {
|
|
7286
|
+
type: "string",
|
|
7287
|
+
enum: ["notes", "profile"],
|
|
7288
|
+
description: "notes (default): preferences. profile: who the creator is.",
|
|
7289
|
+
},
|
|
6757
7290
|
},
|
|
6758
7291
|
required: ["query"],
|
|
6759
7292
|
},
|
|
@@ -6761,8 +7294,17 @@ const TOOLS = [
|
|
|
6761
7294
|
},
|
|
6762
7295
|
{
|
|
6763
7296
|
name: "memory_list",
|
|
6764
|
-
description: "
|
|
6765
|
-
inputSchema: {
|
|
7297
|
+
description: "Both memory lists (notes, profile) with ids and budget use; kind for one list.",
|
|
7298
|
+
inputSchema: {
|
|
7299
|
+
type: "object",
|
|
7300
|
+
properties: {
|
|
7301
|
+
kind: {
|
|
7302
|
+
type: "string",
|
|
7303
|
+
enum: ["notes", "profile"],
|
|
7304
|
+
description: "notes (default): preferences. profile: who the creator is.",
|
|
7305
|
+
},
|
|
7306
|
+
},
|
|
7307
|
+
},
|
|
6766
7308
|
command: "memory.list",
|
|
6767
7309
|
},
|
|
6768
7310
|
{
|
|
@@ -7386,7 +7928,7 @@ const TOOLS = [
|
|
|
7386
7928
|
},
|
|
7387
7929
|
captionTemplate: {
|
|
7388
7930
|
type: "string",
|
|
7389
|
-
description: "Caption template id (default
|
|
7931
|
+
description: "Caption template id (default hormoziEmphasis), or none.",
|
|
7390
7932
|
},
|
|
7391
7933
|
},
|
|
7392
7934
|
required: ["file"],
|
|
@@ -7459,6 +8001,247 @@ const TOOLS = [
|
|
|
7459
8001
|
},
|
|
7460
8002
|
command: "clips.delete",
|
|
7461
8003
|
},
|
|
8004
|
+
{
|
|
8005
|
+
name: "ideas_research",
|
|
8006
|
+
description:
|
|
8007
|
+
"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.",
|
|
8008
|
+
inputSchema: {
|
|
8009
|
+
type: "object",
|
|
8010
|
+
properties: {
|
|
8011
|
+
query: {
|
|
8012
|
+
type: "string",
|
|
8013
|
+
description: 'Topic(s), comma-separated: "ai video editing, descript alternatives".',
|
|
8014
|
+
},
|
|
8015
|
+
seedChannel: {
|
|
8016
|
+
type: "string",
|
|
8017
|
+
description:
|
|
8018
|
+
"A channel the target audience watches: @handle, channel URL or UC id. Give this, query, or both.",
|
|
8019
|
+
},
|
|
8020
|
+
format: { type: "string", description: "videos (long-form, default) | shorts." },
|
|
8021
|
+
minMultiplier: {
|
|
8022
|
+
type: "number",
|
|
8023
|
+
description:
|
|
8024
|
+
"Keep videos at or above this multiple of their channel's median (default 3).",
|
|
8025
|
+
},
|
|
8026
|
+
maxAgeDays: {
|
|
8027
|
+
type: "number",
|
|
8028
|
+
description: "Only outliers published in the last N days (default 365, 0 = any age).",
|
|
8029
|
+
},
|
|
8030
|
+
maxChannels: {
|
|
8031
|
+
type: "number",
|
|
8032
|
+
description: "Channels to read, 3-40 (default 15). More is slower and broader.",
|
|
8033
|
+
},
|
|
8034
|
+
period: {
|
|
8035
|
+
type: "string",
|
|
8036
|
+
description:
|
|
8037
|
+
"Limit the topic search to uploads from the last: any (default) | day | week | month | year.",
|
|
8038
|
+
},
|
|
8039
|
+
},
|
|
8040
|
+
},
|
|
8041
|
+
command: "ideas.research",
|
|
8042
|
+
},
|
|
8043
|
+
{
|
|
8044
|
+
name: "ideas_list",
|
|
8045
|
+
description:
|
|
8046
|
+
"Every outlier research in this workspace, newest first: id, title, options, status, stats and top multiplier. Reuse a recent one instead of researching the same niche again.",
|
|
8047
|
+
inputSchema: {
|
|
8048
|
+
type: "object",
|
|
8049
|
+
properties: {},
|
|
8050
|
+
},
|
|
8051
|
+
command: "ideas.list",
|
|
8052
|
+
},
|
|
8053
|
+
{
|
|
8054
|
+
name: "ideas_get",
|
|
8055
|
+
description:
|
|
8056
|
+
"One research: status, outliers best first (title, url, multiplier, views, channel median, age; onTopic false marks titles that don't mention the topic), the channels read (median views, hit rate, uploads a week) and title patterns (recurring phrases, hook-style shares, title formulas).",
|
|
8057
|
+
inputSchema: {
|
|
8058
|
+
type: "object",
|
|
8059
|
+
properties: {
|
|
8060
|
+
researchId: { type: "string", description: "From ideas.research or ideas.list." },
|
|
8061
|
+
limit: { type: "number", description: "Max outliers returned, 1-200 (default 25)." },
|
|
8062
|
+
offset: { type: "number", description: "Skip this many outliers (to page)." },
|
|
8063
|
+
onTopicOnly: {
|
|
8064
|
+
type: "boolean",
|
|
8065
|
+
description: "Only outliers whose titles mention the topic.",
|
|
8066
|
+
},
|
|
8067
|
+
},
|
|
8068
|
+
required: ["researchId"],
|
|
8069
|
+
},
|
|
8070
|
+
command: "ideas.get",
|
|
8071
|
+
},
|
|
8072
|
+
{
|
|
8073
|
+
name: "ideas_cancel",
|
|
8074
|
+
description: "Stop a running research.",
|
|
8075
|
+
inputSchema: {
|
|
8076
|
+
type: "object",
|
|
8077
|
+
properties: {
|
|
8078
|
+
researchId: { type: "string", description: "The research to stop." },
|
|
8079
|
+
},
|
|
8080
|
+
required: ["researchId"],
|
|
8081
|
+
},
|
|
8082
|
+
command: "ideas.cancel",
|
|
8083
|
+
},
|
|
8084
|
+
{
|
|
8085
|
+
name: "ideas_delete",
|
|
8086
|
+
description: "Forget a research.",
|
|
8087
|
+
inputSchema: {
|
|
8088
|
+
type: "object",
|
|
8089
|
+
properties: {
|
|
8090
|
+
researchId: { type: "string", description: "The research to delete." },
|
|
8091
|
+
},
|
|
8092
|
+
required: ["researchId"],
|
|
8093
|
+
},
|
|
8094
|
+
command: "ideas.delete",
|
|
8095
|
+
},
|
|
8096
|
+
{
|
|
8097
|
+
name: "ideas_channel",
|
|
8098
|
+
description:
|
|
8099
|
+
"One channel's baseline (median views of its recent uploads, hit rate, uploads a week, subscribers) and its uploads that beat it, best first. Use on a competitor, or on the user's own channel to see what already works for them. ~10 s.",
|
|
8100
|
+
inputSchema: {
|
|
8101
|
+
type: "object",
|
|
8102
|
+
properties: {
|
|
8103
|
+
channel: { type: "string", description: "@handle, channel URL or UC id." },
|
|
8104
|
+
format: { type: "string", description: "videos (long-form, default) | shorts." },
|
|
8105
|
+
minMultiplier: { type: "number", description: "Breakout threshold (default 1.5)." },
|
|
8106
|
+
limit: { type: "number", description: "Recent uploads to read, 10-100 (default 40)." },
|
|
8107
|
+
recent: {
|
|
8108
|
+
type: "boolean",
|
|
8109
|
+
description: "Also return every upload read, newest first (default false).",
|
|
8110
|
+
},
|
|
8111
|
+
},
|
|
8112
|
+
required: ["channel"],
|
|
8113
|
+
},
|
|
8114
|
+
command: "ideas.channel",
|
|
8115
|
+
},
|
|
8116
|
+
{
|
|
8117
|
+
name: "ideas_similar",
|
|
8118
|
+
description:
|
|
8119
|
+
"Channels competing for a channel's audience: searches the titles of its best uploads and ranks the channels that keep showing up (matches), each with its baseline (median views, hit rate, uploads a week, subscribers). ~30-60 s.",
|
|
8120
|
+
inputSchema: {
|
|
8121
|
+
type: "object",
|
|
8122
|
+
properties: {
|
|
8123
|
+
channel: { type: "string", description: "@handle, channel URL or UC id." },
|
|
8124
|
+
format: { type: "string", description: "videos (long-form, default) | shorts." },
|
|
8125
|
+
max: { type: "number", description: "Channels to return, 3-25 (default 12)." },
|
|
8126
|
+
},
|
|
8127
|
+
required: ["channel"],
|
|
8128
|
+
},
|
|
8129
|
+
command: "ideas.similar",
|
|
8130
|
+
},
|
|
8131
|
+
{
|
|
8132
|
+
name: "ideas_video",
|
|
8133
|
+
description:
|
|
8134
|
+
"A YouTube video's stats (views, likes, comment count, subscribers), description, tags and chapters. With baseline, also its multiplier against its channel's median: did it break out? With comments > 0, its top comments by likes: what viewers ask for and push back on.",
|
|
8135
|
+
inputSchema: {
|
|
8136
|
+
type: "object",
|
|
8137
|
+
properties: {
|
|
8138
|
+
video: { type: "string", description: "YouTube URL or 11-character id." },
|
|
8139
|
+
baseline: {
|
|
8140
|
+
type: "boolean",
|
|
8141
|
+
description:
|
|
8142
|
+
"Also read its channel's recent uploads and return multiplier and channelMedian. Adds ~5 s.",
|
|
8143
|
+
},
|
|
8144
|
+
comments: {
|
|
8145
|
+
type: "number",
|
|
8146
|
+
description: "Top comments to read, 0-500 (default 0). 100 takes ~10-20 s.",
|
|
8147
|
+
},
|
|
8148
|
+
},
|
|
8149
|
+
required: ["video"],
|
|
8150
|
+
},
|
|
8151
|
+
command: "ideas.video",
|
|
8152
|
+
},
|
|
8153
|
+
{
|
|
8154
|
+
name: "ideas_transcript",
|
|
8155
|
+
description:
|
|
8156
|
+
"A YouTube video's transcript from its captions (uploaded first, else automatic): to study an outlier's hook, structure and pacing.",
|
|
8157
|
+
inputSchema: {
|
|
8158
|
+
type: "object",
|
|
8159
|
+
properties: {
|
|
8160
|
+
video: { type: "string", description: "YouTube URL or 11-character id." },
|
|
8161
|
+
language: { type: "string", description: "Caption language code (default en)." },
|
|
8162
|
+
timestamps: {
|
|
8163
|
+
type: "boolean",
|
|
8164
|
+
description: "Return timed segments instead of plain text (default false).",
|
|
8165
|
+
},
|
|
8166
|
+
},
|
|
8167
|
+
required: ["video"],
|
|
8168
|
+
},
|
|
8169
|
+
command: "ideas.transcript",
|
|
8170
|
+
},
|
|
8171
|
+
{
|
|
8172
|
+
name: "ideas_keywords",
|
|
8173
|
+
description:
|
|
8174
|
+
"What people type into YouTube search around a seed phrase (autocomplete, expanded a-z and with question prefixes). Then ideas.demand on the promising ones.",
|
|
8175
|
+
inputSchema: {
|
|
8176
|
+
type: "object",
|
|
8177
|
+
properties: {
|
|
8178
|
+
seed: { type: "string", description: 'Seed phrase, e.g. "notion template".' },
|
|
8179
|
+
expand: {
|
|
8180
|
+
type: "boolean",
|
|
8181
|
+
description: "Expand with a-z and question prefixes (default true).",
|
|
8182
|
+
},
|
|
8183
|
+
},
|
|
8184
|
+
required: ["seed"],
|
|
8185
|
+
},
|
|
8186
|
+
command: "ideas.keywords",
|
|
8187
|
+
},
|
|
8188
|
+
{
|
|
8189
|
+
name: "ideas_demand",
|
|
8190
|
+
description:
|
|
8191
|
+
"How much a few YouTube search terms pull: for each, the median and top views of its top 20 results, the share under a year old, how many channels, and the 3 most-viewed. Pick the term worth a video after ideas.keywords. ~30 s for 10 terms.",
|
|
8192
|
+
inputSchema: {
|
|
8193
|
+
type: "object",
|
|
8194
|
+
properties: {
|
|
8195
|
+
keywords: {
|
|
8196
|
+
type: "array",
|
|
8197
|
+
items: { type: "string" },
|
|
8198
|
+
description: "Search terms to check (1-15).",
|
|
8199
|
+
},
|
|
8200
|
+
},
|
|
8201
|
+
required: ["keywords"],
|
|
8202
|
+
},
|
|
8203
|
+
command: "ideas.demand",
|
|
8204
|
+
},
|
|
8205
|
+
{
|
|
8206
|
+
name: "ideas_competitors",
|
|
8207
|
+
description:
|
|
8208
|
+
"The channels this workspace tracks, each with its baseline at the last scan and its uploads from the last 90 days at 2x or more (breakouts). Remembered across conversations; ideas.scan refreshes them.",
|
|
8209
|
+
inputSchema: {
|
|
8210
|
+
type: "object",
|
|
8211
|
+
properties: {},
|
|
8212
|
+
},
|
|
8213
|
+
command: "ideas.competitors",
|
|
8214
|
+
},
|
|
8215
|
+
{
|
|
8216
|
+
name: "ideas_track",
|
|
8217
|
+
description:
|
|
8218
|
+
"Start tracking a channel as a competitor (reads it once), or stop with tracked: false. Up to 40 per workspace.",
|
|
8219
|
+
inputSchema: {
|
|
8220
|
+
type: "object",
|
|
8221
|
+
properties: {
|
|
8222
|
+
channel: {
|
|
8223
|
+
type: "string",
|
|
8224
|
+
description: "@handle, channel URL or UC id (to stop: the UC id from ideas.competitors).",
|
|
8225
|
+
},
|
|
8226
|
+
tracked: { type: "boolean", description: "true (default) to track, false to stop." },
|
|
8227
|
+
format: { type: "string", description: "videos (long-form, default) | shorts." },
|
|
8228
|
+
},
|
|
8229
|
+
required: ["channel"],
|
|
8230
|
+
},
|
|
8231
|
+
command: "ideas.track",
|
|
8232
|
+
},
|
|
8233
|
+
{
|
|
8234
|
+
name: "ideas_scan",
|
|
8235
|
+
description:
|
|
8236
|
+
"Re-read every tracked competitor and return the breakouts across all of them (uploads from the last 90 days at 2x or more), best first. ~5-10 s per 5 channels.",
|
|
8237
|
+
inputSchema: {
|
|
8238
|
+
type: "object",
|
|
8239
|
+
properties: {
|
|
8240
|
+
limit: { type: "number", description: "Max breakouts returned, 1-100 (default 20)." },
|
|
8241
|
+
},
|
|
8242
|
+
},
|
|
8243
|
+
command: "ideas.scan",
|
|
8244
|
+
},
|
|
7462
8245
|
{
|
|
7463
8246
|
name: "export_generate_shots",
|
|
7464
8247
|
description:
|
|
@@ -7865,14 +8648,14 @@ Read-only tools (project_read, transcript_get / _search / _find_issues, audio_pr
|
|
|
7865
8648
|
|
|
7866
8649
|
Before an editing pass, read the skill's "Which tool for which moment" section (skill_read section="Which tool for which moment").
|
|
7867
8650
|
|
|
7868
|
-
"Edit my video" / "make this a Short" with no specifics = this pipeline, in order.
|
|
8651
|
+
"Edit my video" / "make this a Short" with no specifics = this pipeline, in order. In PandaStudio's own chat: write it as a plan first (plan_propose: the steps below that apply, the scope question on it), end your turn, and run it when the user presses Start editing, with plan_update_step after each step. Other clients: confirm scope once ("full polish, or just part of it?"), then run it all:
|
|
7869
8652
|
1. transcript_transcribe clips not yet transcribed (project_read clipStates).
|
|
7870
8653
|
2. transcript_remove_fillers.
|
|
7871
8654
|
3. Fix misheard names / brands with transcript_find_replace (transcript_insert_words for dropped words).
|
|
7872
8655
|
4. transcript_find_issues, then transcript_delete_words on each duplicate take / false start (keep the LAST take; keep severity "low" ones).
|
|
7873
8656
|
5. transcript_remove_silences.
|
|
7874
|
-
6. audio_enhance (Enhance voice) on clips not yet enhanced
|
|
7875
|
-
7. The style, after steps 2-5 (they shift the timeline). The user's named style, recipe, creator or a saved memory wins. Otherwise call recipe_pick: it returns the recipes that fit this project's format and footage, each with pickWhen, plus defaultId. Read the transcript, choose the ONE candidate whose pickWhen matches what is said (defaultId when none clearly fits), do its "before" step if any, then recipe_apply_style + recipe_render and follow the prompt: the recipe decides the style (captions, pacing, kinds of moves, music, transitions). Graphics inside it are designed by you: a named template is the reference look; author your own (motion_render_html, same palette and type) when a beat needs something the template can't show. (An app without recipe_pick, 2.0.5 and older: recipe_list with format short or long, and choose by description and footage.) Tell the user which recipe and why in one line and name one or two alternatives. Only when no candidate exists or the user asked for a plain clean-up: captions (caption_toggle,
|
|
8657
|
+
6. audio_enhance (Enhance voice) on clips not yet enhanced with its defaults (Light, plus Studio mic sound on Apple silicon; don't pass strength or restore unless the user asked); keepBackground true for vlogs / ambience; no echo (Enhance voice already removes room echo with the Studio AI model; only use echo when the result reports the model did not run (fallback)).
|
|
8658
|
+
7. The style, after steps 2-5 (they shift the timeline). The user's named style, recipe, creator or a saved memory wins. Otherwise call recipe_pick: it returns the recipes that fit this project's format and footage, each with pickWhen, plus defaultId. Read the transcript, choose the ONE candidate whose pickWhen matches what is said (defaultId when none clearly fits), do its "before" step if any, then recipe_apply_style + recipe_render and follow the prompt: the recipe decides the style (captions, pacing, kinds of moves, music, transitions). Graphics inside it are designed by you: a named template is the reference look; author your own (motion_render_html, same palette and type) when a beat needs something the template can't show. (An app without recipe_pick, 2.0.5 and older: recipe_list with format short or long, and choose by description and footage.) Tell the user which recipe and why in one line and name one or two alternatives. Only when no candidate exists or the user asked for a plain clean-up: captions (caption_toggle, then caption_set_template: hormoziEmphasis for vertical, classic for long-form; not glowStack unless asked), a few motion graphics, emphasis zooms.
|
|
7876
8659
|
8. B-roll, last: pick the moments yourself from what's said (any language), check them with project_check_broll, show the user your moments and ASK: their own images, generated on their image connector (only if one is connected; it uses their credits), or no B-roll. Never generate or invent images without their answer. Place what they give with project_add_broll. Nobody to ask: skip it and say so.
|
|
7877
8660
|
9. llm_generate_title / description / timestamps, then preview_show and ask before export_start. Never export before the user has seen the preview.
|
|
7878
8661
|
Report the real count each step returned. No music, intro/outro cards or FX overlays unless the recipe or the user asks for them.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@writepanda/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.259.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",
|