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 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
- ## Two ways to run
57
+ ## Setup methods (pick one)
58
58
 
59
- | Mode | Command | When |
60
- |------|---------|------|
61
- | **CDN / npx** (no clone) | `npx -y webcake-landing-mcp` | Fastest start npm fetches & runs it, no clone or build. Auto-updates to the latest published version. |
62
- | **Local** (cloned build) | `node /abs/path/dist/index.js` | Hacking on the server, offline, or pinning a specific build. Run `npm run build` first. |
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
- Both expose the exact same tools. Every IDE config below shows the **local** form; to use **CDN** mode,
65
- just swap `command`/`args` for the npx form (see [Run without cloning](#run-without-cloning-npx)).
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 basic claude.ai connector dialog may not let you set custom headers (it offers OAuth, which this
226
- > server does not implement yet). For the header-based flow, use a client/proxy that can inject headers, or
227
- > run single-user with env vars behind a private URL.
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 `jwt` cookie server-side and hands the token back to a localhost callback —
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). JWTs last 90–365 days, so you rarely reconnect.
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 `jwt` cookie (the logged-in user's token)
280
- → 302 to <redirect_uri>?token=<jwt>&state=<s>
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
- ## Hai cách chạy
58
+ ## Các cách setup (chọn một)
59
59
 
60
- | Chế độ | Lệnh | Khi nào |
61
- |------|------|------|
62
- | **CDN / npx** (không clone) | `npx -y webcake-landing-mcp` | Khởi động nhanh nhất npm tự tải & chạy, không cần clone hay build. Tự cập nhật bản mới nhất. |
63
- | **Local** (clone & build) | `node /abs/path/dist/index.js` | Khi đang sửa server, offline, hoặc cần ghim một bản build cụ thể. Chạy `npm run build` trước. |
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
- Cả hai cùng expose y hệt các tool. Mọi cấu hình IDE bên dưới dùng dạng **local**; để dùng **CDN**, chỉ cần
66
- đổi `command`/`args` sang dạng npx (xem [Chạy không cần clone (npx)](#chạy-không-cần-clone-npx)).
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. Every request's headers carry the caller's OWN Webcake JWT
8
- * (see persistence/config.ts#configFromHeaders), so a hosted server is multi-user
9
- * and never bakes a shared token into env.
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.8",
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": {