@writepanda/mcp 1.191.0 → 1.198.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.
Files changed (2) hide show
  1. package/bin/server.mjs +265 -25
  2. package/package.json +1 -1
package/bin/server.mjs CHANGED
@@ -620,10 +620,43 @@ const TOOLS = [
620
620
  {
621
621
  name: "system_status",
622
622
  description:
623
- "App version and license; automationGated true = trial expired, every other tool fails. Call first.",
623
+ "App version and license; automationGated true = trial expired, every other tool fails; license.socialPublishing.allowed false = the plan has no Instagram/TikTok/social publishing (Creator, Team, Pro only). Call first.",
624
624
  inputSchema: { type: "object", properties: {} },
625
625
  command: "system.status",
626
626
  },
627
+ {
628
+ name: "system_report_issue",
629
+ description:
630
+ "Report a PandaStudio problem to the team (emailed; repeats group into one issue). Call it yourself, without asking, on a capability gap, an unexpected command failure, or output that doesn't match the project; then say in chat that you reported it. Not for user mistakes, missing keys, network or taste. Technical facts only: never put transcript/captions in title or details (userContent + userConsented only after the user agrees). sent=false with a reason: don't retry.",
631
+ inputSchema: {
632
+ type: "object",
633
+ properties: {
634
+ title: { type: "string", description: "One line: what's broken." },
635
+ details: {
636
+ type: "string",
637
+ description: "What happened and your diagnosis (no user content).",
638
+ },
639
+ kind: {
640
+ type: "string",
641
+ enum: ["capability-gap", "command-failed", "wrong-output", "crash", "confusing", "other"],
642
+ },
643
+ key: {
644
+ type: "string",
645
+ description: "Kebab-case problem name, e.g. custom-font-not-in-export.",
646
+ },
647
+ userGoal: { type: "string" },
648
+ command: { type: "string", description: "e.g. caption.set-style" },
649
+ workaround: { type: "string" },
650
+ agent: { type: "string", description: "Your runtime / model." },
651
+ id: { type: "string", description: "Project id (default: open project)." },
652
+ path: { type: "string" },
653
+ userContent: { type: "string" },
654
+ userConsented: { type: "boolean" },
655
+ },
656
+ required: ["title", "details"],
657
+ },
658
+ command: "system.report-issue",
659
+ },
627
660
  {
628
661
  name: "skill_read",
629
662
  description:
@@ -1052,51 +1085,88 @@ const TOOLS = [
1052
1085
  },
1053
1086
  command: "export.publish-youtube",
1054
1087
  },
1088
+ // ── Social publishing (2.0.3): Instagram, TikTok, Facebook, LinkedIn, X ──
1089
+ // Through PandaQueue; every verb acts on the ACTIVE workspace's own
1090
+ // accounts. The older instagram.* verbs remain callable via pandastudio_call.
1055
1091
  {
1056
- name: "instagram_connect",
1092
+ name: "social_channels",
1057
1093
  description:
1058
- "Start connecting Instagram (Business / Creator only); the user finishes in the browser, then poll instagram_status.",
1094
+ "Social accounts connected in the active workspace (Instagram, TikTok, Facebook, LinkedIn, X) with ids, limits and per-post settings, plus each network's count.",
1059
1095
  inputSchema: { type: "object", properties: {} },
1060
- command: "instagram.connect",
1096
+ command: "social.channels",
1061
1097
  },
1062
1098
  {
1063
- name: "instagram_status",
1064
- description: "Instagram connection { status, active }. Poll after instagram_connect.",
1099
+ name: "social_connect",
1100
+ description:
1101
+ "Connect a network to the active workspace: opens its sign-in in the user's browser, returns { sessionId } at once; poll social_connect_status. Instagram: Business/Creator only.",
1065
1102
  inputSchema: {
1066
1103
  type: "object",
1067
1104
  properties: {
1068
- connectionId: { type: "string" },
1105
+ network: { type: "string", enum: ["instagram", "tiktok", "facebook", "linkedin", "x"] },
1069
1106
  },
1107
+ required: ["network"],
1070
1108
  },
1071
- command: "instagram.status",
1109
+ command: "social.connect",
1072
1110
  },
1073
1111
  {
1074
- name: "instagram_account",
1075
- description: "Connected Instagram account and whether it can publish.",
1076
- inputSchema: { type: "object", properties: {} },
1077
- command: "instagram.account",
1112
+ name: "social_connect_status",
1113
+ description: "{ state: pending | connected | failed, channels } for a social_connect session.",
1114
+ inputSchema: {
1115
+ type: "object",
1116
+ properties: { sessionId: { type: "string" } },
1117
+ required: ["sessionId"],
1118
+ },
1119
+ command: "social.connect-status",
1078
1120
  },
1079
1121
  {
1080
- name: "instagram_disconnect",
1122
+ name: "social_disconnect",
1081
1123
  description:
1082
- "Disconnect Instagram. Published Reels stay. Destructive: user confirms (see instructions).",
1083
- inputSchema: { type: "object", properties: {} },
1084
- command: "instagram.disconnect",
1124
+ "Disconnect one social account (id from social_channels). Destructive: user confirms (see instructions).",
1125
+ inputSchema: {
1126
+ type: "object",
1127
+ properties: { channelId: { type: "string" } },
1128
+ required: ["channelId"],
1129
+ },
1130
+ command: "social.disconnect",
1085
1131
  },
1086
1132
  {
1087
- name: "export_publish_instagram",
1133
+ name: "export_publish_social",
1088
1134
  description:
1089
- "Publish an export entry (9:16, up to ~90 s) as an Instagram Reel. Slow. Returns { permalink }.",
1135
+ "Post an export entry to connected social accounts, now or scheduled. Public: confirm accounts + caption first. Returns { jobId }; job_wait gives { state, channels[{ permalink, error }], summary }.",
1090
1136
  inputSchema: {
1091
1137
  type: "object",
1092
1138
  properties: {
1093
1139
  id: { type: "string", description: "Export entry id." },
1094
- caption: { type: "string", description: "Max 2200 chars." },
1095
- shareToFeed: { type: "boolean", description: "Default true." },
1140
+ channelIds: {
1141
+ type: "array",
1142
+ items: { type: "string" },
1143
+ description: "Account ids from social_channels.",
1144
+ },
1145
+ networks: {
1146
+ type: "array",
1147
+ items: { type: "string" },
1148
+ description: "Every connected account of these networks.",
1149
+ },
1150
+ caption: { type: "string" },
1151
+ captions: { type: "object", description: "{ channelId: caption } overrides." },
1152
+ settings: { type: "object", description: "{ channelId: { ...network settings } }." },
1153
+ when: { type: "string", enum: ["now", "schedule"] },
1154
+ scheduledAt: { type: "string", description: "ISO 8601 with offset; for schedule." },
1096
1155
  },
1097
1156
  required: ["id"],
1098
1157
  },
1099
- command: "export.publish-instagram",
1158
+ command: "export.publish-social",
1159
+ },
1160
+ {
1161
+ name: "social_post_status",
1162
+ description:
1163
+ "Status and links of a post from export_publish_social (pass exportId to update the export's record).",
1164
+ inputSchema: {
1165
+ type: "object",
1166
+ properties: { postId: { type: "string" }, exportId: { type: "string" } },
1167
+ required: ["postId"],
1168
+ },
1169
+ command: "social.post-status",
1100
1170
  },
1101
1171
  {
1102
1172
  name: "export_list_youtube",
@@ -1973,6 +2043,153 @@ const TOOLS = [
1973
2043
  },
1974
2044
  command: "project.remove-mute-region",
1975
2045
  },
2046
+ {
2047
+ name: "project_add_bleep",
2048
+ description:
2049
+ "Bleep words instead of cutting them: audio silenced, a tone of exactly their length plays, captions mask them (d***). wordIds from transcript.get (adjacent words = one bleep; stays on those words through later cuts) or startMs/endMs edited ms. Overlaps merge. Returns bleepIds.",
2050
+ inputSchema: {
2051
+ type: "object",
2052
+ properties: {
2053
+ id: { type: "string" },
2054
+ path: { type: "string" },
2055
+ wordIds: { type: "array", items: { type: "string" } },
2056
+ startMs: { type: "number" },
2057
+ endMs: { type: "number" },
2058
+ sound: {
2059
+ type: "string",
2060
+ enum: ["tv", "low", "high", "retro", "silence"],
2061
+ description: "Default tv (1 kHz).",
2062
+ },
2063
+ volume: { type: "number", description: "0-1, default 0.5." },
2064
+ mask: {
2065
+ type: "string",
2066
+ enum: ["stars", "none"],
2067
+ description: "Caption masking, default stars.",
2068
+ },
2069
+ padMs: { type: "number", description: "Padding each side, default 30." },
2070
+ padStartMs: { type: "number" },
2071
+ padEndMs: { type: "number" },
2072
+ expectedRevision: { type: "number" },
2073
+ },
2074
+ },
2075
+ command: "project.add-bleep",
2076
+ },
2077
+ {
2078
+ name: "project_update_bleep",
2079
+ description:
2080
+ "Change a bleep's sound, volume or caption mask, or its edges: nudgeStartMs (+ = earlier start), nudgeEndMs (+ = later end), or padStartMs/padEndMs.",
2081
+ inputSchema: {
2082
+ type: "object",
2083
+ properties: {
2084
+ id: { type: "string" },
2085
+ path: { type: "string" },
2086
+ bleepId: { type: "string" },
2087
+ sound: { type: "string", enum: ["tv", "low", "high", "retro", "silence"] },
2088
+ volume: { type: "number" },
2089
+ mask: { type: "string", enum: ["stars", "none"] },
2090
+ padStartMs: { type: "number" },
2091
+ padEndMs: { type: "number" },
2092
+ nudgeStartMs: { type: "number" },
2093
+ nudgeEndMs: { type: "number" },
2094
+ expectedRevision: { type: "number" },
2095
+ },
2096
+ required: ["bleepId"],
2097
+ },
2098
+ command: "project.update-bleep",
2099
+ },
2100
+ {
2101
+ name: "project_remove_bleep",
2102
+ description: "Remove a bleep (bleepId) or un-bleep specific words (wordIds).",
2103
+ inputSchema: {
2104
+ type: "object",
2105
+ properties: {
2106
+ id: { type: "string" },
2107
+ path: { type: "string" },
2108
+ bleepId: { type: "string" },
2109
+ wordIds: { type: "array", items: { type: "string" } },
2110
+ expectedRevision: { type: "number" },
2111
+ },
2112
+ },
2113
+ command: "project.remove-bleep",
2114
+ },
2115
+ {
2116
+ name: "project_check_broll",
2117
+ description:
2118
+ "B-roll, the LAST step of an edit. YOU pick the moments from what's said (transcript_get; any language, any topic; ~1 per 10-15 s) and what each picture shows; this checks them: span, clashes with the steps list / end card / other pictures, spacing, a nearby suggestion when blocked, insetSide (card away from the face). No moments: free stretches. Returns imageConnector. Never makes images: show the user your moments and ASK: their own images, generate on their connector (uses credits), or none. No one to ask: skip it and say so.",
2119
+ inputSchema: {
2120
+ type: "object",
2121
+ properties: {
2122
+ id: { type: "string" },
2123
+ path: { type: "string" },
2124
+ moments: {
2125
+ type: "array",
2126
+ items: {
2127
+ type: "object",
2128
+ properties: {
2129
+ wordId: { type: "string" },
2130
+ atMs: { type: "number" },
2131
+ endWordId: { type: "string" },
2132
+ durationMs: { type: "number" },
2133
+ picture: { type: "string", description: "What the picture shows." },
2134
+ },
2135
+ },
2136
+ },
2137
+ minGapMs: { type: "number" },
2138
+ },
2139
+ },
2140
+ command: "project.check-broll",
2141
+ },
2142
+ {
2143
+ name: "project_add_broll",
2144
+ description:
2145
+ "Place a B-roll beat on a word: the picture (user's own, or generated after they agreed) for ~2 s with a slow push, shutter click and a transition on both edges; moves / deletes / follows cuts as one (brollId).",
2146
+ inputSchema: {
2147
+ type: "object",
2148
+ properties: {
2149
+ id: { type: "string" },
2150
+ path: { type: "string" },
2151
+ imagePath: { type: "string" },
2152
+ wordId: { type: "string" },
2153
+ atMs: { type: "number" },
2154
+ durationMs: { type: "number", description: "1400-4000, default 2000." },
2155
+ endWordId: { type: "string" },
2156
+ layout: { type: "string", enum: ["full", "inset"] },
2157
+ transition: {
2158
+ type: "string",
2159
+ enum: ["flash", "light-sweep", "film-burn", "fade-white", "glitch", "none"],
2160
+ },
2161
+ sound: { type: "string", enum: ["shutter", "click", "none"] },
2162
+ push: { type: "string", enum: ["in", "out", "none"] },
2163
+ expectedRevision: { type: "number" },
2164
+ },
2165
+ required: ["imagePath"],
2166
+ },
2167
+ command: "project.add-broll",
2168
+ },
2169
+ {
2170
+ name: "project_list_broll",
2171
+ description: "The project's B-roll beats (brollId, picture, span, overlay ids).",
2172
+ inputSchema: {
2173
+ type: "object",
2174
+ properties: { id: { type: "string" }, path: { type: "string" } },
2175
+ },
2176
+ command: "project.list-broll",
2177
+ },
2178
+ {
2179
+ name: "project_remove_broll",
2180
+ description: "Remove a B-roll beat (picture + transitions) by brollId.",
2181
+ inputSchema: {
2182
+ type: "object",
2183
+ properties: {
2184
+ id: { type: "string" },
2185
+ path: { type: "string" },
2186
+ brollId: { type: "string" },
2187
+ expectedRevision: { type: "number" },
2188
+ },
2189
+ required: ["brollId"],
2190
+ },
2191
+ command: "project.remove-broll",
2192
+ },
1976
2193
  {
1977
2194
  name: "project_add_spotlight",
1978
2195
  description:
@@ -3560,7 +3777,11 @@ const TOOLS = [
3560
3777
  path: { type: "string" },
3561
3778
  wordsPerLine: { type: "number" },
3562
3779
  positionY: { type: "number", description: "% from the top, default 85." },
3563
- fontFamily: { type: "string" },
3780
+ fontFamily: {
3781
+ type: "string",
3782
+ description:
3783
+ "A family from asset_list_fonts (bundled, custom or system). Unknown names render in Inter and come back as a warning.",
3784
+ },
3564
3785
  color: { type: "string" },
3565
3786
  backgroundColor: { type: "string" },
3566
3787
  highlightColor: { type: "string", description: "Spoken word." },
@@ -3641,7 +3862,7 @@ const TOOLS = [
3641
3862
  {
3642
3863
  name: "media_generate_image",
3643
3864
  description:
3644
- "Generate one image on the user's own image connector (auto: Replicate, else Higgsfield; their credits). Returns { imagePath, provider, model, transparent }. transparent=true: trimmed PNG sticker. No connector: code NO_IMAGE_CONNECTOR, so ask the user for their own images. Each call is a paid generation.",
3865
+ "Generate one image on the user's own image connector (auto: Replicate, else Higgsfield; their credits). Only after the user agreed to generating (ask first; B-roll: pick moments, project_check_broll, then ask). Returns { imagePath, provider, model, transparent }. transparent=true: trimmed PNG sticker. No connector: code NO_IMAGE_CONNECTOR, so ask the user for their own images. Each call is a paid generation.",
3645
3866
  inputSchema: {
3646
3867
  type: "object",
3647
3868
  properties: {
@@ -4394,6 +4615,10 @@ const TOOLS = [
4394
4615
  description: "Omit for the template's natural mode.",
4395
4616
  },
4396
4617
  outputName: { type: "string" },
4618
+ durationMs: {
4619
+ type: "number",
4620
+ description: "Length for templates with a durationRangeMs (clamped); ignored otherwise.",
4621
+ },
4397
4622
  },
4398
4623
  required: ["templateId", "slots"],
4399
4624
  },
@@ -4630,6 +4855,18 @@ const TOOLS = [
4630
4855
  inputSchema: { type: "object", properties: {} },
4631
4856
  command: "asset.list-luts",
4632
4857
  },
4858
+ {
4859
+ name: "asset_list_fonts",
4860
+ description:
4861
+ "Font families text can use: bundled, scriptFallbacks (Noto, used per character for Indic/Arabic/Hebrew/Thai text), custom (the user's imported fonts; prefer one covering the video's language), system with includeSystem. Pass one to caption_set_style fontFamily.",
4862
+ inputSchema: {
4863
+ type: "object",
4864
+ properties: {
4865
+ includeSystem: { type: "boolean", description: "Also list installed families (long)." },
4866
+ },
4867
+ },
4868
+ command: "asset.list-fonts",
4869
+ },
4633
4870
 
4634
4871
  // ── project-aware LLM ──────────────────────────────────────────
4635
4872
  {
@@ -5041,7 +5278,8 @@ Before an editing pass, read the skill's "Which tool for which moment" section (
5041
5278
  5. transcript_remove_silences.
5042
5279
  6. audio_clean clips not yet cleaned.
5043
5280
  7. Captions (caption_toggle; template glowStack unless a recipe says otherwise), motion graphics, emphasis zooms: only after steps 2-5, which shift the timeline.
5044
- 8. llm_generate_title / description / timestamps, then preview_show and ask before export_start. Never export before the user has seen the preview.
5281
+ 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.
5282
+ 9. llm_generate_title / description / timestamps, then preview_show and ask before export_start. Never export before the user has seen the preview.
5045
5283
  Report the real count each step returned. Never add music, intro/outro cards or FX overlays unless asked.
5046
5284
 
5047
5285
  Style defaults when the user names no style, recipe or creator (their choice or a saved memory wins):
@@ -5049,7 +5287,9 @@ Style defaults when the user names no style, recipe or creator (their choice or
5049
5287
  - Shorts / Reels / TikTok (9:16): the Shorts recipe that fits: hard-truth-one-liner-short (one blunt claim), rules-listicle-cutaways-short (numbered tips), rapid-fire-list-short (many one-line items), storytime-turn-short (story with a twist), framework-explainer-short (one concept), split-screen-short-broll (showable things), social-ad-hook-variants (selling an offer), faceless-short (no footage), else warm-educator-short.
5050
5288
  A Short from a SCREEN RECORDING first gets project_set_vertical_screen_layout, then the recipe. Say which recipe you used and why, and offer others (recipe_list).
5051
5289
 
5052
- Destructive actions need the user's own confirmation: project_delete, workspace_delete, recipe_delete, memory_forget, export_delete, export_clear_thumbnail, youtube_disconnect, instagram_disconnect. Ask plainly in chat first ("Delete project 'Demo'? This can't be undone.") and call only after they agree. PandaStudio then confirms with them itself: in its own chat the call returns confirmation_required and changes nothing while a Delete / Cancel card waits (tell them to press it; don't call again; the outcome arrives as their next message); from other apps a dialog asks, and the call is refused when nobody is at the app. Nothing you send can approve it.
5290
+ Destructive actions need the user's own confirmation: project_delete, workspace_delete, recipe_delete, memory_forget, export_delete, export_clear_thumbnail, youtube_disconnect, social_disconnect. Ask plainly in chat first ("Delete project 'Demo'? This can't be undone.") and call only after they agree. PandaStudio then confirms with them itself: in its own chat the call returns confirmation_required and changes nothing while a Delete / Cancel card waits (tell them to press it; don't call again; the outcome arrives as their next message); from other apps a dialog asks, and the call is refused when nobody is at the app. Nothing you send can approve it.
5291
+
5292
+ 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.
5053
5293
 
5054
5294
  Destination decides everything: infer it (Shorts/TikTok/vertical/<=90s: shorts; YouTube/tutorial/>8 min: youtube-long; LinkedIn; Loom/internal), else ask once.
5055
5295
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writepanda/mcp",
3
- "version": "1.191.0",
3
+ "version": "1.198.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",