posterly-mcp-server 0.46.0 → 0.47.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 +4 -3
- package/dist/lib/api-client.d.ts +28 -1
- package/dist/lib/api-client.js +12 -2
- package/dist/lib/version.d.ts +1 -1
- package/dist/lib/version.js +1 -1
- package/dist/tools/create-post.d.ts +882 -6
- package/dist/tools/create-post.js +49 -1
- package/dist/tools/create-posts-batch.d.ts +318 -4
- package/dist/tools/delete-post.d.ts +4 -0
- package/dist/tools/delete-post.js +10 -5
- package/dist/tools/list-analytics.js +4 -1
- package/dist/tools/list-posts.d.ts +4 -0
- package/dist/tools/list-posts.js +5 -1
- package/dist/tools/update-post.d.ts +414 -2
- package/dist/tools/update-post.js +63 -1
- package/dist/tools/validate-post.d.ts +480 -4
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/lib/api-client.ts +41 -2
- package/src/lib/version.ts +1 -1
- package/src/tools/create-post.ts +47 -1
- package/src/tools/delete-post.ts +16 -7
- package/src/tools/list-analytics.ts +4 -1
- package/src/tools/list-posts.ts +6 -1
- package/src/tools/update-post.ts +82 -1
- package/tool-registry.json +40 -0
|
@@ -29,6 +29,31 @@ const instagramSettingsSchema = z.object({
|
|
|
29
29
|
reel_thumb_offset: z.number().nonnegative().optional(),
|
|
30
30
|
is_ai_generated: z.boolean().optional().describe('Label the parent Instagram media container as AI-generated. For carousels, set on the parent only.'),
|
|
31
31
|
audio_id: z.string().optional().describe('Licensed Instagram audio ID for Reels. Meta-linked Facebook Login accounts only.'),
|
|
32
|
+
caption_addon: z.union([
|
|
33
|
+
z.object({
|
|
34
|
+
type: z.enum(['none', 'poll', 'comment_prompt']).optional(),
|
|
35
|
+
kind: z.enum(['none', 'poll', 'comment_prompt']).optional(),
|
|
36
|
+
options: z.array(z.string()).max(4).optional(),
|
|
37
|
+
extended_duration: z.boolean().optional(),
|
|
38
|
+
poll_attachment: z.object({
|
|
39
|
+
option_a: z.string().optional(),
|
|
40
|
+
option_b: z.string().optional(),
|
|
41
|
+
option_c: z.string().optional(),
|
|
42
|
+
option_d: z.string().optional(),
|
|
43
|
+
options: z.array(z.string()).max(4).optional(),
|
|
44
|
+
}).optional(),
|
|
45
|
+
}),
|
|
46
|
+
z.null(),
|
|
47
|
+
]).optional().describe('Optional Instagram caption add-on. type is none, poll, or comment_prompt. A poll needs 2 to 4 options of 1 to 25 characters (an emoji counts as one) and the caption is the question. A comment prompt uses the caption as the prompt. Facebook Login only. Not available on Stories. At most one add-on per post. Pass null or type none to clear it.'),
|
|
48
|
+
poll_attachment: z.object({
|
|
49
|
+
option_a: z.string().optional(),
|
|
50
|
+
option_b: z.string().optional(),
|
|
51
|
+
option_c: z.string().optional(),
|
|
52
|
+
option_d: z.string().optional(),
|
|
53
|
+
options: z.array(z.string()).max(4).optional(),
|
|
54
|
+
}).optional().describe('Instagram poll choices. option_a and option_b are required, option_c and option_d are optional, and option_d requires option_c. Mutually exclusive with a comment prompt. The caption is the question. Serialised JSON must be 200 characters or fewer.'),
|
|
55
|
+
is_comment_prompt_used: z.boolean().optional().describe('Set true to attach an Instagram comment prompt. The caption is the prompt. Mutually exclusive with a poll. Facebook Login only. Not available on Stories.'),
|
|
56
|
+
is_poll_duration_extended: z.boolean().optional().describe('Set true only together with a poll, to request the longer Instagram poll duration.'),
|
|
32
57
|
});
|
|
33
58
|
const platformSettingsSchema = z.object({
|
|
34
59
|
__type: z.string().optional(),
|
|
@@ -104,11 +129,22 @@ const platformSettingsSchema = z.object({
|
|
|
104
129
|
paid_partnership: z.boolean().optional(),
|
|
105
130
|
is_ai_generated: z.boolean().optional(),
|
|
106
131
|
audio_id: z.string().optional(),
|
|
132
|
+
caption_addon: z.union([
|
|
133
|
+
z.object({
|
|
134
|
+
type: z.enum(['none', 'poll', 'comment_prompt']).optional(),
|
|
135
|
+
options: z.array(z.string()).max(4).optional(),
|
|
136
|
+
extended_duration: z.boolean().optional(),
|
|
137
|
+
}),
|
|
138
|
+
z.null(),
|
|
139
|
+
]).optional(),
|
|
140
|
+
poll_attachment: z.record(z.string(), z.unknown()).optional(),
|
|
141
|
+
is_comment_prompt_used: z.boolean().optional(),
|
|
142
|
+
is_poll_duration_extended: z.boolean().optional(),
|
|
107
143
|
ai_generated: z.boolean().optional(),
|
|
108
144
|
}).passthrough();
|
|
109
145
|
export const updatePostTool = {
|
|
110
146
|
name: 'update_post',
|
|
111
|
-
description: 'Change a scheduled or draft post. DESTRUCTIVE WRITE. Edit (default): caption, media, schedule, post_type, or settings; overwrites the existing post; cannot edit published or currently publishing posts; if a client has already approved the post, a caption edit reopens caption approval, a media or thumbnail edit reopens asset approval, and a reschedule, account change or settings change reopens both. status (scheduled, paused, or draft, with scheduled_at when scheduling a draft): pause, resume, or move back to draft; send it on its own. release_id (with optional group_id): set or repair external release/group IDs; send it on its own.\n\n' +
|
|
147
|
+
description: 'Change a scheduled or draft post. DESTRUCTIVE WRITE. Edit (default): caption, media, schedule, post_type, or settings; overwrites the existing post; cannot edit published or currently publishing posts; if a client has already approved the post, a caption edit reopens caption approval, a media or thumbnail edit reopens asset approval, and a reschedule, account change or settings change reopens both. status (scheduled, paused, or draft, with scheduled_at when scheduling a draft): pause, resume, or move back to draft; send it on its own. release_id (with optional group_id): set or repair external release/group IDs; send it on its own. approval_action (request, approve, request_changes, or reject): change client approval. Only a workspace owner or admin may do this. The actor is the API key user, never a brand guest. request emails the brand reviewers. approve, request_changes, and reject are team-side decisions. request_changes needs approval_note. Optional approval_axis is asset or caption; omit it for both. Send approval_action on its own.\n\n' +
|
|
112
148
|
'REQUIRED BEFORE CALLING: Show the user a side-by-side of the CURRENT post (caption, scheduled time, media, status) and the PROPOSED change, and get explicit confirmation ("yes update it", "apply those changes") before calling. Do not auto-edit posts based on a general instruction - each change needs its own confirmation.',
|
|
113
149
|
inputSchema: z.object({
|
|
114
150
|
post_id: z.number().describe('The post ID to update'),
|
|
@@ -146,6 +182,18 @@ export const updatePostTool = {
|
|
|
146
182
|
.optional()
|
|
147
183
|
.describe('Set an external release ID instead of editing the post. Send with post_id and optional group_id only.'),
|
|
148
184
|
group_id: z.string().min(1).max(160).optional().describe('With release_id only: an external group/campaign ID.'),
|
|
185
|
+
approval_action: z
|
|
186
|
+
.enum(['request', 'approve', 'request_changes', 'reject'])
|
|
187
|
+
.optional()
|
|
188
|
+
.describe('Change client approval instead of editing the post. Owner or admin only. The actor is the API key user, never a brand guest. Send on its own.'),
|
|
189
|
+
approval_axis: z
|
|
190
|
+
.enum(['asset', 'caption'])
|
|
191
|
+
.optional()
|
|
192
|
+
.describe('With approval_action approve, request_changes, or reject: which axis to decide. Omit for both. Not allowed with request.'),
|
|
193
|
+
approval_note: z
|
|
194
|
+
.string()
|
|
195
|
+
.optional()
|
|
196
|
+
.describe('Note stored with the approval change. Required for request_changes.'),
|
|
149
197
|
confirm: z.literal(true).describe('Must be true after explicit user confirmation of the proposed change.'),
|
|
150
198
|
}),
|
|
151
199
|
/** The old tools' exact input schemas, for alias calls (see alias-transport.ts). */
|
|
@@ -169,6 +217,9 @@ export const updatePostTool = {
|
|
|
169
217
|
return updateStatus(client, args);
|
|
170
218
|
if (mode === 'release_id')
|
|
171
219
|
return updateReleaseId(client, args);
|
|
220
|
+
if (mode === 'approval') {
|
|
221
|
+
return updateApproval(client, args);
|
|
222
|
+
}
|
|
172
223
|
return editPost(client, args);
|
|
173
224
|
},
|
|
174
225
|
};
|
|
@@ -209,6 +260,17 @@ async function updateStatus(client, input) {
|
|
|
209
260
|
const transition = result.transition || {};
|
|
210
261
|
return `Post #${input.post_id} status changed from ${transition.old_status || 'unknown'} to ${transition.new_status || input.status}.`;
|
|
211
262
|
}
|
|
263
|
+
async function updateApproval(client, input) {
|
|
264
|
+
if (input.confirm !== true) {
|
|
265
|
+
throw new Error('Refusing to change client approval without confirm=true after explicit user confirmation. Only a workspace owner or admin can do this, and the actor is the API key user, never a brand guest.');
|
|
266
|
+
}
|
|
267
|
+
const result = await client.setPostApproval(input.post_id, {
|
|
268
|
+
action: input.approval_action,
|
|
269
|
+
axis: input.approval_axis,
|
|
270
|
+
note: input.approval_note,
|
|
271
|
+
});
|
|
272
|
+
return JSON.stringify(result, null, 2);
|
|
273
|
+
}
|
|
212
274
|
async function updateReleaseId(client, input) {
|
|
213
275
|
const result = await client.updatePostReleaseId(input.post_id, {
|
|
214
276
|
release_id: input.release_id,
|