@socialneuron/mcp-server 1.5.0 → 1.5.1
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/CHANGELOG.md +9 -0
- package/dist/http.js +448 -76
- package/dist/index.js +448 -76
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var MCP_VERSION;
|
|
|
14
14
|
var init_version = __esm({
|
|
15
15
|
"src/lib/version.ts"() {
|
|
16
16
|
"use strict";
|
|
17
|
-
MCP_VERSION = "1.5.
|
|
17
|
+
MCP_VERSION = "1.5.1";
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
|
|
@@ -3928,6 +3928,13 @@ function registerIdeationTools(server2) {
|
|
|
3928
3928
|
"Project ID to auto-load brand profile and performance context for prompt enrichment."
|
|
3929
3929
|
)
|
|
3930
3930
|
},
|
|
3931
|
+
{
|
|
3932
|
+
title: "Generate Content",
|
|
3933
|
+
readOnlyHint: false,
|
|
3934
|
+
destructiveHint: false,
|
|
3935
|
+
idempotentHint: false,
|
|
3936
|
+
openWorldHint: true
|
|
3937
|
+
},
|
|
3931
3938
|
async ({
|
|
3932
3939
|
prompt: prompt2,
|
|
3933
3940
|
content_type,
|
|
@@ -4091,6 +4098,13 @@ Content Type: ${content_type}`;
|
|
|
4091
4098
|
),
|
|
4092
4099
|
force_refresh: z.boolean().optional().describe("Skip the server-side cache and fetch fresh data.")
|
|
4093
4100
|
},
|
|
4101
|
+
{
|
|
4102
|
+
title: "Fetch Trends",
|
|
4103
|
+
readOnlyHint: true,
|
|
4104
|
+
destructiveHint: false,
|
|
4105
|
+
idempotentHint: false,
|
|
4106
|
+
openWorldHint: true
|
|
4107
|
+
},
|
|
4094
4108
|
async ({ source, category, niche, url, force_refresh }) => {
|
|
4095
4109
|
if ((source === "rss" || source === "url") && !url) {
|
|
4096
4110
|
return {
|
|
@@ -4195,6 +4209,13 @@ Content Type: ${content_type}`;
|
|
|
4195
4209
|
"Optional project ID to load platform voice overrides from brand profile."
|
|
4196
4210
|
)
|
|
4197
4211
|
},
|
|
4212
|
+
{
|
|
4213
|
+
title: "Adapt Content",
|
|
4214
|
+
readOnlyHint: false,
|
|
4215
|
+
destructiveHint: false,
|
|
4216
|
+
idempotentHint: false,
|
|
4217
|
+
openWorldHint: true
|
|
4218
|
+
},
|
|
4198
4219
|
async ({
|
|
4199
4220
|
content,
|
|
4200
4221
|
source_platform,
|
|
@@ -4493,6 +4514,13 @@ function registerContentTools(server2) {
|
|
|
4493
4514
|
),
|
|
4494
4515
|
response_format: z2.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
4495
4516
|
},
|
|
4517
|
+
{
|
|
4518
|
+
title: "Generate Video",
|
|
4519
|
+
readOnlyHint: false,
|
|
4520
|
+
destructiveHint: false,
|
|
4521
|
+
idempotentHint: false,
|
|
4522
|
+
openWorldHint: true
|
|
4523
|
+
},
|
|
4496
4524
|
async ({
|
|
4497
4525
|
prompt: prompt2,
|
|
4498
4526
|
model,
|
|
@@ -4691,6 +4719,13 @@ function registerContentTools(server2) {
|
|
|
4691
4719
|
),
|
|
4692
4720
|
response_format: z2.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
4693
4721
|
},
|
|
4722
|
+
{
|
|
4723
|
+
title: "Generate Image",
|
|
4724
|
+
readOnlyHint: false,
|
|
4725
|
+
destructiveHint: false,
|
|
4726
|
+
idempotentHint: false,
|
|
4727
|
+
openWorldHint: true
|
|
4728
|
+
},
|
|
4694
4729
|
async ({ prompt: prompt2, model, aspect_ratio, image_url, response_format }) => {
|
|
4695
4730
|
const format = response_format ?? "text";
|
|
4696
4731
|
const startedAt = Date.now();
|
|
@@ -4854,6 +4889,13 @@ function registerContentTools(server2) {
|
|
|
4854
4889
|
),
|
|
4855
4890
|
response_format: z2.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
4856
4891
|
},
|
|
4892
|
+
{
|
|
4893
|
+
title: "Check Job Status",
|
|
4894
|
+
readOnlyHint: true,
|
|
4895
|
+
destructiveHint: false,
|
|
4896
|
+
idempotentHint: true,
|
|
4897
|
+
openWorldHint: true
|
|
4898
|
+
},
|
|
4857
4899
|
async ({ job_id, response_format }) => {
|
|
4858
4900
|
const format = response_format ?? "text";
|
|
4859
4901
|
const startedAt = Date.now();
|
|
@@ -5051,6 +5093,13 @@ function registerContentTools(server2) {
|
|
|
5051
5093
|
"Response format. Defaults to json for structured storyboard data."
|
|
5052
5094
|
)
|
|
5053
5095
|
},
|
|
5096
|
+
{
|
|
5097
|
+
title: "Create Storyboard",
|
|
5098
|
+
readOnlyHint: false,
|
|
5099
|
+
destructiveHint: false,
|
|
5100
|
+
idempotentHint: false,
|
|
5101
|
+
openWorldHint: true
|
|
5102
|
+
},
|
|
5054
5103
|
async ({
|
|
5055
5104
|
concept,
|
|
5056
5105
|
brand_context,
|
|
@@ -5231,6 +5280,13 @@ Return ONLY valid JSON in this exact format:
|
|
|
5231
5280
|
speed: z2.number().min(0.5).max(2).optional().describe("Speech speed multiplier. 1.0 is normal. Defaults to 1.0."),
|
|
5232
5281
|
response_format: z2.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
5233
5282
|
},
|
|
5283
|
+
{
|
|
5284
|
+
title: "Generate Voiceover",
|
|
5285
|
+
readOnlyHint: false,
|
|
5286
|
+
destructiveHint: false,
|
|
5287
|
+
idempotentHint: false,
|
|
5288
|
+
openWorldHint: true
|
|
5289
|
+
},
|
|
5234
5290
|
async ({ text, voice, speed, response_format }) => {
|
|
5235
5291
|
const format = response_format ?? "text";
|
|
5236
5292
|
const startedAt = Date.now();
|
|
@@ -5389,6 +5445,13 @@ Return ONLY valid JSON in this exact format:
|
|
|
5389
5445
|
project_id: z2.string().optional().describe("Project ID to associate the carousel with."),
|
|
5390
5446
|
response_format: z2.enum(["text", "json"]).optional().describe("Response format. Defaults to json.")
|
|
5391
5447
|
},
|
|
5448
|
+
{
|
|
5449
|
+
title: "Generate Carousel",
|
|
5450
|
+
readOnlyHint: false,
|
|
5451
|
+
destructiveHint: false,
|
|
5452
|
+
idempotentHint: false,
|
|
5453
|
+
openWorldHint: true
|
|
5454
|
+
},
|
|
5392
5455
|
async ({
|
|
5393
5456
|
topic,
|
|
5394
5457
|
template_id,
|
|
@@ -5602,6 +5665,13 @@ function registerDistributionTools(server2) {
|
|
|
5602
5665
|
'If true, appends "Created with Social Neuron" to the caption. Default: false.'
|
|
5603
5666
|
)
|
|
5604
5667
|
},
|
|
5668
|
+
{
|
|
5669
|
+
title: "Schedule Post",
|
|
5670
|
+
readOnlyHint: false,
|
|
5671
|
+
destructiveHint: false,
|
|
5672
|
+
idempotentHint: false,
|
|
5673
|
+
openWorldHint: true
|
|
5674
|
+
},
|
|
5605
5675
|
async ({
|
|
5606
5676
|
media_url,
|
|
5607
5677
|
media_urls,
|
|
@@ -5753,6 +5823,13 @@ Created with Social Neuron`;
|
|
|
5753
5823
|
{
|
|
5754
5824
|
response_format: z3.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
5755
5825
|
},
|
|
5826
|
+
{
|
|
5827
|
+
title: "List Connected Accounts",
|
|
5828
|
+
readOnlyHint: true,
|
|
5829
|
+
destructiveHint: false,
|
|
5830
|
+
idempotentHint: true,
|
|
5831
|
+
openWorldHint: false
|
|
5832
|
+
},
|
|
5756
5833
|
async ({ response_format }) => {
|
|
5757
5834
|
const format = response_format ?? "text";
|
|
5758
5835
|
const supabase = getSupabaseClient();
|
|
@@ -5831,6 +5908,13 @@ Created with Social Neuron`;
|
|
|
5831
5908
|
limit: z3.number().min(1).max(50).optional().describe("Maximum number of posts to return. Defaults to 20."),
|
|
5832
5909
|
response_format: z3.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
5833
5910
|
},
|
|
5911
|
+
{
|
|
5912
|
+
title: "List Recent Posts",
|
|
5913
|
+
readOnlyHint: true,
|
|
5914
|
+
destructiveHint: false,
|
|
5915
|
+
idempotentHint: true,
|
|
5916
|
+
openWorldHint: false
|
|
5917
|
+
},
|
|
5834
5918
|
async ({ platform: platform3, status, days, limit, response_format }) => {
|
|
5835
5919
|
const format = response_format ?? "text";
|
|
5836
5920
|
const supabase = getSupabaseClient();
|
|
@@ -5930,7 +6014,7 @@ Created with Social Neuron`;
|
|
|
5930
6014
|
};
|
|
5931
6015
|
server2.tool(
|
|
5932
6016
|
"find_next_slots",
|
|
5933
|
-
"Find
|
|
6017
|
+
"Find the next available posting time slots that avoid conflicts with already-scheduled posts. Uses engagement data from get_best_posting_times to rank slots. Call this before schedule_content_plan to pick optimal, non-overlapping times for each post.",
|
|
5934
6018
|
{
|
|
5935
6019
|
platforms: z3.array(
|
|
5936
6020
|
z3.enum([
|
|
@@ -5943,11 +6027,18 @@ Created with Social Neuron`;
|
|
|
5943
6027
|
"threads",
|
|
5944
6028
|
"bluesky"
|
|
5945
6029
|
])
|
|
5946
|
-
).min(1),
|
|
6030
|
+
).min(1).describe("Platforms to find posting slots for."),
|
|
5947
6031
|
count: z3.number().min(1).max(20).default(7).describe("Number of slots to find"),
|
|
5948
6032
|
start_after: z3.string().optional().describe("ISO datetime, defaults to now"),
|
|
5949
6033
|
min_gap_hours: z3.number().min(1).max(24).default(4).describe("Minimum gap between posts on same platform"),
|
|
5950
|
-
response_format: z3.enum(["text", "json"]).default("text")
|
|
6034
|
+
response_format: z3.enum(["text", "json"]).default("text").describe("Response format. Defaults to text.")
|
|
6035
|
+
},
|
|
6036
|
+
{
|
|
6037
|
+
title: "Find Next Posting Slots",
|
|
6038
|
+
readOnlyHint: true,
|
|
6039
|
+
destructiveHint: false,
|
|
6040
|
+
idempotentHint: true,
|
|
6041
|
+
openWorldHint: false
|
|
5951
6042
|
},
|
|
5952
6043
|
async ({
|
|
5953
6044
|
platforms,
|
|
@@ -6067,20 +6158,20 @@ Created with Social Neuron`;
|
|
|
6067
6158
|
plan: z3.object({
|
|
6068
6159
|
posts: z3.array(
|
|
6069
6160
|
z3.object({
|
|
6070
|
-
id: z3.string(),
|
|
6071
|
-
caption: z3.string(),
|
|
6072
|
-
platform: z3.string(),
|
|
6073
|
-
title: z3.string().optional(),
|
|
6074
|
-
media_url: z3.string().optional(),
|
|
6075
|
-
schedule_at: z3.string().optional(),
|
|
6076
|
-
hashtags: z3.array(z3.string()).optional()
|
|
6161
|
+
id: z3.string().describe("Unique post identifier from the content plan."),
|
|
6162
|
+
caption: z3.string().describe("Post caption/body text."),
|
|
6163
|
+
platform: z3.string().describe("Target platform name (e.g. instagram, youtube)."),
|
|
6164
|
+
title: z3.string().optional().describe("Post title, required for YouTube."),
|
|
6165
|
+
media_url: z3.string().optional().describe("Public or R2 signed URL for the post media."),
|
|
6166
|
+
schedule_at: z3.string().optional().describe("ISO 8601 UTC datetime to publish (e.g. 2026-03-20T14:00:00Z)."),
|
|
6167
|
+
hashtags: z3.array(z3.string()).optional().describe("Hashtags to append to the caption.")
|
|
6077
6168
|
})
|
|
6078
6169
|
)
|
|
6079
|
-
}).passthrough().optional(),
|
|
6170
|
+
}).passthrough().optional().describe("Inline content plan object with a posts array. Provide this or plan_id."),
|
|
6080
6171
|
plan_id: z3.string().uuid().optional().describe("Persisted content plan ID from content_plans table"),
|
|
6081
6172
|
auto_slot: z3.boolean().default(true).describe("Auto-assign time slots for posts without schedule_at"),
|
|
6082
6173
|
dry_run: z3.boolean().default(false).describe("Preview without actually scheduling"),
|
|
6083
|
-
response_format: z3.enum(["text", "json"]).default("text"),
|
|
6174
|
+
response_format: z3.enum(["text", "json"]).default("text").describe("Response format. Defaults to text."),
|
|
6084
6175
|
enforce_quality: z3.boolean().default(true).describe(
|
|
6085
6176
|
"When true, block scheduling for posts that fail quality checks."
|
|
6086
6177
|
),
|
|
@@ -6090,6 +6181,13 @@ Created with Social Neuron`;
|
|
|
6090
6181
|
batch_size: z3.number().int().min(1).max(10).default(4).describe("Concurrent schedule calls per platform batch."),
|
|
6091
6182
|
idempotency_seed: z3.string().max(128).optional().describe("Optional stable seed used when building idempotency keys.")
|
|
6092
6183
|
},
|
|
6184
|
+
{
|
|
6185
|
+
title: "Schedule Content Plan",
|
|
6186
|
+
readOnlyHint: false,
|
|
6187
|
+
destructiveHint: false,
|
|
6188
|
+
idempotentHint: false,
|
|
6189
|
+
openWorldHint: true
|
|
6190
|
+
},
|
|
6093
6191
|
async ({
|
|
6094
6192
|
plan,
|
|
6095
6193
|
plan_id,
|
|
@@ -6662,6 +6760,7 @@ function registerAnalyticsTools(server2) {
|
|
|
6662
6760
|
limit: z4.number().min(1).max(100).optional().describe("Maximum number of posts to return. Defaults to 20."),
|
|
6663
6761
|
response_format: z4.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
6664
6762
|
},
|
|
6763
|
+
{ title: "Fetch Analytics", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
6665
6764
|
async ({ platform: platform3, days, content_id, limit, response_format }) => {
|
|
6666
6765
|
const format = response_format ?? "text";
|
|
6667
6766
|
const supabase = getSupabaseClient();
|
|
@@ -6839,6 +6938,13 @@ function registerAnalyticsTools(server2) {
|
|
|
6839
6938
|
{
|
|
6840
6939
|
response_format: z4.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
6841
6940
|
},
|
|
6941
|
+
{
|
|
6942
|
+
title: "Refresh Platform Analytics",
|
|
6943
|
+
readOnlyHint: false,
|
|
6944
|
+
destructiveHint: false,
|
|
6945
|
+
idempotentHint: false,
|
|
6946
|
+
openWorldHint: true
|
|
6947
|
+
},
|
|
6842
6948
|
async ({ response_format }) => {
|
|
6843
6949
|
const format = response_format ?? "text";
|
|
6844
6950
|
const startedAt = Date.now();
|
|
@@ -7240,6 +7346,13 @@ function registerBrandTools(server2) {
|
|
|
7240
7346
|
),
|
|
7241
7347
|
response_format: z5.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
7242
7348
|
},
|
|
7349
|
+
{
|
|
7350
|
+
title: "Extract Brand",
|
|
7351
|
+
readOnlyHint: true,
|
|
7352
|
+
destructiveHint: false,
|
|
7353
|
+
idempotentHint: true,
|
|
7354
|
+
openWorldHint: true
|
|
7355
|
+
},
|
|
7243
7356
|
async ({ url, response_format }) => {
|
|
7244
7357
|
const ssrfCheck = await validateUrlForSSRF(url);
|
|
7245
7358
|
if (!ssrfCheck.isValid) {
|
|
@@ -7323,6 +7436,13 @@ function registerBrandTools(server2) {
|
|
|
7323
7436
|
project_id: z5.string().uuid().optional().describe("Project ID. Defaults to active project context."),
|
|
7324
7437
|
response_format: z5.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
7325
7438
|
},
|
|
7439
|
+
{
|
|
7440
|
+
title: "Get Brand Profile",
|
|
7441
|
+
readOnlyHint: true,
|
|
7442
|
+
destructiveHint: false,
|
|
7443
|
+
idempotentHint: true,
|
|
7444
|
+
openWorldHint: false
|
|
7445
|
+
},
|
|
7326
7446
|
async ({ project_id, response_format }) => {
|
|
7327
7447
|
const supabase = getSupabaseClient();
|
|
7328
7448
|
const userId = await getDefaultUserId();
|
|
@@ -7420,8 +7540,17 @@ function registerBrandTools(server2) {
|
|
|
7420
7540
|
"product_showcase"
|
|
7421
7541
|
]).optional().describe("Extraction method metadata."),
|
|
7422
7542
|
overall_confidence: z5.number().min(0).max(1).optional().describe("Optional overall confidence score in range 0..1."),
|
|
7423
|
-
extraction_metadata: z5.record(z5.string(), z5.unknown()).optional()
|
|
7424
|
-
|
|
7543
|
+
extraction_metadata: z5.record(z5.string(), z5.unknown()).optional().describe(
|
|
7544
|
+
"Arbitrary key-value metadata about the extraction process."
|
|
7545
|
+
),
|
|
7546
|
+
response_format: z5.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
7547
|
+
},
|
|
7548
|
+
{
|
|
7549
|
+
title: "Save Brand Profile",
|
|
7550
|
+
readOnlyHint: false,
|
|
7551
|
+
destructiveHint: false,
|
|
7552
|
+
idempotentHint: false,
|
|
7553
|
+
openWorldHint: false
|
|
7425
7554
|
},
|
|
7426
7555
|
async ({
|
|
7427
7556
|
project_id,
|
|
@@ -7534,15 +7663,32 @@ Version: ${payload.version ?? "N/A"}`
|
|
|
7534
7663
|
"facebook",
|
|
7535
7664
|
"threads",
|
|
7536
7665
|
"bluesky"
|
|
7537
|
-
]),
|
|
7666
|
+
]).describe("Social platform to set voice overrides for."),
|
|
7538
7667
|
project_id: z5.string().uuid().optional().describe("Project ID. Defaults to active project context."),
|
|
7539
7668
|
samples: z5.string().max(3e3).optional().describe("3-5 real platform post examples for style anchoring."),
|
|
7540
|
-
tone: z5.array(z5.string()).optional()
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7669
|
+
tone: z5.array(z5.string()).optional().describe(
|
|
7670
|
+
'Tone descriptors for this platform (e.g. ["casual", "witty", "informative"]).'
|
|
7671
|
+
),
|
|
7672
|
+
style: z5.array(z5.string()).optional().describe(
|
|
7673
|
+
'Writing style tags (e.g. ["short-form", "emoji-heavy", "storytelling"]).'
|
|
7674
|
+
),
|
|
7675
|
+
avoid_patterns: z5.array(z5.string()).optional().describe(
|
|
7676
|
+
'Phrases or patterns the brand should never use on this platform (e.g. ["click here", "buy now"]).'
|
|
7677
|
+
),
|
|
7678
|
+
hashtag_strategy: z5.string().max(300).optional().describe(
|
|
7679
|
+
'Hashtag usage guidelines for this platform (e.g. "3-5 niche hashtags, no generic tags").'
|
|
7680
|
+
),
|
|
7681
|
+
cta_style: z5.string().max(300).optional().describe(
|
|
7682
|
+
'Preferred call-to-action style (e.g. "soft CTA with question" or "direct link in bio").'
|
|
7683
|
+
),
|
|
7684
|
+
response_format: z5.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
7685
|
+
},
|
|
7686
|
+
{
|
|
7687
|
+
title: "Update Platform Voice",
|
|
7688
|
+
readOnlyHint: false,
|
|
7689
|
+
destructiveHint: false,
|
|
7690
|
+
idempotentHint: false,
|
|
7691
|
+
openWorldHint: false
|
|
7546
7692
|
},
|
|
7547
7693
|
async ({
|
|
7548
7694
|
platform: platform3,
|
|
@@ -7791,6 +7937,13 @@ function registerScreenshotTools(server2) {
|
|
|
7791
7937
|
"Extra milliseconds to wait after page load before capturing. Useful for animations. Defaults to 2000."
|
|
7792
7938
|
)
|
|
7793
7939
|
},
|
|
7940
|
+
{
|
|
7941
|
+
title: "Capture App Page",
|
|
7942
|
+
readOnlyHint: true,
|
|
7943
|
+
destructiveHint: false,
|
|
7944
|
+
idempotentHint: false,
|
|
7945
|
+
openWorldHint: false
|
|
7946
|
+
},
|
|
7794
7947
|
async ({ page: pageName, viewport, theme, selector, wait_ms }) => {
|
|
7795
7948
|
const startedAt = Date.now();
|
|
7796
7949
|
let rateLimitKey = "anonymous";
|
|
@@ -7911,6 +8064,13 @@ function registerScreenshotTools(server2) {
|
|
|
7911
8064
|
),
|
|
7912
8065
|
wait_ms: z6.number().min(0).max(3e4).optional().describe("Extra milliseconds to wait after page load before capturing. Defaults to 1000.")
|
|
7913
8066
|
},
|
|
8067
|
+
{
|
|
8068
|
+
title: "Capture Screenshot",
|
|
8069
|
+
readOnlyHint: true,
|
|
8070
|
+
destructiveHint: false,
|
|
8071
|
+
idempotentHint: false,
|
|
8072
|
+
openWorldHint: true
|
|
8073
|
+
},
|
|
7914
8074
|
async ({ url, viewport, selector, output_path, wait_ms }) => {
|
|
7915
8075
|
const startedAt = Date.now();
|
|
7916
8076
|
let rateLimitKey = "anonymous";
|
|
@@ -8173,6 +8333,13 @@ function registerRemotionTools(server2) {
|
|
|
8173
8333
|
"list_compositions",
|
|
8174
8334
|
"List all available Remotion video compositions defined in Social Neuron. Returns composition IDs, dimensions, duration, and descriptions. Use this to discover what videos can be rendered with render_demo_video.",
|
|
8175
8335
|
{},
|
|
8336
|
+
{
|
|
8337
|
+
title: "List Compositions",
|
|
8338
|
+
readOnlyHint: true,
|
|
8339
|
+
destructiveHint: false,
|
|
8340
|
+
idempotentHint: true,
|
|
8341
|
+
openWorldHint: false
|
|
8342
|
+
},
|
|
8176
8343
|
async () => {
|
|
8177
8344
|
const lines = [`${COMPOSITIONS.length} Remotion compositions available:`, ""];
|
|
8178
8345
|
for (const comp of COMPOSITIONS) {
|
|
@@ -8201,6 +8368,13 @@ function registerRemotionTools(server2) {
|
|
|
8201
8368
|
"JSON string of input props to pass to the composition. Each composition accepts different props. Omit for defaults."
|
|
8202
8369
|
)
|
|
8203
8370
|
},
|
|
8371
|
+
{
|
|
8372
|
+
title: "Render Demo Video",
|
|
8373
|
+
readOnlyHint: false,
|
|
8374
|
+
destructiveHint: false,
|
|
8375
|
+
idempotentHint: false,
|
|
8376
|
+
openWorldHint: false
|
|
8377
|
+
},
|
|
8204
8378
|
async ({ composition_id, output_format, props }) => {
|
|
8205
8379
|
const startedAt = Date.now();
|
|
8206
8380
|
const userId = await getDefaultUserId();
|
|
@@ -8382,6 +8556,13 @@ function registerInsightsTools(server2) {
|
|
|
8382
8556
|
limit: z8.number().min(1).max(50).optional().describe("Maximum number of insights to return. Defaults to 10."),
|
|
8383
8557
|
response_format: z8.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
8384
8558
|
},
|
|
8559
|
+
{
|
|
8560
|
+
title: "Get Performance Insights",
|
|
8561
|
+
readOnlyHint: true,
|
|
8562
|
+
destructiveHint: false,
|
|
8563
|
+
idempotentHint: true,
|
|
8564
|
+
openWorldHint: false
|
|
8565
|
+
},
|
|
8385
8566
|
async ({ insight_type, days, limit, response_format }) => {
|
|
8386
8567
|
const format = response_format ?? "text";
|
|
8387
8568
|
const supabase = getSupabaseClient();
|
|
@@ -8509,6 +8690,13 @@ function registerInsightsTools(server2) {
|
|
|
8509
8690
|
days: z8.number().min(1).max(90).optional().describe("Number of days to analyze. Defaults to 30. Max 90."),
|
|
8510
8691
|
response_format: z8.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
8511
8692
|
},
|
|
8693
|
+
{
|
|
8694
|
+
title: "Get Best Posting Times",
|
|
8695
|
+
readOnlyHint: true,
|
|
8696
|
+
destructiveHint: false,
|
|
8697
|
+
idempotentHint: true,
|
|
8698
|
+
openWorldHint: false
|
|
8699
|
+
},
|
|
8512
8700
|
async ({ platform: platform3, days, response_format }) => {
|
|
8513
8701
|
const format = response_format ?? "text";
|
|
8514
8702
|
const supabase = getSupabaseClient();
|
|
@@ -8658,6 +8846,13 @@ function registerYouTubeAnalyticsTools(server2) {
|
|
|
8658
8846
|
video_id: z9.string().optional().describe('YouTube video ID. Required when action is "video".'),
|
|
8659
8847
|
max_results: z9.number().min(1).max(50).optional().describe('Max videos to return for "topVideos" action. Defaults to 10.')
|
|
8660
8848
|
},
|
|
8849
|
+
{
|
|
8850
|
+
title: "Fetch YouTube Analytics",
|
|
8851
|
+
readOnlyHint: true,
|
|
8852
|
+
destructiveHint: false,
|
|
8853
|
+
idempotentHint: true,
|
|
8854
|
+
openWorldHint: true
|
|
8855
|
+
},
|
|
8661
8856
|
async ({ action, start_date, end_date, video_id, max_results }) => {
|
|
8662
8857
|
if (action === "video" && !video_id) {
|
|
8663
8858
|
return {
|
|
@@ -8778,6 +8973,13 @@ function registerCommentsTools(server2) {
|
|
|
8778
8973
|
page_token: z10.string().optional().describe("Pagination cursor from previous list_comments response nextPageToken field. Omit for first page of results."),
|
|
8779
8974
|
response_format: z10.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
8780
8975
|
},
|
|
8976
|
+
{
|
|
8977
|
+
title: "List Comments",
|
|
8978
|
+
readOnlyHint: true,
|
|
8979
|
+
destructiveHint: false,
|
|
8980
|
+
idempotentHint: true,
|
|
8981
|
+
openWorldHint: true
|
|
8982
|
+
},
|
|
8781
8983
|
async ({ video_id, max_results, page_token, response_format }) => {
|
|
8782
8984
|
const format = response_format ?? "text";
|
|
8783
8985
|
const { data, error } = await callEdgeFunction("youtube-comments", {
|
|
@@ -8848,6 +9050,13 @@ function registerCommentsTools(server2) {
|
|
|
8848
9050
|
text: z10.string().min(1).describe("The reply text."),
|
|
8849
9051
|
response_format: z10.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
8850
9052
|
},
|
|
9053
|
+
{
|
|
9054
|
+
title: "Reply to Comment",
|
|
9055
|
+
readOnlyHint: false,
|
|
9056
|
+
destructiveHint: false,
|
|
9057
|
+
idempotentHint: false,
|
|
9058
|
+
openWorldHint: true
|
|
9059
|
+
},
|
|
8851
9060
|
async ({ parent_id, text, response_format }) => {
|
|
8852
9061
|
const format = response_format ?? "text";
|
|
8853
9062
|
const startedAt = Date.now();
|
|
@@ -8929,6 +9138,13 @@ function registerCommentsTools(server2) {
|
|
|
8929
9138
|
text: z10.string().min(1).describe("The comment text."),
|
|
8930
9139
|
response_format: z10.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
8931
9140
|
},
|
|
9141
|
+
{
|
|
9142
|
+
title: "Post Comment",
|
|
9143
|
+
readOnlyHint: false,
|
|
9144
|
+
destructiveHint: false,
|
|
9145
|
+
idempotentHint: false,
|
|
9146
|
+
openWorldHint: true
|
|
9147
|
+
},
|
|
8932
9148
|
async ({ video_id, text, response_format }) => {
|
|
8933
9149
|
const format = response_format ?? "text";
|
|
8934
9150
|
const startedAt = Date.now();
|
|
@@ -9007,6 +9223,13 @@ function registerCommentsTools(server2) {
|
|
|
9007
9223
|
moderation_status: z10.enum(["published", "rejected"]).describe('"published" to approve, "rejected" to hide.'),
|
|
9008
9224
|
response_format: z10.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9009
9225
|
},
|
|
9226
|
+
{
|
|
9227
|
+
title: "Moderate Comment",
|
|
9228
|
+
readOnlyHint: false,
|
|
9229
|
+
destructiveHint: false,
|
|
9230
|
+
idempotentHint: true,
|
|
9231
|
+
openWorldHint: true
|
|
9232
|
+
},
|
|
9010
9233
|
async ({ comment_id, moderation_status, response_format }) => {
|
|
9011
9234
|
const format = response_format ?? "text";
|
|
9012
9235
|
const startedAt = Date.now();
|
|
@@ -9092,6 +9315,13 @@ function registerCommentsTools(server2) {
|
|
|
9092
9315
|
comment_id: z10.string().describe("The comment ID to delete."),
|
|
9093
9316
|
response_format: z10.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9094
9317
|
},
|
|
9318
|
+
{
|
|
9319
|
+
title: "Delete Comment",
|
|
9320
|
+
readOnlyHint: false,
|
|
9321
|
+
destructiveHint: true,
|
|
9322
|
+
idempotentHint: true,
|
|
9323
|
+
openWorldHint: true
|
|
9324
|
+
},
|
|
9095
9325
|
async ({ comment_id, response_format }) => {
|
|
9096
9326
|
const format = response_format ?? "text";
|
|
9097
9327
|
const startedAt = Date.now();
|
|
@@ -9241,12 +9471,19 @@ function asEnvelope7(data) {
|
|
|
9241
9471
|
function registerIdeationContextTools(server2) {
|
|
9242
9472
|
server2.tool(
|
|
9243
9473
|
"get_ideation_context",
|
|
9244
|
-
"
|
|
9474
|
+
"Load performance-derived context (top hooks, optimal timing, winning patterns) that should inform your next content generation. Call this before generate_content or plan_content_week to ground new content in what has actually performed well. Returns a promptInjection string ready to pass into generation tools.",
|
|
9245
9475
|
{
|
|
9246
9476
|
project_id: z11.string().uuid().optional().describe("Project ID to scope insights."),
|
|
9247
9477
|
days: z11.number().min(1).max(90).optional().describe("Lookback window for insights. Defaults to 30 days."),
|
|
9248
9478
|
response_format: z11.enum(["text", "json"]).optional().describe("Optional output format. Defaults to text.")
|
|
9249
9479
|
},
|
|
9480
|
+
{
|
|
9481
|
+
title: "Get Ideation Context",
|
|
9482
|
+
readOnlyHint: true,
|
|
9483
|
+
destructiveHint: false,
|
|
9484
|
+
idempotentHint: true,
|
|
9485
|
+
openWorldHint: false
|
|
9486
|
+
},
|
|
9250
9487
|
async ({ project_id, days, response_format }) => {
|
|
9251
9488
|
const supabase = getSupabaseClient();
|
|
9252
9489
|
const userId = await getDefaultUserId();
|
|
@@ -9377,6 +9614,13 @@ function registerCreditsTools(server2) {
|
|
|
9377
9614
|
{
|
|
9378
9615
|
response_format: z12.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9379
9616
|
},
|
|
9617
|
+
{
|
|
9618
|
+
title: "Get Credit Balance",
|
|
9619
|
+
readOnlyHint: true,
|
|
9620
|
+
destructiveHint: false,
|
|
9621
|
+
idempotentHint: true,
|
|
9622
|
+
openWorldHint: false
|
|
9623
|
+
},
|
|
9380
9624
|
async ({ response_format }) => {
|
|
9381
9625
|
const supabase = getSupabaseClient();
|
|
9382
9626
|
const userId = await getDefaultUserId();
|
|
@@ -9430,6 +9674,13 @@ Monthly used: ${payload.monthlyUsed}` + (payload.monthlyLimit ? ` / ${payload.mo
|
|
|
9430
9674
|
{
|
|
9431
9675
|
response_format: z12.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9432
9676
|
},
|
|
9677
|
+
{
|
|
9678
|
+
title: "Get Budget Status",
|
|
9679
|
+
readOnlyHint: true,
|
|
9680
|
+
destructiveHint: false,
|
|
9681
|
+
idempotentHint: true,
|
|
9682
|
+
openWorldHint: false
|
|
9683
|
+
},
|
|
9433
9684
|
async ({ response_format }) => {
|
|
9434
9685
|
const budget = getCurrentBudgetStatus();
|
|
9435
9686
|
const payload = {
|
|
@@ -9484,11 +9735,18 @@ function asEnvelope9(data) {
|
|
|
9484
9735
|
function registerLoopSummaryTools(server2) {
|
|
9485
9736
|
server2.tool(
|
|
9486
9737
|
"get_loop_summary",
|
|
9487
|
-
"Get a
|
|
9738
|
+
"Get a single-call health check of the content feedback loop: brand profile status, recent content, and active insights. Call at the start of a session to decide what to do next. The response includes a recommendedNextAction field that tells you which tool to call.",
|
|
9488
9739
|
{
|
|
9489
9740
|
project_id: z13.string().uuid().optional().describe("Project ID. Defaults to active project context."),
|
|
9490
9741
|
response_format: z13.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9491
9742
|
},
|
|
9743
|
+
{
|
|
9744
|
+
title: "Get Loop Summary",
|
|
9745
|
+
readOnlyHint: true,
|
|
9746
|
+
destructiveHint: false,
|
|
9747
|
+
idempotentHint: true,
|
|
9748
|
+
openWorldHint: false
|
|
9749
|
+
},
|
|
9492
9750
|
async ({ project_id, response_format }) => {
|
|
9493
9751
|
const supabase = getSupabaseClient();
|
|
9494
9752
|
const userId = await getDefaultUserId();
|
|
@@ -9587,6 +9845,13 @@ function registerUsageTools(server2) {
|
|
|
9587
9845
|
{
|
|
9588
9846
|
response_format: z14.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9589
9847
|
},
|
|
9848
|
+
{
|
|
9849
|
+
title: "Get MCP Usage",
|
|
9850
|
+
readOnlyHint: true,
|
|
9851
|
+
destructiveHint: false,
|
|
9852
|
+
idempotentHint: true,
|
|
9853
|
+
openWorldHint: false
|
|
9854
|
+
},
|
|
9590
9855
|
async ({ response_format }) => {
|
|
9591
9856
|
const format = response_format ?? "text";
|
|
9592
9857
|
const supabase = getSupabaseClient();
|
|
@@ -9677,6 +9942,13 @@ function registerAutopilotTools(server2) {
|
|
|
9677
9942
|
active_only: z15.boolean().optional().describe("If true, only return active configs. Defaults to false (show all)."),
|
|
9678
9943
|
response_format: z15.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9679
9944
|
},
|
|
9945
|
+
{
|
|
9946
|
+
title: "List Autopilot Configs",
|
|
9947
|
+
readOnlyHint: true,
|
|
9948
|
+
destructiveHint: false,
|
|
9949
|
+
idempotentHint: true,
|
|
9950
|
+
openWorldHint: false
|
|
9951
|
+
},
|
|
9680
9952
|
async ({ active_only, response_format }) => {
|
|
9681
9953
|
const format = response_format ?? "text";
|
|
9682
9954
|
const supabase = getSupabaseClient();
|
|
@@ -9754,11 +10026,18 @@ ${"=".repeat(40)}
|
|
|
9754
10026
|
{
|
|
9755
10027
|
config_id: z15.string().uuid().describe("The autopilot config ID to update."),
|
|
9756
10028
|
is_active: z15.boolean().optional().describe("Enable or disable this autopilot config."),
|
|
9757
|
-
schedule_days: z15.array(z15.enum(["mon", "tue", "wed", "thu", "fri", "sat", "sun"])).optional().describe('Days of the week to run (e.g
|
|
10029
|
+
schedule_days: z15.array(z15.enum(["mon", "tue", "wed", "thu", "fri", "sat", "sun"]).describe("Three-letter lowercase day abbreviation.")).optional().describe('Days of the week to run (e.g. ["mon", "wed", "fri"]).'),
|
|
9758
10030
|
schedule_time: z15.string().optional().describe('Time to run in HH:MM format (24h, user timezone). E.g., "09:00".'),
|
|
9759
10031
|
max_credits_per_run: z15.number().optional().describe("Maximum credits per execution."),
|
|
9760
10032
|
max_credits_per_week: z15.number().optional().describe("Maximum credits per week.")
|
|
9761
10033
|
},
|
|
10034
|
+
{
|
|
10035
|
+
title: "Update Autopilot Config",
|
|
10036
|
+
readOnlyHint: false,
|
|
10037
|
+
destructiveHint: false,
|
|
10038
|
+
idempotentHint: true,
|
|
10039
|
+
openWorldHint: false
|
|
10040
|
+
},
|
|
9762
10041
|
async ({
|
|
9763
10042
|
config_id,
|
|
9764
10043
|
is_active,
|
|
@@ -9822,6 +10101,13 @@ Schedule: ${JSON.stringify(updated.schedule_config)}`
|
|
|
9822
10101
|
{
|
|
9823
10102
|
response_format: z15.enum(["text", "json"]).optional().describe("Optional response format. Defaults to text.")
|
|
9824
10103
|
},
|
|
10104
|
+
{
|
|
10105
|
+
title: "Get Autopilot Status",
|
|
10106
|
+
readOnlyHint: true,
|
|
10107
|
+
destructiveHint: false,
|
|
10108
|
+
idempotentHint: true,
|
|
10109
|
+
openWorldHint: false
|
|
10110
|
+
},
|
|
9825
10111
|
async ({ response_format }) => {
|
|
9826
10112
|
const format = response_format ?? "text";
|
|
9827
10113
|
const supabase = getSupabaseClient();
|
|
@@ -9943,7 +10229,14 @@ function registerExtractionTools(server2) {
|
|
|
9943
10229
|
extract_type: z16.enum(["auto", "transcript", "article", "product"]).default("auto").describe("Type of extraction"),
|
|
9944
10230
|
include_comments: z16.boolean().default(false).describe("Include top comments (YouTube only)"),
|
|
9945
10231
|
max_results: z16.number().min(1).max(100).default(10).describe("Max comments to include"),
|
|
9946
|
-
response_format: z16.enum(["text", "json"]).default("text")
|
|
10232
|
+
response_format: z16.enum(["text", "json"]).default("text").describe("Response format. Defaults to text.")
|
|
10233
|
+
},
|
|
10234
|
+
{
|
|
10235
|
+
title: "Extract URL Content",
|
|
10236
|
+
readOnlyHint: true,
|
|
10237
|
+
destructiveHint: false,
|
|
10238
|
+
idempotentHint: true,
|
|
10239
|
+
openWorldHint: true
|
|
9947
10240
|
},
|
|
9948
10241
|
async ({
|
|
9949
10242
|
url,
|
|
@@ -10155,9 +10448,16 @@ function registerQualityTools(server2) {
|
|
|
10155
10448
|
).min(1).describe("Target platforms"),
|
|
10156
10449
|
threshold: z17.number().min(0).max(35).default(26).describe("Minimum total score to pass (max 35, scored across 7 categories at 0-5 each). Default 26 (~75%). Use 20 for rough drafts, 28+ for final posts going to large audiences."),
|
|
10157
10450
|
brand_keyword: z17.string().optional().describe("Brand keyword for alignment check"),
|
|
10158
|
-
brand_avoid_patterns: z17.array(z17.string()).optional(),
|
|
10159
|
-
custom_banned_terms: z17.array(z17.string()).optional(),
|
|
10160
|
-
response_format: z17.enum(["text", "json"]).default("text")
|
|
10451
|
+
brand_avoid_patterns: z17.array(z17.string()).optional().describe("Phrases the brand should never use (e.g. competitor names, off-brand slang). Matched case-insensitively."),
|
|
10452
|
+
custom_banned_terms: z17.array(z17.string()).optional().describe("Additional banned words beyond the built-in safety list. Useful for industry-specific compliance terms."),
|
|
10453
|
+
response_format: z17.enum(["text", "json"]).default("text").describe("'text' for human-readable report, 'json' for structured scores suitable for pipeline automation.")
|
|
10454
|
+
},
|
|
10455
|
+
{
|
|
10456
|
+
title: "Quality Check",
|
|
10457
|
+
readOnlyHint: true,
|
|
10458
|
+
destructiveHint: false,
|
|
10459
|
+
idempotentHint: true,
|
|
10460
|
+
openWorldHint: false
|
|
10161
10461
|
},
|
|
10162
10462
|
async ({
|
|
10163
10463
|
caption,
|
|
@@ -10229,15 +10529,22 @@ function registerQualityTools(server2) {
|
|
|
10229
10529
|
plan: z17.object({
|
|
10230
10530
|
posts: z17.array(
|
|
10231
10531
|
z17.object({
|
|
10232
|
-
id: z17.string(),
|
|
10233
|
-
caption: z17.string(),
|
|
10234
|
-
title: z17.string().optional(),
|
|
10235
|
-
platform: z17.string()
|
|
10532
|
+
id: z17.string().describe("Unique post identifier."),
|
|
10533
|
+
caption: z17.string().describe("Post caption/body text to quality-check."),
|
|
10534
|
+
title: z17.string().optional().describe("Post title (important for YouTube)."),
|
|
10535
|
+
platform: z17.string().describe("Target platform (e.g. instagram, youtube).")
|
|
10236
10536
|
})
|
|
10237
10537
|
)
|
|
10238
|
-
}).passthrough().describe("Content plan with posts array"),
|
|
10538
|
+
}).passthrough().describe("Content plan with posts array."),
|
|
10239
10539
|
threshold: z17.number().min(0).max(35).default(26).describe("Minimum total score to pass (max 35, scored across 7 categories at 0-5 each). Default 26 (~75%). Use 20 for rough drafts, 28+ for final posts going to large audiences."),
|
|
10240
|
-
response_format: z17.enum(["text", "json"]).default("text")
|
|
10540
|
+
response_format: z17.enum(["text", "json"]).default("text").describe("Response format. Defaults to text.")
|
|
10541
|
+
},
|
|
10542
|
+
{
|
|
10543
|
+
title: "Quality Check Plan",
|
|
10544
|
+
readOnlyHint: true,
|
|
10545
|
+
destructiveHint: false,
|
|
10546
|
+
idempotentHint: true,
|
|
10547
|
+
openWorldHint: false
|
|
10241
10548
|
},
|
|
10242
10549
|
async ({ plan, threshold, response_format }) => {
|
|
10243
10550
|
const startedAt = Date.now();
|
|
@@ -10440,7 +10747,14 @@ function registerPlanningTools(server2) {
|
|
|
10440
10747
|
start_date: z18.string().optional().describe("ISO date, defaults to tomorrow"),
|
|
10441
10748
|
brand_voice: z18.string().optional().describe("Override brand voice description"),
|
|
10442
10749
|
project_id: z18.string().optional().describe("Project ID for brand/insights context"),
|
|
10443
|
-
response_format: z18.enum(["text", "json"]).default("json")
|
|
10750
|
+
response_format: z18.enum(["text", "json"]).default("json").describe("Response format. Defaults to json.")
|
|
10751
|
+
},
|
|
10752
|
+
{
|
|
10753
|
+
title: "Plan Content Week",
|
|
10754
|
+
readOnlyHint: false,
|
|
10755
|
+
destructiveHint: false,
|
|
10756
|
+
idempotentHint: false,
|
|
10757
|
+
openWorldHint: true
|
|
10444
10758
|
},
|
|
10445
10759
|
async ({
|
|
10446
10760
|
topic,
|
|
@@ -10758,12 +11072,19 @@ ${rawText.slice(0, 1e3)}`
|
|
|
10758
11072
|
"Save a content plan to the database for team review, approval workflows, and scheduled publishing. Creates a plan_id you can reference in get_content_plan, update_content_plan, and schedule_content_plan.",
|
|
10759
11073
|
{
|
|
10760
11074
|
plan: z18.object({
|
|
10761
|
-
topic: z18.string(),
|
|
10762
|
-
posts: z18.array(z18.record(z18.string(), z18.unknown()))
|
|
10763
|
-
}).passthrough(),
|
|
10764
|
-
project_id: z18.string().uuid().optional(),
|
|
10765
|
-
status: z18.enum(["draft", "in_review", "approved", "scheduled", "completed"]).default("draft"),
|
|
10766
|
-
response_format: z18.enum(["text", "json"]).default("json")
|
|
11075
|
+
topic: z18.string().describe("Content plan topic or theme."),
|
|
11076
|
+
posts: z18.array(z18.record(z18.string(), z18.unknown())).describe("Array of post objects to save.")
|
|
11077
|
+
}).passthrough().describe("Content plan object with topic and posts array."),
|
|
11078
|
+
project_id: z18.string().uuid().optional().describe("Project ID. Defaults to active project context."),
|
|
11079
|
+
status: z18.enum(["draft", "in_review", "approved", "scheduled", "completed"]).default("draft").describe("Initial plan status. Defaults to draft."),
|
|
11080
|
+
response_format: z18.enum(["text", "json"]).default("json").describe("Response format. Defaults to json.")
|
|
11081
|
+
},
|
|
11082
|
+
{
|
|
11083
|
+
title: "Save Content Plan",
|
|
11084
|
+
readOnlyHint: false,
|
|
11085
|
+
destructiveHint: false,
|
|
11086
|
+
idempotentHint: false,
|
|
11087
|
+
openWorldHint: false
|
|
10767
11088
|
},
|
|
10768
11089
|
async ({ plan, project_id, status, response_format }) => {
|
|
10769
11090
|
const startedAt = Date.now();
|
|
@@ -10861,10 +11182,17 @@ ${rawText.slice(0, 1e3)}`
|
|
|
10861
11182
|
);
|
|
10862
11183
|
server2.tool(
|
|
10863
11184
|
"get_content_plan",
|
|
10864
|
-
"Retrieve a
|
|
11185
|
+
"Retrieve a saved content plan to review its posts, status, and applied insights. Use after plan_content_week or save_content_plan to inspect what was generated. Feed the result into update_content_plan to revise posts or submit_content_plan_for_approval to start the review workflow.",
|
|
10865
11186
|
{
|
|
10866
11187
|
plan_id: z18.string().uuid().describe("Persisted content plan ID"),
|
|
10867
|
-
response_format: z18.enum(["text", "json"]).default("json")
|
|
11188
|
+
response_format: z18.enum(["text", "json"]).default("json").describe("Response format. Defaults to json.")
|
|
11189
|
+
},
|
|
11190
|
+
{
|
|
11191
|
+
title: "Get Content Plan",
|
|
11192
|
+
readOnlyHint: true,
|
|
11193
|
+
destructiveHint: false,
|
|
11194
|
+
idempotentHint: true,
|
|
11195
|
+
openWorldHint: false
|
|
10868
11196
|
},
|
|
10869
11197
|
async ({ plan_id, response_format }) => {
|
|
10870
11198
|
const supabase = getSupabaseClient();
|
|
@@ -10929,25 +11257,32 @@ ${rawText.slice(0, 1e3)}`
|
|
|
10929
11257
|
);
|
|
10930
11258
|
server2.tool(
|
|
10931
11259
|
"update_content_plan",
|
|
10932
|
-
"
|
|
11260
|
+
"Revise specific posts in a saved content plan -- edit captions, hooks, hashtags, schedule times, or mark posts as approved/rejected. Call after reviewing a plan with get_content_plan. When all posts are approved, the plan status auto-advances so it can be scheduled.",
|
|
10933
11261
|
{
|
|
10934
|
-
plan_id: z18.string().uuid(),
|
|
11262
|
+
plan_id: z18.string().uuid().describe("Content plan ID to update."),
|
|
10935
11263
|
post_updates: z18.array(
|
|
10936
11264
|
z18.object({
|
|
10937
|
-
post_id: z18.string(),
|
|
10938
|
-
caption: z18.string().optional(),
|
|
10939
|
-
title: z18.string().optional(),
|
|
10940
|
-
hashtags: z18.array(z18.string()).optional(),
|
|
10941
|
-
hook: z18.string().optional(),
|
|
10942
|
-
angle: z18.string().optional(),
|
|
10943
|
-
visual_direction: z18.string().optional(),
|
|
10944
|
-
media_url: z18.string().optional(),
|
|
10945
|
-
schedule_at: z18.string().optional(),
|
|
10946
|
-
platform: z18.string().optional(),
|
|
10947
|
-
status: z18.enum(["approved", "rejected", "needs_edit"]).optional()
|
|
11265
|
+
post_id: z18.string().describe("ID of the post to update within this plan."),
|
|
11266
|
+
caption: z18.string().optional().describe("Revised caption/body text."),
|
|
11267
|
+
title: z18.string().optional().describe("Revised post title."),
|
|
11268
|
+
hashtags: z18.array(z18.string()).optional().describe("Revised hashtags array."),
|
|
11269
|
+
hook: z18.string().optional().describe("Revised attention-grabbing opening line."),
|
|
11270
|
+
angle: z18.string().optional().describe("Revised content angle or perspective."),
|
|
11271
|
+
visual_direction: z18.string().optional().describe("Revised visual/media direction notes."),
|
|
11272
|
+
media_url: z18.string().optional().describe("Revised media URL (public or R2 signed URL)."),
|
|
11273
|
+
schedule_at: z18.string().optional().describe("Revised ISO 8601 UTC publish datetime."),
|
|
11274
|
+
platform: z18.string().optional().describe("Revised target platform."),
|
|
11275
|
+
status: z18.enum(["approved", "rejected", "needs_edit"]).optional().describe("Review status for this post.")
|
|
10948
11276
|
})
|
|
10949
|
-
).min(1),
|
|
10950
|
-
response_format: z18.enum(["text", "json"]).default("json")
|
|
11277
|
+
).min(1).describe("Array of post-level updates to apply."),
|
|
11278
|
+
response_format: z18.enum(["text", "json"]).default("json").describe("Response format. Defaults to json.")
|
|
11279
|
+
},
|
|
11280
|
+
{
|
|
11281
|
+
title: "Update Content Plan",
|
|
11282
|
+
readOnlyHint: false,
|
|
11283
|
+
destructiveHint: false,
|
|
11284
|
+
idempotentHint: true,
|
|
11285
|
+
openWorldHint: false
|
|
10951
11286
|
},
|
|
10952
11287
|
async ({ plan_id, post_updates, response_format }) => {
|
|
10953
11288
|
const supabase = getSupabaseClient();
|
|
@@ -11048,10 +11383,17 @@ ${rawText.slice(0, 1e3)}`
|
|
|
11048
11383
|
);
|
|
11049
11384
|
server2.tool(
|
|
11050
11385
|
"submit_content_plan_for_approval",
|
|
11051
|
-
"
|
|
11386
|
+
"Submit an entire saved content plan for team review in one call -- creates approval items for every post and sets the plan to in_review status. Call after plan_content_week and any update_content_plan edits are done. Use list_plan_approvals to track reviewer decisions.",
|
|
11387
|
+
{
|
|
11388
|
+
plan_id: z18.string().uuid().describe("Content plan ID to submit for review."),
|
|
11389
|
+
response_format: z18.enum(["text", "json"]).default("json").describe("Response format. Defaults to json.")
|
|
11390
|
+
},
|
|
11052
11391
|
{
|
|
11053
|
-
|
|
11054
|
-
|
|
11392
|
+
title: "Submit Plan for Approval",
|
|
11393
|
+
readOnlyHint: false,
|
|
11394
|
+
destructiveHint: false,
|
|
11395
|
+
idempotentHint: true,
|
|
11396
|
+
openWorldHint: false
|
|
11055
11397
|
},
|
|
11056
11398
|
async ({ plan_id, response_format }) => {
|
|
11057
11399
|
const supabase = getSupabaseClient();
|
|
@@ -11176,21 +11518,28 @@ async function assertProjectAccess(supabase, userId, projectId) {
|
|
|
11176
11518
|
function registerPlanApprovalTools(server2) {
|
|
11177
11519
|
server2.tool(
|
|
11178
11520
|
"create_plan_approvals",
|
|
11179
|
-
"Create
|
|
11521
|
+
"Create individual approval items for posts you supply explicitly, useful when building a custom approval queue outside the standard plan workflow. Requires the post array as input. Use list_plan_approvals to check status afterward, and respond_plan_approval to approve or reject each item.",
|
|
11180
11522
|
{
|
|
11181
11523
|
plan_id: z19.string().uuid().describe("Content plan ID"),
|
|
11182
11524
|
posts: z19.array(
|
|
11183
11525
|
z19.object({
|
|
11184
|
-
id: z19.string(),
|
|
11185
|
-
platform: z19.string().optional(),
|
|
11186
|
-
caption: z19.string().optional(),
|
|
11187
|
-
title: z19.string().optional(),
|
|
11188
|
-
media_url: z19.string().optional(),
|
|
11189
|
-
schedule_at: z19.string().optional()
|
|
11526
|
+
id: z19.string().describe("Unique post identifier from the content plan."),
|
|
11527
|
+
platform: z19.string().optional().describe("Target platform (e.g. instagram, youtube)."),
|
|
11528
|
+
caption: z19.string().optional().describe("Post caption/body text."),
|
|
11529
|
+
title: z19.string().optional().describe("Post title, used by YouTube and LinkedIn articles."),
|
|
11530
|
+
media_url: z19.string().optional().describe("Public or R2 signed URL for the post media."),
|
|
11531
|
+
schedule_at: z19.string().optional().describe("ISO 8601 UTC datetime to publish (e.g. 2026-03-20T14:00:00Z).")
|
|
11190
11532
|
}).passthrough()
|
|
11191
11533
|
).min(1).describe("Posts to create approval entries for."),
|
|
11192
11534
|
project_id: z19.string().uuid().optional().describe("Project ID. Defaults to active project context."),
|
|
11193
|
-
response_format: z19.enum(["text", "json"]).optional()
|
|
11535
|
+
response_format: z19.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
11536
|
+
},
|
|
11537
|
+
{
|
|
11538
|
+
title: "Create Plan Approvals",
|
|
11539
|
+
readOnlyHint: false,
|
|
11540
|
+
destructiveHint: false,
|
|
11541
|
+
idempotentHint: false,
|
|
11542
|
+
openWorldHint: false
|
|
11194
11543
|
},
|
|
11195
11544
|
async ({ plan_id, posts, project_id, response_format }) => {
|
|
11196
11545
|
const supabase = getSupabaseClient();
|
|
@@ -11270,8 +11619,15 @@ function registerPlanApprovalTools(server2) {
|
|
|
11270
11619
|
"List MCP-native approval items for a specific content plan.",
|
|
11271
11620
|
{
|
|
11272
11621
|
plan_id: z19.string().uuid().describe("Content plan ID"),
|
|
11273
|
-
status: z19.enum(["pending", "approved", "rejected", "edited"]).optional(),
|
|
11274
|
-
response_format: z19.enum(["text", "json"]).optional()
|
|
11622
|
+
status: z19.enum(["pending", "approved", "rejected", "edited"]).optional().describe("Filter approvals by status. Omit to return all statuses."),
|
|
11623
|
+
response_format: z19.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
11624
|
+
},
|
|
11625
|
+
{
|
|
11626
|
+
title: "List Plan Approvals",
|
|
11627
|
+
readOnlyHint: true,
|
|
11628
|
+
destructiveHint: false,
|
|
11629
|
+
idempotentHint: true,
|
|
11630
|
+
openWorldHint: false
|
|
11275
11631
|
},
|
|
11276
11632
|
async ({ plan_id, status, response_format }) => {
|
|
11277
11633
|
const supabase = getSupabaseClient();
|
|
@@ -11338,10 +11694,19 @@ function registerPlanApprovalTools(server2) {
|
|
|
11338
11694
|
"Approve, reject, or edit a pending plan approval item.",
|
|
11339
11695
|
{
|
|
11340
11696
|
approval_id: z19.string().uuid().describe("Approval item ID"),
|
|
11341
|
-
decision: z19.enum(["approved", "rejected", "edited"]),
|
|
11342
|
-
edited_post: z19.record(z19.string(), z19.unknown()).optional()
|
|
11343
|
-
|
|
11344
|
-
|
|
11697
|
+
decision: z19.enum(["approved", "rejected", "edited"]).describe("Approval decision for this post."),
|
|
11698
|
+
edited_post: z19.record(z19.string(), z19.unknown()).optional().describe(
|
|
11699
|
+
'Revised post fields when decision is "edited" (e.g. {caption: "...", hashtags: [...]}).'
|
|
11700
|
+
),
|
|
11701
|
+
reason: z19.string().max(1e3).optional().describe("Optional reason for the decision, visible to the plan author."),
|
|
11702
|
+
response_format: z19.enum(["text", "json"]).optional().describe("Response format. Defaults to text.")
|
|
11703
|
+
},
|
|
11704
|
+
{
|
|
11705
|
+
title: "Respond to Plan Approval",
|
|
11706
|
+
readOnlyHint: false,
|
|
11707
|
+
destructiveHint: false,
|
|
11708
|
+
idempotentHint: true,
|
|
11709
|
+
openWorldHint: false
|
|
11345
11710
|
},
|
|
11346
11711
|
async ({ approval_id, decision, edited_post, reason, response_format }) => {
|
|
11347
11712
|
const supabase = getSupabaseClient();
|
|
@@ -11429,6 +11794,13 @@ function registerDiscoveryTools(server2) {
|
|
|
11429
11794
|
'Detail level: "name" for just tool names, "summary" for names + descriptions, "full" for complete info including scope and module'
|
|
11430
11795
|
)
|
|
11431
11796
|
},
|
|
11797
|
+
{
|
|
11798
|
+
title: "Search Tools",
|
|
11799
|
+
readOnlyHint: true,
|
|
11800
|
+
destructiveHint: false,
|
|
11801
|
+
idempotentHint: true,
|
|
11802
|
+
openWorldHint: false
|
|
11803
|
+
},
|
|
11432
11804
|
async ({ query, module, scope, detail }) => {
|
|
11433
11805
|
let results = [...TOOL_CATALOG];
|
|
11434
11806
|
if (query) {
|