prepublish-mcp 1.0.0 → 1.0.1

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 (3) hide show
  1. package/README.md +137 -58
  2. package/dist/bridge.js +1 -1
  3. package/package.json +6 -2
package/README.md CHANGED
@@ -1,93 +1,172 @@
1
1
  # prepublish-mcp
2
2
 
3
- Tooling around the hosted PrePublish MCP server. The server itself is **not** in this package — it lives in the web app and is served at `https://prepublish.ai/mcp`.
3
+ Audit a YouTube script **before** you record it, from inside your AI client.
4
4
 
5
- | Path | What it is |
6
- | --- | --- |
7
- | `prepublish-fe/app/mcp/route.ts` | The live endpoint. Streamable HTTP, stateless, anonymous-friendly |
8
- | `prepublish-fe/lib/mcp/protocol.ts` | JSON-RPC / MCP core |
9
- | `prepublish-fe/lib/mcp/tools.ts` | The six tools and their descriptions |
10
- | `prepublish-fe/lib/mcp/limits.ts` | Daily spend cap and per-caller burst limit |
11
- | `prepublish-fe/app/mcp-server/` | Public documentation page |
12
- | `prepublish-mcp/src/bridge.ts` | stdio bridge for clients that cannot use a remote server |
13
- | `prepublish-mcp/test/` | Conformance suite driven by the official MCP SDK client |
14
- | `prepublish-mcp/server.json` | Registry entry for `ai.prepublish/script-audit` |
5
+ Prepublish is a remote MCP server. It reads a draft that does not exist as a
6
+ video yet and returns hook, structure and pacing scores, the passages most
7
+ likely to lose viewers, an inauthentic-content check, a YouTube policy
8
+ pre-flight that cites YouTube's own published pages, and a words-to-runtime
9
+ calculator built on measured speaking rates.
10
+
11
+ Every other YouTube MCP server fetches the transcript of a video that is
12
+ already published. This one reads the script you have not filmed.
13
+
14
+ Free, anonymous, no API key, no account.
15
+
16
+ ## Install
17
+
18
+ **Claude Code**, one command:
19
+
20
+ ```bash
21
+ claude mcp add --transport http prepublish https://mcp.prepublish.ai
22
+ ```
23
+
24
+ **Cursor, VS Code, Windsurf, Claude Code project scope**, or anything that
25
+ reads an `mcpServers` object:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "prepublish": {
31
+ "type": "http",
32
+ "url": "https://mcp.prepublish.ai"
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ **Claude Desktop**: add a custom connector under Customize, then Connectors,
39
+ and paste `https://mcp.prepublish.ai`.
15
40
 
16
- One source of truth for tools: the app. The bridge fetches its tool list from the hosted server at startup, so adding a tool needs no release here.
41
+ **Codex CLI**, `~/.codex/config.toml`:
42
+
43
+ ```toml
44
+ [mcp_servers.prepublish]
45
+ url = "https://mcp.prepublish.ai"
46
+ ```
47
+
48
+ **Clients that can only launch a command** use the stdio bridge in this
49
+ repository. It needs Node 20 or newer and forwards to the same endpoint:
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "prepublish": {
55
+ "command": "npx",
56
+ "args": ["-y", "prepublish-mcp"]
57
+ }
58
+ }
59
+ }
60
+ ```
17
61
 
18
- ## Why the server is hand-rolled rather than SDK-hosted
62
+ Agents installing this on a user's behalf should read
63
+ [`llms-install.md`](./llms-install.md).
19
64
 
20
- `@modelcontextprotocol/sdk`'s `StreamableHTTPServerTransport` speaks Node's `IncomingMessage`/`ServerResponse`; a Next App Router route handler speaks Web `Request`/`Response`. Shimming one onto the other is more code, and more fragile code, than answering the five JSON-RPC methods a tools-only server needs. Conformance is not taken on trust: `test/conformance.test.ts` drives the endpoint with the official SDK **client** over Streamable HTTP, so the wire format is checked against the reference implementation.
65
+ ### Check it worked
21
66
 
22
- Supported protocol revisions: `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05`. A client asking for a supported revision gets it back; anything else negotiates down to the newest we implement.
67
+ Ask for a runtime estimate: *"Use prepublish to convert 1500 words into a
68
+ runtime range."* `script_runtime` is local arithmetic, never rate limited, and
69
+ returns three estimates. If that answers, the connection is good.
23
70
 
24
71
  ## Tools
25
72
 
26
- | Tool | Cost | Purpose |
73
+ | Tool | Cost | What it returns |
27
74
  | --- | --- | --- |
28
- | `audit_script` | AI-backed | Full audit of a finished draft. Scores, attention-risk map, per-passage rewrites. Polls to completion, then returns the analysis and its id |
29
- | `get_audit` | free | Collect an audit by `analysis_id` |
30
- | `audit_hook` | AI-backed | Per-sentence attention pull, curiosity gap, payoff distance, grade, rewrites |
31
- | `check_authenticity` | AI-backed | Reused / templated / mass-produced content risk with quotes and remediation |
32
- | `policy_preflight` | AI-backed | YouTube advertiser and monetisation policy exposure, each category citing YouTube's own page. Quoted passages are the paid half |
33
- | `script_runtime` | free, local | Words runtime from measured speaking rates (160 / 181 / 201 wpm across 349 videos) |
75
+ | `audit_script` | AI-backed | Full audit of a finished draft: hook, structure and pacing scores, an attention-risk map naming the passages most likely to lose viewers, and a rewrite. Returns the analysis and its id |
76
+ | `get_audit` | free | Collect an earlier audit by `analysis_id` |
77
+ | `audit_hook` | AI-backed | Per-sentence attention pull across the opening, curiosity gap, payoff distance, a grade, and rewritten alternatives |
78
+ | `check_authenticity` | AI-backed | Reused, templated or mass-produced content risk, with the quotes that fired each signal |
79
+ | `policy_preflight` | AI-backed | Which YouTube policy families a script touches, each citing YouTube's own page |
80
+ | `script_runtime` | free, local | Words to runtime and runtime to a word budget, at 160, 181 and 201 words per minute measured across 349 videos |
81
+
82
+ `audit_script` asks for an email address, because the full audit is released by
83
+ email. The other five do not.
34
84
 
35
- Every AI-backed response carries the same `notice`: the check is text-only, it maps relative attention risk inside an unrecorded script, and it does not measure or predict published YouTube retention. That sentence is repeated to the user by the model, so it is in the tool descriptions as well as the payloads.
85
+ ### What it does not do
36
86
 
37
- Failures return the next action rather than a stack trace: `402` asks the user for an email, `401`/`403` points at the plan, `429` says the allowance is spent and not to retry, `503` says try later.
87
+ Every AI-backed response carries the same notice, and it is worth stating here
88
+ too. These checks are text-only. They map relative attention risk inside an
89
+ unrecorded script. They do not measure or predict the retention a published
90
+ video will get, and no output here is a forecast of views, watch time or
91
+ revenue.
92
+
93
+ Nothing fetches a video, a transcript or a channel. Every tool reads text you
94
+ pass it.
38
95
 
39
96
  ## Limits
40
97
 
41
- Set on the web app, visible at `GET https://prepublish.ai/mcp`:
98
+ The free tier is published live at `GET https://mcp.prepublish.ai`, which
99
+ returns a machine-readable server card with the current day's usage.
42
100
 
43
- | Variable | Default | Meaning |
44
- | --- | --- | --- |
45
- | `MCP_DAILY_CALL_CAP` | `100` | AI-backed calls per UTC day across the whole endpoint |
46
- | `MCP_CALLER_CALL_LIMIT` | `6` | AI-backed calls per caller per 10 minutes |
101
+ | Limit | Default |
102
+ | --- | --- |
103
+ | AI-backed calls per UTC day, across the whole endpoint | 100 |
104
+ | AI-backed calls per caller per 10 minutes | 6 |
47
105
 
48
- Both counters are in-process. One web container, small numbers, and a restart resets a counter rather than wrongly blocking someone. Move them to Valkey if the app ever runs replicas.
106
+ `script_runtime` is local arithmetic and never counts against either.
49
107
 
50
- The backend's own limiter keys on client IP, and every MCP call reaches it from the web container's single IP — which is exactly why the per-caller limit exists here.
108
+ A bearer token in `PREPUBLISH_TOKEN` raises the limits without changing the
109
+ tool list.
51
110
 
52
- ## Local development
111
+ When the daily cap is reached the tool returns an error that tells the model
112
+ not to retry and names the web alternative for that day. Failures return the
113
+ next action rather than a stack trace.
53
114
 
54
- ```bash
55
- # 1. run the app (serves /mcp)
56
- cd ../prepublish-fe && npm run build && npm run start -- --port 4910
115
+ ## Transport and protocol
57
116
 
58
- # 2. conformance suite against it
59
- cd ../prepublish-mcp && npm install && npm run build && npm test
60
- ```
117
+ Streamable HTTP, stateless. Supported revisions: `2025-11-25`, `2025-06-18`,
118
+ `2025-03-26`, `2024-11-05`. A client asking for a supported revision gets it
119
+ back; anything else negotiates to the newest one implemented, and the
120
+ negotiated revision is reported identically in the response header and in the
121
+ `initialize` result.
61
122
 
62
- `npm test` covers the handshake, tool discovery, schema shape, both directions of `script_runtime`, unknown-tool errors, the server card, batching rejection, notification handling, protocol negotiation in both directions, and the stdio bridge round trip. One AI-backed test is skipped unless `MCP_TEST_BILLABLE=1`, because a real call costs money and writes a row.
123
+ The endpoint validates the `Origin` header. Requests without one, which is
124
+ every non-browser client, are always served. A browser origin that is not
125
+ `prepublish.ai` is refused with 403, as the transport specification requires.
126
+ An unsupported `MCP-Protocol-Version` header is a 400.
63
127
 
64
- Verify a deployment:
128
+ Aliases: `https://prepublish.ai/mcp` and `https://mcp.prepublish.ai/mcp` serve
129
+ the same handler.
130
+
131
+ ## Development
132
+
133
+ The server itself lives in the Prepublish web application, not in this
134
+ repository. What is here is the stdio bridge and the conformance suite that
135
+ holds the hosted endpoint to the specification.
65
136
 
66
137
  ```bash
67
- MCP_URL=https://prepublish.ai/mcp npm run test:conformance
138
+ npm install
139
+ npm run build
140
+ MCP_URL=https://mcp.prepublish.ai npm test
68
141
  ```
69
142
 
70
- ## The bridge
143
+ The suite drives the endpoint with the official MCP SDK **client** over
144
+ Streamable HTTP, so the wire format is checked against the reference
145
+ implementation rather than against our own assumptions. It covers the
146
+ handshake, tool discovery, schema shape, both directions of `script_runtime`,
147
+ unknown-tool errors, the server card, batching rejection, notification
148
+ handling, protocol negotiation in both directions, Origin validation, protocol
149
+ version validation, and the stdio bridge round trip.
71
150
 
72
- For clients that require a local stdio command:
151
+ One AI-backed test is skipped unless `MCP_TEST_BILLABLE=1`, because a real call
152
+ costs money and writes a row.
73
153
 
74
- ```json
75
- {
76
- "mcpServers": {
77
- "prepublish": { "command": "npx", "args": ["-y", "prepublish-mcp"] }
78
- }
79
- }
80
- ```
81
-
82
- `PREPUBLISH_MCP_URL` overrides the upstream endpoint; `PREPUBLISH_TOKEN` forwards a bearer token. The bridge adds and hides nothing — a test asserts its tool list equals the hosted one.
154
+ `PREPUBLISH_MCP_URL` overrides the upstream endpoint for the bridge. The bridge
155
+ adds and hides nothing: a test asserts its tool list equals the hosted one, so
156
+ adding a tool on the server needs no release here.
83
157
 
84
158
  ## Registry
85
159
 
86
- `server.json` claims the DNS-verified namespace `ai.prepublish/script-audit` with a remote-only entry. Two ways to prove the domain, both documented in `ops/mcp/launch-2026-09-10.md`: a DNS TXT record, or the `MCP_REGISTRY_PUBLIC_KEY` environment variable, which makes `https://prepublish.ai/.well-known/mcp-registry-auth` serve the same value. The route 404s until that variable is set, so an unconfigured deployment cannot advertise a half-finished claim.
160
+ Published to the official MCP registry as `ai.prepublish/script-audit`, a
161
+ remote-only entry under the DNS-verified `ai.prepublish` namespace. See
162
+ [`server.json`](./server.json).
163
+
164
+ ## Links
165
+
166
+ - Documentation: <https://prepublish.ai/mcp-server>
167
+ - Privacy: <https://prepublish.ai/privacy>
168
+ - Contact: <https://prepublish.ai/contact>
87
169
 
88
- ## Known gaps
170
+ ## License
89
171
 
90
- - **Protocol revision lag.** The revision in force is `2026-07-28`; this server implements up to `2025-11-25`, which the SDK also treats as latest. Newer clients are required to handle older dialects. Revisit when the SDK ships `2026-07-28`.
91
- - **No OAuth 2.1.** Anonymous plus optional bearer token. OAuth is only needed for per-user identity and verified-directory status.
92
- - **No per-user API keys.** Authenticated use means an existing magic-link JWT. Real API keys are the prerequisite for selling MCP access.
93
- - **Path, not subdomain.** `mcp.prepublish.ai` needs a DNS record and a Dokploy service; when it exists, only the URL in `server.json`, the docs page and the card change.
172
+ MIT. See [LICENSE](./LICENSE).
package/dist/bridge.js CHANGED
@@ -32,6 +32,6 @@ const { tools } = await upstream.listTools();
32
32
  const local = new Server({ name: 'prepublish', version: '1.0.0' }, { capabilities: { tools: { listChanged: false } } });
33
33
  local.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
34
34
  local.setRequestHandler(CallToolRequestSchema, async (request) => upstream.callTool({ name: request.params.name, arguments: request.params.arguments ?? {} }));
35
- process.stderr.write(`prepublish-mcp bridge ready upstream=${remoteUrl} tools=${tools.length} auth=${token ? 'bearer' : 'anonymous'}\n`);
35
+ process.stderr.write(`prepublish-mcp bridge ready: upstream=${remoteUrl} tools=${tools.length} auth=${token ? 'bearer' : 'anonymous'}\n`);
36
36
  await local.connect(new StdioServerTransport());
37
37
  //# sourceMappingURL=bridge.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prepublish-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "stdio bridge to the hosted PrePublish MCP server: audit a YouTube script before recording from any MCP client",
5
5
  "keywords": [
6
6
  "mcp",
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "homepage": "https://prepublish.ai/mcp-server",
16
16
  "bugs": {
17
- "url": "https://prepublish.ai/contact"
17
+ "url": "https://github.com/prepublish/prepublish-mcp/issues"
18
18
  },
19
19
  "license": "MIT",
20
20
  "author": "PrePublish (https://prepublish.ai)",
@@ -47,5 +47,9 @@
47
47
  "@types/node": "^24.0.0",
48
48
  "tsx": "^4.0.0",
49
49
  "typescript": "^5.0.0"
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/prepublish/prepublish-mcp"
50
54
  }
51
55
  }