@omnisocials/mcp-server 1.0.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 ADDED
@@ -0,0 +1,139 @@
1
+ # @omnisocials/mcp-server
2
+
3
+ MCP (Model Context Protocol) server for the [OmniSocials](https://omnisocials.com) API. Lets AI assistants manage your social media — create posts, upload media, view analytics, and more.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 18+
8
+ - An OmniSocials API key (get one from **Settings > API** in the app)
9
+
10
+ ## Setup
11
+
12
+ ### Claude Code
13
+
14
+ ```bash
15
+ claude mcp add omnisocials -- npx -y @omnisocials/mcp-server
16
+ ```
17
+
18
+ Then set your API key:
19
+
20
+ ```bash
21
+ export OMNISOCIALS_API_KEY=omsk_live_your_key_here
22
+ ```
23
+
24
+ ### Claude Desktop
25
+
26
+ Add to your `claude_desktop_config.json`:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "omnisocials": {
32
+ "command": "npx",
33
+ "args": ["-y", "@omnisocials/mcp-server"],
34
+ "env": {
35
+ "OMNISOCIALS_API_KEY": "omsk_live_your_key_here"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ ### Cursor
43
+
44
+ Add to your `.cursor/mcp.json`:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "omnisocials": {
50
+ "command": "npx",
51
+ "args": ["-y", "@omnisocials/mcp-server"],
52
+ "env": {
53
+ "OMNISOCIALS_API_KEY": "omsk_live_your_key_here"
54
+ }
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### Windsurf
61
+
62
+ Add to your `~/.codeium/windsurf/mcp_config.json`:
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "omnisocials": {
68
+ "command": "npx",
69
+ "args": ["-y", "@omnisocials/mcp-server"],
70
+ "env": {
71
+ "OMNISOCIALS_API_KEY": "omsk_live_your_key_here"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Available Tools
79
+
80
+ ### Posts (7 tools)
81
+
82
+ | Tool | Description |
83
+ |------|-------------|
84
+ | `list_posts` | List all posts, optionally filter by status |
85
+ | `get_post` | Get details of a specific post |
86
+ | `create_post` | Create a new post, story, or reel |
87
+ | `create_and_publish_post` | Create and publish immediately |
88
+ | `update_post` | Update a draft or scheduled post |
89
+ | `delete_post` | Delete a post |
90
+ | `publish_post` | Publish a draft or scheduled post now |
91
+
92
+ ### Media (3 tools)
93
+
94
+ | Tool | Description |
95
+ |------|-------------|
96
+ | `list_media` | List all media files |
97
+ | `upload_media` | Upload media from a URL (max 50MB) |
98
+ | `delete_media` | Delete a media file |
99
+
100
+ ### Accounts (2 tools)
101
+
102
+ | Tool | Description |
103
+ |------|-------------|
104
+ | `list_accounts` | List connected social media accounts |
105
+ | `get_account` | Get account details |
106
+
107
+ ### Analytics (3 tools)
108
+
109
+ | Tool | Description |
110
+ |------|-------------|
111
+ | `get_post_analytics` | Get stats for a published post |
112
+ | `get_analytics_overview` | Overview analytics for a time period |
113
+ | `get_account_analytics` | Account-level analytics (followers, etc.) |
114
+
115
+ ### Webhooks (5 tools)
116
+
117
+ | Tool | Description |
118
+ |------|-------------|
119
+ | `list_webhooks` | List all webhooks |
120
+ | `create_webhook` | Create a webhook for event notifications |
121
+ | `get_webhook` | Get webhook details |
122
+ | `update_webhook` | Update a webhook |
123
+ | `delete_webhook` | Delete a webhook |
124
+ | `rotate_webhook_secret` | Rotate a webhook's signing secret |
125
+
126
+ ## Environment Variables
127
+
128
+ | Variable | Required | Description |
129
+ |----------|----------|-------------|
130
+ | `OMNISOCIALS_API_KEY` | Yes | Your API key (`omsk_live_*` or `omsk_test_*`) |
131
+ | `OMNISOCIALS_BASE_URL` | No | Custom API base URL (defaults to production) |
132
+
133
+ ## API Documentation
134
+
135
+ Full API docs: [docs.omnisocials.com](https://docs.omnisocials.com)
136
+
137
+ ## License
138
+
139
+ MIT
@@ -0,0 +1,87 @@
1
+ import type { ApiResponse } from "./types.js";
2
+ export declare class OmniSocialsClient {
3
+ private baseUrl;
4
+ private apiKey;
5
+ constructor(apiKey: string, baseUrl?: string);
6
+ request<T = unknown>(method: string, path: string, body?: unknown, queryParams?: Record<string, string>): Promise<ApiResponse<T>>;
7
+ listPosts(params?: {
8
+ status?: string;
9
+ limit?: string;
10
+ offset?: string;
11
+ }): Promise<ApiResponse<unknown>>;
12
+ getPost(id: string): Promise<ApiResponse<unknown>>;
13
+ createPost(data: {
14
+ content: string;
15
+ channels?: string[];
16
+ scheduled_at?: string;
17
+ media_ids?: string[] | Record<string, string[]>;
18
+ media_urls?: string[] | Record<string, string[]>;
19
+ type?: string;
20
+ pinterest?: Record<string, unknown>;
21
+ youtube?: Record<string, unknown>;
22
+ instagram?: Record<string, unknown>;
23
+ tiktok?: Record<string, unknown>;
24
+ x?: Record<string, unknown>;
25
+ }): Promise<ApiResponse<unknown>>;
26
+ createAndPublishPost(data: {
27
+ content: string;
28
+ channels?: string[];
29
+ media_ids?: string[] | Record<string, string[]>;
30
+ media_urls?: string[] | Record<string, string[]>;
31
+ type?: string;
32
+ pinterest?: Record<string, unknown>;
33
+ youtube?: Record<string, unknown>;
34
+ instagram?: Record<string, unknown>;
35
+ tiktok?: Record<string, unknown>;
36
+ x?: Record<string, unknown>;
37
+ }): Promise<ApiResponse<unknown>>;
38
+ updatePost(id: string, data: {
39
+ content?: string;
40
+ scheduled_at?: string;
41
+ channels?: string[];
42
+ media_ids?: string[] | Record<string, string[]>;
43
+ media_urls?: string[] | Record<string, string[]>;
44
+ type?: string;
45
+ pinterest?: Record<string, unknown>;
46
+ youtube?: Record<string, unknown>;
47
+ instagram?: Record<string, unknown>;
48
+ tiktok?: Record<string, unknown>;
49
+ x?: Record<string, unknown>;
50
+ }): Promise<ApiResponse<unknown>>;
51
+ deletePost(id: string): Promise<ApiResponse<unknown>>;
52
+ publishPost(id: string): Promise<ApiResponse<unknown>>;
53
+ listMedia(params?: {
54
+ limit?: string;
55
+ offset?: string;
56
+ }): Promise<ApiResponse<unknown>>;
57
+ uploadMedia(data: {
58
+ url: string;
59
+ filename?: string;
60
+ }): Promise<ApiResponse<unknown>>;
61
+ deleteMedia(id: string): Promise<ApiResponse<unknown>>;
62
+ listAccounts(): Promise<ApiResponse<unknown>>;
63
+ getAccount(id: string): Promise<ApiResponse<unknown>>;
64
+ getPostAnalytics(postId: string): Promise<ApiResponse<unknown>>;
65
+ getAnalyticsOverview(params?: {
66
+ period?: string;
67
+ start_date?: string;
68
+ end_date?: string;
69
+ }): Promise<ApiResponse<unknown>>;
70
+ getAccountAnalytics(params?: {
71
+ platform?: string;
72
+ date?: string;
73
+ }): Promise<ApiResponse<unknown>>;
74
+ listWebhooks(): Promise<ApiResponse<unknown>>;
75
+ createWebhook(data: {
76
+ url: string;
77
+ events: string[];
78
+ }): Promise<ApiResponse<unknown>>;
79
+ deleteWebhook(id: string): Promise<ApiResponse<unknown>>;
80
+ getWebhook(id: string): Promise<ApiResponse<unknown>>;
81
+ updateWebhook(id: string, data: {
82
+ url?: string;
83
+ events?: string[];
84
+ is_active?: boolean;
85
+ }): Promise<ApiResponse<unknown>>;
86
+ rotateWebhookSecret(id: string): Promise<ApiResponse<unknown>>;
87
+ }
@@ -0,0 +1,108 @@
1
+ export class OmniSocialsClient {
2
+ baseUrl;
3
+ apiKey;
4
+ constructor(apiKey, baseUrl) {
5
+ this.apiKey = apiKey;
6
+ this.baseUrl =
7
+ baseUrl || "https://app.omnisocials.com/api/v1";
8
+ }
9
+ async request(method, path, body, queryParams) {
10
+ let url = `${this.baseUrl}${path}`;
11
+ if (queryParams) {
12
+ const params = new URLSearchParams(Object.entries(queryParams).filter(([, v]) => v !== undefined));
13
+ const qs = params.toString();
14
+ if (qs)
15
+ url += `?${qs}`;
16
+ }
17
+ const headers = {
18
+ Authorization: `Bearer ${this.apiKey}`,
19
+ "Content-Type": "application/json",
20
+ };
21
+ const options = { method, headers };
22
+ if (body && (method === "POST" || method === "PATCH" || method === "PUT")) {
23
+ options.body = JSON.stringify(body);
24
+ }
25
+ const response = await fetch(url, options);
26
+ if (response.status === 204) {
27
+ return { data: undefined };
28
+ }
29
+ const json = await response.json();
30
+ if (!response.ok) {
31
+ return {
32
+ error: json.error || {
33
+ code: "api_error",
34
+ message: `Request failed with status ${response.status}`,
35
+ },
36
+ };
37
+ }
38
+ return json;
39
+ }
40
+ // Posts
41
+ async listPosts(params) {
42
+ return this.request("GET", "/posts", undefined, params);
43
+ }
44
+ async getPost(id) {
45
+ return this.request("GET", `/posts/${id}`);
46
+ }
47
+ async createPost(data) {
48
+ return this.request("POST", "/posts/create", data);
49
+ }
50
+ async createAndPublishPost(data) {
51
+ return this.request("POST", "/posts/create-and-publish", data);
52
+ }
53
+ async updatePost(id, data) {
54
+ return this.request("PATCH", `/posts/${id}`, data);
55
+ }
56
+ async deletePost(id) {
57
+ return this.request("DELETE", `/posts/${id}`);
58
+ }
59
+ async publishPost(id) {
60
+ return this.request("POST", `/posts/${id}/publish`);
61
+ }
62
+ // Media
63
+ async listMedia(params) {
64
+ return this.request("GET", "/media", undefined, params);
65
+ }
66
+ async uploadMedia(data) {
67
+ return this.request("POST", "/media/upload-from-url", data);
68
+ }
69
+ async deleteMedia(id) {
70
+ return this.request("DELETE", `/media/${id}`);
71
+ }
72
+ // Accounts
73
+ async listAccounts() {
74
+ return this.request("GET", "/accounts");
75
+ }
76
+ async getAccount(id) {
77
+ return this.request("GET", `/accounts/${id}`);
78
+ }
79
+ // Analytics
80
+ async getPostAnalytics(postId) {
81
+ return this.request("GET", `/analytics/posts/${postId}`);
82
+ }
83
+ async getAnalyticsOverview(params) {
84
+ return this.request("GET", "/analytics/overview", undefined, params);
85
+ }
86
+ async getAccountAnalytics(params) {
87
+ return this.request("GET", "/analytics/accounts", undefined, params);
88
+ }
89
+ // Webhooks
90
+ async listWebhooks() {
91
+ return this.request("GET", "/webhooks");
92
+ }
93
+ async createWebhook(data) {
94
+ return this.request("POST", "/webhooks", data);
95
+ }
96
+ async deleteWebhook(id) {
97
+ return this.request("DELETE", `/webhooks/${id}`);
98
+ }
99
+ async getWebhook(id) {
100
+ return this.request("GET", `/webhooks/${id}`);
101
+ }
102
+ async updateWebhook(id, data) {
103
+ return this.request("PATCH", `/webhooks/${id}`, data);
104
+ }
105
+ async rotateWebhookSecret(id) {
106
+ return this.request("POST", `/webhooks/${id}/rotate-secret`);
107
+ }
108
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { OmniSocialsClient } from "./client.js";
5
+ import { registerPostTools } from "./tools/posts.js";
6
+ import { registerMediaTools } from "./tools/media.js";
7
+ import { registerAccountTools } from "./tools/accounts.js";
8
+ import { registerAnalyticsTools } from "./tools/analytics.js";
9
+ import { registerWebhookTools } from "./tools/webhooks.js";
10
+ const apiKey = process.env.OMNISOCIALS_API_KEY;
11
+ if (!apiKey) {
12
+ console.error("Error: OMNISOCIALS_API_KEY environment variable is required.");
13
+ console.error("Get your API key from OmniSocials Settings > API.");
14
+ process.exit(1);
15
+ }
16
+ const baseUrl = process.env.OMNISOCIALS_BASE_URL;
17
+ const client = new OmniSocialsClient(apiKey, baseUrl);
18
+ const server = new McpServer({
19
+ name: "OmniSocials",
20
+ version: "1.0.0",
21
+ });
22
+ // Register all tools
23
+ registerPostTools(server, client);
24
+ registerMediaTools(server, client);
25
+ registerAccountTools(server, client);
26
+ registerAnalyticsTools(server, client);
27
+ registerWebhookTools(server, client);
28
+ // Start the server
29
+ async function main() {
30
+ const transport = new StdioServerTransport();
31
+ await server.connect(transport);
32
+ }
33
+ main().catch((error) => {
34
+ console.error("Failed to start MCP server:", error);
35
+ process.exit(1);
36
+ });
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerAccountTools(server: McpServer, client: OmniSocialsClient): void;
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ export function registerAccountTools(server, client) {
3
+ server.tool("list_accounts", "List all connected social media accounts in the workspace.", {}, async () => {
4
+ const result = await client.listAccounts();
5
+ return {
6
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
7
+ };
8
+ });
9
+ server.tool("get_account", "Get details of a specific connected social media account.", {
10
+ id: z.string().describe("The account ID"),
11
+ }, async ({ id }) => {
12
+ const result = await client.getAccount(id);
13
+ return {
14
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
15
+ };
16
+ });
17
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerAnalyticsTools(server: McpServer, client: OmniSocialsClient): void;
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ export function registerAnalyticsTools(server, client) {
3
+ server.tool("get_post_analytics", "Get analytics/statistics for a specific published post (impressions, engagements, likes, etc.).", {
4
+ post_id: z.string().describe("The post ID to get analytics for"),
5
+ }, async ({ post_id }) => {
6
+ const result = await client.getPostAnalytics(post_id);
7
+ return {
8
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
9
+ };
10
+ });
11
+ server.tool("get_analytics_overview", "Get an overview of analytics across all posts and accounts for a time period.", {
12
+ period: z.string().optional().describe("Time period: 7d, 30d, 90d (default: 30d)"),
13
+ start_date: z.string().optional().describe("Custom start date (ISO 8601)"),
14
+ end_date: z.string().optional().describe("Custom end date (ISO 8601)"),
15
+ }, async (params) => {
16
+ const result = await client.getAnalyticsOverview(params);
17
+ return {
18
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
19
+ };
20
+ });
21
+ server.tool("get_account_analytics", "Get account-level analytics (followers, subscribers, etc.) for connected social accounts.", {
22
+ platform: z.string().optional().describe("Filter by platform (e.g., instagram, youtube)"),
23
+ date: z.string().optional().describe("Date to get analytics for (YYYY-MM-DD, defaults to today)"),
24
+ }, async (params) => {
25
+ const result = await client.getAccountAnalytics(params);
26
+ return {
27
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
28
+ };
29
+ });
30
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerMediaTools(server: McpServer, client: OmniSocialsClient): void;
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ export function registerMediaTools(server, client) {
3
+ server.tool("list_media", "List all media files in the workspace.", {
4
+ limit: z.string().optional().describe("Max results to return"),
5
+ offset: z.string().optional().describe("Offset for pagination"),
6
+ }, async (params) => {
7
+ const result = await client.listMedia(params);
8
+ return {
9
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
10
+ };
11
+ });
12
+ server.tool("upload_media", "Upload media from a URL. The file will be downloaded and stored. Max 50MB.", {
13
+ url: z.string().describe("Public URL of the media file to upload"),
14
+ filename: z.string().optional().describe("Optional filename for the uploaded media"),
15
+ }, async (params) => {
16
+ const result = await client.uploadMedia(params);
17
+ return {
18
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
19
+ };
20
+ });
21
+ server.tool("delete_media", "Delete a media file by ID.", {
22
+ id: z.string().describe("The media ID to delete"),
23
+ }, async ({ id }) => {
24
+ const result = await client.deleteMedia(id);
25
+ return {
26
+ content: [{ type: "text", text: result.error ? JSON.stringify(result.error) : "Media deleted successfully." }],
27
+ };
28
+ });
29
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerPostTools(server: McpServer, client: OmniSocialsClient): void;
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ export function registerPostTools(server, client) {
3
+ server.tool("list_posts", "List all posts in the workspace. Optionally filter by status.", {
4
+ status: z.string().optional().describe("Filter by status: draft, scheduled, published, failed"),
5
+ limit: z.string().optional().describe("Max results to return (default: 20)"),
6
+ offset: z.string().optional().describe("Offset for pagination"),
7
+ }, async (params) => {
8
+ const result = await client.listPosts(params);
9
+ return {
10
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
11
+ };
12
+ });
13
+ server.tool("get_post", "Get details of a specific post by ID.", {
14
+ id: z.string().describe("The post ID"),
15
+ }, async ({ id }) => {
16
+ const result = await client.getPost(id);
17
+ return {
18
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
19
+ };
20
+ });
21
+ server.tool("create_post", "Create a new social media post, story, or reel. Specify content, target channels, type, and optional platform-specific options.", {
22
+ content: z.string().describe("The post content/caption text"),
23
+ channels: z.array(z.string()).optional().describe("Array of channel IDs to post to"),
24
+ scheduled_at: z.string().optional().describe("ISO 8601 date for scheduled publishing"),
25
+ media_ids: z.union([
26
+ z.array(z.string()),
27
+ z.record(z.string(), z.array(z.string())),
28
+ ]).optional().describe("Media IDs from upload — flat array (same for all platforms) or object with platform keys: { default: [...], instagram: [...] }"),
29
+ media_urls: z.union([
30
+ z.array(z.string()),
31
+ z.record(z.string(), z.array(z.string())),
32
+ ]).optional().describe("External image/video URLs — flat array (same for all platforms) or object with platform keys: { default: [...], instagram: [...], pinterest: [...] }. Max 10 total."),
33
+ type: z.enum(["post", "story", "reel"]).optional().describe("Content type: 'post' (default), 'story' (Instagram/Facebook/Snapchat), 'reel' (Instagram/Facebook/YouTube/TikTok)"),
34
+ pinterest: z.object({
35
+ board_id: z.string().optional(),
36
+ title: z.string().optional(),
37
+ link: z.string().optional(),
38
+ }).optional().describe("Pinterest-specific options"),
39
+ youtube: z.object({
40
+ title: z.string().optional(),
41
+ tags: z.array(z.string()).optional(),
42
+ privacy_status: z.enum(["public", "private", "unlisted"]).optional(),
43
+ category_id: z.string().optional(),
44
+ made_for_kids: z.boolean().optional(),
45
+ notify_subscribers: z.boolean().optional(),
46
+ contains_synthetic_media: z.boolean().optional(),
47
+ }).optional().describe("YouTube Shorts options"),
48
+ instagram: z.object({
49
+ share_to_feed: z.boolean().optional(),
50
+ thumbnail_type: z.enum(["from-video", "from-library"]).optional(),
51
+ thumb_offset: z.number().optional(),
52
+ cover_url: z.string().optional(),
53
+ }).optional().describe("Instagram Reel options"),
54
+ tiktok: z.object({
55
+ privacy_level: z.enum(["PUBLIC_TO_EVERYONE", "MUTUAL_FOLLOW_FRIENDS", "FOLLOWER_OF_CREATOR", "SELF_ONLY"]).optional(),
56
+ disable_comment: z.boolean().optional(),
57
+ disable_duet: z.boolean().optional(),
58
+ disable_stitch: z.boolean().optional(),
59
+ is_aigc: z.boolean().optional(),
60
+ brand_content_toggle: z.boolean().optional(),
61
+ }).optional().describe("TikTok options"),
62
+ x: z.object({
63
+ reply_settings: z.enum(["", "following", "mentionedUsers"]).optional(),
64
+ }).optional().describe("X (Twitter) options"),
65
+ }, async (params) => {
66
+ const result = await client.createPost(params);
67
+ return {
68
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
69
+ };
70
+ });
71
+ server.tool("create_and_publish_post", "Create a new post and publish it immediately to all selected platforms. No scheduling needed.", {
72
+ content: z.string().describe("The post content/caption text"),
73
+ channels: z.array(z.string()).optional().describe("Array of channel IDs to post to"),
74
+ media_ids: z.union([
75
+ z.array(z.string()),
76
+ z.record(z.string(), z.array(z.string())),
77
+ ]).optional().describe("Media IDs from upload — flat array or per-platform object"),
78
+ media_urls: z.union([
79
+ z.array(z.string()),
80
+ z.record(z.string(), z.array(z.string())),
81
+ ]).optional().describe("External image/video URLs — flat array or per-platform object. Max 10 total."),
82
+ type: z.enum(["post", "story", "reel"]).optional().describe("Content type: 'post' (default), 'story', 'reel'"),
83
+ pinterest: z.object({
84
+ board_id: z.string().optional(),
85
+ title: z.string().optional(),
86
+ link: z.string().optional(),
87
+ }).optional().describe("Pinterest-specific options"),
88
+ youtube: z.object({
89
+ title: z.string().optional(),
90
+ tags: z.array(z.string()).optional(),
91
+ privacy_status: z.enum(["public", "private", "unlisted"]).optional(),
92
+ }).optional().describe("YouTube Shorts options"),
93
+ tiktok: z.object({
94
+ privacy_level: z.enum(["PUBLIC_TO_EVERYONE", "MUTUAL_FOLLOW_FRIENDS", "FOLLOWER_OF_CREATOR", "SELF_ONLY"]).optional(),
95
+ }).optional().describe("TikTok options"),
96
+ }, async (params) => {
97
+ const result = await client.createAndPublishPost(params);
98
+ return {
99
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
100
+ };
101
+ });
102
+ server.tool("update_post", "Update an existing post. Only draft and scheduled posts can be updated.", {
103
+ id: z.string().describe("The post ID to update"),
104
+ content: z.string().optional().describe("Updated post content"),
105
+ scheduled_at: z.string().optional().describe("Updated scheduled date (ISO 8601)"),
106
+ channels: z.array(z.string()).optional().describe("Updated channel IDs"),
107
+ media_ids: z.union([
108
+ z.array(z.string()),
109
+ z.record(z.string(), z.array(z.string())),
110
+ ]).optional().describe("Media IDs — flat array or per-platform object"),
111
+ media_urls: z.union([
112
+ z.array(z.string()),
113
+ z.record(z.string(), z.array(z.string())),
114
+ ]).optional().describe("External URLs — flat array or per-platform object. Max 10 total."),
115
+ }, async ({ id, ...data }) => {
116
+ const result = await client.updatePost(id, data);
117
+ return {
118
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
119
+ };
120
+ });
121
+ server.tool("delete_post", "Delete a post by ID. This action cannot be undone.", {
122
+ id: z.string().describe("The post ID to delete"),
123
+ }, async ({ id }) => {
124
+ const result = await client.deletePost(id);
125
+ return {
126
+ content: [{ type: "text", text: result.error ? JSON.stringify(result.error) : "Post deleted successfully." }],
127
+ };
128
+ });
129
+ server.tool("publish_post", "Publish a draft or scheduled post immediately. The post will be queued for immediate publishing.", {
130
+ id: z.string().describe("The post ID to publish"),
131
+ }, async ({ id }) => {
132
+ const result = await client.publishPost(id);
133
+ return {
134
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
135
+ };
136
+ });
137
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { OmniSocialsClient } from "../client.js";
3
+ export declare function registerWebhookTools(server: McpServer, client: OmniSocialsClient): void;
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ export function registerWebhookTools(server, client) {
3
+ server.tool("list_webhooks", "List all configured webhooks.", {}, async () => {
4
+ const result = await client.listWebhooks();
5
+ return {
6
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
7
+ };
8
+ });
9
+ server.tool("create_webhook", "Create a new webhook to receive event notifications. Available events: post.scheduled, post.published, post.failed", {
10
+ url: z.string().describe("The HTTPS URL to send webhook events to"),
11
+ events: z.array(z.string()).describe("Events to subscribe to: post.scheduled, post.published, post.failed"),
12
+ }, async (params) => {
13
+ const result = await client.createWebhook(params);
14
+ return {
15
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
16
+ };
17
+ });
18
+ server.tool("get_webhook", "Get details of a specific webhook by ID.", {
19
+ id: z.string().describe("The webhook ID"),
20
+ }, async ({ id }) => {
21
+ const result = await client.getWebhook(id);
22
+ return {
23
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
24
+ };
25
+ });
26
+ server.tool("update_webhook", "Update a webhook's URL, events, or active status.", {
27
+ id: z.string().describe("The webhook ID to update"),
28
+ url: z.string().optional().describe("Updated HTTPS URL"),
29
+ events: z.array(z.string()).optional().describe("Updated event list"),
30
+ is_active: z.boolean().optional().describe("Enable or disable the webhook"),
31
+ }, async ({ id, ...data }) => {
32
+ const result = await client.updateWebhook(id, data);
33
+ return {
34
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
35
+ };
36
+ });
37
+ server.tool("delete_webhook", "Delete a webhook by ID. You will stop receiving notifications at this URL.", {
38
+ id: z.string().describe("The webhook ID to delete"),
39
+ }, async ({ id }) => {
40
+ const result = await client.deleteWebhook(id);
41
+ return {
42
+ content: [{ type: "text", text: result.error ? JSON.stringify(result.error) : "Webhook deleted successfully." }],
43
+ };
44
+ });
45
+ server.tool("rotate_webhook_secret", "Rotate the signing secret for a webhook. The new secret will only be shown once.", {
46
+ id: z.string().describe("The webhook ID"),
47
+ }, async ({ id }) => {
48
+ const result = await client.rotateWebhookSecret(id);
49
+ return {
50
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
51
+ };
52
+ });
53
+ }
@@ -0,0 +1,56 @@
1
+ export interface ApiResponse<T = unknown> {
2
+ data?: T;
3
+ error?: {
4
+ code: string;
5
+ message: string;
6
+ };
7
+ }
8
+ export interface Post {
9
+ id: string;
10
+ content: string;
11
+ status: string;
12
+ scheduled_at: string | null;
13
+ published_at: string | null;
14
+ channels: string[];
15
+ media: string[];
16
+ created_at: string;
17
+ }
18
+ export interface MediaItem {
19
+ id: string;
20
+ url: string;
21
+ type: string;
22
+ filename: string;
23
+ size: number;
24
+ created_at: string;
25
+ }
26
+ export interface Account {
27
+ id: string;
28
+ platform: string;
29
+ username: string;
30
+ profile_picture: string | null;
31
+ is_connected: boolean;
32
+ }
33
+ export interface Webhook {
34
+ id: string;
35
+ url: string;
36
+ events: string[];
37
+ is_active: boolean;
38
+ last_triggered_at: string | null;
39
+ failure_count: number;
40
+ created_at: string;
41
+ }
42
+ export interface AnalyticsOverview {
43
+ total_posts: number;
44
+ total_impressions: number;
45
+ total_engagements: number;
46
+ period: string;
47
+ }
48
+ export interface PostAnalytics {
49
+ post_id: string;
50
+ impressions: number;
51
+ engagements: number;
52
+ likes: number;
53
+ comments: number;
54
+ shares: number;
55
+ platform_stats: Record<string, unknown>;
56
+ }
package/build/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@omnisocials/mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for OmniSocials API - manage social media posts, media, accounts, analytics, and webhooks",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "omnisocials-mcp": "build/index.js"
9
+ },
10
+ "files": [
11
+ "build/"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "start": "node build/index.js",
17
+ "prepare": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "omnisocials",
22
+ "social-media",
23
+ "claude",
24
+ "model-context-protocol",
25
+ "ai"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/omnisocials/mcp-server"
30
+ },
31
+ "homepage": "https://docs.omnisocials.com",
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ },
35
+ "license": "MIT",
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.12.1"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.3.3",
41
+ "typescript": "^5.8.2"
42
+ }
43
+ }