posterly-mcp-server 0.50.4 → 0.51.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 (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -2
  3. package/dist/lib/version.d.ts +1 -1
  4. package/dist/lib/version.js +1 -1
  5. package/dist/tools/create-post.d.ts +180 -0
  6. package/dist/tools/create-post.js +5 -0
  7. package/dist/tools/create-posts-batch.d.ts +70 -0
  8. package/dist/tools/manage-google-business-media.js +1 -1
  9. package/dist/tools/update-post.d.ts +80 -0
  10. package/dist/tools/update-post.js +1 -0
  11. package/dist/tools/validate-post.d.ts +100 -0
  12. package/package.json +11 -4
  13. package/server.json +4 -5
  14. package/RELEASING.md +0 -115
  15. package/SUBMISSIONS.md +0 -109
  16. package/scripts/test-alias-transport.mjs +0 -368
  17. package/scripts/test-claude-directory-profile.mjs +0 -38
  18. package/scripts/test-client-header-sanitization.mjs +0 -78
  19. package/scripts/test-payload-builders.mjs +0 -210
  20. package/scripts/test-tool-annotations.mjs +0 -68
  21. package/src/generated/platform-manifest.ts +0 -753
  22. package/src/index.ts +0 -291
  23. package/src/lib/alias-transport.ts +0 -245
  24. package/src/lib/api-client.ts +0 -2638
  25. package/src/lib/claude-directory-profile.ts +0 -94
  26. package/src/lib/format.ts +0 -446
  27. package/src/lib/preview-token-core.ts +0 -157
  28. package/src/lib/preview-token.ts +0 -54
  29. package/src/lib/tool-annotations.ts +0 -47
  30. package/src/lib/tool-registry.ts +0 -538
  31. package/src/lib/tool-runtime.ts +0 -117
  32. package/src/lib/version.ts +0 -8
  33. package/src/tools/ask-support.ts +0 -55
  34. package/src/tools/audit-google-business-profile.ts +0 -57
  35. package/src/tools/cancel-subscription.ts +0 -50
  36. package/src/tools/connect-account.ts +0 -91
  37. package/src/tools/create-api-key.ts +0 -41
  38. package/src/tools/create-connect-session.ts +0 -55
  39. package/src/tools/create-media-drop.ts +0 -41
  40. package/src/tools/create-post.ts +0 -430
  41. package/src/tools/create-posts-batch.ts +0 -80
  42. package/src/tools/create-signed-upload.ts +0 -29
  43. package/src/tools/create-webhook.ts +0 -34
  44. package/src/tools/delete-api-key.ts +0 -31
  45. package/src/tools/delete-post.ts +0 -86
  46. package/src/tools/disconnect-account.ts +0 -30
  47. package/src/tools/dismiss-suggestion.ts +0 -22
  48. package/src/tools/downgrade-subscription.ts +0 -29
  49. package/src/tools/find-slot.ts +0 -101
  50. package/src/tools/generate-captions.ts +0 -77
  51. package/src/tools/generate-image.ts +0 -108
  52. package/src/tools/generate-video.ts +0 -45
  53. package/src/tools/get-agent-signup-info.ts +0 -47
  54. package/src/tools/get-credits.ts +0 -38
  55. package/src/tools/get-post.ts +0 -49
  56. package/src/tools/get-signup-session.ts +0 -100
  57. package/src/tools/get-subscription.ts +0 -31
  58. package/src/tools/get-updates.ts +0 -55
  59. package/src/tools/get-video-options.ts +0 -30
  60. package/src/tools/get-x-posting-quota.ts +0 -25
  61. package/src/tools/list-accounts.ts +0 -202
  62. package/src/tools/list-activity.ts +0 -65
  63. package/src/tools/list-analytics.ts +0 -447
  64. package/src/tools/list-brands.ts +0 -175
  65. package/src/tools/list-comments.ts +0 -125
  66. package/src/tools/list-conversations.ts +0 -119
  67. package/src/tools/list-google-business-media.ts +0 -33
  68. package/src/tools/list-google-business-reviews.ts +0 -165
  69. package/src/tools/list-jobs.ts +0 -91
  70. package/src/tools/list-media.ts +0 -69
  71. package/src/tools/list-oauth-clients.ts +0 -18
  72. package/src/tools/list-platforms.ts +0 -149
  73. package/src/tools/list-post-suggestions.ts +0 -69
  74. package/src/tools/list-posts.ts +0 -120
  75. package/src/tools/list-publishing-pauses.ts +0 -98
  76. package/src/tools/list-webhooks.ts +0 -29
  77. package/src/tools/list-workspace-members.ts +0 -75
  78. package/src/tools/manage-comment.ts +0 -142
  79. package/src/tools/manage-conversation.ts +0 -89
  80. package/src/tools/manage-google-business-media.ts +0 -147
  81. package/src/tools/manage-google-business-review.ts +0 -139
  82. package/src/tools/manage-oauth-client.ts +0 -116
  83. package/src/tools/manage-publishing-pause.ts +0 -62
  84. package/src/tools/manage-webhook.ts +0 -103
  85. package/src/tools/manage-workspace-member.ts +0 -163
  86. package/src/tools/pause-subscription.ts +0 -26
  87. package/src/tools/resume-subscription.ts +0 -15
  88. package/src/tools/run-video-function.ts +0 -32
  89. package/src/tools/start-signup.ts +0 -150
  90. package/src/tools/submit-agent-feedback.ts +0 -47
  91. package/src/tools/submit-product-feedback.ts +0 -56
  92. package/src/tools/trigger-platform-helper.ts +0 -34
  93. package/src/tools/update-post.ts +0 -334
  94. package/src/tools/upload-media.ts +0 -107
  95. package/src/tools/validate-post.ts +0 -42
  96. package/src/tools/webhook-events.ts +0 -20
  97. package/src/tools/whoami.ts +0 -262
  98. package/tsconfig.json +0 -14
@@ -275,6 +275,16 @@ export declare const validatePostInputSchema: import("zod").ZodObject<{
275
275
  question?: string | undefined;
276
276
  allows_multiple_answers?: boolean | undefined;
277
277
  }>>;
278
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
279
+ title: import("zod").ZodString;
280
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
281
+ }, "strip", import("zod").ZodTypeAny, {
282
+ title: string;
283
+ cover?: "none" | "first_image" | undefined;
284
+ }, {
285
+ title: string;
286
+ cover?: "none" | "first_image" | undefined;
287
+ }>>>;
278
288
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
279
289
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
280
290
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -414,6 +424,16 @@ export declare const validatePostInputSchema: import("zod").ZodObject<{
414
424
  question?: string | undefined;
415
425
  allows_multiple_answers?: boolean | undefined;
416
426
  }>>;
427
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
428
+ title: import("zod").ZodString;
429
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
430
+ }, "strip", import("zod").ZodTypeAny, {
431
+ title: string;
432
+ cover?: "none" | "first_image" | undefined;
433
+ }, {
434
+ title: string;
435
+ cover?: "none" | "first_image" | undefined;
436
+ }>>>;
417
437
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
418
438
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
419
439
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -553,6 +573,16 @@ export declare const validatePostInputSchema: import("zod").ZodObject<{
553
573
  question?: string | undefined;
554
574
  allows_multiple_answers?: boolean | undefined;
555
575
  }>>;
576
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
577
+ title: import("zod").ZodString;
578
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
579
+ }, "strip", import("zod").ZodTypeAny, {
580
+ title: string;
581
+ cover?: "none" | "first_image" | undefined;
582
+ }, {
583
+ title: string;
584
+ cover?: "none" | "first_image" | undefined;
585
+ }>>>;
556
586
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
557
587
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
558
588
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -755,6 +785,16 @@ export declare const validatePostInputSchema: import("zod").ZodObject<{
755
785
  question?: string | undefined;
756
786
  allows_multiple_answers?: boolean | undefined;
757
787
  }>>;
788
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
789
+ title: import("zod").ZodString;
790
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
791
+ }, "strip", import("zod").ZodTypeAny, {
792
+ title: string;
793
+ cover?: "none" | "first_image" | undefined;
794
+ }, {
795
+ title: string;
796
+ cover?: "none" | "first_image" | undefined;
797
+ }>>>;
758
798
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
759
799
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
760
800
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -956,6 +996,16 @@ export declare const validatePostInputSchema: import("zod").ZodObject<{
956
996
  question?: string | undefined;
957
997
  allows_multiple_answers?: boolean | undefined;
958
998
  }>>;
999
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
1000
+ title: import("zod").ZodString;
1001
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
1002
+ }, "strip", import("zod").ZodTypeAny, {
1003
+ title: string;
1004
+ cover?: "none" | "first_image" | undefined;
1005
+ }, {
1006
+ title: string;
1007
+ cover?: "none" | "first_image" | undefined;
1008
+ }>>>;
959
1009
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
960
1010
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
961
1011
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -1333,6 +1383,16 @@ export declare const validatePostTool: {
1333
1383
  question?: string | undefined;
1334
1384
  allows_multiple_answers?: boolean | undefined;
1335
1385
  }>>;
1386
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
1387
+ title: import("zod").ZodString;
1388
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
1389
+ }, "strip", import("zod").ZodTypeAny, {
1390
+ title: string;
1391
+ cover?: "none" | "first_image" | undefined;
1392
+ }, {
1393
+ title: string;
1394
+ cover?: "none" | "first_image" | undefined;
1395
+ }>>>;
1336
1396
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
1337
1397
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
1338
1398
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -1472,6 +1532,16 @@ export declare const validatePostTool: {
1472
1532
  question?: string | undefined;
1473
1533
  allows_multiple_answers?: boolean | undefined;
1474
1534
  }>>;
1535
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
1536
+ title: import("zod").ZodString;
1537
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
1538
+ }, "strip", import("zod").ZodTypeAny, {
1539
+ title: string;
1540
+ cover?: "none" | "first_image" | undefined;
1541
+ }, {
1542
+ title: string;
1543
+ cover?: "none" | "first_image" | undefined;
1544
+ }>>>;
1475
1545
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
1476
1546
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
1477
1547
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -1611,6 +1681,16 @@ export declare const validatePostTool: {
1611
1681
  question?: string | undefined;
1612
1682
  allows_multiple_answers?: boolean | undefined;
1613
1683
  }>>;
1684
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
1685
+ title: import("zod").ZodString;
1686
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
1687
+ }, "strip", import("zod").ZodTypeAny, {
1688
+ title: string;
1689
+ cover?: "none" | "first_image" | undefined;
1690
+ }, {
1691
+ title: string;
1692
+ cover?: "none" | "first_image" | undefined;
1693
+ }>>>;
1614
1694
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
1615
1695
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
1616
1696
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -1813,6 +1893,16 @@ export declare const validatePostTool: {
1813
1893
  question?: string | undefined;
1814
1894
  allows_multiple_answers?: boolean | undefined;
1815
1895
  }>>;
1896
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
1897
+ title: import("zod").ZodString;
1898
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
1899
+ }, "strip", import("zod").ZodTypeAny, {
1900
+ title: string;
1901
+ cover?: "none" | "first_image" | undefined;
1902
+ }, {
1903
+ title: string;
1904
+ cover?: "none" | "first_image" | undefined;
1905
+ }>>>;
1816
1906
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
1817
1907
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
1818
1908
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -2014,6 +2104,16 @@ export declare const validatePostTool: {
2014
2104
  question?: string | undefined;
2015
2105
  allows_multiple_answers?: boolean | undefined;
2016
2106
  }>>;
2107
+ article: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
2108
+ title: import("zod").ZodString;
2109
+ cover: import("zod").ZodOptional<import("zod").ZodEnum<["first_image", "none"]>>;
2110
+ }, "strip", import("zod").ZodTypeAny, {
2111
+ title: string;
2112
+ cover?: "none" | "first_image" | undefined;
2113
+ }, {
2114
+ title: string;
2115
+ cover?: "none" | "first_image" | undefined;
2116
+ }>>>;
2017
2117
  reply_control: import("zod").ZodOptional<import("zod").ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "followers_only", "parent_post_author_only"]>>;
2018
2118
  topic_tag: import("zod").ZodOptional<import("zod").ZodString>;
2019
2119
  share_to_instagram: import("zod").ZodOptional<import("zod").ZodBoolean>;
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "posterly-mcp-server",
3
- "version": "0.50.4",
3
+ "version": "0.51.0",
4
4
  "mcpName": "io.github.awpthorp/posterly",
5
5
  "description": "MCP server for posterly: schedule and publish social media posts across 18 platforms from any MCP client (Claude, ChatGPT, Cursor, Windsurf, Cline, and more)",
6
6
  "license": "MIT",
7
7
  "homepage": "https://www.poster.ly/mcp",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/awpthorp/posterly.git",
11
- "directory": "mcp-server"
10
+ "url": "git+https://github.com/awpthorp/posterly-mcp-server.git"
12
11
  },
13
12
  "bugs": {
14
- "url": "https://github.com/awpthorp/posterly/issues"
13
+ "url": "https://github.com/awpthorp/posterly-mcp-server/issues"
15
14
  },
16
15
  "keywords": [
17
16
  "mcp",
@@ -28,6 +27,14 @@
28
27
  "posterly-mcp": "dist/index.js"
29
28
  },
30
29
  "main": "./dist/index.js",
30
+ "files": [
31
+ "dist",
32
+ "tool-registry.json",
33
+ "tool-annotations.json",
34
+ "server.json",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
31
38
  "scripts": {
32
39
  "build": "tsc",
33
40
  "dev": "tsc --watch",
package/server.json CHANGED
@@ -3,18 +3,17 @@
3
3
  "name": "io.github.awpthorp/posterly",
4
4
  "title": "posterly",
5
5
  "description": "Validate, schedule, publish, and analyze social content across 18 platforms with posterly.",
6
- "version": "0.50.4",
6
+ "version": "0.51.0",
7
7
  "websiteUrl": "https://www.poster.ly/mcp",
8
8
  "repository": {
9
- "url": "https://github.com/awpthorp/posterly",
10
- "source": "github",
11
- "subfolder": "mcp-server"
9
+ "url": "https://github.com/awpthorp/posterly-mcp-server",
10
+ "source": "github"
12
11
  },
13
12
  "packages": [
14
13
  {
15
14
  "registryType": "npm",
16
15
  "identifier": "posterly-mcp-server",
17
- "version": "0.50.4",
16
+ "version": "0.51.0",
18
17
  "transport": {
19
18
  "type": "stdio"
20
19
  },
package/RELEASING.md DELETED
@@ -1,115 +0,0 @@
1
- # Releasing the MCP surfaces
2
-
3
- posterly has two MCP surfaces sharing one version namespace:
4
-
5
- | Surface | Where it lives | How it reaches users |
6
- | --- | --- | --- |
7
- | Hosted HTTP | `lib/mcp/` → `POST /api/mcp` | **Automatically**, with the Vercel deploy of `main` |
8
- | npm stdio | `mcp-server/src/` → `posterly-mcp-server` | **Only when someone runs `npm publish`** |
9
-
10
- That asymmetry is the whole reason this file exists.
11
-
12
- ## The failure this prevents
13
-
14
- The docs tell users to install with `npx -y posterly-mcp-server@latest`, so most
15
- MCP traffic is the npm package. The package is a thin client over `/api/v1/*`,
16
- which makes it tempting to assume a server-side fix reaches everyone. It does
17
- not. **The npm package does its own output formatting**, so anything the client
18
- renders itself stays broken until a publish:
19
-
20
- - tool output formatting (truncation, row caps, what columns are shown)
21
- - input schemas (new parameters like `limit` / `offset`)
22
- - tool descriptions and names
23
-
24
- This is not hypothetical. In Aug 2026 the Google Business review truncation was
25
- fixed server-side and merged. Hosted users got the fix on deploy. npm users kept
26
- seeing reviews clipped to ~180 characters, capped at 25 rows, with no dates —
27
- because that formatting lives in `mcp-server/src/tools/`. Only a publish fixed it.
28
-
29
- ## Release order
30
-
31
- ```
32
- change an MCP surface -> bump the version -> merge -> deploy -> npm publish
33
- ```
34
-
35
- Bumping and publishing are separate steps with different failure modes:
36
-
37
- - **Skipping the bump is unrecoverable.** npm versions are immutable. Tool
38
- changes merged under a version already on npm can never be delivered under
39
- that version. `npm run check:mcp-version-bump` fails the build to prevent it.
40
- - **Skipping the publish is recoverable** — just publish. `npm run
41
- check:mcp-published` tells you when one is outstanding.
42
-
43
- ## 1. Bump the version
44
-
45
- The version appears in six places and `npm run check:mcp-parity` enforces that
46
- they all agree:
47
-
48
- - `lib/mcp/version.ts` — hosted endpoint
49
- - `mcp-server/src/lib/version.ts` — stdio package
50
- - `mcp-server/package.json`
51
- - `mcp-server/package-lock.json` (two entries)
52
- - `mcp-server/server.json` (two entries)
53
- - `mcp-server/README.md` — the `posterly-mcp-server@X.Y.Z exposes N tools` line
54
-
55
- Then rebuild so the compiled output matches, since the parity check reads
56
- `mcp-server/dist/lib/version.js` too:
57
-
58
- ```bash
59
- npm --prefix mcp-server run build
60
- npm run check:mcp-parity
61
- ```
62
-
63
- Use a patch bump for tool fixes and additive schema changes; a minor bump for
64
- new tools or a changed tool surface.
65
-
66
- ## 2. Merge and deploy
67
-
68
- Land the PR and let `main` deploy. The hosted endpoint is live at this point;
69
- npm users are not.
70
-
71
- ## 3. Publish
72
-
73
- ```bash
74
- cd mcp-server
75
- npm whoami # must be an account that can publish posterly-mcp-server
76
- npm publish # add --otp=<code> if 2FA prompts
77
- ```
78
-
79
- `prepack` rebuilds `dist/` and re-runs the parity check before packing, so a
80
- stale build or a drifted version cannot ship. `dist/` is gitignored but is
81
- included in the tarball — `prepack` is what puts it there.
82
-
83
- Sanity-check the tarball first if you want:
84
-
85
- ```bash
86
- npm pack --dry-run
87
- ```
88
-
89
- ## 4. Verify
90
-
91
- ```bash
92
- npm view posterly-mcp-server version dist-tags
93
- npm run check:mcp-published
94
- ```
95
-
96
- Both should report the version you just published. Users on `@latest` pick it
97
- up on their next client restart; there is nothing for them to do.
98
-
99
- ## If you published something broken
100
-
101
- Do not `npm unpublish` and do not republish the same number — npm versions are
102
- immutable and unpublishing breaks anyone who already resolved it. Cut the next
103
- patch version and publish that.
104
-
105
-
106
- ## Publishing from GitHub (trusted publishing)
107
-
108
- npm now requires 2FA or a trusted publisher to publish. The repo has a manual
109
- workflow, `.github/workflows/publish-mcp.yml` ("Publish MCP"), that publishes
110
- `mcp-server/` with GitHub OIDC, so no npm token or one-time code is needed.
111
- One-time setup on npmjs.com: package `posterly-mcp-server` > Settings >
112
- Trusted Publisher > GitHub Actions, owner `awpthorp`, repository `posterly`,
113
- workflow `publish-mcp.yml`. After an MCP change merges and deploys, run it from
114
- the Actions tab (or `gh workflow run publish-mcp.yml`), then
115
- `npm run check:mcp-published`. It skips if the version is already on npm.
package/SUBMISSIONS.md DELETED
@@ -1,109 +0,0 @@
1
- # MCP connector submissions
2
-
3
- Notes for listing the hosted MCP server as a one-click connector. The pipework
4
- (hosted HTTP MCP + stdio MCP) already works with API keys. Dynamic Client
5
- Registration and refresh-token rotation are what Claude.ai / ChatGPT-style hosts
6
- need for a connect flow without a human-allowlisted `client_id`.
7
-
8
- Do not publish these notes as user-facing marketing copy. They are for the
9
- person who applies the production migration and files the directory forms.
10
-
11
- ## Preconditions
12
-
13
- 1. Apply the DCR / refresh-token migration
14
- (`supabase/migrations/20260906140000_oauth_dynamic_registration_and_refresh.sql`)
15
- **before or with** the production deploy, not after. Shipping the app first
16
- leaves `oauth_refresh_tokens` missing: the token endpoint then falls back to
17
- a 365-day access-only grant for dynamic clients, and DCR verification that
18
- expects refresh tokens will fail. Do not apply the SQL from an agent session
19
- that can write straight to prod.
20
- 2. Confirm `NEXT_PUBLIC_SITE_URL` is `https://www.poster.ly` in the production
21
- deploy so discovery documents advertise the right issuer.
22
- 3. Create a reviewer test account with the API add-on enabled, plus a short
23
- setup note they can follow.
24
- 4. Confirm discovery before submitting:
25
- - `GET /.well-known/oauth-authorization-server` includes
26
- `registration_endpoint` and `refresh_token` in `grant_types_supported`
27
- - `POST /api/oauth/register` returns `201` with a `dyn_` `client_id`
28
- - consent shows the self-registered warning, callback host, and `client_id`
29
- for that client
30
- - refresh-token reuse within 30 seconds returns `invalid_grant` without
31
- revoking the chain; reuse older than 30 seconds revokes the chain
32
- - `/api/mcp` returns `403` `origin_not_allowed` for an untrusted Origin
33
- - `tools/list` includes annotations on every tool
34
-
35
- ## Anthropic Connectors Directory
36
-
37
- This is the remote MCP connector listing (Claude.ai / Claude desktop
38
- connectors). It is distinct from the Claude Code plugin already pending review.
39
-
40
- Submit the remote MCP server at
41
- https://claude.ai/admin-settings/directory/submissions/new or
42
- https://clau.de/mcp-directory-submission.
43
-
44
- Fallback contact: mcp-review@anthropic.com.
45
-
46
- Use:
47
-
48
- - Server URL: `https://www.poster.ly/api/mcp`
49
- - Server card: `https://www.poster.ly/.well-known/mcp/server-card.json`
50
- - Docs: `https://www.poster.ly/mcp` and `https://www.poster.ly/agents`
51
- (public pages only; do not submit auth-gated `https://www.poster.ly/docs/...`
52
- URLs)
53
- - Auth: OAuth 2.1 + PKCE, RFC 7591 Dynamic Client Registration, rotating
54
- refresh tokens (1-hour access, 30-day refresh for DCR clients)
55
- - Platforms: all 18 production platforms
56
-
57
- Connectors Connect (the in-product connect form) uses a Client ID Metadata
58
- Document, not DCR, for this flow:
59
-
60
- - `client_id`: `https://claude.ai/oauth/mcp-oauth-client-metadata`
61
- - `redirect_uri`: `https://claude.ai/api/mcp/auth_callback`
62
-
63
- DCR at `POST /api/oauth/register` remains available for other hosts. It is
64
- not what Claude Connectors uses for Connect.
65
-
66
- Do not claim Autopilot ships. Do not claim the connector is already listed.
67
-
68
- Optional after deploy: bump and publish `posterly-mcp-server` if you want the
69
- stdio README changes on npm. Hosted `/api/mcp` picks up this repo deploy
70
- without an npm publish.
71
-
72
- ## ChatGPT / OpenAI Plugins Directory
73
-
74
- This is a different form from the Claude plugin directory (already submitted)
75
- and from the Anthropic Connectors Directory above. File it after the OAuth DCR
76
- deploy is live. An agent cannot submit the form: Alex must complete OpenAI org
77
- verification / Apps Management write access.
78
-
79
- Portal: https://platform.openai.com/plugins
80
-
81
- Use:
82
-
83
- - MCP URL: `https://www.poster.ly/api/mcp`
84
- - Auth: OAuth 2.1 + PKCE + DCR at `POST /api/oauth/register` (now live on prod)
85
- - Domain verification: set `OPENAI_APPS_CHALLENGE_TOKEN` in Vercel to the
86
- portal token, deploy, then Scan Tools. OpenAI fetches
87
- `https://www.poster.ly/.well-known/openai-apps-challenge` and expects the
88
- exact token as `text/plain` (no JSON).
89
- - Homepage: `https://www.poster.ly/agents`
90
- - Privacy: `https://www.poster.ly/privacy`
91
- - Terms: `https://www.poster.ly/terms`
92
- - Support: `https://www.poster.ly/dashboard/support` (or `/agents`)
93
-
94
- Do not claim the plugin is listed until OpenAI publishes it.
95
-
96
- ## Other hosted hosts
97
-
98
- ChatGPT-style hosts follow the same DCR + authorize + token flow. HTTPS
99
- callbacks such as `https://chatgpt.com/oauth/callback` are already accepted by
100
- the redirect URI validator. Extra browser origins can be added with
101
- `MCP_TRUSTED_ORIGINS` (comma-separated hostnames or full URLs).
102
-
103
- The ChatGPT plugin / app directory form is covered in the section above.
104
-
105
- ## Registry metadata
106
-
107
- `server.json` is the official MCP Registry metadata for the stdio package
108
- (`io.github.awpthorp/posterly`). Publishing that package is a separate release
109
- step. See `RELEASING.md`.