postfast-mcp 0.1.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,91 @@
1
+ # PostFast MCP Server
2
+
3
+ MCP server for the [PostFast](https://postfa.st) API — schedule and manage social media posts via AI tools like Claude.
4
+
5
+ ## Setup
6
+
7
+ ### 1. Get your API key
8
+
9
+ Go to **PostFast → Workspace Settings → API Key** and generate a key.
10
+
11
+ ### 2. Configure in Claude Code
12
+
13
+ Add to your `.mcp.json` (project) or `~/.claude.json` (global):
14
+
15
+ ```json
16
+ {
17
+ "mcpServers": {
18
+ "postfast": {
19
+ "type": "stdio",
20
+ "command": "npx",
21
+ "args": ["postfast-mcp"],
22
+ "env": {
23
+ "POSTFAST_API_KEY": "your-api-key-here"
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ ### 3. Use it
31
+
32
+ Ask Claude things like:
33
+
34
+ - "List my connected social accounts"
35
+ - "Schedule a post to Instagram for tomorrow at 9am"
36
+ - "Show me all scheduled posts for this week"
37
+ - "Upload this image and create a LinkedIn post with it"
38
+
39
+ ## Available Tools
40
+
41
+ | Tool | Description |
42
+ |------|-------------|
43
+ | `list_posts` | List posts with filters (platform, status, date range) |
44
+ | `create_posts` | Create and schedule posts (batch, up to 15) |
45
+ | `delete_post` | Delete a post by ID |
46
+ | `list_accounts` | List connected social media accounts |
47
+ | `list_pinterest_boards` | Get Pinterest boards for an account |
48
+ | `list_youtube_playlists` | Get YouTube playlists for an account |
49
+ | `generate_connect_link` | Generate a link for clients to connect accounts |
50
+ | `get_upload_urls` | Get signed URLs to upload media files |
51
+ | `upload_media` | Upload a local file and get a media key (handles the full flow) |
52
+
53
+ ## Supported Platforms
54
+
55
+ Facebook, Instagram, X (Twitter), TikTok, LinkedIn, YouTube, BlueSky, Threads, Pinterest, Telegram
56
+
57
+ ## Media Upload
58
+
59
+ The `upload_media` tool handles the full flow in a single call:
60
+
61
+ 1. Detects content type from file extension
62
+ 2. Gets a signed upload URL from PostFast
63
+ 3. Uploads the file
64
+ 4. Returns a `key` and `type` ready to use in `create_posts`
65
+
66
+ Supported formats: JPEG, PNG, GIF, WebP, MP4, WebM, MOV
67
+
68
+ You can also use `get_upload_urls` directly if you need more control over the upload process.
69
+
70
+ ## Environment Variables
71
+
72
+ | Variable | Required | Description |
73
+ |----------|----------|-------------|
74
+ | `POSTFAST_API_KEY` | Yes | Your workspace API key |
75
+ | `POSTFAST_API_URL` | No | API base URL (default: `https://api.postfa.st`) |
76
+
77
+ ## API Docs
78
+
79
+ Full REST API documentation: [postfa.st/docs](https://postfa.st/docs)
80
+
81
+ ## Development
82
+
83
+ ```bash
84
+ npm install
85
+ npm run build
86
+ node dist/index.js
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,9 @@
1
+ export declare class PostFastClient {
2
+ private baseUrl;
3
+ private apiKey;
4
+ constructor();
5
+ request<T>(method: string, path: string, body?: unknown, query?: Record<string, string | undefined>): Promise<T>;
6
+ get<T>(path: string, query?: Record<string, string | undefined>): Promise<T>;
7
+ post<T>(path: string, body?: unknown): Promise<T>;
8
+ delete<T>(path: string): Promise<T>;
9
+ }
package/dist/client.js ADDED
@@ -0,0 +1,57 @@
1
+ const DEFAULT_BASE_URL = 'https://api.postfa.st';
2
+ export class PostFastClient {
3
+ baseUrl;
4
+ apiKey;
5
+ constructor() {
6
+ this.apiKey = process.env.POSTFAST_API_KEY ?? '';
7
+ this.baseUrl = (process.env.POSTFAST_API_URL ?? DEFAULT_BASE_URL).replace(/\/$/, '');
8
+ if (!this.apiKey) {
9
+ throw new Error('POSTFAST_API_KEY environment variable is required. Generate one in PostFast → Workspace Settings → API Key.');
10
+ }
11
+ }
12
+ async request(method, path, body, query) {
13
+ const url = new URL(`${this.baseUrl}${path}`);
14
+ if (query) {
15
+ for (const [key, value] of Object.entries(query)) {
16
+ if (value !== undefined && value !== '') {
17
+ url.searchParams.set(key, value);
18
+ }
19
+ }
20
+ }
21
+ const headers = {
22
+ 'pf-api-key': this.apiKey,
23
+ 'Content-Type': 'application/json',
24
+ };
25
+ const response = await fetch(url.toString(), {
26
+ method,
27
+ headers,
28
+ body: body ? JSON.stringify(body) : undefined,
29
+ });
30
+ if (!response.ok) {
31
+ const text = await response.text();
32
+ let message;
33
+ try {
34
+ const json = JSON.parse(text);
35
+ message = json.message ?? json.error ?? text;
36
+ }
37
+ catch {
38
+ message = text;
39
+ }
40
+ throw new Error(`PostFast API error (${response.status}): ${message}`);
41
+ }
42
+ const text = await response.text();
43
+ if (!text)
44
+ return undefined;
45
+ return JSON.parse(text);
46
+ }
47
+ get(path, query) {
48
+ return this.request('GET', path, undefined, query);
49
+ }
50
+ post(path, body) {
51
+ return this.request('POST', path, body);
52
+ }
53
+ delete(path) {
54
+ return this.request('DELETE', path);
55
+ }
56
+ }
57
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD,MAAM,OAAO,cAAc;IACjB,OAAO,CAAS;IAChB,MAAM,CAAS;IAEvB;QACE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,OAAO,CACvE,KAAK,EACL,EAAE,CACH,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,6GAA6G,CAC9G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CACX,MAAc,EACd,IAAY,EACZ,IAAc,EACd,KAA0C;QAE1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC;QAE9C,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;oBACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,YAAY,EAAE,IAAI,CAAC,MAAM;YACzB,cAAc,EAAE,kBAAkB;SACnC,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,OAAe,CAAC;YAEpB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9B,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,SAAc,CAAC;QAEjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAED,GAAG,CAAI,IAAY,EAAE,KAA0C;QAC7D,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,CAAI,IAAY,EAAE,IAAc;QAClC,OAAO,IAAI,CAAC,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAI,IAAY;QACpB,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
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 { PostFastClient } from './client.js';
5
+ import { registerPostTools } from './tools/posts.js';
6
+ import { registerAccountTools } from './tools/accounts.js';
7
+ import { registerFileTools } from './tools/files.js';
8
+ const server = new McpServer({
9
+ name: 'postfast',
10
+ version: '0.1.0',
11
+ });
12
+ const client = new PostFastClient();
13
+ registerPostTools(server, client);
14
+ registerAccountTools(server, client);
15
+ registerFileTools(server, client);
16
+ const transport = new StdioServerTransport();
17
+ await server.connect(transport);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;AAEpC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { PostFastClient } from '../client.js';
3
+ export declare function registerAccountTools(server: McpServer, client: PostFastClient): void;
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ export function registerAccountTools(server, client) {
3
+ server.tool('list_accounts', 'List all social media accounts connected to the workspace', {}, async () => {
4
+ const data = await client.get('/social-media/my-social-accounts');
5
+ return {
6
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
7
+ };
8
+ });
9
+ server.tool('list_pinterest_boards', 'List Pinterest boards for a connected Pinterest account', {
10
+ socialMediaId: z
11
+ .string()
12
+ .uuid()
13
+ .describe('Pinterest account ID (from list_accounts)'),
14
+ }, async (input) => {
15
+ const data = await client.get(`/social-media/${input.socialMediaId}/pinterest-boards`);
16
+ return {
17
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
18
+ };
19
+ });
20
+ server.tool('list_youtube_playlists', 'List YouTube playlists for a connected YouTube account', {
21
+ socialMediaId: z
22
+ .string()
23
+ .uuid()
24
+ .describe('YouTube account ID (from list_accounts)'),
25
+ }, async (input) => {
26
+ const data = await client.get(`/social-media/${input.socialMediaId}/youtube-playlists`);
27
+ return {
28
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
29
+ };
30
+ });
31
+ server.tool('generate_connect_link', 'Generate a shareable link for external clients to connect their social accounts to the workspace', {
32
+ expiryDays: z
33
+ .number()
34
+ .int()
35
+ .min(1)
36
+ .max(30)
37
+ .default(7)
38
+ .describe('Link expiry in days (1-30, default 7)'),
39
+ sendEmail: z
40
+ .boolean()
41
+ .default(false)
42
+ .describe('Send the link via email'),
43
+ email: z
44
+ .string()
45
+ .email()
46
+ .optional()
47
+ .describe('Recipient email (required if sendEmail is true)'),
48
+ }, async (input) => {
49
+ const data = await client.post('/social-media/connect-link', {
50
+ expiryDays: input.expiryDays,
51
+ sendEmail: input.sendEmail,
52
+ email: input.email,
53
+ });
54
+ return {
55
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
56
+ };
57
+ });
58
+ }
59
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/tools/accounts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,MAAM,UAAU,oBAAoB,CAClC,MAAiB,EACjB,MAAsB;IAEtB,MAAM,CAAC,IAAI,CACT,eAAe,EACf,2DAA2D,EAC3D,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,kCAAkC,CACnC,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,yDAAyD,EACzD;QACE,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,IAAI,EAAE;aACN,QAAQ,CAAC,2CAA2C,CAAC;KACzD,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,iBAAiB,KAAK,CAAC,aAAa,mBAAmB,CACxD,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,wDAAwD,EACxD;QACE,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,IAAI,EAAE;aACN,QAAQ,CAAC,yCAAyC,CAAC;KACvD,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,iBAAiB,KAAK,CAAC,aAAa,oBAAoB,CACzD,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,kGAAkG,EAClG;QACE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,OAAO,CAAC,CAAC,CAAC;aACV,QAAQ,CAAC,uCAAuC,CAAC;QACpD,SAAS,EAAE,CAAC;aACT,OAAO,EAAE;aACT,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CAAC,yBAAyB,CAAC;QACtC,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,KAAK,EAAE;aACP,QAAQ,EAAE;aACV,QAAQ,CAAC,iDAAiD,CAAC;KAC/D,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAC5B,4BAA4B,EAC5B;YACE,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CACF,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { PostFastClient } from '../client.js';
3
+ export declare function registerFileTools(server: McpServer, client: PostFastClient): void;
@@ -0,0 +1,81 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { extname } from 'node:path';
3
+ import { z } from 'zod';
4
+ const MIME_MAP = {
5
+ '.jpg': 'image/jpeg',
6
+ '.jpeg': 'image/jpeg',
7
+ '.png': 'image/png',
8
+ '.gif': 'image/gif',
9
+ '.webp': 'image/webp',
10
+ '.mp4': 'video/mp4',
11
+ '.webm': 'video/webm',
12
+ '.mov': 'video/quicktime',
13
+ };
14
+ const IMAGE_TYPES = [
15
+ 'image/jpeg',
16
+ 'image/png',
17
+ 'image/gif',
18
+ 'image/webp',
19
+ ];
20
+ const VIDEO_TYPES = ['video/mp4', 'video/webm', 'video/quicktime'];
21
+ function detectContentType(filePath) {
22
+ const ext = extname(filePath).toLowerCase();
23
+ const mime = MIME_MAP[ext];
24
+ if (!mime) {
25
+ throw new Error(`Unsupported file extension "${ext}". Supported: ${Object.keys(MIME_MAP).join(', ')}`);
26
+ }
27
+ return mime;
28
+ }
29
+ export function registerFileTools(server, client) {
30
+ server.tool('get_upload_urls', 'Get signed upload URLs for media files. Upload your file to the returned URL via PUT, then use the key in create_posts mediaItems.', {
31
+ contentType: z
32
+ .string()
33
+ .describe(`MIME type of the file. Supported: ${[...IMAGE_TYPES, ...VIDEO_TYPES].join(', ')}`),
34
+ count: z
35
+ .number()
36
+ .int()
37
+ .min(1)
38
+ .max(8)
39
+ .default(1)
40
+ .describe('Number of upload URLs (1-8 for images, 1 for videos)'),
41
+ }, async (input) => {
42
+ const data = await client.post('/file/get-signed-upload-urls', {
43
+ contentType: input.contentType,
44
+ count: input.count,
45
+ });
46
+ return {
47
+ content: [
48
+ { type: 'text', text: JSON.stringify(data, null, 2) },
49
+ ],
50
+ };
51
+ });
52
+ server.tool('upload_media', 'Upload a local file to PostFast and get back a media key for use in create_posts. Handles the full flow: detects content type, gets a signed URL, uploads the file, and returns the key and type.', {
53
+ filePath: z
54
+ .string()
55
+ .describe('Absolute path to the local file (e.g. /Users/me/photo.jpg)'),
56
+ }, async (input) => {
57
+ const contentType = detectContentType(input.filePath);
58
+ const isVideo = contentType.startsWith('video/');
59
+ const [uploadUrl] = await client.post('/file/get-signed-upload-urls', { contentType, count: 1 });
60
+ const fileBuffer = await readFile(input.filePath);
61
+ const uploadResponse = await fetch(uploadUrl.signedUrl, {
62
+ method: 'PUT',
63
+ headers: { 'Content-Type': contentType },
64
+ body: fileBuffer,
65
+ });
66
+ if (!uploadResponse.ok) {
67
+ throw new Error(`Upload failed (${uploadResponse.status}): ${await uploadResponse.text()}`);
68
+ }
69
+ const result = {
70
+ key: uploadUrl.key,
71
+ type: isVideo ? 'VIDEO' : 'IMAGE',
72
+ contentType,
73
+ };
74
+ return {
75
+ content: [
76
+ { type: 'text', text: JSON.stringify(result, null, 2) },
77
+ ],
78
+ };
79
+ });
80
+ }
81
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/tools/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { PostFastClient } from '../client.js';
3
+ export declare function registerPostTools(server: McpServer, client: PostFastClient): void;
@@ -0,0 +1,154 @@
1
+ import { z } from 'zod';
2
+ const PLATFORMS = [
3
+ 'FACEBOOK',
4
+ 'INSTAGRAM',
5
+ 'X',
6
+ 'TIKTOK',
7
+ 'LINKEDIN',
8
+ 'YOUTUBE',
9
+ 'BLUESKY',
10
+ 'THREADS',
11
+ 'PINTEREST',
12
+ 'TELEGRAM',
13
+ ];
14
+ const STATUSES = ['DRAFT', 'SCHEDULED', 'PUBLISHED', 'FAILED'];
15
+ export function registerPostTools(server, client) {
16
+ server.tool('list_posts', 'List social media posts with optional filters for platform, status, and date range', {
17
+ page: z.number().int().min(0).default(0).describe('Page number (0-based)'),
18
+ limit: z
19
+ .number()
20
+ .int()
21
+ .min(1)
22
+ .max(50)
23
+ .default(20)
24
+ .describe('Posts per page (max 50)'),
25
+ platforms: z
26
+ .array(z.enum(PLATFORMS))
27
+ .optional()
28
+ .describe('Filter by platforms'),
29
+ statuses: z
30
+ .array(z.enum(STATUSES))
31
+ .optional()
32
+ .describe('Filter by post statuses'),
33
+ from: z
34
+ .string()
35
+ .optional()
36
+ .describe('Start date filter (ISO 8601, e.g. 2025-01-01T00:00:00.000Z)'),
37
+ to: z
38
+ .string()
39
+ .optional()
40
+ .describe('End date filter (ISO 8601, e.g. 2025-01-31T23:59:59.999Z)'),
41
+ }, async (input) => {
42
+ const data = await client.get('/social-posts', {
43
+ page: String(input.page),
44
+ limit: String(input.limit),
45
+ platforms: input.platforms?.join(','),
46
+ statuses: input.statuses?.join(','),
47
+ from: input.from,
48
+ to: input.to,
49
+ });
50
+ return {
51
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
52
+ };
53
+ });
54
+ server.tool('create_posts', 'Create and schedule social media posts. Supports batch creation (up to 15 posts). Each post targets a specific social account.', {
55
+ posts: z
56
+ .array(z.object({
57
+ content: z.string().describe('Post text content'),
58
+ firstComment: z.string().optional().describe('First comment to add after publishing'),
59
+ mediaItems: z
60
+ .array(z.object({
61
+ key: z.string().describe('S3 media key from get_upload_urls'),
62
+ type: z.enum(['IMAGE', 'VIDEO']),
63
+ sortOrder: z.number().int().min(0),
64
+ coverTimestamp: z.string().optional().describe('Video cover timestamp'),
65
+ }))
66
+ .optional()
67
+ .describe('Media attachments'),
68
+ scheduledAt: z
69
+ .string()
70
+ .optional()
71
+ .describe('Schedule time (ISO 8601). Required when status is SCHEDULED.'),
72
+ socialMediaId: z
73
+ .string()
74
+ .uuid()
75
+ .describe('Target social account ID (from list_accounts)'),
76
+ }))
77
+ .min(1)
78
+ .max(15)
79
+ .describe('Array of posts to create'),
80
+ status: z
81
+ .enum(['DRAFT', 'SCHEDULED'])
82
+ .default('SCHEDULED')
83
+ .describe('Post status. SCHEDULED requires scheduledAt on all posts.'),
84
+ approvalStatus: z
85
+ .enum(['PENDING_APPROVAL', 'APPROVED'])
86
+ .default('APPROVED')
87
+ .describe('Approval workflow status'),
88
+ controls: z
89
+ .object({
90
+ // X/Twitter
91
+ xCommunityId: z.string().optional(),
92
+ xQuoteTweetUrl: z.string().optional(),
93
+ xRetweetUrl: z.string().optional(),
94
+ // TikTok
95
+ tiktokPrivacy: z.enum(['PUBLIC', 'MUTUAL_FRIENDS', 'ONLY_ME']).optional(),
96
+ tiktokIsDraft: z.boolean().optional(),
97
+ tiktokAllowComments: z.boolean().optional(),
98
+ tiktokAllowDuet: z.boolean().optional(),
99
+ tiktokAllowStitch: z.boolean().optional(),
100
+ tiktokBrandOrganic: z.boolean().optional(),
101
+ tiktokBrandContent: z.boolean().optional(),
102
+ tiktokAutoAddMusic: z.boolean().optional(),
103
+ // Instagram
104
+ instagramPostToGrid: z.boolean().optional(),
105
+ instagramPublishType: z.enum(['TIMELINE', 'STORY', 'REEL']).optional(),
106
+ instagramCollaborators: z.array(z.string()).optional(),
107
+ // YouTube
108
+ youtubePrivacy: z.enum(['PUBLIC', 'PRIVATE', 'UNLISTED']).optional(),
109
+ youtubeTags: z.array(z.string()).optional(),
110
+ youtubeCategoryId: z.string().optional(),
111
+ youtubeIsShort: z.boolean().optional(),
112
+ youtubeMadeForKids: z.boolean().optional(),
113
+ youtubeTitle: z.string().optional(),
114
+ youtubePlaylistId: z.string().optional(),
115
+ // Facebook
116
+ facebookContentType: z.enum(['POST', 'REEL', 'STORY']).optional(),
117
+ facebookAllowComments: z.boolean().optional(),
118
+ facebookPrivacy: z
119
+ .enum(['PUBLIC', 'FRIENDS_OF_FRIENDS', 'FRIENDS', 'SELF'])
120
+ .optional(),
121
+ facebookCarouselMainLink: z.string().optional(),
122
+ facebookCarouselShowEndCard: z.boolean().optional(),
123
+ facebookReelsCoverImageKey: z.string().optional(),
124
+ facebookReelsCollaborators: z.array(z.string()).optional(),
125
+ // Pinterest
126
+ pinterestBoardId: z.string().optional(),
127
+ pinterestLink: z.string().optional(),
128
+ // LinkedIn
129
+ linkedinAttachmentKey: z.string().optional(),
130
+ linkedinAttachmentTitle: z.string().optional(),
131
+ })
132
+ .optional()
133
+ .describe('Platform-specific controls (shared across all posts in the batch)'),
134
+ }, async (input) => {
135
+ const data = await client.post('/social-posts', {
136
+ posts: input.posts,
137
+ status: input.status,
138
+ approvalStatus: input.approvalStatus,
139
+ controls: input.controls,
140
+ });
141
+ return {
142
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
143
+ };
144
+ });
145
+ server.tool('delete_post', 'Delete a social media post by ID', {
146
+ id: z.string().uuid().describe('Post ID to delete'),
147
+ }, async (input) => {
148
+ const data = await client.delete(`/social-posts/${input.id}`);
149
+ return {
150
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
151
+ };
152
+ });
153
+ }
154
+ //# sourceMappingURL=posts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posts.js","sourceRoot":"","sources":["../../src/tools/posts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,SAAS,GAAG;IAChB,UAAU;IACV,WAAW;IACX,GAAG;IACH,QAAQ;IACR,UAAU;IACV,SAAS;IACT,SAAS;IACT,SAAS;IACT,WAAW;IACX,UAAU;CACF,CAAC;AAEX,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AAExE,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAsB;IACzE,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,oFAAoF,EACpF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAC1E,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,yBAAyB,CAAC;QACtC,SAAS,EAAE,CAAC;aACT,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aACxB,QAAQ,EAAE;aACV,QAAQ,CAAC,qBAAqB,CAAC;QAClC,QAAQ,EAAE,CAAC;aACR,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;aACvB,QAAQ,EAAE;aACV,QAAQ,CAAC,yBAAyB,CAAC;QACtC,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,6DAA6D,CAAC;QAC1E,EAAE,EAAE,CAAC;aACF,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2DAA2D,CAAC;KACzE,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAiB,eAAe,EAAE;YAC7D,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YACxB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YAC1B,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC;YACrC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC;YACnC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,EAAE,EAAE,KAAK,CAAC,EAAE;SACb,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,gIAAgI,EAChI;QACE,KAAK,EAAE,CAAC;aACL,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACjD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;YACrF,UAAU,EAAE,CAAC;iBACV,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;gBACP,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;gBAC7D,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;aACxE,CAAC,CACH;iBACA,QAAQ,EAAE;iBACV,QAAQ,CAAC,mBAAmB,CAAC;YAChC,WAAW,EAAE,CAAC;iBACX,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,8DAA8D,CAC/D;YACH,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,IAAI,EAAE;iBACN,QAAQ,CAAC,+CAA+C,CAAC;SAC7D,CAAC,CACH;aACA,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,QAAQ,CAAC,0BAA0B,CAAC;QACvC,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;aAC5B,OAAO,CAAC,WAAW,CAAC;aACpB,QAAQ,CAAC,2DAA2D,CAAC;QACxE,cAAc,EAAE,CAAC;aACd,IAAI,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;aACtC,OAAO,CAAC,UAAU,CAAC;aACnB,QAAQ,CAAC,0BAA0B,CAAC;QACvC,QAAQ,EAAE,CAAC;aACR,MAAM,CAAC;YACN,YAAY;YACZ,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAClC,SAAS;YACT,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE;YACzE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACrC,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC3C,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACvC,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACzC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC1C,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC1C,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC1C,YAAY;YACZ,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC3C,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE;YACtE,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YACtD,UAAU;YACV,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;YACpE,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YAC3C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACxC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACtC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC1C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACnC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACxC,WAAW;YACX,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;YACjE,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC7C,eAAe,EAAE,CAAC;iBACf,IAAI,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;iBACzD,QAAQ,EAAE;YACb,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC/C,2BAA2B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACnD,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACjD,0BAA0B,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YAC1D,YAAY;YACZ,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACvC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACpC,WAAW;YACX,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC5C,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC/C,CAAC;aACD,QAAQ,EAAE;aACV,QAAQ,CAAC,mEAAmE,CAAC;KACjF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAwB,eAAe,EAAE;YACrE,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,kCAAkC,EAClC;QACE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KACpD,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAC9B,iBAAiB,KAAK,CAAC,EAAE,EAAE,CAC5B,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,103 @@
1
+ export type Platform = 'FACEBOOK' | 'INSTAGRAM' | 'X' | 'TIKTOK' | 'LINKEDIN' | 'YOUTUBE' | 'BLUESKY' | 'THREADS' | 'PINTEREST' | 'TELEGRAM';
2
+ export type PostStatus = 'DRAFT' | 'SCHEDULED' | 'PUBLISHED' | 'FAILED';
3
+ export type ApprovalStatus = 'PENDING_APPROVAL' | 'IN_PROGRESS' | 'APPROVED' | 'REJECTED' | 'NEEDS_WORK';
4
+ export interface SocialPost {
5
+ id: string;
6
+ content: string;
7
+ status: PostStatus;
8
+ approvalStatus: ApprovalStatus;
9
+ socialMediaId: string;
10
+ mediaItems: MediaItem[];
11
+ scheduledAt: string | null;
12
+ publishedAt: string | null;
13
+ failedAt: string | null;
14
+ platformPostId: string | null;
15
+ groupId: string | null;
16
+ firstComment: string | null;
17
+ firstCommentError: string | null;
18
+ lastError: {
19
+ message: string;
20
+ code: string | null;
21
+ } | null;
22
+ }
23
+ export interface MediaItem {
24
+ key: string;
25
+ type: 'IMAGE' | 'VIDEO';
26
+ sortOrder: number;
27
+ url?: string;
28
+ coverTimestamp?: string;
29
+ }
30
+ export interface PaginatedPosts {
31
+ data: SocialPost[];
32
+ totalCount: number;
33
+ pageInfo: {
34
+ page: number;
35
+ hasNextPage: boolean;
36
+ perPage: number;
37
+ };
38
+ }
39
+ export interface SocialAccount {
40
+ id: string;
41
+ platform: Platform;
42
+ platformUsername: string | null;
43
+ displayName: string | null;
44
+ }
45
+ export interface PinterestBoard {
46
+ id: string;
47
+ boardId: string;
48
+ name: string;
49
+ description: string | null;
50
+ imageUrl: string | null;
51
+ }
52
+ export interface YouTubePlaylist {
53
+ id: string;
54
+ playlistId: string;
55
+ title: string;
56
+ description: string | null;
57
+ thumbnailUrl: string | null;
58
+ }
59
+ export interface SignedUploadUrl {
60
+ key: string;
61
+ signedUrl: string;
62
+ }
63
+ export interface CreatePostInput {
64
+ content: string;
65
+ firstComment?: string;
66
+ mediaItems?: MediaItem[];
67
+ scheduledAt?: string;
68
+ socialMediaId: string;
69
+ }
70
+ export interface PostControls {
71
+ xCommunityId?: string;
72
+ xQuoteTweetUrl?: string;
73
+ xRetweetUrl?: string;
74
+ tiktokPrivacy?: 'PUBLIC' | 'MUTUAL_FRIENDS' | 'ONLY_ME';
75
+ tiktokIsDraft?: boolean;
76
+ tiktokAllowComments?: boolean;
77
+ tiktokAllowDuet?: boolean;
78
+ tiktokAllowStitch?: boolean;
79
+ tiktokBrandOrganic?: boolean;
80
+ tiktokBrandContent?: boolean;
81
+ tiktokAutoAddMusic?: boolean;
82
+ instagramPostToGrid?: boolean;
83
+ instagramPublishType?: 'TIMELINE' | 'STORY' | 'REEL';
84
+ instagramCollaborators?: string[];
85
+ youtubePrivacy?: 'PUBLIC' | 'PRIVATE' | 'UNLISTED';
86
+ youtubeTags?: string[];
87
+ youtubeCategoryId?: string;
88
+ youtubeIsShort?: boolean;
89
+ youtubeMadeForKids?: boolean;
90
+ youtubeTitle?: string;
91
+ youtubePlaylistId?: string;
92
+ facebookContentType?: 'POST' | 'REEL' | 'STORY';
93
+ facebookAllowComments?: boolean;
94
+ facebookPrivacy?: 'PUBLIC' | 'FRIENDS_OF_FRIENDS' | 'FRIENDS' | 'SELF';
95
+ facebookCarouselMainLink?: string;
96
+ facebookCarouselShowEndCard?: boolean;
97
+ facebookReelsCoverImageKey?: string;
98
+ facebookReelsCollaborators?: string[];
99
+ pinterestBoardId?: string;
100
+ pinterestLink?: string;
101
+ linkedinAttachmentKey?: string;
102
+ linkedinAttachmentTitle?: string;
103
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "postfast-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for the PostFast API — schedule and manage social media posts via AI tools",
5
+ "type": "module",
6
+ "bin": {
7
+ "postfast-mcp": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "start": "node dist/index.js",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "postfast",
23
+ "social-media",
24
+ "scheduling",
25
+ "model-context-protocol",
26
+ "claude",
27
+ "ai"
28
+ ],
29
+ "author": "PostFast",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/peturgeorgievv-factory/postfast-mcp"
34
+ },
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.12.0"
40
+ },
41
+ "devDependencies": {
42
+ "typescript": "^5.7.0",
43
+ "@types/node": "^22.0.0"
44
+ }
45
+ }