webcake-landing-mcp 1.5.10 → 1.5.11

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.
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "v": "1.5.11",
4
+ "d": "13/10/2026",
5
+ "type": "Fixed",
6
+ "en": "The HTTP server now answers HEAD requests the same way it answers GET on every public read-only route (/privacy, /privacy-policy, /terms, /tos,…",
7
+ "vi": "HTTP server nay trả lời request HEAD giống như GET trên mọi route công khai chỉ-đọc (/privacy, /privacy-policy, /terms, /tos, /favicon.ico,…"
8
+ },
2
9
  {
3
10
  "v": "1.5.10",
4
11
  "d": "13/10/2026",
@@ -33,12 +40,5 @@
33
40
  "type": "Fixed",
34
41
  "en": "The HTTP server now serves a 192px PNG at /favicon.ico, /favicon.png, and /apple-touch-icon.png (with matching <link rel=\"icon\">/<link…",
35
42
  "vi": "HTTP server nay phục vụ PNG 192px tại /favicon.ico, /favicon.png, và /apple-touch-icon.png (kèm thẻ <link rel=\"icon\">/<link rel=\"apple-touch-icon\">…"
36
- },
37
- {
38
- "v": "1.5.5",
39
- "d": "13/10/2026",
40
- "type": "Fixed",
41
- "en": "The page/source/sections/patches parameters on validate_page, create_page, update_page, add_section, and patch_page now declare a typed JSON Schema…",
42
- "vi": "Các tham số page/source/sections/patches của validate_page, create_page, update_page, add_section, và patch_page nay khai báo JSON Schema có kiểu rõ…"
43
43
  }
44
44
  ]
package/dist/http.js CHANGED
@@ -81,6 +81,12 @@ function iconPng() {
81
81
  return null;
82
82
  }
83
83
  }
84
+ // Public pages/assets answer HEAD like GET (Node drops the body on HEAD): link
85
+ // checkers — incl. the connector-directory form — probe with HEAD, and a 404
86
+ // there made /privacy and /terms look missing.
87
+ function isRead(req) {
88
+ return req.method === "GET" || req.method === "HEAD";
89
+ }
84
90
  function sendJson(res, status, body) {
85
91
  res.writeHead(status, { "content-type": "application/json" });
86
92
  res.end(JSON.stringify(body));
@@ -186,12 +192,12 @@ function htmlError(res, status, message) {
186
192
  async function handleOAuth(req, res, path) {
187
193
  const issuer = publicBase(req);
188
194
  // ---- Metadata (RFC 8414 / RFC 9728) ----
189
- if (req.method === "GET" && path === WELL_KNOWN_PR) {
195
+ if (isRead(req) && path === WELL_KNOWN_PR) {
190
196
  res.writeHead(200, { "content-type": "application/json", "access-control-allow-origin": "*" });
191
197
  res.end(JSON.stringify(protectedResourceMetadata(`${issuer}${MCP_PATH}`, issuer)));
192
198
  return true;
193
199
  }
194
- if (req.method === "GET" && path === WELL_KNOWN_AS) {
200
+ if (isRead(req) && path === WELL_KNOWN_AS) {
195
201
  res.writeHead(200, { "content-type": "application/json", "access-control-allow-origin": "*" });
196
202
  res.end(JSON.stringify(authServerMetadata(issuer)));
197
203
  return true;
@@ -397,21 +403,21 @@ export async function startHttpServer(port) {
397
403
  const path = (req.url ?? "").split("?")[0];
398
404
  // Brand icon — clients (e.g. the claude.ai connector) fetch a favicon from the
399
405
  // server origin; without one they show a generic globe. Served raw as SVG.
400
- if (req.method === "GET" && (path === "/favicon.ico" || path === "/favicon.png" || path === "/icon.png" || path === "/apple-touch-icon.png")) {
406
+ if (isRead(req) && (path === "/favicon.ico" || path === "/favicon.png" || path === "/icon.png" || path === "/apple-touch-icon.png")) {
401
407
  const png = iconPng();
402
408
  if (png) {
403
409
  res.writeHead(200, { "content-type": "image/png", "cache-control": "public, max-age=86400" });
404
410
  return res.end(png);
405
411
  }
406
412
  }
407
- if (req.method === "GET" && (path === "/favicon.ico" || path === "/favicon.svg" || path === "/icon.svg")) {
413
+ if (isRead(req) && (path === "/favicon.ico" || path === "/favicon.svg" || path === "/icon.svg")) {
408
414
  res.writeHead(200, { "content-type": ICON_MIME, "cache-control": "public, max-age=86400" });
409
415
  return res.end(ICON_SVG);
410
416
  }
411
417
  // Social-card image referenced by the landing page's og:image / twitter:image.
412
418
  // PNG is the canonical og:image (unfurls everywhere); the SVG stays for clients
413
419
  // that prefer it (Slack/Telegram/Discord) and as a fallback if og.png is absent.
414
- if (req.method === "GET" && path === "/og.png") {
420
+ if (isRead(req) && path === "/og.png") {
415
421
  const png = ogImagePng();
416
422
  if (png) {
417
423
  res.writeHead(200, { "content-type": "image/png", "cache-control": "public, max-age=86400" });
@@ -421,21 +427,21 @@ export async function startHttpServer(port) {
421
427
  res.writeHead(200, { "content-type": ICON_MIME, "cache-control": "public, max-age=86400" });
422
428
  return res.end(ogImageSvg());
423
429
  }
424
- if (req.method === "GET" && path === "/og.svg") {
430
+ if (isRead(req) && path === "/og.svg") {
425
431
  res.writeHead(200, { "content-type": ICON_MIME, "cache-control": "public, max-age=86400" });
426
432
  return res.end(ogImageSvg());
427
433
  }
428
434
  // Public legal pages — required URLs for the Claude/ChatGPT directory submission.
429
- if (req.method === "GET" && (path === "/privacy" || path === "/privacy-policy")) {
435
+ if (isRead(req) && (path === "/privacy" || path === "/privacy-policy")) {
430
436
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "public, max-age=3600" });
431
437
  return res.end(privacyHtml());
432
438
  }
433
- if (req.method === "GET" && (path === "/terms" || path === "/tos")) {
439
+ if (isRead(req) && (path === "/terms" || path === "/tos")) {
434
440
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "public, max-age=3600" });
435
441
  return res.end(termsHtml());
436
442
  }
437
443
  // Lightweight health check for hosting platforms.
438
- if (req.method === "GET" && (path === "/" || path === "/health")) {
444
+ if (isRead(req) && (path === "/" || path === "/health")) {
439
445
  // A browser/connector probing the root with `Accept: text/html` gets a tiny
440
446
  // page that links the favicon (helps icon discovery); programmatic probes
441
447
  // (the container healthcheck uses `Accept: */*`) still get the JSON health.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcake-landing-mcp",
3
- "version": "1.5.10",
3
+ "version": "1.5.11",
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
  "mcpName": "io.github.vuluu2k/webcake-landing-mcp",
6
6
  "type": "module",