@omnisocials/mcp-server 1.12.0 → 1.13.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
@@ -1,4 +1,4 @@
1
- import type { ApiResponse, MediaItem, PdfUploadResult } from "./types.js";
1
+ import type { ApiResponse, MediaItem, PdfUploadResult, InboxConversation, InboxMessage } from "./types.js";
2
2
  export declare function fetchImageAsBase64(url: string): Promise<{
3
3
  data: string;
4
4
  mimeType: string;
@@ -264,4 +264,21 @@ export declare class OmniSocialsClient {
264
264
  is_active?: boolean;
265
265
  }): Promise<ApiResponse<unknown>>;
266
266
  rotateWebhookSecret(id: string): Promise<ApiResponse<unknown>>;
267
+ listInboxConversations(params?: {
268
+ platform?: string;
269
+ type?: string;
270
+ unread?: string;
271
+ limit?: string;
272
+ cursor?: string;
273
+ }): Promise<ApiResponse<InboxConversation[]>>;
274
+ getInboxMessages(conversationId: string, params?: {
275
+ limit?: string;
276
+ cursor?: string;
277
+ }): Promise<ApiResponse<InboxMessage[]>>;
278
+ markInboxRead(conversationId: string): Promise<ApiResponse<unknown>>;
279
+ replyToInboxConversation(conversationId: string, data: {
280
+ text: string;
281
+ attachment_url?: string;
282
+ attachment_type?: string;
283
+ }): Promise<ApiResponse<InboxMessage>>;
267
284
  }
package/build/client.js CHANGED
@@ -318,4 +318,18 @@ export class OmniSocialsClient {
318
318
  async rotateWebhookSecret(id) {
319
319
  return this.request("POST", `/webhooks/${id}/rotate-secret`);
320
320
  }
321
+ // Inbox — conversation ids can contain ":" and "()" (LinkedIn URNs), so any
322
+ // path segment built from one must be URL-encoded.
323
+ async listInboxConversations(params) {
324
+ return this.request("GET", "/inbox/conversations", undefined, params);
325
+ }
326
+ async getInboxMessages(conversationId, params) {
327
+ return this.request("GET", `/inbox/conversations/${encodeURIComponent(conversationId)}/messages`, undefined, params);
328
+ }
329
+ async markInboxRead(conversationId) {
330
+ return this.request("POST", `/inbox/conversations/${encodeURIComponent(conversationId)}/read`);
331
+ }
332
+ async replyToInboxConversation(conversationId, data) {
333
+ return this.request("POST", `/inbox/conversations/${encodeURIComponent(conversationId)}/reply`, data);
334
+ }
321
335
  }
package/build/index.js CHANGED
@@ -8,6 +8,7 @@ import { registerMediaTools } from "./tools/media.js";
8
8
  import { registerAccountTools } from "./tools/accounts.js";
9
9
  import { registerAnalyticsTools } from "./tools/analytics.js";
10
10
  import { registerWebhookTools } from "./tools/webhooks.js";
11
+ import { registerInboxTools } from "./tools/inbox.js";
11
12
  import { registerWorkspaceTools } from "./tools/workspaces.js";
12
13
  const apiKeyEnv = process.env.OMNISOCIALS_API_KEY;
13
14
  if (!apiKeyEnv) {
@@ -27,7 +28,7 @@ const sessionState = { activeIndex: 0 };
27
28
  const getActiveClient = () => workspaceClients[sessionState.activeIndex].client;
28
29
  const server = new McpServer({
29
30
  name: "OmniSocials",
30
- version: "1.12.0",
31
+ version: "1.13.0",
31
32
  });
32
33
  // Register all tools - pass getter function so tools always use the active workspace's client
33
34
  registerPostTools(server, getActiveClient);
@@ -35,6 +36,7 @@ registerMediaTools(server, getActiveClient);
35
36
  registerAccountTools(server, getActiveClient);
36
37
  registerAnalyticsTools(server, getActiveClient);
37
38
  registerWebhookTools(server, getActiveClient);
39
+ registerInboxTools(server, getActiveClient);
38
40
  registerWorkspaceTools(server, workspaceClients, sessionState);
39
41
  // Register prompts
40
42
  server.prompt("weekly-report", "Generate a weekly social media performance report", {}, async () => ({
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerInboxTools(server: McpServer, getClient: () => OmniSocialsClient): void;
@@ -0,0 +1,166 @@
1
+ import { z } from "zod";
2
+ import { formatDateTime } from "../client.js";
3
+ const PLATFORM_EMOJI = {
4
+ instagram: "📸",
5
+ facebook: "📘",
6
+ linkedin: "💼",
7
+ };
8
+ export function registerInboxTools(server, getClient) {
9
+ server.tool("list_inbox_conversations", "List social inbox conversations (Instagram/Facebook DMs, comments, mentions, and LinkedIn company-page comments/mentions), newest activity first. Cursor-paginated: pass the returned cursor to get the next page.", {
10
+ platform: z
11
+ .enum(["instagram", "facebook", "linkedin"])
12
+ .optional()
13
+ .describe("Filter to one platform"),
14
+ type: z
15
+ .enum(["dm", "comment", "mention"])
16
+ .optional()
17
+ .describe("Filter to one conversation type"),
18
+ unread: z
19
+ .boolean()
20
+ .optional()
21
+ .describe("Only conversations with unread incoming messages"),
22
+ limit: z
23
+ .number()
24
+ .optional()
25
+ .describe("Max conversations per page (1-100, default 25)"),
26
+ cursor: z
27
+ .string()
28
+ .optional()
29
+ .describe("Pagination cursor from a previous response"),
30
+ }, async (params) => {
31
+ const query = {};
32
+ if (params.platform)
33
+ query.platform = params.platform;
34
+ if (params.type)
35
+ query.type = params.type;
36
+ if (params.unread !== undefined)
37
+ query.unread = String(params.unread);
38
+ if (params.limit !== undefined)
39
+ query.limit = String(params.limit);
40
+ if (params.cursor)
41
+ query.cursor = params.cursor;
42
+ const result = await getClient().listInboxConversations(query);
43
+ if (result.error) {
44
+ return {
45
+ content: [
46
+ {
47
+ type: "text",
48
+ text: `Error (${result.error.code}): ${result.error.message}`,
49
+ },
50
+ ],
51
+ };
52
+ }
53
+ const convos = result.data || [];
54
+ if (!convos.length) {
55
+ return {
56
+ content: [{ type: "text", text: "No conversations found." }],
57
+ };
58
+ }
59
+ let md = `## Inbox Conversations (${convos.length})\n\n`;
60
+ md += `| Platform | Type | From | Unread | Latest message | Conversation ID |\n`;
61
+ md += `|----------|------|------|--------|----------------|----------------|\n`;
62
+ for (const c of convos) {
63
+ const who = c.participant?.name || c.participant?.username || "Unknown";
64
+ const text = (c.last_message?.text || "").replace(/\n/g, " ").slice(0, 40);
65
+ md += `| ${PLATFORM_EMOJI[c.platform] || ""} ${c.platform} | ${c.type} | ${who} | ${c.unread_count || 0} | ${text} | \`${c.conversation_id}\` |\n`;
66
+ }
67
+ if (result.pagination?.next_cursor) {
68
+ md += `\n_More available — call list_inbox_conversations again with cursor "${result.pagination.next_cursor}"._`;
69
+ }
70
+ return { content: [{ type: "text", text: md }] };
71
+ });
72
+ server.tool("get_inbox_conversation", "Get the full message history of one inbox conversation, oldest first. Use the conversation_id from list_inbox_conversations.", {
73
+ conversation_id: z.string().describe("The conversation ID to fetch"),
74
+ limit: z
75
+ .number()
76
+ .optional()
77
+ .describe("Max messages per page (1-100, default 50)"),
78
+ cursor: z.string().optional().describe("Pagination cursor"),
79
+ }, async ({ conversation_id, limit, cursor }) => {
80
+ const query = {};
81
+ if (limit !== undefined)
82
+ query.limit = String(limit);
83
+ if (cursor)
84
+ query.cursor = cursor;
85
+ const result = await getClient().getInboxMessages(conversation_id, query);
86
+ if (result.error) {
87
+ return {
88
+ content: [
89
+ {
90
+ type: "text",
91
+ text: `Error (${result.error.code}): ${result.error.message}`,
92
+ },
93
+ ],
94
+ };
95
+ }
96
+ const msgs = result.data || [];
97
+ if (!msgs.length) {
98
+ return {
99
+ content: [
100
+ { type: "text", text: "No messages in this conversation." },
101
+ ],
102
+ };
103
+ }
104
+ let md = `## Conversation \`${conversation_id}\`\n\n`;
105
+ for (const m of msgs) {
106
+ const who = m.direction === "outgoing"
107
+ ? "→ You"
108
+ : `← ${m.sender?.name || m.sender?.username || "Them"}`;
109
+ md += `**${who}** _(${formatDateTime(m.timestamp)})_\n${m.text || ""}\n\n`;
110
+ }
111
+ if (result.pagination?.next_cursor) {
112
+ md += `_More messages — call again with cursor "${result.pagination.next_cursor}"._`;
113
+ }
114
+ return { content: [{ type: "text", text: md }] };
115
+ });
116
+ server.tool("mark_inbox_read", "Mark all incoming messages in a conversation as read.", {
117
+ conversation_id: z.string().describe("The conversation ID to mark read"),
118
+ }, async ({ conversation_id }) => {
119
+ const result = await getClient().markInboxRead(conversation_id);
120
+ if (result.error) {
121
+ return {
122
+ content: [
123
+ {
124
+ type: "text",
125
+ text: `Error (${result.error.code}): ${result.error.message}`,
126
+ },
127
+ ],
128
+ };
129
+ }
130
+ return {
131
+ content: [
132
+ {
133
+ type: "text",
134
+ text: `Marked ${result.marked_read ?? 0} message(s) as read in \`${conversation_id}\`.`,
135
+ },
136
+ ],
137
+ };
138
+ });
139
+ server.tool("reply_to_inbox", "Reply to an existing inbox conversation (DM, comment, or mention) on Instagram, Facebook, or LinkedIn. You can only reply to conversations that already exist. Direct-message replies must be within the platform's 24-hour messaging window. Each workspace can send up to 1,000 replies per day.", {
140
+ conversation_id: z.string().describe("The conversation ID to reply to"),
141
+ text: z.string().describe("The reply text (max 2000 characters)"),
142
+ }, async ({ conversation_id, text }) => {
143
+ const result = await getClient().replyToInboxConversation(conversation_id, {
144
+ text,
145
+ });
146
+ if (result.error) {
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: `Error (${result.error.code}): ${result.error.message}`,
152
+ },
153
+ ],
154
+ };
155
+ }
156
+ const m = result.data;
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: `Reply sent to \`${conversation_id}\`${m?.platform ? ` on ${m.platform}` : ""}.`,
162
+ },
163
+ ],
164
+ };
165
+ });
166
+ }
package/build/types.d.ts CHANGED
@@ -4,6 +4,57 @@ export interface ApiResponse<T = unknown> {
4
4
  code: string;
5
5
  message: string;
6
6
  };
7
+ pagination?: {
8
+ next_cursor: string | null;
9
+ has_more: boolean;
10
+ limit: number;
11
+ };
12
+ conversation_id?: string;
13
+ marked_read?: number;
14
+ }
15
+ export interface InboxParticipant {
16
+ id: string;
17
+ name: string;
18
+ username: string;
19
+ profile_picture: string | null;
20
+ }
21
+ export interface InboxConversation {
22
+ conversation_id: string;
23
+ platform: "instagram" | "facebook" | "linkedin";
24
+ type: "dm" | "comment" | "mention";
25
+ participant: InboxParticipant;
26
+ unread_count: number;
27
+ last_message: {
28
+ id: string;
29
+ direction: "incoming" | "outgoing";
30
+ text: string;
31
+ timestamp: string;
32
+ is_read: boolean;
33
+ };
34
+ post: {
35
+ id: string | null;
36
+ caption: string | null;
37
+ thumbnail: string | null;
38
+ } | null;
39
+ }
40
+ export interface InboxMessage {
41
+ id: string;
42
+ conversation_id: string;
43
+ platform: string;
44
+ type: "dm" | "comment" | "mention";
45
+ direction: "incoming" | "outgoing";
46
+ text: string;
47
+ timestamp: string;
48
+ is_read: boolean;
49
+ is_replied: boolean;
50
+ reaction: string | null;
51
+ parent_comment_id: string | null;
52
+ sender: InboxParticipant;
53
+ post: {
54
+ id: string | null;
55
+ caption: string | null;
56
+ thumbnail: string | null;
57
+ } | null;
7
58
  }
8
59
  export interface Post {
9
60
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnisocials/mcp-server",
3
- "version": "1.12.0",
3
+ "version": "1.13.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",