@cmo-so/mcp 0.12.16 → 0.12.17

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 (2) hide show
  1. package/dist/cmo-mcp.mjs +34 -10
  2. package/package.json +1 -1
package/dist/cmo-mcp.mjs CHANGED
@@ -24489,7 +24489,7 @@ var require_dist3 = __commonJS({
24489
24489
  // package.json
24490
24490
  var package_default = {
24491
24491
  name: "@cmo-so/cli",
24492
- version: "0.12.16",
24492
+ version: "0.12.17",
24493
24493
  description: "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
24494
24494
  type: "module",
24495
24495
  license: "MIT",
@@ -42723,30 +42723,54 @@ async function techAudit(site, o2 = {}) {
42723
42723
  ...urls.length > crawl.length ? { note: `Crawled the first ${crawl.length} of ${urls.length} sitemap addresses (limit up to 200).` } : {}
42724
42724
  };
42725
42725
  }
42726
- async function pageSpeed(url) {
42727
- const key = globalThis.process?.env?.PAGESPEED_API_KEY;
42726
+ async function pageSpeedRun(url, key) {
42728
42727
  const q4 = new URLSearchParams({ url, strategy: "mobile", category: "performance" });
42729
42728
  if (key) q4.set("key", key);
42730
42729
  const r = await fetch(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?${q4}`, {
42731
42730
  signal: AbortSignal.timeout(9e4)
42732
42731
  }).catch(() => null);
42733
- if (!r || !r.ok)
42734
- return {
42735
- error: `PageSpeed Insights didn't answer (${r?.status ?? "timeout"})${r?.status === 429 && !key ? ": the server needs a PAGESPEED_API_KEY (Google Cloud, free)" : ""}.`
42736
- };
42732
+ if (!r || !r.ok) return { status: r?.status ?? 0 };
42737
42733
  const j2 = await r.json();
42738
42734
  const f2 = j2.loadingExperience?.metrics ?? {};
42739
42735
  const a3 = j2.lighthouseResult?.audits ?? {};
42740
42736
  const field = !!f2.LARGEST_CONTENTFUL_PAINT_MS;
42741
42737
  return {
42742
- source: field ? "real visitors (Chrome UX Report, 28 days)" : "lab test (no real-visitor data yet)",
42738
+ status: 200,
42739
+ field,
42743
42740
  score: Math.round((j2.lighthouseResult?.categories?.performance?.score ?? 0) * 100),
42744
- lcp_ms: field ? f2.LARGEST_CONTENTFUL_PAINT_MS?.percentile : Math.round(a3["largest-contentful-paint"]?.numericValue ?? 0),
42741
+ lcp_ms: field ? f2.LARGEST_CONTENTFUL_PAINT_MS?.percentile ?? 0 : Math.round(a3["largest-contentful-paint"]?.numericValue ?? 0),
42745
42742
  cls: field ? (f2.CUMULATIVE_LAYOUT_SHIFT_SCORE?.percentile ?? 0) / 100 : Number((a3["cumulative-layout-shift"]?.numericValue ?? 0).toFixed(3)),
42746
42743
  inp_ms: f2.INTERACTION_TO_NEXT_PAINT?.percentile ?? null,
42747
42744
  tbt_ms: Math.round(a3["total-blocking-time"]?.numericValue ?? 0)
42748
42745
  };
42749
42746
  }
42747
+ async function pageSpeed(url) {
42748
+ const key = globalThis.process?.env?.PAGESPEED_API_KEY;
42749
+ const runs = await Promise.all(
42750
+ [1, 2, 3].map((n2) => pageSpeedRun(`${url}${url.includes("?") ? "&" : "?"}cmo-speed=${Date.now()}-${n2}`, key))
42751
+ );
42752
+ const ok2 = runs.filter((r) => r.status === 200 && "lcp_ms" in r);
42753
+ if (!ok2.length) {
42754
+ const status = runs[0]?.status ?? 0;
42755
+ return {
42756
+ error: `PageSpeed Insights didn't answer (${status || "timeout"})${status === 429 && !key ? ": the server needs a PAGESPEED_API_KEY (Google Cloud, free)" : ""}.`
42757
+ };
42758
+ }
42759
+ const median = (xs) => {
42760
+ const s = [...xs].sort((a3, b2) => a3 - b2);
42761
+ return s[Math.floor((s.length - 1) / 2)];
42762
+ };
42763
+ const field = ok2.some((r) => r.field);
42764
+ return {
42765
+ source: field ? "real visitors (Chrome UX Report, 28 days)" : `lab test, median of ${ok2.length} runs (no real-visitor data yet)`,
42766
+ score: median(ok2.map((r) => r.score)),
42767
+ lcp_ms: median(ok2.map((r) => r.lcp_ms)),
42768
+ cls: median(ok2.map((r) => r.cls)),
42769
+ inp_ms: ok2.find((r) => r.inp_ms != null)?.inp_ms ?? null,
42770
+ tbt_ms: median(ok2.map((r) => r.tbt_ms)),
42771
+ runs: ok2.map((r) => ({ score: r.score, lcp_ms: r.lcp_ms }))
42772
+ };
42773
+ }
42750
42774
  var STOP = new Set(
42751
42775
  "the a an and or of to in for on with by at from is are be your our you we it this that how what why best guide near vs and/or my me us".split(
42752
42776
  " "
@@ -45729,7 +45753,7 @@ function withRelated(blocks, heading2, links2) {
45729
45753
  var seoTechTools = [
45730
45754
  tool({
45731
45755
  name: "wp_seo_tech_audit",
45732
- description: "Technical SEO check of the connected site, like a crawler: robots.txt (sitemap line, Google or AI crawlers blocked), the sitemap and every page it lists (status, redirects, noindex in the sitemap, canonicals pointing elsewhere, H1 count, missing or duplicate titles and descriptions, long titles, pictures without alt text, broken structured data, thin pages), broken and redirected internal links, generic link words, llms.txt; speed: true adds Core Web Vitals for the homepage (PageSpeed Insights). Findings ranked p0\u2026p4 with the fix and a tool when one can do it. Read-only. Internal-link layout: wp_internal_links_plan.",
45756
+ description: "Technical SEO check of the connected site, like a crawler: robots.txt (sitemap line, Google or AI crawlers blocked), the sitemap and every page it lists (status, redirects, noindex in the sitemap, canonicals pointing elsewhere, H1 count, missing or duplicate titles and descriptions, long titles, pictures without alt text, broken structured data, thin pages), broken and redirected internal links, generic link words, llms.txt; speed: true adds Core Web Vitals for the homepage (PageSpeed Insights: real visitors when Google has them, else the median of three lab runs). Findings ranked p0\u2026p4 with the fix and a tool when one can do it. Read-only. Internal-link layout: wp_internal_links_plan.",
45733
45757
  parameters: {
45734
45758
  type: "object",
45735
45759
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmo-so/mcp",
3
- "version": "0.12.16",
3
+ "version": "0.12.17",
4
4
  "description": "CMO.so's MCP server for Claude Desktop, Cursor, VS Code and other MCP clients: manage your websites, blog posts, LinkedIn queue and results with Maggie.",
5
5
  "type": "module",
6
6
  "license": "MIT",