webcake-landing-mcp 1.0.8 → 1.0.9
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 +70 -14
- package/README.vi.md +152 -7
- package/dist/http.js +35 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,15 +54,18 @@ valid element/page skeletons, a page validator, and tools to create or edit page
|
|
|
54
54
|
The AI agent produces the full `{ page, popup, settings, options, cartConfigs }` JSON; `create_page`
|
|
55
55
|
persists it (source-only — the page opens in the editor where re-saving renders it).
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Setup methods (pick one)
|
|
58
58
|
|
|
59
|
-
|
|
|
60
|
-
|
|
61
|
-
|
|
|
62
|
-
|
|
|
59
|
+
| # | Method | Best for | Auth | Jump to |
|
|
60
|
+
|---|--------|----------|------|---------|
|
|
61
|
+
| 1 | **Local stdio** — add to an IDE (Claude Desktop / Cursor / …) via `npx` or a built file | Daily use on your machine | env `WEBCAKE_JWT`, or `login`, or none (reference tools) | [IDE config](#configuration-by-ide--ai-tool) |
|
|
62
|
+
| 2 | **`login`** — grab the token through the browser (no copy-paste) | Avoiding a manual token paste (stdio / single-user remote) | browser session → saved `auth.json` | [Connect once](#connect-once--grab-your-token-automatically-login) |
|
|
63
|
+
| 3 | **Remote HTTP (`serve`)** — run as an HTTP server, test with MCP Inspector / `mcp-remote` / curl | Trying the remote transport locally | per-request `x-webcake-jwt` header, or env | [Remote](#run-as-a-remote-connector-streamable-http) |
|
|
64
|
+
| 4 | **VPS + claude.ai connector** — deploy public HTTPS, add as a custom connector | Sharing one hosted server | single-account (env token); per-user needs OAuth (not implemented) | [Deploy on a VPS](#deploy-on-a-vps) |
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
Two **run forms** apply to any method: **`npx -y webcake-landing-mcp …`** (no clone, auto-updates) or **`node /abs/path/dist/index.js …`** (a cloned build — run `npm run build` first). The IDE configs below show the local form; swap `command`/`args` for the npx form to use CDN mode.
|
|
67
|
+
|
|
68
|
+
The **reference + generation tools** (`get_generation_guide`, `list_elements`, `validate_page`, …) work with **zero config**; only the **persistence tools** (`create_page`, `update_page`, `list_pages`, `get_page`, `list_organizations`) need a token. Credentials resolve in order: **per-request header → env var → saved `auth.json`** (`login`).
|
|
66
69
|
|
|
67
70
|
## Quick Install (Recommended)
|
|
68
71
|
|
|
@@ -202,6 +205,12 @@ host), then in Claude → **Add custom connector**:
|
|
|
202
205
|
- **Name**: `webcake-landing`
|
|
203
206
|
- **Remote MCP server URL**: `https://<your-host>/mcp`
|
|
204
207
|
|
|
208
|
+
The dialog has no header field, so to pass a token through it, **put it in the URL**:
|
|
209
|
+
`https://<your-host>/mcp?jwt=<ljwt>` (also accepts `&api_base=…`, `&org_id=…`, `&host=…`, `&app_base=…`).
|
|
210
|
+
Give each person a URL with their own `jwt` → **per-user without OAuth**. An explicit `x-webcake-jwt` header
|
|
211
|
+
still wins over the query. ⚠️ A token in a URL can land in access/proxy logs — require **HTTPS** and disable
|
|
212
|
+
query-string logging on your reverse proxy; a header (or OAuth) is safer when the client supports it.
|
|
213
|
+
|
|
205
214
|
### Auth — per-request, multi-user (no shared token)
|
|
206
215
|
|
|
207
216
|
In stdio mode the JWT comes from env. In HTTP mode each request carries the caller's **own** credentials
|
|
@@ -222,9 +231,54 @@ by setting `WEBCAKE_API_BASE` + `WEBCAKE_JWT` in the host's env and keeping the
|
|
|
222
231
|
> no secret; only the persistence tools (`create_page`, `update_page`, …) use the JWT. If a request has no
|
|
223
232
|
> JWT, those tools return `missing_env` instead of touching the network.
|
|
224
233
|
>
|
|
225
|
-
> Note: the
|
|
226
|
-
>
|
|
227
|
-
>
|
|
234
|
+
> Note: the claude.ai connector dialog has **no header field** (only OAuth, which this server does not
|
|
235
|
+
> implement yet). Two ways around it: put the token in the URL as `?jwt=<ljwt>` (above — per-user, but the
|
|
236
|
+
> token shows up in logs), or use a header-capable client (`mcp-remote --header …`, below). A token in the
|
|
237
|
+
> server's env instead gives a shared **single-account** for everyone on that URL.
|
|
238
|
+
|
|
239
|
+
### Test it locally (no public URL needed)
|
|
240
|
+
|
|
241
|
+
`localhost` can't be used in the claude.ai dialog (Anthropic fetches the URL from its own servers). To try the
|
|
242
|
+
running `serve` server on your machine:
|
|
243
|
+
|
|
244
|
+
- **MCP Inspector** (GUI — easiest): `npx @modelcontextprotocol/inspector` → Transport **Streamable HTTP** →
|
|
245
|
+
URL `http://localhost:8787/mcp` → under Headers add `x-webcake-jwt` (+ `x-webcake-api-base`) → Connect → call tools.
|
|
246
|
+
- **`mcp-remote`** (use the remote server from a stdio client like Claude Desktop, with headers):
|
|
247
|
+
```json
|
|
248
|
+
{ "mcpServers": { "webcake-remote": { "command": "npx",
|
|
249
|
+
"args": ["-y", "mcp-remote", "http://localhost:8787/mcp",
|
|
250
|
+
"--header", "x-webcake-jwt:<ljwt>",
|
|
251
|
+
"--header", "x-webcake-api-base:https://api.webcake.io"] } } }
|
|
252
|
+
```
|
|
253
|
+
- **curl**: `initialize` (read the `mcp-session-id` response header) → `tools/list` → `tools/call`, all with
|
|
254
|
+
`Accept: application/json, text/event-stream`.
|
|
255
|
+
|
|
256
|
+
### Deploy on a VPS
|
|
257
|
+
|
|
258
|
+
1. **Build + run as a service** — `/etc/systemd/system/webcake-mcp.service`:
|
|
259
|
+
```ini
|
|
260
|
+
[Service]
|
|
261
|
+
WorkingDirectory=/opt/webcake-landing-mcp
|
|
262
|
+
ExecStart=/usr/bin/node dist/index.js serve --port 8787
|
|
263
|
+
Environment=WEBCAKE_API_BASE=https://api.webcake.io
|
|
264
|
+
Environment=WEBCAKE_JWT=<ljwt> # single-account only — see auth note below
|
|
265
|
+
Restart=always
|
|
266
|
+
[Install]
|
|
267
|
+
WantedBy=multi-user.target
|
|
268
|
+
```
|
|
269
|
+
`sudo systemctl enable --now webcake-mcp` (build once: `npm install && npm run build`).
|
|
270
|
+
2. **HTTPS + domain** (claude.ai requires https) — e.g. Caddy auto-TLS, `/etc/caddy/Caddyfile`:
|
|
271
|
+
```
|
|
272
|
+
mcp.yourdomain.com { reverse_proxy localhost:8787 }
|
|
273
|
+
```
|
|
274
|
+
3. **Add to claude.ai** → Remote MCP server URL = `https://mcp.yourdomain.com/mcp`.
|
|
275
|
+
|
|
276
|
+
**Auth on a shared server:**
|
|
277
|
+
- **Single-account** (works with the dialog today): `WEBCAKE_JWT` in the service env → everyone using the
|
|
278
|
+
connector shares that one Webcake account. Keep the URL private / gated; the token expires (~90 days).
|
|
279
|
+
- **Per-user** (each person their own account): give each person a URL with their own `?jwt=<ljwt>` (works
|
|
280
|
+
through the dialog, but the token appears in logs), or use a header-capable client (`mcp-remote --header …`),
|
|
281
|
+
or add **OAuth** (not implemented) for the cleanest flow.
|
|
228
282
|
|
|
229
283
|
## Manual Setup (local)
|
|
230
284
|
|
|
@@ -257,9 +311,9 @@ It opens your browser → (log into Webcake if needed) → the token is saved to
|
|
|
257
311
|
`~/.webcake-landing-mcp/auth.json`, which the server then reads automatically.
|
|
258
312
|
|
|
259
313
|
You're already logged in to Webcake in your browser, so `login` just opens a Webcake "connect"
|
|
260
|
-
page that reads your
|
|
314
|
+
page that reads your **`ljwt`** (landing) cookie and hands the token back to a localhost callback —
|
|
261
315
|
no copy-paste. The saved token is used by **both** the stdio server and a single-user `serve`
|
|
262
|
-
deployment (env vars still take precedence).
|
|
316
|
+
deployment (env vars still take precedence). The landing JWT lasts ~90 days, so you rarely reconnect.
|
|
263
317
|
|
|
264
318
|
Two URLs, don't mix them up:
|
|
265
319
|
|
|
@@ -276,12 +330,14 @@ Other flags: `--org-id`, `--port`, `--no-open`. Saved-file dir: `WEBCAKE_CONFIG_
|
|
|
276
330
|
|
|
277
331
|
```
|
|
278
332
|
GET /mcp-connect?redirect_uri=<loopback>&state=<s>
|
|
279
|
-
→ read the `
|
|
280
|
-
→ 302 to <redirect_uri>?token=<
|
|
333
|
+
→ read the `ljwt` cookie (the logged-in user's landing token)
|
|
334
|
+
→ 302 to <redirect_uri>?token=<ljwt>&state=<s>
|
|
281
335
|
(if there's no cookie: 302 to the login page first, then back here)
|
|
282
336
|
```
|
|
283
337
|
|
|
284
338
|
For safety, only honor `redirect_uri` values on `http://127.0.0.1:*` / `http://localhost:*`.
|
|
339
|
+
(Reference implementation: `builderx_spa/src/views/McpConnect.vue` reads `cookies.get('ljwt')` — so this
|
|
340
|
+
flow can also be done entirely in the SPA, no backend route needed.)
|
|
285
341
|
|
|
286
342
|
> Multi-user remote (the claude.ai connector dialog) can't do this browser loopback — there each
|
|
287
343
|
> user sends their own token via the `x-webcake-jwt` header (see the remote-connector section above).
|
package/README.vi.md
CHANGED
|
@@ -55,15 +55,18 @@ element/trang hợp lệ, bộ kiểm tra trang, và các tool để tạo/sửa
|
|
|
55
55
|
`{ page, popup, settings, options, cartConfigs }`; `create_page` lưu nó (chỉ-source — trang mở trong editor,
|
|
56
56
|
lưu lại sẽ render).
|
|
57
57
|
|
|
58
|
-
##
|
|
58
|
+
## Các cách setup (chọn một)
|
|
59
59
|
|
|
60
|
-
|
|
|
61
|
-
|
|
62
|
-
|
|
|
63
|
-
|
|
|
60
|
+
| # | Cách | Hợp cho | Auth | Xem |
|
|
61
|
+
|---|------|---------|------|-----|
|
|
62
|
+
| 1 | **Local stdio** — gắn vào IDE (Claude Desktop / Cursor / …) qua `npx` hoặc file build | Dùng hằng ngày trên máy | env `WEBCAKE_JWT`, hoặc `login`, hoặc không cần (tool tham chiếu) | [Cấu hình IDE](#cấu-hình-theo-ide--công-cụ-ai) |
|
|
63
|
+
| 2 | **`login`** — tự lấy token qua browser (khỏi copy-paste) | Khỏi dán token tay (stdio / remote 1 người) | session browser → file `auth.json` | [Kết nối một lần](#kết-nối-một-lần--tự-lấy-token-login) |
|
|
64
|
+
| 3 | **Remote HTTP (`serve`)** — chạy như HTTP server, test bằng MCP Inspector / `mcp-remote` / curl | Thử transport remote ở local | header `x-webcake-jwt` mỗi request, hoặc env | [Remote](#chạy-như-remote-connector-streamable-http) |
|
|
65
|
+
| 4 | **VPS + claude.ai connector** — deploy HTTPS public, thêm làm custom connector | Chia sẻ 1 server hosted | single-account (token env); per-user cần OAuth (chưa có) | [Deploy lên VPS](#deploy-lên-vps) |
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
Hai **dạng chạy** áp dụng cho mọi cách: **`npx -y webcake-landing-mcp …`** (không clone, tự cập nhật) hoặc **`node /abs/path/dist/index.js …`** (bản đã clone & build — chạy `npm run build` trước). Cấu hình IDE bên dưới dùng dạng local; đổi `command`/`args` sang dạng npx để dùng CDN.
|
|
68
|
+
|
|
69
|
+
Các **tool tham chiếu + generation** (`get_generation_guide`, `list_elements`, `validate_page`, …) chạy **zero config**; chỉ **tool lưu trữ** (`create_page`, `update_page`, `list_pages`, `get_page`, `list_organizations`) mới cần token. Token ưu tiên theo thứ tự: **header mỗi request → biến env → file `auth.json`** (`login`).
|
|
67
70
|
|
|
68
71
|
## Cài nhanh (Khuyến nghị)
|
|
69
72
|
|
|
@@ -184,6 +187,97 @@ Cấu hình MCP giống bản local, chỉ khác `command`/`args` trỏ tới `n
|
|
|
184
187
|
> npx cache lại package sau lần chạy đầu, nên các lần sau khởi động nhanh. Dùng phiên bản ghim
|
|
185
188
|
> (`webcake-landing-mcp@1.0.0`) nếu cần build tái lập được.
|
|
186
189
|
|
|
190
|
+
## Chạy như remote connector (Streamable HTTP)
|
|
191
|
+
|
|
192
|
+
Server còn nói được transport **remote MCP** (Streamable HTTP), nên có thể thêm qua dialog
|
|
193
|
+
**"Add custom connector"** của Claude bằng một URL — không chỉ stdio local.
|
|
194
|
+
|
|
195
|
+
Chạy chế độ HTTP (port mặc định `8787`, hoặc đặt `PORT` / `--port`):
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npx -y webcake-landing-mcp serve --port 8787
|
|
199
|
+
# → endpoint MCP tại http://localhost:8787/mcp (GET / hoặc /health trả JSON trạng thái)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Đưa ra **HTTPS** ở URL public (reverse proxy, tunnel như `ngrok http 8787`, hoặc host bất kỳ), rồi vào
|
|
203
|
+
Claude → **Add custom connector**:
|
|
204
|
+
|
|
205
|
+
- **Name**: `webcake-landing`
|
|
206
|
+
- **Remote MCP server URL**: `https://<host-của-bạn>/mcp`
|
|
207
|
+
|
|
208
|
+
Dialog không có ô header, nên muốn truyền token qua đó thì **để vào URL**:
|
|
209
|
+
`https://<host-của-bạn>/mcp?jwt=<ljwt>` (nhận thêm `&api_base=…`, `&org_id=…`, `&host=…`, `&app_base=…`).
|
|
210
|
+
Mỗi người một URL với `jwt` riêng → **per-user mà không cần OAuth**. Header `x-webcake-jwt` thật vẫn ưu tiên
|
|
211
|
+
hơn query. ⚠️ Token nằm trong URL có thể lọt vào access/proxy log — **bắt buộc HTTPS** và tắt log query ở
|
|
212
|
+
reverse proxy; dùng header (hoặc OAuth) an toàn hơn nếu client hỗ trợ.
|
|
213
|
+
|
|
214
|
+
### Auth — mỗi request, đa người dùng (không token chung)
|
|
215
|
+
|
|
216
|
+
Ở stdio JWT lấy từ env. Ở chế độ HTTP, mỗi request mang credential **riêng** của người gọi qua header,
|
|
217
|
+
nên server hosted là đa người dùng và không nhúng secret chung:
|
|
218
|
+
|
|
219
|
+
| Header | Tương ứng | Ghi chú |
|
|
220
|
+
|--------|-----------|---------|
|
|
221
|
+
| `x-webcake-jwt` (hoặc `Authorization: Bearer <jwt>`) | `WEBCAKE_JWT` | token tài khoản — gửi mỗi request |
|
|
222
|
+
| `x-webcake-org-id` | `WEBCAKE_ORG_ID` | org mặc định |
|
|
223
|
+
| `x-webcake-api-base` | `WEBCAKE_API_BASE` | thường set 1 lần qua env trên host |
|
|
224
|
+
| `x-webcake-app-base` | `WEBCAKE_APP_BASE` | base URL editor/preview |
|
|
225
|
+
|
|
226
|
+
Header nào thiếu thì fallback về biến env tương ứng — nên cũng chạy **một người dùng** được bằng cách đặt
|
|
227
|
+
`WEBCAKE_API_BASE` + `WEBCAKE_JWT` trong env của host và giữ URL riêng tư.
|
|
228
|
+
|
|
229
|
+
> ⚠️ Tool tham chiếu + generation (`get_generation_guide`, `list_elements`, `validate_page`, …) không cần
|
|
230
|
+
> secret; chỉ tool lưu trữ (`create_page`, `update_page`, …) dùng JWT. Request không có JWT thì các tool đó
|
|
231
|
+
> trả `missing_env` chứ không gọi mạng.
|
|
232
|
+
>
|
|
233
|
+
> Lưu ý: dialog claude.ai **không có ô header** (chỉ có OAuth, mà server này **chưa làm**). Hai cách lách:
|
|
234
|
+
> để token vào URL dạng `?jwt=<ljwt>` (như trên — per-user, nhưng token lộ trong log), hoặc dùng client hỗ trợ
|
|
235
|
+
> header (`mcp-remote --header …`, bên dưới). Đặt token ở env server thì thành **single-account** chung cho mọi người trên URL đó.
|
|
236
|
+
|
|
237
|
+
### Test ở local (không cần URL public)
|
|
238
|
+
|
|
239
|
+
`localhost` không dùng được trong dialog claude.ai (Anthropic gọi URL từ server của họ). Để thử server `serve`
|
|
240
|
+
chạy trên máy:
|
|
241
|
+
|
|
242
|
+
- **MCP Inspector** (GUI — dễ nhất): `npx @modelcontextprotocol/inspector` → Transport **Streamable HTTP** →
|
|
243
|
+
URL `http://localhost:8787/mcp` → mục Headers thêm `x-webcake-jwt` (+ `x-webcake-api-base`) → Connect → bấm gọi tool.
|
|
244
|
+
- **`mcp-remote`** (dùng server remote từ client stdio như Claude Desktop, kèm header):
|
|
245
|
+
```json
|
|
246
|
+
{ "mcpServers": { "webcake-remote": { "command": "npx",
|
|
247
|
+
"args": ["-y", "mcp-remote", "http://localhost:8787/mcp",
|
|
248
|
+
"--header", "x-webcake-jwt:<ljwt>",
|
|
249
|
+
"--header", "x-webcake-api-base:https://api.webcake.io"] } } }
|
|
250
|
+
```
|
|
251
|
+
- **curl**: `initialize` (đọc header `mcp-session-id` trả về) → `tools/list` → `tools/call`, tất cả kèm
|
|
252
|
+
`Accept: application/json, text/event-stream`.
|
|
253
|
+
|
|
254
|
+
### Deploy lên VPS
|
|
255
|
+
|
|
256
|
+
1. **Build + chạy như service** — `/etc/systemd/system/webcake-mcp.service`:
|
|
257
|
+
```ini
|
|
258
|
+
[Service]
|
|
259
|
+
WorkingDirectory=/opt/webcake-landing-mcp
|
|
260
|
+
ExecStart=/usr/bin/node dist/index.js serve --port 8787
|
|
261
|
+
Environment=WEBCAKE_API_BASE=https://api.webcake.io
|
|
262
|
+
Environment=WEBCAKE_JWT=<ljwt> # chỉ cho single-account — xem ghi chú auth dưới
|
|
263
|
+
Restart=always
|
|
264
|
+
[Install]
|
|
265
|
+
WantedBy=multi-user.target
|
|
266
|
+
```
|
|
267
|
+
`sudo systemctl enable --now webcake-mcp` (build 1 lần: `npm install && npm run build`).
|
|
268
|
+
2. **HTTPS + domain** (claude.ai bắt buộc https) — vd Caddy tự cấp TLS, `/etc/caddy/Caddyfile`:
|
|
269
|
+
```
|
|
270
|
+
mcp.yourdomain.com { reverse_proxy localhost:8787 }
|
|
271
|
+
```
|
|
272
|
+
3. **Thêm vào claude.ai** → Remote MCP server URL = `https://mcp.yourdomain.com/mcp`.
|
|
273
|
+
|
|
274
|
+
**Auth trên server chia sẻ:**
|
|
275
|
+
- **Single-account** (dùng được với dialog ngay): đặt `WEBCAKE_JWT` ở env service → mọi người dùng connector
|
|
276
|
+
chung 1 tài khoản Webcake. Giữ URL riêng tư / có cổng chặn; token hết hạn (~90 ngày).
|
|
277
|
+
- **Per-user** (mỗi người 1 account): cho mỗi người một URL với `?jwt=<ljwt>` riêng (chạy được qua dialog,
|
|
278
|
+
nhưng token lộ trong log), hoặc dùng client hỗ trợ header (`mcp-remote --header …`), hoặc thêm **OAuth**
|
|
279
|
+
(chưa làm) cho gọn nhất.
|
|
280
|
+
|
|
187
281
|
## Cài thủ công (local)
|
|
188
282
|
|
|
189
283
|
```bash
|
|
@@ -197,6 +291,55 @@ npm run smoke # self-test offline của factory + validator (in "ALL GOOD")
|
|
|
197
291
|
Các tool tham chiếu/kiểm tra chạy với **zero config**. Biến môi trường chỉ cần cho các tool lưu trữ
|
|
198
292
|
(`create_page`, `update_page`, `list_pages`, `get_page`, `list_organizations`).
|
|
199
293
|
|
|
294
|
+
## Kết nối một lần — tự lấy token (`login`)
|
|
295
|
+
|
|
296
|
+
Thay vì copy JWT bằng tay, chạy:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Production — zero config (mặc định: connect qua webcake.io, API qua api.webcake.io):
|
|
300
|
+
npx -y webcake-landing-mcp login
|
|
301
|
+
|
|
302
|
+
# Local dev — trỏ vào SPA (5173) + API (5800) ở máy:
|
|
303
|
+
node dist/index.js login \
|
|
304
|
+
--connect-url http://localhost:5173/mcp-connect \
|
|
305
|
+
--api-base http://localhost:5800
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Nó mở browser → (đăng nhập Webcake nếu cần) → token được lưu vào
|
|
309
|
+
`~/.webcake-landing-mcp/auth.json`, server tự đọc.
|
|
310
|
+
|
|
311
|
+
Bạn đang đăng nhập Webcake sẵn trong browser, nên `login` chỉ mở trang "connect" của Webcake — trang này
|
|
312
|
+
đọc cookie **`ljwt`** (landing) và trả token về một callback loopback nội bộ — khỏi copy-paste. Token đã lưu
|
|
313
|
+
được dùng bởi **cả** server stdio lẫn deploy `serve` một-người-dùng (env vẫn ưu tiên). Landing JWT sống ~90
|
|
314
|
+
ngày nên hiếm khi phải kết nối lại.
|
|
315
|
+
|
|
316
|
+
Hai URL, đừng nhầm:
|
|
317
|
+
|
|
318
|
+
- **Trang connect = SPA** (`--connect-url` / `WEBCAKE_CONNECT_URL`): `https://webcake.io/mcp-connect` ở prod,
|
|
319
|
+
`http://localhost:5173/mcp-connect` ở local. Nếu không, suy ra từ `WEBCAKE_APP_BASE` + `/mcp-connect`,
|
|
320
|
+
mặc định `https://webcake.io/mcp-connect`.
|
|
321
|
+
- **API base = backend** (`--api-base` / `WEBCAKE_API_BASE`): `https://api.webcake.io` ở prod,
|
|
322
|
+
`http://localhost:5800` ở local. Mặc định `https://api.webcake.io`.
|
|
323
|
+
|
|
324
|
+
Cờ khác: `--org-id`, `--port`, `--no-open`. Thư mục file lưu: `WEBCAKE_CONFIG_DIR` (mặc định
|
|
325
|
+
`~/.webcake-landing-mcp`).
|
|
326
|
+
|
|
327
|
+
**Endpoint cần thêm ở backend** (trong Webcake backend — nơi giữ cookie session):
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
GET /mcp-connect?redirect_uri=<loopback>&state=<s>
|
|
331
|
+
→ đọc cookie `ljwt` (landing token của user đang đăng nhập)
|
|
332
|
+
→ 302 tới <redirect_uri>?token=<ljwt>&state=<s>
|
|
333
|
+
(nếu chưa có cookie: 302 sang trang login trước, xong quay lại đây)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Để an toàn, chỉ chấp nhận `redirect_uri` ở `http://127.0.0.1:*` / `http://localhost:*`.
|
|
337
|
+
(Mẫu tham khảo: `builderx_spa/src/views/McpConnect.vue` đọc `cookies.get('ljwt')` — nên flow này làm hẳn ở
|
|
338
|
+
SPA cũng được, khỏi cần route backend.)
|
|
339
|
+
|
|
340
|
+
> Remote đa người dùng (dialog claude.ai) không làm được browser loopback này — ở đó mỗi user gửi token riêng
|
|
341
|
+
> qua header `x-webcake-jwt` (xem mục remote-connector ở trên).
|
|
342
|
+
|
|
200
343
|
## Biến môi trường
|
|
201
344
|
|
|
202
345
|
| Biến | Bắt buộc | Mô tả |
|
|
@@ -206,6 +349,8 @@ Các tool tham chiếu/kiểm tra chạy với **zero config**. Biến môi trư
|
|
|
206
349
|
| `WEBCAKE_ORG_ID` | Không | Organization mặc định cho `create_page` (bị ghi đè bởi tham số `organization_id`). Bỏ trống → trang cá nhân. |
|
|
207
350
|
| `WEBCAKE_HOST` | Không | Header `Host` tuỳ chọn (Phoenix route theo host, ví dụ `builder.localhost`). |
|
|
208
351
|
| `WEBCAKE_APP_BASE` | Không | Base tuỳ chọn để dựng URL editor/preview trong kết quả. |
|
|
352
|
+
| `WEBCAKE_CONNECT_URL` | Không | Trang "connect" (SPA) cho `login` (mặc định `https://webcake.io/mcp-connect`; nếu không thì `WEBCAKE_APP_BASE` + `/mcp-connect`). |
|
|
353
|
+
| `WEBCAKE_CONFIG_DIR` | Không | Thư mục chứa `auth.json` do `login` ghi (mặc định `~/.webcake-landing-mcp`). |
|
|
209
354
|
|
|
210
355
|
> \* `WEBCAKE_API_BASE` và `WEBCAKE_JWT` chỉ cần cho các tool lưu trữ. Các tool tham chiếu và kiểm tra
|
|
211
356
|
> (`get_generation_guide`, `list_elements`, `get_element`, `validate_page`, …) chạy không cần chúng.
|
package/dist/http.js
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Stateful sessions: an `initialize` POST (no session id) spins up a fresh
|
|
6
6
|
* McpServer + transport and returns an `mcp-session-id`; later requests reuse it
|
|
7
|
-
* via that header.
|
|
8
|
-
* (
|
|
9
|
-
*
|
|
7
|
+
* via that header. Each request carries the caller's OWN Webcake JWT — via a header
|
|
8
|
+
* (x-webcake-jwt / Authorization) OR a URL query param (.../mcp?jwt=<token>, for
|
|
9
|
+
* clients like the claude.ai dialog that can't set headers; see applyQueryAuth +
|
|
10
|
+
* persistence/config.ts#configFromHeaders). So a hosted server is multi-user.
|
|
10
11
|
*
|
|
11
12
|
* All logging stays on stderr (console.error), same as stdio mode.
|
|
12
13
|
*/
|
|
@@ -30,6 +31,35 @@ async function readBody(req) {
|
|
|
30
31
|
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
31
32
|
return raw ? JSON.parse(raw) : undefined;
|
|
32
33
|
}
|
|
34
|
+
// Map credentials passed in the URL query (e.g. .../mcp?jwt=<token>) onto the
|
|
35
|
+
// x-webcake-* headers so the normal per-request config path handles them. This is
|
|
36
|
+
// for clients that can't set custom headers — notably the claude.ai connector
|
|
37
|
+
// dialog, which only takes a URL. An explicit header always wins over the query.
|
|
38
|
+
// SECURITY: a token in the URL can land in access/proxy logs — prefer headers,
|
|
39
|
+
// require HTTPS, and disable query-string logging on your reverse proxy.
|
|
40
|
+
const QUERY_AUTH = {
|
|
41
|
+
jwt: "x-webcake-jwt",
|
|
42
|
+
api_base: "x-webcake-api-base",
|
|
43
|
+
org_id: "x-webcake-org-id",
|
|
44
|
+
host: "x-webcake-host",
|
|
45
|
+
app_base: "x-webcake-app-base",
|
|
46
|
+
};
|
|
47
|
+
function applyQueryAuth(req) {
|
|
48
|
+
const q = (req.url ?? "").indexOf("?");
|
|
49
|
+
if (q === -1)
|
|
50
|
+
return;
|
|
51
|
+
const params = new URLSearchParams((req.url ?? "").slice(q + 1));
|
|
52
|
+
for (const [param, header] of Object.entries(QUERY_AUTH)) {
|
|
53
|
+
const value = params.get(param);
|
|
54
|
+
// Only fill in when there's no explicit header (header wins). The transport
|
|
55
|
+
// builds its Request from `req.rawHeaders` (via @hono/node-server), so we MUST
|
|
56
|
+
// push there — mutating `req.headers` alone is not seen by the tool handlers.
|
|
57
|
+
if (value && req.headers[header] == null) {
|
|
58
|
+
req.headers[header] = value;
|
|
59
|
+
req.rawHeaders.push(header, value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
33
63
|
export async function startHttpServer(port) {
|
|
34
64
|
// mcp-session-id -> live transport (each bound to its own McpServer instance).
|
|
35
65
|
const transports = new Map();
|
|
@@ -41,6 +71,8 @@ export async function startHttpServer(port) {
|
|
|
41
71
|
}
|
|
42
72
|
if (path !== MCP_PATH)
|
|
43
73
|
return rpcError(res, 404, `Not found. Send MCP requests to ${MCP_PATH}.`);
|
|
74
|
+
// Accept credentials via ?jwt=/?api_base=/... (for clients that can't set headers).
|
|
75
|
+
applyQueryAuth(req);
|
|
44
76
|
const sidHeader = req.headers["mcp-session-id"];
|
|
45
77
|
const sessionId = Array.isArray(sidHeader) ? sidHeader[0] : sidHeader;
|
|
46
78
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-landing-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "MCP server exposing Webcake landing-page element schemas + AI usage hints, and persisting LLM-generated page sources to a Webcake backend.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|