prepublish-mcp 1.0.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.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/bridge.d.ts +20 -0
- package/dist/bridge.js +37 -0
- package/package.json +51 -0
- package/server.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PrePublish (prepublish.ai)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# prepublish-mcp
|
|
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`.
|
|
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` |
|
|
15
|
+
|
|
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.
|
|
17
|
+
|
|
18
|
+
## Why the server is hand-rolled rather than SDK-hosted
|
|
19
|
+
|
|
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.
|
|
21
|
+
|
|
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.
|
|
23
|
+
|
|
24
|
+
## Tools
|
|
25
|
+
|
|
26
|
+
| Tool | Cost | Purpose |
|
|
27
|
+
| --- | --- | --- |
|
|
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) |
|
|
34
|
+
|
|
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.
|
|
36
|
+
|
|
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.
|
|
38
|
+
|
|
39
|
+
## Limits
|
|
40
|
+
|
|
41
|
+
Set on the web app, visible at `GET https://prepublish.ai/mcp`:
|
|
42
|
+
|
|
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 |
|
|
47
|
+
|
|
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.
|
|
49
|
+
|
|
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.
|
|
51
|
+
|
|
52
|
+
## Local development
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# 1. run the app (serves /mcp)
|
|
56
|
+
cd ../prepublish-fe && npm run build && npm run start -- --port 4910
|
|
57
|
+
|
|
58
|
+
# 2. conformance suite against it
|
|
59
|
+
cd ../prepublish-mcp && npm install && npm run build && npm test
|
|
60
|
+
```
|
|
61
|
+
|
|
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.
|
|
63
|
+
|
|
64
|
+
Verify a deployment:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
MCP_URL=https://prepublish.ai/mcp npm run test:conformance
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## The bridge
|
|
71
|
+
|
|
72
|
+
For clients that require a local stdio command:
|
|
73
|
+
|
|
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.
|
|
83
|
+
|
|
84
|
+
## Registry
|
|
85
|
+
|
|
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.
|
|
87
|
+
|
|
88
|
+
## Known gaps
|
|
89
|
+
|
|
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.
|
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* stdio bridge to the hosted PrePublish MCP server.
|
|
4
|
+
*
|
|
5
|
+
* The tools themselves live in the web app and are served over Streamable HTTP
|
|
6
|
+
* at https://prepublish.ai/mcp. That is the single source of truth: this process
|
|
7
|
+
* adds no tools of its own, it forwards. It exists for clients that can only
|
|
8
|
+
* speak stdio to a local command (Claude Desktop bundles, some editors and
|
|
9
|
+
* local agent runtimes), so those users are not left out while a remote
|
|
10
|
+
* connector is unavailable to them.
|
|
11
|
+
*
|
|
12
|
+
* The tool list is fetched from the remote server at startup, so adding a tool
|
|
13
|
+
* in the app requires no release here.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* npx prepublish-mcp # bridges to https://mcp.prepublish.ai
|
|
17
|
+
* PREPUBLISH_MCP_URL=... npx prepublish-mcp # bridges to another deployment
|
|
18
|
+
* PREPUBLISH_TOKEN=... npx prepublish-mcp # forwards a bearer token upstream
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* stdio bridge to the hosted PrePublish MCP server.
|
|
4
|
+
*
|
|
5
|
+
* The tools themselves live in the web app and are served over Streamable HTTP
|
|
6
|
+
* at https://prepublish.ai/mcp. That is the single source of truth: this process
|
|
7
|
+
* adds no tools of its own, it forwards. It exists for clients that can only
|
|
8
|
+
* speak stdio to a local command (Claude Desktop bundles, some editors and
|
|
9
|
+
* local agent runtimes), so those users are not left out while a remote
|
|
10
|
+
* connector is unavailable to them.
|
|
11
|
+
*
|
|
12
|
+
* The tool list is fetched from the remote server at startup, so adding a tool
|
|
13
|
+
* in the app requires no release here.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* npx prepublish-mcp # bridges to https://mcp.prepublish.ai
|
|
17
|
+
* PREPUBLISH_MCP_URL=... npx prepublish-mcp # bridges to another deployment
|
|
18
|
+
* PREPUBLISH_TOKEN=... npx prepublish-mcp # forwards a bearer token upstream
|
|
19
|
+
*/
|
|
20
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
21
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
22
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
23
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
24
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
25
|
+
const remoteUrl = process.env.PREPUBLISH_MCP_URL ?? 'https://mcp.prepublish.ai';
|
|
26
|
+
const token = process.env.PREPUBLISH_TOKEN;
|
|
27
|
+
const upstream = new Client({ name: 'prepublish-stdio-bridge', version: '1.0.0' });
|
|
28
|
+
await upstream.connect(new StreamableHTTPClientTransport(new URL(remoteUrl), {
|
|
29
|
+
requestInit: token ? { headers: { authorization: `Bearer ${token}` } } : undefined,
|
|
30
|
+
}));
|
|
31
|
+
const { tools } = await upstream.listTools();
|
|
32
|
+
const local = new Server({ name: 'prepublish', version: '1.0.0' }, { capabilities: { tools: { listChanged: false } } });
|
|
33
|
+
local.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
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`);
|
|
36
|
+
await local.connect(new StdioServerTransport());
|
|
37
|
+
//# sourceMappingURL=bridge.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prepublish-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "stdio bridge to the hosted PrePublish MCP server: audit a YouTube script before recording from any MCP client",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"youtube",
|
|
9
|
+
"script",
|
|
10
|
+
"retention",
|
|
11
|
+
"prepublish",
|
|
12
|
+
"claude",
|
|
13
|
+
"llm-tools"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://prepublish.ai/mcp-server",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://prepublish.ai/contact"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": "PrePublish (https://prepublish.ai)",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bin": {
|
|
23
|
+
"prepublish-mcp": "dist/bridge.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/bridge.js",
|
|
27
|
+
"dist/bridge.d.ts",
|
|
28
|
+
"server.json",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -p tsconfig.json",
|
|
37
|
+
"start": "node dist/bridge.js",
|
|
38
|
+
"test": "tsx --test test/*.test.ts",
|
|
39
|
+
"test:conformance": "tsx --test test/conformance.test.ts",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
41
|
+
"prepublishOnly": "npm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "1.30.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^24.0.0",
|
|
48
|
+
"tsx": "^4.0.0",
|
|
49
|
+
"typescript": "^5.0.0"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "ai.prepublish/script-audit",
|
|
4
|
+
"title": "PrePublish - YouTube script QA",
|
|
5
|
+
"description": "Audit a YouTube script before recording: hook, pacing, drop-off risk, copy-paste rewrites.",
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"websiteUrl": "https://prepublish.ai/mcp-server",
|
|
8
|
+
"remotes": [
|
|
9
|
+
{
|
|
10
|
+
"type": "streamable-http",
|
|
11
|
+
"url": "https://mcp.prepublish.ai"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|