@omnisocials/mcp-server 1.20.1 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/client.d.ts CHANGED
@@ -100,6 +100,12 @@ export interface MastodonPostOptions {
100
100
  export interface MastodonPostOptionsUpdate {
101
101
  thread_parts?: MastodonThreadPartInput[] | null;
102
102
  }
103
+ /** Non-sponsored LinkedIn poll: question + 2-4 options + duration. */
104
+ export interface LinkedInPollInput {
105
+ question: string;
106
+ options: string[];
107
+ duration: "ONE_DAY" | "THREE_DAYS" | "SEVEN_DAYS" | "FOURTEEN_DAYS";
108
+ }
103
109
  /**
104
110
  * Request body for POST /posts/create. `createAndPublishPost` accepts the
105
111
  * same shape minus `scheduled_at` (publishing is immediate).
@@ -130,6 +136,7 @@ export interface CreatePostInput {
130
136
  facebook?: Record<string, unknown>;
131
137
  linkedin?: Record<string, unknown>;
132
138
  linkedin_page?: Record<string, unknown>;
139
+ linkedin_poll?: LinkedInPollInput | null;
133
140
  tiktok?: Record<string, unknown>;
134
141
  x?: XPostOptions;
135
142
  bluesky?: BlueskyPostOptions;
@@ -183,6 +190,7 @@ export declare class OmniSocialsClient {
183
190
  facebook?: Record<string, unknown>;
184
191
  linkedin?: Record<string, unknown>;
185
192
  linkedin_page?: Record<string, unknown>;
193
+ linkedin_poll?: LinkedInPollInput | null;
186
194
  tiktok?: Record<string, unknown>;
187
195
  x?: XPostOptionsUpdate;
188
196
  bluesky?: BlueskyPostOptionsUpdate;
package/build/index.js CHANGED
@@ -29,7 +29,7 @@ const sessionState = { activeIndex: 0 };
29
29
  const getActiveClient = () => workspaceClients[sessionState.activeIndex].client;
30
30
  const server = new McpServer({
31
31
  name: "OmniSocials",
32
- version: "1.20.0",
32
+ version: "1.21.0",
33
33
  });
34
34
  // Register all tools - pass getter function so tools always use the active workspace's client
35
35
  registerPostTools(server, getActiveClient);
@@ -83,6 +83,21 @@ const LINKEDIN_PAGE_OPTIONS = z
83
83
  })
84
84
  .optional()
85
85
  .describe("LinkedIn Company Page options");
86
+ const LINKEDIN_POLL_OPTIONS = z
87
+ .object({
88
+ question: z.string().max(140).describe("The poll question (max 140 characters)."),
89
+ options: z
90
+ .array(z.string().max(30))
91
+ .min(2)
92
+ .max(4)
93
+ .describe("2-4 answer options (max 30 characters each)."),
94
+ duration: z
95
+ .enum(["ONE_DAY", "THREE_DAYS", "SEVEN_DAYS", "FOURTEEN_DAYS"])
96
+ .describe("How long the poll stays open for votes."),
97
+ })
98
+ .nullable()
99
+ .optional()
100
+ .describe("Non-sponsored LinkedIn poll, posted to whichever of `linkedin`/`linkedin_page` is selected in `accounts`. Mutually exclusive with media and a link share — a poll takes priority over both at publish time. Still requires `content.linkedin` (or `content.default`) as the post's caption; the poll itself only carries the question/options/duration. Pass `null` on update_post to clear a poll and revert to a normal post.");
86
101
  // Per-platform option schemas shared verbatim by create_post,
87
102
  // create_and_publish_post and update_post (they were byte-identical in all
88
103
  // three). Platform blocks that genuinely differ per tool (instagram, youtube,
@@ -259,7 +274,7 @@ export function registerPostTools(server, getClient) {
259
274
  content: [{ type: "text", text: md }],
260
275
  };
261
276
  });
262
- server.tool("get_post", "Get details of a specific post by ID — content, channels, media (with URLs + any per-media alt text), first comment, Instagram collaborators/user tags/location/Trial Reel state/Reel cover (thumbnail_type + thumb_offset in ms), dates and live URLs, enough to fully verify a scheduled post without opening the dashboard. When a post has per-platform caption overrides (e.g. a shorter X version alongside the default), every variant is rendered as its own labeled block under `### Content` so you can see exactly what each platform will publish. X threads are rendered under `### X Thread` with each tweet labeled in publish order — read this to see the full chained tweet text, since thread-only posts have no caption in `content`. After publishing, includes `published_urls` — a map of platform → live URL for each platform that successfully posted (e.g. facebook, instagram, linkedin, x). Useful for polling: when a post's status is `published`, read `published_urls` to surface the live links.", {
277
+ server.tool("get_post", "Get details of a specific post by ID — content, channels, media (with URLs + any per-media alt text), first comment, Instagram collaborators/user tags/location/Trial Reel state/Reel cover (thumbnail_type + thumb_offset in ms), dates and live URLs, enough to fully verify a scheduled post without opening the dashboard. When a post has per-platform caption overrides (e.g. a shorter X version alongside the default), every variant is rendered as its own labeled block under `### Content` so you can see exactly what each platform will publish. X threads are rendered under `### X Thread` with each tweet labeled in publish order — read this to see the full chained tweet text, since thread-only posts have no caption in `content`. A LinkedIn poll is rendered under `### LinkedIn Poll` with the question, options, and duration. After publishing, includes `published_urls` — a map of platform → live URL for each platform that successfully posted (e.g. facebook, instagram, linkedin, x). Useful for polling: when a post's status is `published`, read `published_urls` to surface the live links.", {
263
278
  id: z.string().describe("The post ID"),
264
279
  }, async ({ id }) => {
265
280
  const result = await getClient().getPost(id);
@@ -392,6 +407,17 @@ export function registerPostTools(server, getClient) {
392
407
  md += `\n`;
393
408
  }
394
409
  }
410
+ // LinkedIn poll: mutually exclusive with media/link-share, so surface
411
+ // it prominently rather than leaving callers to infer it's a poll.
412
+ if (p.linkedin_poll?.question) {
413
+ const poll = p.linkedin_poll;
414
+ md += `\n\n### LinkedIn Poll\n\n`;
415
+ md += `**${poll.question}**\n\n`;
416
+ for (const option of poll.options || []) {
417
+ md += `- ${option}\n`;
418
+ }
419
+ md += `\n_Duration: ${poll.duration}_\n`;
420
+ }
395
421
  const publishedUrls = (p.published_urls && typeof p.published_urls === "object" && !Array.isArray(p.published_urls))
396
422
  ? p.published_urls
397
423
  : {};
@@ -559,6 +585,7 @@ Do NOT call this tool without media when creating stories, reels, Instagram post
559
585
  facebook: FACEBOOK_OPTIONS,
560
586
  linkedin: LINKEDIN_OPTIONS,
561
587
  linkedin_page: LINKEDIN_PAGE_OPTIONS,
588
+ linkedin_poll: LINKEDIN_POLL_OPTIONS,
562
589
  tiktok: TIKTOK_OPTIONS,
563
590
  x: z.object({
564
591
  reply_settings: z.enum(["", "following", "mentionedUsers"]).optional(),
@@ -698,6 +725,7 @@ Do NOT call without required media — it will fail.`, {
698
725
  facebook: FACEBOOK_OPTIONS,
699
726
  linkedin: LINKEDIN_OPTIONS,
700
727
  linkedin_page: LINKEDIN_PAGE_OPTIONS,
728
+ linkedin_poll: LINKEDIN_POLL_OPTIONS,
701
729
  tiktok: TIKTOK_OPTIONS,
702
730
  x: z.object({
703
731
  reply_settings: z.enum(["", "following", "mentionedUsers"]).optional(),
@@ -803,6 +831,7 @@ Do NOT call without required media — it will fail.`, {
803
831
  facebook: FACEBOOK_OPTIONS,
804
832
  linkedin: LINKEDIN_OPTIONS,
805
833
  linkedin_page: LINKEDIN_PAGE_OPTIONS,
834
+ linkedin_poll: LINKEDIN_POLL_OPTIONS,
806
835
  tiktok: TIKTOK_OPTIONS,
807
836
  x: z.object({
808
837
  reply_settings: z.enum(["", "following", "mentionedUsers"]).optional(),
package/build/types.d.ts CHANGED
@@ -152,6 +152,12 @@ export interface ApiPost {
152
152
  facebook?: ApiPlatformOptionsOut;
153
153
  linkedin?: ApiPlatformOptionsOut;
154
154
  linkedin_page?: ApiPlatformOptionsOut;
155
+ /** Non-sponsored LinkedIn poll echoed back after create/update/publish. */
156
+ linkedin_poll?: {
157
+ question: string;
158
+ options: string[];
159
+ duration: string;
160
+ } | null;
155
161
  tiktok?: ApiPlatformOptionsOut;
156
162
  google_business?: ApiPlatformOptionsOut;
157
163
  x?: ApiPlatformOptionsOut;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnisocials/mcp-server",
3
- "version": "1.20.1",
3
+ "version": "1.21.0",
4
4
  "description": "MCP server for OmniSocials API - manage social media posts, media, accounts, analytics, and webhooks",
5
5
  "type": "module",
6
6
  "main": "build/index.js",