postproxy-mcp 1.0.0 → 1.0.2
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 +96 -0
- package/package.json +1 -1
- package/worker/index.ts +86 -0
package/README.md
CHANGED
|
@@ -94,6 +94,35 @@ List all available social media profiles for posting.
|
|
|
94
94
|
}
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
#### `profiles.placements`
|
|
98
|
+
|
|
99
|
+
List available placements for a profile. For Facebook profiles, placements are business pages. For LinkedIn profiles, placements include the personal profile and organizations. For Pinterest profiles, placements are boards. Available for `facebook`, `linkedin`, and `pinterest` profiles.
|
|
100
|
+
|
|
101
|
+
**Parameters**:
|
|
102
|
+
- `profile_id` (string, required): Profile hashid
|
|
103
|
+
|
|
104
|
+
**Returns** (LinkedIn example):
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"placements": [
|
|
108
|
+
{
|
|
109
|
+
"id": null,
|
|
110
|
+
"name": "Personal Profile"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "108520199",
|
|
114
|
+
"name": "Acme Marketing"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Notes**:
|
|
121
|
+
- If no placement is specified when creating a post:
|
|
122
|
+
- **LinkedIn**: defaults to the personal profile
|
|
123
|
+
- **Facebook**: defaults to a random connected page (if only one page is connected, no need to set a placement ID)
|
|
124
|
+
- **Pinterest**: it fails
|
|
125
|
+
|
|
97
126
|
### Post Management
|
|
98
127
|
|
|
99
128
|
#### `post.publish`
|
|
@@ -207,6 +236,57 @@ Delete a post by job ID.
|
|
|
207
236
|
}
|
|
208
237
|
```
|
|
209
238
|
|
|
239
|
+
#### `post.stats`
|
|
240
|
+
|
|
241
|
+
Get stats snapshots for one or more posts. Returns all matching snapshots so you can see trends over time. Supports filtering by profiles/networks and timespan.
|
|
242
|
+
|
|
243
|
+
**Parameters**:
|
|
244
|
+
- `post_ids` (string[], required): Array of post hashids (max 50)
|
|
245
|
+
- `profiles` (string, optional): Comma-separated list of profile hashids or network names (e.g. `instagram,twitter` or `abc123,def456` or mixed)
|
|
246
|
+
- `from` (string, optional): ISO 8601 timestamp — only include snapshots recorded at or after this time
|
|
247
|
+
- `to` (string, optional): ISO 8601 timestamp — only include snapshots recorded at or before this time
|
|
248
|
+
|
|
249
|
+
**Returns**:
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"data": {
|
|
253
|
+
"abc123": {
|
|
254
|
+
"platforms": [
|
|
255
|
+
{
|
|
256
|
+
"profile_id": "prof_abc",
|
|
257
|
+
"platform": "instagram",
|
|
258
|
+
"records": [
|
|
259
|
+
{
|
|
260
|
+
"stats": {
|
|
261
|
+
"impressions": 1200,
|
|
262
|
+
"likes": 85,
|
|
263
|
+
"comments": 12,
|
|
264
|
+
"saved": 8
|
|
265
|
+
},
|
|
266
|
+
"recorded_at": "2026-02-20T12:00:00Z"
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Stats fields by platform**:
|
|
277
|
+
| Platform | Fields |
|
|
278
|
+
|----------|--------|
|
|
279
|
+
| Instagram | `impressions`, `likes`, `comments`, `saved`, `profile_visits`, `follows` |
|
|
280
|
+
| Facebook | `impressions`, `clicks`, `likes` |
|
|
281
|
+
| Threads | `impressions`, `likes`, `replies`, `reposts`, `quotes`, `shares` |
|
|
282
|
+
| Twitter | `impressions`, `likes`, `retweets`, `comments`, `quotes`, `saved` |
|
|
283
|
+
| YouTube | `impressions`, `likes`, `comments`, `saved` |
|
|
284
|
+
| LinkedIn | `impressions` |
|
|
285
|
+
| TikTok | `impressions`, `likes`, `comments`, `shares` |
|
|
286
|
+
| Pinterest | `impressions`, `likes`, `comments`, `saved`, `outbound_clicks` |
|
|
287
|
+
|
|
288
|
+
**Notes**: Instagram stories do not return stats. TikTok stats require the post to have a public ID.
|
|
289
|
+
|
|
210
290
|
### History
|
|
211
291
|
|
|
212
292
|
#### `history.list`
|
|
@@ -561,6 +641,22 @@ This will show detailed status including draft status, platform-specific errors,
|
|
|
561
641
|
Delete post job-123
|
|
562
642
|
```
|
|
563
643
|
|
|
644
|
+
### Get Post Stats
|
|
645
|
+
|
|
646
|
+
```
|
|
647
|
+
Show me the stats for post abc123
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
```
|
|
651
|
+
Get stats for posts abc123 and def456 filtered to Instagram only, from February 1st to today
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### List Placements
|
|
655
|
+
|
|
656
|
+
```
|
|
657
|
+
Show me the placements for my LinkedIn profile prof123
|
|
658
|
+
```
|
|
659
|
+
|
|
564
660
|
### View History
|
|
565
661
|
|
|
566
662
|
```
|
package/package.json
CHANGED
package/worker/index.ts
CHANGED
|
@@ -676,6 +676,61 @@ export default class PostProxyMCP extends WorkerEntrypoint<Env> {
|
|
|
676
676
|
return JSON.stringify({ jobs }, null, 2);
|
|
677
677
|
}
|
|
678
678
|
|
|
679
|
+
/**
|
|
680
|
+
* Get stats snapshots for one or more posts
|
|
681
|
+
* @param post_ids {string} Comma-separated list of post hashids (max 50)
|
|
682
|
+
* @param profiles {string} Optional comma-separated list of profile hashids or network names
|
|
683
|
+
* @param from {string} Optional ISO 8601 timestamp — only include snapshots at or after this time
|
|
684
|
+
* @param to {string} Optional ISO 8601 timestamp — only include snapshots at or before this time
|
|
685
|
+
* @return {Promise<string>} Post stats as JSON
|
|
686
|
+
*/
|
|
687
|
+
async postStats(
|
|
688
|
+
post_ids: string,
|
|
689
|
+
profiles?: string,
|
|
690
|
+
from?: string,
|
|
691
|
+
to?: string
|
|
692
|
+
): Promise<string> {
|
|
693
|
+
if (!post_ids || post_ids.trim() === "") {
|
|
694
|
+
throw new Error("post_ids is required");
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const ids = post_ids.split(",").map((id) => id.trim()).filter(Boolean);
|
|
698
|
+
if (ids.length > 50) {
|
|
699
|
+
throw new Error("Maximum 50 post IDs allowed");
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const queryParams = new URLSearchParams();
|
|
703
|
+
queryParams.append("post_ids", ids.join(","));
|
|
704
|
+
if (profiles) {
|
|
705
|
+
queryParams.append("profiles", profiles);
|
|
706
|
+
}
|
|
707
|
+
if (from) {
|
|
708
|
+
queryParams.append("from", from);
|
|
709
|
+
}
|
|
710
|
+
if (to) {
|
|
711
|
+
queryParams.append("to", to);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const response = await this.apiRequest<any>("GET", `/posts/stats?${queryParams.toString()}`);
|
|
715
|
+
return JSON.stringify(response, null, 2);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* List available placements for a profile (Facebook pages, LinkedIn orgs, Pinterest boards)
|
|
720
|
+
* @param profile_id {string} Profile hashid
|
|
721
|
+
* @return {Promise<string>} List of placements as JSON
|
|
722
|
+
*/
|
|
723
|
+
async profilesPlacements(profile_id: string): Promise<string> {
|
|
724
|
+
if (!profile_id) {
|
|
725
|
+
throw new Error("profile_id is required");
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const response = await this.apiRequest<any>("GET", `/profiles/${profile_id}/placements`);
|
|
729
|
+
const placements = this.extractArray<{ id: string | null; name: string }>(response);
|
|
730
|
+
|
|
731
|
+
return JSON.stringify({ placements }, null, 2);
|
|
732
|
+
}
|
|
733
|
+
|
|
679
734
|
/**
|
|
680
735
|
* MCP tool definitions
|
|
681
736
|
*/
|
|
@@ -754,6 +809,31 @@ export default class PostProxyMCP extends WorkerEntrypoint<Env> {
|
|
|
754
809
|
required: [],
|
|
755
810
|
},
|
|
756
811
|
},
|
|
812
|
+
{
|
|
813
|
+
name: "postStats",
|
|
814
|
+
description: "Get stats snapshots for one or more posts. Returns all matching snapshots so you can see trends over time. Supports filtering by profiles/networks and timespan.",
|
|
815
|
+
inputSchema: {
|
|
816
|
+
type: "object",
|
|
817
|
+
properties: {
|
|
818
|
+
post_ids: { type: "string", description: "Comma-separated list of post hashids (max 50)" },
|
|
819
|
+
profiles: { type: "string", description: "Optional comma-separated list of profile hashids or network names (e.g. 'instagram,twitter')" },
|
|
820
|
+
from: { type: "string", description: "Optional ISO 8601 timestamp — only include snapshots at or after this time" },
|
|
821
|
+
to: { type: "string", description: "Optional ISO 8601 timestamp — only include snapshots at or before this time" },
|
|
822
|
+
},
|
|
823
|
+
required: ["post_ids"],
|
|
824
|
+
},
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "profilesPlacements",
|
|
828
|
+
description: "List available placements for a profile. For Facebook: business pages. For LinkedIn: personal profile and organizations. For Pinterest: boards. Available for facebook, linkedin, and pinterest profiles.",
|
|
829
|
+
inputSchema: {
|
|
830
|
+
type: "object",
|
|
831
|
+
properties: {
|
|
832
|
+
profile_id: { type: "string", description: "Profile hashid" },
|
|
833
|
+
},
|
|
834
|
+
required: ["profile_id"],
|
|
835
|
+
},
|
|
836
|
+
},
|
|
757
837
|
];
|
|
758
838
|
}
|
|
759
839
|
|
|
@@ -825,6 +905,12 @@ export default class PostProxyMCP extends WorkerEntrypoint<Env> {
|
|
|
825
905
|
case "historyList":
|
|
826
906
|
result = await this.historyList(args?.limit);
|
|
827
907
|
break;
|
|
908
|
+
case "postStats":
|
|
909
|
+
result = await this.postStats(args.post_ids, args.profiles, args.from, args.to);
|
|
910
|
+
break;
|
|
911
|
+
case "profilesPlacements":
|
|
912
|
+
result = await this.profilesPlacements(args.profile_id);
|
|
913
|
+
break;
|
|
828
914
|
default:
|
|
829
915
|
return {
|
|
830
916
|
jsonrpc: "2.0",
|