postfast-mcp 0.1.23 → 0.2.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.
Files changed (62) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +11 -5
  4. package/dist/core/backend-port.d.ts +97 -0
  5. package/dist/core/backend-port.js +2 -0
  6. package/dist/core/backend-port.js.map +1 -0
  7. package/dist/core/build-tools.d.ts +32 -0
  8. package/dist/core/build-tools.js +73 -0
  9. package/dist/core/build-tools.js.map +1 -0
  10. package/dist/core/index.d.ts +12 -0
  11. package/dist/core/index.js +12 -0
  12. package/dist/core/index.js.map +1 -0
  13. package/dist/core/instructions.d.ts +3 -0
  14. package/dist/core/instructions.js +63 -0
  15. package/dist/core/instructions.js.map +1 -0
  16. package/dist/core/shared.d.ts +21 -0
  17. package/dist/core/shared.js +58 -0
  18. package/dist/core/shared.js.map +1 -0
  19. package/dist/core/tool-def.d.ts +47 -0
  20. package/dist/core/tool-def.js +2 -0
  21. package/dist/core/tool-def.js.map +1 -0
  22. package/dist/core/tools/accounts.d.ts +2 -0
  23. package/dist/core/tools/accounts.js +112 -0
  24. package/dist/core/tools/accounts.js.map +1 -0
  25. package/dist/core/tools/index.d.ts +7 -0
  26. package/dist/core/tools/index.js +16 -0
  27. package/dist/core/tools/index.js.map +1 -0
  28. package/dist/core/tools/posts.d.ts +2 -0
  29. package/dist/core/tools/posts.js +264 -0
  30. package/dist/core/tools/posts.js.map +1 -0
  31. package/dist/core/tools/uploads.d.ts +8 -0
  32. package/dist/core/tools/uploads.js +102 -0
  33. package/dist/core/tools/uploads.js.map +1 -0
  34. package/dist/core/tools/workspaces.d.ts +2 -0
  35. package/dist/core/tools/workspaces.js +15 -0
  36. package/dist/core/tools/workspaces.js.map +1 -0
  37. package/dist/{types.d.ts → core/types.d.ts} +7 -1
  38. package/dist/core/types.js.map +1 -0
  39. package/dist/stdio/index.js +15 -0
  40. package/dist/stdio/index.js.map +1 -0
  41. package/dist/stdio/rest-adapter.d.ts +27 -0
  42. package/dist/stdio/rest-adapter.js +170 -0
  43. package/dist/stdio/rest-adapter.js.map +1 -0
  44. package/package.json +22 -8
  45. package/skills/social-media-post/SKILL.md +1 -0
  46. package/dist/client.d.ts +0 -9
  47. package/dist/client.js +0 -57
  48. package/dist/client.js.map +0 -1
  49. package/dist/index.js +0 -18
  50. package/dist/index.js.map +0 -1
  51. package/dist/tools/accounts.d.ts +0 -3
  52. package/dist/tools/accounts.js +0 -118
  53. package/dist/tools/accounts.js.map +0 -1
  54. package/dist/tools/files.d.ts +0 -3
  55. package/dist/tools/files.js +0 -87
  56. package/dist/tools/files.js.map +0 -1
  57. package/dist/tools/posts.d.ts +0 -3
  58. package/dist/tools/posts.js +0 -228
  59. package/dist/tools/posts.js.map +0 -1
  60. package/dist/types.js.map +0 -1
  61. /package/dist/{types.js → core/types.js} +0 -0
  62. /package/dist/{index.d.ts → stdio/index.d.ts} +0 -0
@@ -0,0 +1,27 @@
1
+ import type { AnalyticsArgs, ApprovePostsArgs, BackendPort, ConnectLinkArgs, CreatePostsArgs, FollowerHistoryArgs, ListPostsArgs, LocalUploadResult, UploadUrlsArgs } from '../core/backend-port.js';
2
+ /** The stdio bin's BackendPort: the public PostFast REST API over pf-api-key. */
3
+ export declare class RestAdapter implements BackendPort {
4
+ private baseUrl;
5
+ private apiKey;
6
+ constructor();
7
+ private request;
8
+ private get;
9
+ private post;
10
+ listWorkspaces(): Promise<unknown>;
11
+ listAccounts(): Promise<unknown>;
12
+ getFollowerHistory(args: FollowerHistoryArgs): Promise<unknown>;
13
+ listPinterestBoards(socialMediaId: string): Promise<unknown>;
14
+ listYoutubePlaylists(socialMediaId: string): Promise<unknown>;
15
+ listGbpLocations(socialMediaId: string): Promise<unknown>;
16
+ searchPlaces(query: string): Promise<unknown>;
17
+ generateConnectLink(args: ConnectLinkArgs): Promise<unknown>;
18
+ listPosts(args: ListPostsArgs): Promise<unknown>;
19
+ createPosts(args: CreatePostsArgs): Promise<unknown>;
20
+ approvePosts(_args: ApprovePostsArgs): Promise<unknown>;
21
+ deletePost(id: string): Promise<unknown>;
22
+ getPostAnalytics(args: AnalyticsArgs): Promise<unknown>;
23
+ getUploadUrls(args: UploadUrlsArgs): Promise<unknown>;
24
+ uploadLocalFile(filePath: string): Promise<LocalUploadResult>;
25
+ uploadFromUrl(): Promise<unknown>;
26
+ uploadMedia(): Promise<unknown>;
27
+ }
@@ -0,0 +1,170 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { extname } from 'node:path';
3
+ const DEFAULT_BASE_URL = 'https://api.postfa.st';
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
+ function detectContentType(filePath) {
15
+ const ext = extname(filePath).toLowerCase();
16
+ const mime = MIME_MAP[ext];
17
+ if (!mime) {
18
+ throw new Error(`Unsupported file extension "${ext}". Supported: ${Object.keys(MIME_MAP).join(', ')}`);
19
+ }
20
+ return mime;
21
+ }
22
+ /** The stdio bin's BackendPort: the public PostFast REST API over pf-api-key. */
23
+ export class RestAdapter {
24
+ baseUrl;
25
+ apiKey;
26
+ constructor() {
27
+ this.apiKey = process.env.POSTFAST_API_KEY ?? '';
28
+ this.baseUrl = (process.env.POSTFAST_API_URL ?? DEFAULT_BASE_URL).replace(/\/$/, '');
29
+ if (!this.apiKey) {
30
+ throw new Error('POSTFAST_API_KEY environment variable is required. Generate one in PostFast → Workspace Settings → API Key.');
31
+ }
32
+ }
33
+ async request(method, path, body, query) {
34
+ const url = new URL(`${this.baseUrl}${path}`);
35
+ if (query) {
36
+ for (const [key, value] of Object.entries(query)) {
37
+ if (value !== undefined && value !== '') {
38
+ url.searchParams.set(key, value);
39
+ }
40
+ }
41
+ }
42
+ const headers = {
43
+ 'pf-api-key': this.apiKey,
44
+ 'Content-Type': 'application/json',
45
+ };
46
+ const response = await fetch(url.toString(), {
47
+ method,
48
+ headers,
49
+ body: body ? JSON.stringify(body) : undefined,
50
+ });
51
+ if (!response.ok) {
52
+ const text = await response.text();
53
+ let message;
54
+ try {
55
+ const json = JSON.parse(text);
56
+ message = json.message ?? json.error ?? text;
57
+ }
58
+ catch {
59
+ message = text;
60
+ }
61
+ throw new Error(`PostFast API error (${response.status}): ${message}`);
62
+ }
63
+ const text = await response.text();
64
+ if (!text)
65
+ return undefined;
66
+ return JSON.parse(text);
67
+ }
68
+ get(path, query) {
69
+ return this.request('GET', path, undefined, query);
70
+ }
71
+ post(path, body) {
72
+ return this.request('POST', path, body);
73
+ }
74
+ listWorkspaces() {
75
+ throw new Error('list_workspaces is not available over the public REST API.');
76
+ }
77
+ listAccounts() {
78
+ return this.get('/social-media/my-social-accounts');
79
+ }
80
+ getFollowerHistory(args) {
81
+ return this.get(`/social-media/${args.socialMediaId}/follower-history`, {
82
+ from: args.from,
83
+ to: args.to,
84
+ });
85
+ }
86
+ listPinterestBoards(socialMediaId) {
87
+ return this.get(`/social-media/${socialMediaId}/pinterest-boards`);
88
+ }
89
+ listYoutubePlaylists(socialMediaId) {
90
+ return this.get(`/social-media/${socialMediaId}/youtube-playlists`);
91
+ }
92
+ listGbpLocations(socialMediaId) {
93
+ return this.get(`/social-media/${socialMediaId}/gbp-locations`);
94
+ }
95
+ searchPlaces(query) {
96
+ return this.get('/social-media/search-places', { q: query });
97
+ }
98
+ generateConnectLink(args) {
99
+ return this.post('/social-media/connect-link', {
100
+ expiryDays: args.expiryDays,
101
+ sendEmail: args.sendEmail,
102
+ email: args.email,
103
+ });
104
+ }
105
+ listPosts(args) {
106
+ return this.get('/social-posts', {
107
+ page: String(args.page),
108
+ limit: String(args.limit),
109
+ ids: args.ids?.join(','),
110
+ platforms: args.platforms?.join(','),
111
+ statuses: args.statuses?.join(','),
112
+ from: args.from,
113
+ to: args.to,
114
+ });
115
+ }
116
+ createPosts(args) {
117
+ return this.post('/social-posts', {
118
+ posts: args.posts,
119
+ status: args.status,
120
+ approvalStatus: args.approvalStatus,
121
+ controls: args.controls,
122
+ });
123
+ }
124
+ approvePosts(_args) {
125
+ throw new Error('approve_posts is not available over the public REST API.');
126
+ }
127
+ deletePost(id) {
128
+ return this.request('DELETE', `/social-posts/${id}`);
129
+ }
130
+ getPostAnalytics(args) {
131
+ return this.get('/social-posts/analytics', {
132
+ startDate: args.startDate,
133
+ endDate: args.endDate,
134
+ platforms: args.platforms?.join(','),
135
+ socialMediaIds: args.socialMediaIds?.join(','),
136
+ });
137
+ }
138
+ getUploadUrls(args) {
139
+ return this.post('/file/get-signed-upload-urls', {
140
+ contentType: args.contentType,
141
+ count: args.count,
142
+ });
143
+ }
144
+ async uploadLocalFile(filePath) {
145
+ const contentType = detectContentType(filePath);
146
+ const isVideo = contentType.startsWith('video/');
147
+ const [uploadUrl] = await this.post('/file/get-signed-upload-urls', { contentType, count: 1 });
148
+ const fileBuffer = await readFile(filePath);
149
+ const uploadResponse = await fetch(uploadUrl.signedUrl, {
150
+ method: 'PUT',
151
+ headers: { 'Content-Type': contentType },
152
+ body: fileBuffer,
153
+ });
154
+ if (!uploadResponse.ok) {
155
+ throw new Error(`Upload failed (${uploadResponse.status}): ${await uploadResponse.text()}`);
156
+ }
157
+ return {
158
+ key: uploadUrl.key,
159
+ type: isVideo ? 'VIDEO' : 'IMAGE',
160
+ contentType,
161
+ };
162
+ }
163
+ uploadFromUrl() {
164
+ throw new Error('upload_from_url is only available on the hosted PostFast MCP server.');
165
+ }
166
+ uploadMedia() {
167
+ throw new Error('Conversation-media upload is only available on the hosted PostFast MCP server.');
168
+ }
169
+ }
170
+ //# sourceMappingURL=rest-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest-adapter.js","sourceRoot":"","sources":["../../src/stdio/rest-adapter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  "name": "postfast-mcp",
3
- "version": "0.1.23",
3
+ "version": "0.2.0",
4
4
  "mcpName": "io.github.peturgeorgievv-factory/postfast-mcp",
5
5
  "description": "MCP server for the PostFast API — schedule and manage social media posts via AI tools",
6
6
  "type": "module",
7
7
  "bin": {
8
- "postfast-mcp": "./dist/index.js"
8
+ "postfast-mcp": "dist/stdio/index.js"
9
+ },
10
+ "main": "./dist/stdio/index.js",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/stdio/index.d.ts",
14
+ "default": "./dist/stdio/index.js"
15
+ },
16
+ "./core": {
17
+ "types": "./dist/core/index.d.ts",
18
+ "default": "./dist/core/index.js"
19
+ }
9
20
  },
10
- "main": "./dist/index.js",
11
21
  "files": [
12
22
  "dist",
13
23
  ".claude-plugin",
@@ -17,7 +27,9 @@
17
27
  "scripts": {
18
28
  "build": "tsc",
19
29
  "dev": "tsc --watch",
20
- "start": "node dist/index.js",
30
+ "start": "node dist/stdio/index.js",
31
+ "version": "changeset version && node scripts/stamp-versions.mjs",
32
+ "release": "npm run build && changeset publish",
21
33
  "prepublishOnly": "npm run build"
22
34
  },
23
35
  "keywords": [
@@ -33,16 +45,18 @@
33
45
  "license": "MIT",
34
46
  "repository": {
35
47
  "type": "git",
36
- "url": "https://github.com/peturgeorgievv-factory/postfast-mcp"
48
+ "url": "git+https://github.com/peturgeorgievv-factory/postfast-mcp.git"
37
49
  },
38
50
  "engines": {
39
51
  "node": ">=18"
40
52
  },
41
53
  "dependencies": {
42
- "@modelcontextprotocol/sdk": "^1.29.0"
54
+ "@modelcontextprotocol/sdk": "^1.29.0",
55
+ "zod": "^4.4.3"
43
56
  },
44
57
  "devDependencies": {
45
- "typescript": "^5.9.3",
46
- "@types/node": "^22.19.21"
58
+ "@changesets/cli": "^2.29.8",
59
+ "@types/node": "^22.19.21",
60
+ "typescript": "^5.9.3"
47
61
  }
48
62
  }
@@ -62,6 +62,7 @@ If any PostFast tool call fails with an authentication/401 error, tell the user:
62
62
  - `tiktokBrandContent`: boolean, default false
63
63
  - `tiktokAutoAddMusic`: boolean, default false
64
64
  - `tiktokIsAigc`: boolean, default false (declare video as AI-generated content)
65
+ - `tiktokTitle`: title for photo posts (max 90 chars; photo posts only) — when set, the full content becomes the description; without it, content auto-splits on the first newline into title + description
65
66
 
66
67
  ### YouTube
67
68
  - `youtubeTitle`: defaults to first 100 chars of content
package/dist/client.d.ts DELETED
@@ -1,9 +0,0 @@
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 DELETED
@@ -1,57 +0,0 @@
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
@@ -1 +0,0 @@
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"}
package/dist/index.js DELETED
@@ -1,18 +0,0 @@
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.22',
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
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
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,QAAQ;CAClB,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"}
@@ -1,3 +0,0 @@
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;
@@ -1,118 +0,0 @@
1
- import { z } from 'zod';
2
- export function registerAccountTools(server, client) {
3
- server.registerTool('list_accounts', {
4
- description: 'List all social media accounts connected to the workspace. Each account includes connectionStatus (CONNECTED or DISABLED) and disabledReason (null unless DISABLED). If connectionStatus is DISABLED, the account will not publish until the user reconnects it.',
5
- inputSchema: {},
6
- }, async () => {
7
- const data = await client.get('/social-media/my-social-accounts');
8
- return {
9
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
10
- };
11
- });
12
- server.registerTool('list_pinterest_boards', {
13
- description: 'List Pinterest boards for a connected Pinterest account',
14
- inputSchema: {
15
- socialMediaId: z
16
- .uuid()
17
- .describe('Pinterest account ID (from list_accounts)'),
18
- },
19
- }, async (input) => {
20
- const data = await client.get(`/social-media/${input.socialMediaId}/pinterest-boards`);
21
- return {
22
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
23
- };
24
- });
25
- server.registerTool('list_youtube_playlists', {
26
- description: 'List YouTube playlists for a connected YouTube account',
27
- inputSchema: {
28
- socialMediaId: z
29
- .uuid()
30
- .describe('YouTube account ID (from list_accounts)'),
31
- },
32
- }, async (input) => {
33
- const data = await client.get(`/social-media/${input.socialMediaId}/youtube-playlists`);
34
- return {
35
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
36
- };
37
- });
38
- server.registerTool('list_gbp_locations', {
39
- description: 'List Google Business Profile locations for a connected GBP account',
40
- inputSchema: {
41
- socialMediaId: z
42
- .uuid()
43
- .describe('GBP account ID (from list_accounts)'),
44
- },
45
- }, async (input) => {
46
- const data = await client.get(`/social-media/${input.socialMediaId}/gbp-locations`);
47
- return {
48
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
49
- };
50
- });
51
- server.registerTool('get_follower_history', {
52
- description: 'Daily follower-count snapshots for a connected account, plus the current count (currentFollowerCount) and the net change (delta) over the range. Date range via from/to (ISO 8601); defaults to the last 90 days, capped at 365. Tracking is forward-only: data starts at trackingStartedAt (when PostFast began recording this account), with no snapshots before then. All counts are strings (bigint); currentFollowerCount, delta, and trackingStartedAt may be absent until the account has its first snapshot. Coverage: Facebook Pages, Instagram, YouTube, Pinterest, Threads, Bluesky, Telegram, LinkedIn company pages, and TikTok. Not available: X, personal Facebook.',
53
- inputSchema: {
54
- socialMediaId: z
55
- .uuid()
56
- .describe('Account ID (from list_accounts)'),
57
- from: z
58
- .string()
59
- .optional()
60
- .describe('Range start (ISO 8601, e.g. 2026-03-01T00:00:00.000Z). Defaults to 90 days ago.'),
61
- to: z
62
- .string()
63
- .optional()
64
- .describe('Range end (ISO 8601). Defaults to now. Range is capped at 365 days.'),
65
- },
66
- }, async (input) => {
67
- const data = await client.get(`/social-media/${input.socialMediaId}/follower-history`, { from: input.from, to: input.to });
68
- return {
69
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
70
- };
71
- });
72
- server.registerTool('search_places', {
73
- description: 'Find a place to tag. The returned id works for both facebookPlaceId and instagramLocationId.',
74
- inputSchema: {
75
- query: z
76
- .string()
77
- .min(2)
78
- .describe('Place name to search, e.g. "Eiffel Tower"'),
79
- },
80
- }, async (input) => {
81
- const data = await client.get('/social-media/search-places', {
82
- q: input.query,
83
- });
84
- return {
85
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
86
- };
87
- });
88
- server.registerTool('generate_connect_link', {
89
- description: 'Generate a shareable link for external clients to connect their social accounts to the workspace',
90
- inputSchema: {
91
- expiryDays: z
92
- .number()
93
- .int()
94
- .min(1)
95
- .max(30)
96
- .default(7)
97
- .describe('Link expiry in days (1-30, default 7)'),
98
- sendEmail: z
99
- .boolean()
100
- .default(false)
101
- .describe('Send the link via email'),
102
- email: z
103
- .email()
104
- .optional()
105
- .describe('Recipient email (required if sendEmail is true)'),
106
- },
107
- }, async (input) => {
108
- const data = await client.post('/social-media/connect-link', {
109
- expiryDays: input.expiryDays,
110
- sendEmail: input.sendEmail,
111
- email: input.email,
112
- });
113
- return {
114
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
115
- };
116
- });
117
- }
118
- //# sourceMappingURL=accounts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/tools/accounts.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
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;
@@ -1,87 +0,0 @@
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.registerTool('get_upload_urls', {
31
- description: 'Get signed upload URLs for media files. Upload your file to the returned URL via PUT, then use the key in create_posts mediaItems.',
32
- inputSchema: {
33
- contentType: z
34
- .string()
35
- .describe(`MIME type of the file. Supported: ${[...IMAGE_TYPES, ...VIDEO_TYPES].join(', ')}`),
36
- count: z
37
- .number()
38
- .int()
39
- .min(1)
40
- .max(8)
41
- .default(1)
42
- .describe('Number of upload URLs (1-8 for images, 1 for videos)'),
43
- },
44
- }, async (input) => {
45
- const data = await client.post('/file/get-signed-upload-urls', {
46
- contentType: input.contentType,
47
- count: input.count,
48
- });
49
- return {
50
- content: [
51
- { type: 'text', text: JSON.stringify(data, null, 2) },
52
- ],
53
- };
54
- });
55
- server.registerTool('upload_media', {
56
- description: '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.',
57
- inputSchema: {
58
- filePath: z
59
- .string()
60
- .describe('Absolute path to the local file (e.g. /Users/me/photo.jpg)'),
61
- },
62
- }, async (input) => {
63
- const contentType = detectContentType(input.filePath);
64
- const isVideo = contentType.startsWith('video/');
65
- const [uploadUrl] = await client.post('/file/get-signed-upload-urls', { contentType, count: 1 });
66
- const fileBuffer = await readFile(input.filePath);
67
- const uploadResponse = await fetch(uploadUrl.signedUrl, {
68
- method: 'PUT',
69
- headers: { 'Content-Type': contentType },
70
- body: fileBuffer,
71
- });
72
- if (!uploadResponse.ok) {
73
- throw new Error(`Upload failed (${uploadResponse.status}): ${await uploadResponse.text()}`);
74
- }
75
- const result = {
76
- key: uploadUrl.key,
77
- type: isVideo ? 'VIDEO' : 'IMAGE',
78
- contentType,
79
- };
80
- return {
81
- content: [
82
- { type: 'text', text: JSON.stringify(result, null, 2) },
83
- ],
84
- };
85
- });
86
- }
87
- //# sourceMappingURL=files.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/tools/files.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
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;