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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postproxy-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server for Postproxy API integration with Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
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",