@omnisocials/mcp-server 1.48.0 → 1.49.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/README.md CHANGED
@@ -109,7 +109,7 @@ OmniSocials accepts the following channel IDs in `create_post`, `create_and_publ
109
109
  | `tiktok` | TikTok | Posts and reels |
110
110
  | `pinterest` | Pinterest | Pins (requires `board_id`) |
111
111
  | `x` | X (Twitter) | Posts, chained threads via `x.thread_parts` |
112
- | `threads` | Threads | Posts, chained threads via `threads.thread_parts`, location tagging via `threads.location_id` (rolling out) |
112
+ | `threads` | Threads | Posts, chained threads via `threads.thread_parts`, a topic via `threads.topic_tag`, polls via `threads.poll`, location tagging via `threads.location_id` (rolling out) |
113
113
  | `bluesky` | Bluesky | Posts, chained threads via `bluesky.thread_parts` |
114
114
  | `mastodon` | Mastodon | Posts, chained threads via `mastodon.thread_parts` |
115
115
  | `telegram` | Telegram | A channel or group the OmniSocials bot posts to: text, photos, videos, GIFs, albums of up to 10, native polls and link buttons via `telegram` |
@@ -244,6 +244,10 @@ Full API docs: [docs.omnisocials.com](https://docs.omnisocials.com)
244
244
 
245
245
  ## Changelog
246
246
 
247
+ ### 1.49.0 (2026-10-27)
248
+
249
+ - **Added: the Threads topic.** `threads.topic_tag` on `create_post`, `create_and_publish_post` and `update_post` (one topic per post, 1 to 50 characters, spaces allowed, no period or ampersand; `null` removes it on update). `get_post` shows it.
250
+
247
251
  ### 1.48.0 (2026-10-26)
248
252
 
249
253
  - **Added: video retention in `get_post_analytics`:** a `3-second hold (%)` row (`hold_rate_3s`: TikTok videos with TikTok comments enabled, Facebook Reels, Instagram Reels as 100 minus `skip_rate`) and a `Still watching` row that sums up the retention curve of TikTok videos and Facebook Reels and videos (1, 3, 5, 10, 15, 30 seconds and each quarter). Instagram and YouTube give no curve through their APIs.
package/build/client.d.ts CHANGED
@@ -246,6 +246,9 @@ export interface ThreadsPostOptions {
246
246
  * the tag goes on the first post. Needs the threads_location_tagging
247
247
  * permission on the Threads connection. */
248
248
  location_id?: string | null;
249
+ /** The topic of the post on Threads (1 to 50 characters, no period and
250
+ * no ampersand; spaces allowed). On a thread it goes on the first post. */
251
+ topic_tag?: string | null;
249
252
  }
250
253
  /**
251
254
  * Update-side variant: `thread_parts: null` clears the thread (revert to a
@@ -257,6 +260,8 @@ export interface ThreadsPostOptionsUpdate {
257
260
  /** New Threads location id, or null to remove the tag. Omit to leave the
258
261
  * existing tag untouched. */
259
262
  location_id?: string | null;
263
+ /** New Threads topic, or null to remove it. Omit to leave it untouched. */
264
+ topic_tag?: string | null;
260
265
  }
261
266
  /** Non-sponsored LinkedIn poll: question + 2-4 options + duration. */
262
267
  export interface LinkedInPollFields {
package/build/index.js CHANGED
@@ -30,7 +30,7 @@ const sessionState = { activeIndex: 0 };
30
30
  const getActiveClient = () => workspaceClients[sessionState.activeIndex].client;
31
31
  const server = new McpServer({
32
32
  name: "OmniSocials",
33
- version: "1.48.0",
33
+ version: "1.49.0",
34
34
  });
35
35
  // Register all tools - pass getter function so tools always use the active workspace's client
36
36
  registerPostTools(server, getActiveClient);
@@ -207,6 +207,13 @@ const THREADS_POLL_OPTIONS = z
207
207
  .nullable()
208
208
  .optional()
209
209
  .describe("Attach a poll to the post; the post text is the question. Threads closes the poll 24 hours after it is published (no duration). Polls go on text-only posts: no media on Threads together with a poll. On a thread the poll goes on the first post. On update_post, null removes it.");
210
+ // The Threads topic (2026-10-26): `threads.topic_tag`, one per post.
211
+ const THREADS_TOPIC_TAG = z
212
+ .string()
213
+ .max(50)
214
+ .nullable()
215
+ .optional()
216
+ .describe("The topic of the post on Threads, one per post, e.g. \"Build in public\". Unlike a #tag in the text it can hold spaces. 1 to 50 characters, no period (.) and no ampersand (&); a leading # is dropped. On a multi-post thread the topic goes on the first post. On update_post, pass null to remove it.");
210
217
  const MASTODON_POLL_OPTIONS = z
211
218
  .object({
212
219
  options: z.array(z.string().min(1)).min(2).describe("The answer options, all different; count and length within the instance's limits (Mastodon's defaults: 4 options of 50 characters)."),
@@ -568,6 +575,10 @@ export function registerPostTools(server, getClient) {
568
575
  const locBits = [threadsLoc.name, threadsLoc.city, threadsLoc.country].filter(Boolean).join(", ");
569
576
  md += `| **Threads location** | ${locBits ? `${locBits} ` : ""}\`${threadsLoc.id}\` |\n`;
570
577
  }
578
+ const threadsTopic = p.threads?.topic_tag;
579
+ if (typeof threadsTopic === "string" && threadsTopic) {
580
+ md += `| **Threads topic** | ${threadsTopic} |\n`;
581
+ }
571
582
  if (Array.isArray(p.collaborators) && p.collaborators.length) {
572
583
  md += `| **IG collaborators** | ${p.collaborators.map((c) => `@${c}`).join(", ")} |\n`;
573
584
  }
@@ -1073,9 +1084,10 @@ Do NOT call this tool without media when creating stories, reels, Instagram post
1073
1084
  }).optional().describe("Mastodon options"),
1074
1085
  threads: z.object({
1075
1086
  poll: THREADS_POLL_OPTIONS,
1087
+ topic_tag: THREADS_TOPIC_TAG,
1076
1088
  location_id: z.string().nullable().optional().describe("Tag a location on the Threads post. Use an `id` from search_locations with platform \"threads\" (Threads location ids are NOT Facebook Place IDs, so never reuse the Instagram location_id here). On a multi-post thread the tag goes on the first post. Needs the workspace's Threads connection to have the threads_location_tagging permission; the API returns a clear 400 asking to reconnect Threads when it is missing, and a clear 400 while location tagging is still rolling out (Meta has not approved the permission yet). On update_post, pass null to remove the tag."),
1077
1089
  thread_parts: z.array(THREADS_THREAD_PART).min(2).max(25).optional().describe("Publish as a chained Threads (Meta) thread instead of a single post. Provide 2 to 25 parts; parts after the first are posted as replies to the previous part. Each part holds up to 500 characters and up to 10 media (images and videos can be mixed) via media_ids (from upload_media) or media_urls. When set, the Threads caption is taken from part 1 and content is ignored for Threads. For a single post, omit thread_parts and use content."),
1078
- }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`."),
1090
+ }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`, a poll via `poll`, the topic via `topic_tag`."),
1079
1091
  google_business: GOOGLE_BUSINESS_OPTIONS,
1080
1092
  telegram: TELEGRAM_OPTIONS,
1081
1093
  discord: DISCORD_OPTIONS,
@@ -1249,9 +1261,10 @@ Do NOT call without required media — it will fail.`, {
1249
1261
  }).optional().describe("Mastodon options"),
1250
1262
  threads: z.object({
1251
1263
  poll: THREADS_POLL_OPTIONS,
1264
+ topic_tag: THREADS_TOPIC_TAG,
1252
1265
  location_id: z.string().nullable().optional().describe("Tag a location on the Threads post. Use an `id` from search_locations with platform \"threads\" (Threads location ids are NOT Facebook Place IDs, so never reuse the Instagram location_id here). On a multi-post thread the tag goes on the first post. Needs the workspace's Threads connection to have the threads_location_tagging permission; the API returns a clear 400 asking to reconnect Threads when it is missing, and a clear 400 while location tagging is still rolling out (Meta has not approved the permission yet). On update_post, pass null to remove the tag."),
1253
1266
  thread_parts: z.array(THREADS_THREAD_PART).min(2).max(25).optional().describe("Publish as a chained Threads (Meta) thread (2 to 25 parts). Parts after the first are posted as replies to the previous part. Each part holds up to 500 characters and up to 10 media (images and videos can be mixed) via media_ids or media_urls. The Threads caption is taken from part 1."),
1254
- }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`."),
1267
+ }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`, a poll via `poll`, the topic via `topic_tag`."),
1255
1268
  google_business: GOOGLE_BUSINESS_OPTIONS,
1256
1269
  telegram: TELEGRAM_OPTIONS,
1257
1270
  discord: DISCORD_OPTIONS,
@@ -1372,9 +1385,10 @@ Do NOT call without required media — it will fail.`, {
1372
1385
  }).optional().describe("Mastodon options"),
1373
1386
  threads: z.object({
1374
1387
  poll: THREADS_POLL_OPTIONS,
1388
+ topic_tag: THREADS_TOPIC_TAG,
1375
1389
  location_id: z.string().nullable().optional().describe("Tag a location on the Threads post. Use an `id` from search_locations with platform \"threads\" (Threads location ids are NOT Facebook Place IDs, so never reuse the Instagram location_id here). On a multi-post thread the tag goes on the first post. Needs the workspace's Threads connection to have the threads_location_tagging permission; the API returns a clear 400 asking to reconnect Threads when it is missing, and a clear 400 while location tagging is still rolling out (Meta has not approved the permission yet). On update_post, pass null to remove the tag."),
1376
1390
  thread_parts: z.array(THREADS_THREAD_PART).min(2).max(25).nullable().optional().describe("Replace the Threads (Meta) thread shape on this post. Pass an array (2 to 25 parts, 500 characters per part) to update/create the thread (attach up to 10 media to any part via media_ids or media_urls; images and videos can be mixed), or `null` to revert to single-post mode."),
1377
- }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`."),
1391
+ }).optional().describe("Threads (Meta) options: thread mode via `thread_parts`, location tag via `location_id`, a poll via `poll`, the topic via `topic_tag`."),
1378
1392
  google_business: GOOGLE_BUSINESS_OPTIONS,
1379
1393
  telegram: TELEGRAM_OPTIONS,
1380
1394
  discord: DISCORD_OPTIONS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnisocials/mcp-server",
3
- "version": "1.48.0",
3
+ "version": "1.49.0",
4
4
  "mcpName": "io.github.omnisocials/mcp-server",
5
5
  "description": "MCP server for OmniSocials API - manage social media posts, media, accounts, analytics, and webhooks",
6
6
  "type": "module",