@jclvsh/dropspace 2.6.0 → 2.7.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/README.md +49 -3
- package/dist/cli.js +2 -0
- package/dist/commands/autopilot.d.ts +3 -0
- package/dist/commands/autopilot.js +169 -0
- package/dist/index.js +2 -0
- package/dist/tools/autopilot.d.ts +3 -0
- package/dist/tools/autopilot.js +123 -0
- package/dist/types.d.ts +49 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jclvsh/dropspace
|
|
2
2
|
|
|
3
|
-
MCP server and CLI for the [Dropspace](https://www.dropspace.dev) API. Lets AI agents (Claude Code, Cursor) and humans manage launches, personas, platform connections, API keys, and webhooks.
|
|
3
|
+
MCP server and CLI for the [Dropspace](https://www.dropspace.dev) API. Lets AI agents (Claude Code, Cursor) and humans manage launches, personas, media generation, boosts, autopilot, platform connections, API keys, and webhooks. 54 tools across 12 categories.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -46,11 +46,15 @@ dropspace launches --help
|
|
|
46
46
|
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
|
47
47
|
| launches | list, create, get, update, delete, publish, retry, generate, retry-content, analytics, batch-analytics, status, delete-post, delete-posts | 14 |
|
|
48
48
|
| personas | list, create, get, update, delete, analyze | 6 |
|
|
49
|
+
| media | generate, job | 2 |
|
|
49
50
|
| connections | list | 1 |
|
|
50
|
-
|
|
|
51
|
-
|
|
|
51
|
+
| boosts | create, list, get, activate, cancel, performance | 6 |
|
|
52
|
+
| credits | balance, purchase | 2 |
|
|
53
|
+
| keys | me, list, create, rename, revoke, rotate | 6 |
|
|
54
|
+
| webhooks | list, create, get, update, delete, test, rotate-secret, deliveries | 8 |
|
|
52
55
|
| status | dropspace official account connections | 1 |
|
|
53
56
|
| usage | plan, limits, and billing period | 1 |
|
|
57
|
+
| autopilot | status, configure, review, approve, reject, run, runs | 7 |
|
|
54
58
|
|
|
55
59
|
## MCP Server Configuration
|
|
56
60
|
|
|
@@ -115,6 +119,7 @@ Add to your `.cursor/mcp.json`:
|
|
|
115
119
|
| `generate_content` | Generate AI content and video scripts for a launch |
|
|
116
120
|
| `retry_launch_content` | Retry AI content generation for failed platforms |
|
|
117
121
|
| `get_launch_analytics` | Get publishing analytics with per-post engagement metrics |
|
|
122
|
+
| `get_batch_launch_analytics` | Get analytics for multiple launches in one call |
|
|
118
123
|
| `get_launch_status` | Get detailed posting status with per-platform logs |
|
|
119
124
|
|
|
120
125
|
#### `create_launch` Parameters
|
|
@@ -194,12 +199,37 @@ Add to your `.cursor/mcp.json`:
|
|
|
194
199
|
| `tiktok_samples` | array | No | TikTok writing samples (max 50) |
|
|
195
200
|
| `linkedin_samples` | array | No | LinkedIn writing samples (max 50) |
|
|
196
201
|
|
|
202
|
+
### Media
|
|
203
|
+
|
|
204
|
+
| Tool | Description |
|
|
205
|
+
| ---------------- | ---------------------------------------------------------------------------- |
|
|
206
|
+
| `generate_media` | Submit an AI image or video generation job for a launch (returns a job ID) |
|
|
207
|
+
| `get_media_job` | Poll a media generation job's status; returns the result URL when complete |
|
|
208
|
+
|
|
197
209
|
### Connections
|
|
198
210
|
|
|
199
211
|
| Tool | Description |
|
|
200
212
|
| ------------------ | ----------------------------------------- |
|
|
201
213
|
| `list_connections` | List your connected social media accounts |
|
|
202
214
|
|
|
215
|
+
### Boosts
|
|
216
|
+
|
|
217
|
+
| Tool | Description |
|
|
218
|
+
| ----------------------- | ------------------------------------------------------------------------ |
|
|
219
|
+
| `create_boost` | Create a paid Meta boost on an organic Facebook/Instagram launch (paused) |
|
|
220
|
+
| `list_boosts` | List all boosts attached to a launch |
|
|
221
|
+
| `get_boost` | Get a boost by ID with current performance metrics |
|
|
222
|
+
| `activate_boost` | Activate a paused boost — ad spend begins immediately |
|
|
223
|
+
| `cancel_boost` | Cancel a boost (deletes the Meta campaign, irreversible) |
|
|
224
|
+
| `get_boost_performance` | Fetch latest boost metrics (impressions, clicks, reach, spend) |
|
|
225
|
+
|
|
226
|
+
### Credits
|
|
227
|
+
|
|
228
|
+
| Tool | Description |
|
|
229
|
+
| ---------------------- | ------------------------------------------------------------ |
|
|
230
|
+
| `get_credit_balance` | Get MPP credit balance and available packs (agent payments) |
|
|
231
|
+
| `purchase_credit_pack` | Purchase a credit pack via MPP (Stripe-based agent payments) |
|
|
232
|
+
|
|
203
233
|
### Posts
|
|
204
234
|
|
|
205
235
|
| Tool | Description |
|
|
@@ -216,6 +246,7 @@ Add to your `.cursor/mcp.json`:
|
|
|
216
246
|
| `create_api_key` | Create a new API key (raw key returned once) |
|
|
217
247
|
| `rename_api_key` | Rename an API key |
|
|
218
248
|
| `revoke_api_key` | Permanently revoke an API key |
|
|
249
|
+
| `rotate_api_key` | Rotate an API key (new raw key returned once) |
|
|
219
250
|
|
|
220
251
|
#### `create_api_key` Parameters
|
|
221
252
|
|
|
@@ -233,6 +264,7 @@ Add to your `.cursor/mcp.json`:
|
|
|
233
264
|
| `get_webhook` | Get a webhook by ID |
|
|
234
265
|
| `update_webhook` | Update a webhook's URL, events, or active status |
|
|
235
266
|
| `delete_webhook` | Delete a webhook |
|
|
267
|
+
| `test_webhook` | Send a test delivery to a webhook endpoint |
|
|
236
268
|
| `rotate_webhook_secret` | Rotate a webhook's signing secret (new secret returned once) |
|
|
237
269
|
| `list_webhook_deliveries` | List delivery attempts for a webhook |
|
|
238
270
|
|
|
@@ -264,6 +296,20 @@ Add to your `.cursor/mcp.json`:
|
|
|
264
296
|
| ----------- | ------------------------------------------------------- |
|
|
265
297
|
| `get_usage` | Get your current plan, usage limits, and billing period |
|
|
266
298
|
|
|
299
|
+
### Autopilot
|
|
300
|
+
|
|
301
|
+
| Tool | Description |
|
|
302
|
+
| ------------------------- | -------------------------------------------------------------------------- |
|
|
303
|
+
| `get_autopilot` | Get autopilot status: config, queued ideas, drafts pending review |
|
|
304
|
+
| `configure_autopilot` | Create or update the autopilot config (merge semantics) |
|
|
305
|
+
| `list_autopilot_review` | List autopilot drafts awaiting approval (review mode) |
|
|
306
|
+
| `approve_autopilot_draft` | Approve a draft — schedules it for publishing |
|
|
307
|
+
| `reject_autopilot_draft` | Reject a draft — deletes it, refunds the launch slot, learns from feedback |
|
|
308
|
+
| `run_autopilot_now` | Trigger a manual autopilot run immediately (2 per hour) |
|
|
309
|
+
| `list_autopilot_runs` | Recent run history with per-step stats and errors |
|
|
310
|
+
|
|
311
|
+
Autopilot is available on pro and premium plans.
|
|
312
|
+
|
|
267
313
|
## API Key & Scopes
|
|
268
314
|
|
|
269
315
|
Generate an API key at [www.dropspace.dev/settings](https://www.dropspace.dev/settings) under the API section.
|
package/dist/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ import { registerUsageCommands } from "./commands/usage.js";
|
|
|
14
14
|
import { registerCreditCommands } from "./commands/credits.js";
|
|
15
15
|
import { registerMediaCommands } from "./commands/media.js";
|
|
16
16
|
import { registerBoostCommands } from "./commands/boosts.js";
|
|
17
|
+
import { registerAutopilotCommands } from "./commands/autopilot.js";
|
|
17
18
|
const program = new Command()
|
|
18
19
|
.name("dropspace")
|
|
19
20
|
.description("dropspace CLI - manage launches, personas, boosts, and more")
|
|
@@ -32,6 +33,7 @@ try {
|
|
|
32
33
|
registerCreditCommands(program, client);
|
|
33
34
|
registerMediaCommands(program, client);
|
|
34
35
|
registerBoostCommands(program, client);
|
|
36
|
+
registerAutopilotCommands(program, client);
|
|
35
37
|
await program.parseAsync(process.argv);
|
|
36
38
|
}
|
|
37
39
|
catch (error) {
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { formatOutput, handleError, getFormat } from "../cli-utils.js";
|
|
2
|
+
export function registerAutopilotCommands(program, client) {
|
|
3
|
+
const autopilot = program
|
|
4
|
+
.command("autopilot")
|
|
5
|
+
.alias("ap")
|
|
6
|
+
.description("autonomous content engine (pro/premium plans)");
|
|
7
|
+
autopilot
|
|
8
|
+
.command("status")
|
|
9
|
+
.description("show autopilot config, queued ideas, and pending review count")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
try {
|
|
12
|
+
const result = await client.get("/autopilot");
|
|
13
|
+
formatOutput(result, getFormat(program.opts()));
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
handleError(error);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
autopilot
|
|
20
|
+
.command("configure")
|
|
21
|
+
.description("create or update the autopilot config (only the flags you pass change)")
|
|
22
|
+
.option("--enabled", "turn nightly runs on")
|
|
23
|
+
.option("--disabled", "turn nightly runs off")
|
|
24
|
+
.option("--mode <mode>", "review | auto")
|
|
25
|
+
.option("--platforms <list>", "comma-separated platforms: facebook,linkedin,twitter,reddit,instagram,tiktok,youtube")
|
|
26
|
+
.option("--formats <list>", "comma-separated formats: text,visual,video")
|
|
27
|
+
.option("--persona <id>", 'persona uuid for voice (use "none" to clear)')
|
|
28
|
+
.option("--times <list>", "comma-separated posting times HH:MM (config timezone)")
|
|
29
|
+
.option("--days <list>", "comma-separated days of week 0-6 (0 = sunday)")
|
|
30
|
+
.option("--run-hour <n>", "local hour the nightly run fires (0-23)")
|
|
31
|
+
.option("--timezone <tz>", "IANA timezone, e.g. America/New_York")
|
|
32
|
+
.option("--product-url <url>", "product link included in posts")
|
|
33
|
+
.option("--brief <text>", "product brief (what you're building, who it's for)")
|
|
34
|
+
.option("--pillars <list>", "comma-separated content pillars")
|
|
35
|
+
.option("--min-queue <n>", "ideas to keep queued (1-30)")
|
|
36
|
+
.option("--max-posts <n>", "daily posting cap (1-10)")
|
|
37
|
+
.action(async (opts) => {
|
|
38
|
+
try {
|
|
39
|
+
const body = {};
|
|
40
|
+
if (opts.enabled)
|
|
41
|
+
body.enabled = true;
|
|
42
|
+
if (opts.disabled)
|
|
43
|
+
body.enabled = false;
|
|
44
|
+
if (opts.mode)
|
|
45
|
+
body.mode = opts.mode;
|
|
46
|
+
if (opts.platforms)
|
|
47
|
+
body.platforms = String(opts.platforms)
|
|
48
|
+
.split(",")
|
|
49
|
+
.map((p) => p.trim());
|
|
50
|
+
if (opts.formats)
|
|
51
|
+
body.formats = String(opts.formats)
|
|
52
|
+
.split(",")
|
|
53
|
+
.map((f) => f.trim());
|
|
54
|
+
if (opts.persona)
|
|
55
|
+
body.persona_id = opts.persona === "none" ? null : opts.persona;
|
|
56
|
+
if (opts.times || opts.days) {
|
|
57
|
+
body.posting_times = {
|
|
58
|
+
...(opts.times
|
|
59
|
+
? {
|
|
60
|
+
times: String(opts.times)
|
|
61
|
+
.split(",")
|
|
62
|
+
.map((t) => t.trim()),
|
|
63
|
+
}
|
|
64
|
+
: {}),
|
|
65
|
+
...(opts.days
|
|
66
|
+
? {
|
|
67
|
+
days: String(opts.days)
|
|
68
|
+
.split(",")
|
|
69
|
+
.map((d) => parseInt(d.trim(), 10)),
|
|
70
|
+
}
|
|
71
|
+
: {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (opts.runHour !== undefined)
|
|
75
|
+
body.run_hour = parseInt(opts.runHour, 10);
|
|
76
|
+
if (opts.timezone)
|
|
77
|
+
body.timezone = opts.timezone;
|
|
78
|
+
if (opts.productUrl)
|
|
79
|
+
body.product_url = opts.productUrl;
|
|
80
|
+
if (opts.brief)
|
|
81
|
+
body.product_brief = opts.brief;
|
|
82
|
+
if (opts.pillars)
|
|
83
|
+
body.content_pillars = String(opts.pillars)
|
|
84
|
+
.split(",")
|
|
85
|
+
.map((p) => p.trim());
|
|
86
|
+
if (opts.minQueue !== undefined)
|
|
87
|
+
body.min_queue = parseInt(opts.minQueue, 10);
|
|
88
|
+
if (opts.maxPosts !== undefined)
|
|
89
|
+
body.max_posts_per_day = parseInt(opts.maxPosts, 10);
|
|
90
|
+
const result = await client.patch("/autopilot", body);
|
|
91
|
+
formatOutput(result, getFormat(program.opts()));
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
handleError(error);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
autopilot
|
|
98
|
+
.command("review")
|
|
99
|
+
.description("list drafts awaiting approval")
|
|
100
|
+
.option("-p, --page <n>", "page number", "1")
|
|
101
|
+
.option("-s, --page-size <n>", "items per page (max 50)", "20")
|
|
102
|
+
.action(async (opts) => {
|
|
103
|
+
try {
|
|
104
|
+
const params = {};
|
|
105
|
+
if (opts.page)
|
|
106
|
+
params.page = opts.page;
|
|
107
|
+
if (opts.pageSize)
|
|
108
|
+
params.page_size = opts.pageSize;
|
|
109
|
+
const result = await client.get("/autopilot/review", params);
|
|
110
|
+
formatOutput(result, getFormat(program.opts()));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
handleError(error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
autopilot
|
|
117
|
+
.command("approve <launchId>")
|
|
118
|
+
.description("approve a draft - schedules it for publishing")
|
|
119
|
+
.action(async (launchId) => {
|
|
120
|
+
try {
|
|
121
|
+
const result = await client.post(`/autopilot/review/${launchId}/approve`);
|
|
122
|
+
formatOutput(result, getFormat(program.opts()));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
handleError(error);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
autopilot
|
|
129
|
+
.command("reject <launchId>")
|
|
130
|
+
.description("reject a draft - deletes it and refunds the launch slot")
|
|
131
|
+
.option("-f, --feedback <text>", "what to avoid next time (max 500 chars)")
|
|
132
|
+
.action(async (launchId, opts) => {
|
|
133
|
+
try {
|
|
134
|
+
const result = await client.post(`/autopilot/review/${launchId}/reject`, opts.feedback ? { feedback: opts.feedback } : {});
|
|
135
|
+
formatOutput(result, getFormat(program.opts()));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
handleError(error);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
autopilot
|
|
142
|
+
.command("run")
|
|
143
|
+
.description("trigger a manual run now (limited to 2 per hour)")
|
|
144
|
+
.action(async () => {
|
|
145
|
+
try {
|
|
146
|
+
const result = await client.post("/autopilot/run");
|
|
147
|
+
formatOutput(result, getFormat(program.opts()));
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
handleError(error);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
autopilot
|
|
154
|
+
.command("runs")
|
|
155
|
+
.description("recent run history")
|
|
156
|
+
.option("-l, --limit <n>", "rows to return (max 30)", "9")
|
|
157
|
+
.action(async (opts) => {
|
|
158
|
+
try {
|
|
159
|
+
const params = {};
|
|
160
|
+
if (opts.limit)
|
|
161
|
+
params.limit = opts.limit;
|
|
162
|
+
const result = await client.get("/autopilot/runs", params);
|
|
163
|
+
formatOutput(result, getFormat(program.opts()));
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
handleError(error);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { registerUsageTools } from "./tools/usage.js";
|
|
|
12
12
|
import { registerCreditTools } from "./tools/credits.js";
|
|
13
13
|
import { registerMediaTools } from "./tools/media.js";
|
|
14
14
|
import { registerBoostTools } from "./tools/boosts.js";
|
|
15
|
+
import { registerAutopilotTools } from "./tools/autopilot.js";
|
|
15
16
|
const server = new McpServer({
|
|
16
17
|
name: "dropspace",
|
|
17
18
|
version: "2.5.0",
|
|
@@ -27,5 +28,6 @@ registerUsageTools(server, client);
|
|
|
27
28
|
registerCreditTools(server, client);
|
|
28
29
|
registerMediaTools(server, client);
|
|
29
30
|
registerBoostTools(server, client);
|
|
31
|
+
registerAutopilotTools(server, client);
|
|
30
32
|
const transport = new StdioServerTransport();
|
|
31
33
|
await server.connect(transport);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const AUTO_POST_PLATFORMS = ["facebook", "linkedin", "twitter", "reddit", "instagram", "tiktok", "youtube"];
|
|
3
|
+
function ok(result) {
|
|
4
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
5
|
+
}
|
|
6
|
+
function err(error) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: "text", text: `error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
9
|
+
isError: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function registerAutopilotTools(server, client) {
|
|
13
|
+
server.tool("get_autopilot", "get autopilot status: config, queued ideas, and drafts pending review. autopilot is the autonomous content engine that drafts and schedules posts nightly (pro/premium plans).", {}, async () => {
|
|
14
|
+
try {
|
|
15
|
+
return ok(await client.get("/autopilot"));
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return err(error);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
server.tool("configure_autopilot", "create or update the autopilot config. merge semantics: only the fields you send change. enabling requires at least one platform with a connected account.", {
|
|
22
|
+
enabled: z.boolean().optional().describe("turn nightly runs on/off"),
|
|
23
|
+
mode: z
|
|
24
|
+
.enum(["review", "auto"])
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("review = drafts wait for approval; auto = publishes on schedule"),
|
|
27
|
+
platforms: z
|
|
28
|
+
.array(z.enum(AUTO_POST_PLATFORMS))
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("platforms to post on (must have connected accounts)"),
|
|
31
|
+
formats: z
|
|
32
|
+
.array(z.enum(["text", "visual", "video"]))
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("content formats the engine may produce"),
|
|
35
|
+
persona_id: z.string().nullable().optional().describe("voice persona uuid (null to clear)"),
|
|
36
|
+
posting_times: z
|
|
37
|
+
.object({
|
|
38
|
+
times: z.array(z.string()).describe('posting times as "HH:MM" in the config timezone'),
|
|
39
|
+
days: z.array(z.number().int().min(0).max(6)).describe("days of week (0 = sunday)"),
|
|
40
|
+
})
|
|
41
|
+
.optional(),
|
|
42
|
+
run_hour: z.number().int().min(0).max(23).optional().describe("local hour the nightly run fires"),
|
|
43
|
+
timezone: z.string().optional().describe("IANA timezone, e.g. America/New_York"),
|
|
44
|
+
product_url: z.string().nullable().optional().describe("product link included in posts"),
|
|
45
|
+
product_brief: z
|
|
46
|
+
.string()
|
|
47
|
+
.nullable()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("what you're building, who it's for (max 2000 chars)"),
|
|
50
|
+
content_pillars: z
|
|
51
|
+
.array(z.string())
|
|
52
|
+
.nullable()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("themes the engine rotates across (max 10)"),
|
|
55
|
+
min_queue: z.number().int().min(1).max(30).optional().describe("ideas to keep queued"),
|
|
56
|
+
max_posts_per_day: z.number().int().min(1).max(10).optional().describe("daily posting cap"),
|
|
57
|
+
}, async (input) => {
|
|
58
|
+
try {
|
|
59
|
+
return ok(await client.patch("/autopilot", input));
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return err(error);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
server.tool("list_autopilot_review", "list autopilot drafts awaiting approval (review mode). each item is a draft launch - approve, reject, or edit it via update_launch first.", {
|
|
66
|
+
page: z.number().int().positive().optional().describe("page number (default: 1)"),
|
|
67
|
+
page_size: z.number().int().min(1).max(50).optional().describe("items per page (default: 20, max: 50)"),
|
|
68
|
+
}, async ({ page, page_size }) => {
|
|
69
|
+
try {
|
|
70
|
+
const params = {};
|
|
71
|
+
if (page !== undefined)
|
|
72
|
+
params.page = String(page);
|
|
73
|
+
if (page_size !== undefined)
|
|
74
|
+
params.page_size = String(page_size);
|
|
75
|
+
return ok(await client.get("/autopilot/review", params));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return err(error);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
server.tool("approve_autopilot_draft", "approve an autopilot draft - schedules it for publishing (a stale scheduled date rolls forward to the next posting slot).", {
|
|
82
|
+
launch_id: z.string().describe("the draft launch id from list_autopilot_review"),
|
|
83
|
+
}, async ({ launch_id }) => {
|
|
84
|
+
try {
|
|
85
|
+
return ok(await client.post(`/autopilot/review/${launch_id}/approve`));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return err(error);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
server.tool("reject_autopilot_draft", "reject an autopilot draft - deletes it and refunds the launch slot. optional feedback teaches future runs what to avoid.", {
|
|
92
|
+
launch_id: z.string().describe("the draft launch id from list_autopilot_review"),
|
|
93
|
+
feedback: z.string().max(500).optional().describe("why this doesn't work (feeds future generation)"),
|
|
94
|
+
}, async ({ launch_id, feedback }) => {
|
|
95
|
+
try {
|
|
96
|
+
return ok(await client.post(`/autopilot/review/${launch_id}/reject`, feedback ? { feedback } : {}));
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return err(error);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
server.tool("run_autopilot_now", "trigger a manual autopilot run immediately instead of waiting for the nightly run. steps already completed today are skipped (limited to 2 per hour).", {}, async () => {
|
|
103
|
+
try {
|
|
104
|
+
return ok(await client.post("/autopilot/run"));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return err(error);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.tool("list_autopilot_runs", "recent autopilot run history - one row per run step (refresh_insights, generate_blueprints, schedule_slots) with stats and errors.", {
|
|
111
|
+
limit: z.number().int().min(1).max(30).optional().describe("rows to return (default: 9)"),
|
|
112
|
+
}, async ({ limit }) => {
|
|
113
|
+
try {
|
|
114
|
+
const params = {};
|
|
115
|
+
if (limit !== undefined)
|
|
116
|
+
params.limit = String(limit);
|
|
117
|
+
return ok(await client.get("/autopilot/runs", params));
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
return err(error);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -341,3 +341,52 @@ export interface Boost {
|
|
|
341
341
|
ended_at: string | null;
|
|
342
342
|
last_synced_at: string | null;
|
|
343
343
|
}
|
|
344
|
+
export interface AutopilotPostingTimes {
|
|
345
|
+
times: string[];
|
|
346
|
+
days: number[];
|
|
347
|
+
}
|
|
348
|
+
export interface AutopilotConfig {
|
|
349
|
+
enabled: boolean;
|
|
350
|
+
mode: "review" | "auto";
|
|
351
|
+
platforms: string[];
|
|
352
|
+
formats: string[];
|
|
353
|
+
persona_id: string | null;
|
|
354
|
+
posting_times: AutopilotPostingTimes;
|
|
355
|
+
run_hour: number;
|
|
356
|
+
timezone: string;
|
|
357
|
+
product_url: string | null;
|
|
358
|
+
product_brief: string | null;
|
|
359
|
+
content_pillars: string[] | null;
|
|
360
|
+
min_queue: number;
|
|
361
|
+
max_posts_per_day: number;
|
|
362
|
+
paused: boolean;
|
|
363
|
+
pause_reason: string | null;
|
|
364
|
+
created_at: string;
|
|
365
|
+
updated_at: string;
|
|
366
|
+
}
|
|
367
|
+
export interface AutopilotStatus {
|
|
368
|
+
configured: boolean;
|
|
369
|
+
config: AutopilotConfig | null;
|
|
370
|
+
queued_ideas: number;
|
|
371
|
+
pending_review: number;
|
|
372
|
+
}
|
|
373
|
+
export interface AutopilotReviewItem {
|
|
374
|
+
launch_id: string;
|
|
375
|
+
hook: string;
|
|
376
|
+
platform: string;
|
|
377
|
+
format: string;
|
|
378
|
+
content: string | null;
|
|
379
|
+
reddit_title: string | null;
|
|
380
|
+
scheduled_date: string | null;
|
|
381
|
+
media_count: number;
|
|
382
|
+
created_at: string;
|
|
383
|
+
}
|
|
384
|
+
export interface AutopilotRun {
|
|
385
|
+
run_date: string;
|
|
386
|
+
step: string;
|
|
387
|
+
status: string;
|
|
388
|
+
stats: Record<string, unknown>;
|
|
389
|
+
error: string | null;
|
|
390
|
+
started_at: string;
|
|
391
|
+
completed_at: string | null;
|
|
392
|
+
}
|