@omnisocials/mcp-server 1.4.1 → 1.5.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
@@ -192,6 +192,11 @@ Full API docs: [docs.omnisocials.com](https://docs.omnisocials.com)
192
192
 
193
193
  ## Changelog
194
194
 
195
+ ### 1.5.0
196
+
197
+ - **Added:** Attach uploaded media to any tweet in an X thread. `x.thread_parts[]` now accepts `media_ids` (the same numeric Library IDs returned by `upload_media`) on any part, first tweet or reply, alongside the existing `media_urls`. Combined cap is 4 media per part. This makes graphic-led threads possible without self-hosting image URLs: for example a graphic on the first tweet and the signup link alone in a reply (which keeps the first tweet's reach). Companion server change: media attached to the parent post was previously dropped in thread mode and is now folded into the first tweet.
198
+ - **Changed:** `upload_media` now shows the uploaded file's public URL in its output, so it can be reused anywhere `media_urls` is accepted.
199
+
195
200
  ### 1.4.1
196
201
 
197
202
  - **Fixed:** Long-form X posts from Premium / Premium+ accounts are no longer wrongly capped at 280 characters. Companion server fix — the API validated X text without checking the account's subscription tier, so single posts over 280 chars were rejected even on Premium. Existing clients benefit automatically once the backend deploys; 1.4.1 only refreshes the tool guidance so agents put Premium long-form (up to 25,000 chars) in `content` instead of force-splitting it into a thread. Note: X *threads* still cap each part at 280 chars regardless of tier.
package/build/client.d.ts CHANGED
@@ -12,7 +12,9 @@ export declare function capitalize(str: string): string;
12
12
  export interface XThreadPartInput {
13
13
  /** Tweet text — ≤ 280 chars (the API enforces 280 even for X Premium). */
14
14
  text: string;
15
- /** Optional per-part media URLs (max 4). Overrides top-level media_urls.x. */
15
+ /** Optional per-part media as Library IDs from upload_media (max 4 combined with media_urls). */
16
+ media_ids?: string[];
17
+ /** Optional per-part media as external URLs (max 4 combined with media_ids). */
16
18
  media_urls?: string[];
17
19
  }
18
20
  export interface XPostOptions {
@@ -86,7 +86,9 @@ When the user provides an image in the conversation (not a URL), use base64_data
86
86
  md += `| **Type** | ${m.type || "—"} |\n`;
87
87
  md += `| **Filename** | ${m.filename || "—"} |\n`;
88
88
  md += `| **Size** | ${formatBytes(m.size || 0)} |\n`;
89
- md += `\nUse this Media ID with \`media_ids\` when creating posts.`;
89
+ if (m.url)
90
+ md += `| **URL** | ${m.url} |\n`;
91
+ md += `\nUse this Media ID with \`media_ids\` when creating posts (including inside \`x.thread_parts[].media_ids\`). The public URL above also works anywhere \`media_urls\` is accepted.`;
90
92
  return {
91
93
  content: [{ type: "text", text: md }],
92
94
  };
@@ -264,8 +264,9 @@ Do NOT call this tool without media when creating stories, reels, Instagram post
264
264
  made_with_ai: z.boolean().optional().describe("Mark as AI-generated content"),
265
265
  thread_parts: z.array(z.object({
266
266
  text: z.string().describe("Tweet text (≤ 280 chars)"),
267
- media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media URLs (max 4)"),
268
- })).min(2).max(25).optional().describe("Publish as a chained X thread instead of a single tweet. Provide 2–25 parts; each is posted in order via in_reply_to_tweet_id. Per-part media_urls override top-level media for that specific tweet. For a single tweet, omit thread_parts and use content."),
267
+ media_ids: z.array(z.string()).max(4).optional().describe("Per-tweet media as Library IDs from upload_media (max 4 combined with media_urls). Attach your uploaded graphics to any tweet in the thread."),
268
+ media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media as external URLs (max 4 combined with media_ids)"),
269
+ })).min(2).max(25).optional().describe("Publish as a chained X thread instead of a single tweet. Provide 2–25 parts; each is posted in order via in_reply_to_tweet_id. Attach media to any part (first tweet or reply) via media_ids (from upload_media) or media_urls — max 4 per part. For a single tweet, omit thread_parts and use content."),
269
270
  }).optional().describe("X (Twitter) options"),
270
271
  google_business: z.object({
271
272
  topic_type: z.enum(["STANDARD", "EVENT", "OFFER"]).optional().describe("Local post type. Defaults to STANDARD. ALERT is reserved by Google and not exposed."),
@@ -387,8 +388,9 @@ Do NOT call without required media — it will fail.`, {
387
388
  made_with_ai: z.boolean().optional().describe("Mark as AI-generated content"),
388
389
  thread_parts: z.array(z.object({
389
390
  text: z.string().describe("Tweet text (≤ 280 chars)"),
390
- media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media URLs (max 4)"),
391
- })).min(2).max(25).optional().describe("Publish as a chained X thread (2–25 parts). Each is posted in order via in_reply_to_tweet_id. Per-part media_urls override top-level media."),
391
+ media_ids: z.array(z.string()).max(4).optional().describe("Per-tweet media as Library IDs from upload_media (max 4 combined with media_urls). Attach your uploaded graphics to any tweet in the thread."),
392
+ media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media as external URLs (max 4 combined with media_ids)"),
393
+ })).min(2).max(25).optional().describe("Publish as a chained X thread (2–25 parts). Each is posted in order via in_reply_to_tweet_id. Attach media to any part via media_ids (from upload_media) or media_urls — max 4 per part."),
392
394
  }).optional().describe("X (Twitter) options"),
393
395
  google_business: z.object({
394
396
  topic_type: z.enum(["STANDARD", "EVENT", "OFFER"]).optional(),
@@ -496,8 +498,9 @@ Do NOT call without required media — it will fail.`, {
496
498
  made_with_ai: z.boolean().optional(),
497
499
  thread_parts: z.array(z.object({
498
500
  text: z.string().describe("Tweet text (≤ 280 chars)"),
499
- media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media URLs (max 4)"),
500
- })).min(2).max(25).nullable().optional().describe("Replace the X thread shape on this post. Pass an array (2–25 parts) to update/create the thread, or `null` to revert to single-tweet mode."),
501
+ media_ids: z.array(z.string()).max(4).optional().describe("Per-tweet media as Library IDs from upload_media (max 4 combined with media_urls). Attach your uploaded graphics to any tweet in the thread."),
502
+ media_urls: z.array(z.string()).max(4).optional().describe("Per-tweet media as external URLs (max 4 combined with media_ids)"),
503
+ })).min(2).max(25).nullable().optional().describe("Replace the X thread shape on this post. Pass an array (2–25 parts) to update/create the thread (attach media to any part via media_ids or media_urls, max 4 per part), or `null` to revert to single-tweet mode."),
501
504
  }).optional().describe("X (Twitter) options"),
502
505
  google_business: z.object({
503
506
  topic_type: z.enum(["STANDARD", "EVENT", "OFFER"]).optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnisocials/mcp-server",
3
- "version": "1.4.1",
3
+ "version": "1.5.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",