@cmo-so/mcp 0.12.5 → 0.12.6
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/dist/cmo-mcp.mjs +119 -1
- package/package.json +1 -1
package/dist/cmo-mcp.mjs
CHANGED
|
@@ -7199,7 +7199,7 @@ var require_dist = __commonJS({
|
|
|
7199
7199
|
// package.json
|
|
7200
7200
|
var package_default = {
|
|
7201
7201
|
name: "@cmo-so/cli",
|
|
7202
|
-
version: "0.12.
|
|
7202
|
+
version: "0.12.6",
|
|
7203
7203
|
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.",
|
|
7204
7204
|
type: "module",
|
|
7205
7205
|
license: "MIT",
|
|
@@ -16064,6 +16064,27 @@ async function changePage(ctx, a, fn) {
|
|
|
16064
16064
|
undo: "wp_page_undo goes back to the version before this change."
|
|
16065
16065
|
};
|
|
16066
16066
|
}
|
|
16067
|
+
var findAllBlocks = (list3) => list3.flatMap((b) => [b, ...findAllBlocks(b.inner)]);
|
|
16068
|
+
async function setHome(site, id, postsPage) {
|
|
16069
|
+
const before = await call(site, {
|
|
16070
|
+
path: "/wp/v2/settings",
|
|
16071
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" }
|
|
16072
|
+
});
|
|
16073
|
+
const body = { show_on_front: "page", page_on_front: id };
|
|
16074
|
+
if (postsPage !== void 0) body.page_for_posts = postsPage;
|
|
16075
|
+
if (postsPage === id) throw new Error("The homepage and the posts page can't be the same page.");
|
|
16076
|
+
const after = await call(site, {
|
|
16077
|
+
method: "POST",
|
|
16078
|
+
path: "/wp/v2/settings",
|
|
16079
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" },
|
|
16080
|
+
body
|
|
16081
|
+
});
|
|
16082
|
+
return {
|
|
16083
|
+
before,
|
|
16084
|
+
after,
|
|
16085
|
+
undo: before.show_on_front === "page" && before.page_on_front ? `wp_site_home_set page ${before.page_on_front}` : "wp_site_home_set latest_posts true"
|
|
16086
|
+
};
|
|
16087
|
+
}
|
|
16067
16088
|
function position(a) {
|
|
16068
16089
|
return {
|
|
16069
16090
|
after: a.after || void 0,
|
|
@@ -16436,6 +16457,103 @@ var pageTools = [
|
|
|
16436
16457
|
};
|
|
16437
16458
|
}
|
|
16438
16459
|
}),
|
|
16460
|
+
tool({
|
|
16461
|
+
name: "wp_page_publish",
|
|
16462
|
+
description: "Publish a page (a draft or private page) so visitors and search engines see it. Checks it first: one H1, an SEO title and description (warns when missing). homepage: true also makes it the site's homepage. Afterwards the live page is opened to confirm it works. To take it down again, wp_page_update status draft.",
|
|
16463
|
+
parameters: {
|
|
16464
|
+
type: "object",
|
|
16465
|
+
properties: {
|
|
16466
|
+
page: PAGE,
|
|
16467
|
+
homepage: bool("Also make it the site's homepage."),
|
|
16468
|
+
expect_modified: EXPECT
|
|
16469
|
+
},
|
|
16470
|
+
required: ["page"]
|
|
16471
|
+
},
|
|
16472
|
+
group: "site",
|
|
16473
|
+
need: WRITE,
|
|
16474
|
+
risk: "W3",
|
|
16475
|
+
gates: [...GATES],
|
|
16476
|
+
confirm: (a, lang) => say(
|
|
16477
|
+
lang,
|
|
16478
|
+
`Publish page ${q2(a.page, "")} on your website${a.homepage ? " and make it the homepage" : ""}.`,
|
|
16479
|
+
`\u767C\u4F48\u7DB2\u7AD9\u4E0A\u7684\u9801\u9762 ${q2(a.page, "")}${a.homepage ? "\uFF0C\u4E26\u8A2D\u70BA\u9996\u9801" : ""}\u3002`
|
|
16480
|
+
),
|
|
16481
|
+
run: async (ctx, a) => {
|
|
16482
|
+
const site = siteOf(ctx);
|
|
16483
|
+
const p = await findPage(site, a.page, true);
|
|
16484
|
+
checkFresh(p, a.expect_modified);
|
|
16485
|
+
const m = p.meta ?? {};
|
|
16486
|
+
const blocks = parse(p.content?.raw ?? "");
|
|
16487
|
+
const h1 = findAllBlocks(blocks).filter((b) => b.name === "core/heading" && Number(b.attrs.level) === 1).length;
|
|
16488
|
+
const warnings = [
|
|
16489
|
+
h1 === 1 ? "" : h1 === 0 ? "The page has no H1 in its content (a template may add one)." : `The page has ${h1} H1 headings.`,
|
|
16490
|
+
m.maggie_seo_title ? "" : "No SEO title: the page title is used.",
|
|
16491
|
+
m.maggie_seo_description ? "" : "No meta description: set one with wp_seo_set."
|
|
16492
|
+
].filter(Boolean);
|
|
16493
|
+
const wasStatus = p.status;
|
|
16494
|
+
const saved = p.status === "publish" ? p : await savePage(site, p.id, null, { status: "publish" });
|
|
16495
|
+
let home = null;
|
|
16496
|
+
if (a.homepage) home = await setHome(site, p.id);
|
|
16497
|
+
const live = await check(site, saved.link, "publish");
|
|
16498
|
+
return {
|
|
16499
|
+
published: true,
|
|
16500
|
+
id: p.id,
|
|
16501
|
+
path: path(saved.link),
|
|
16502
|
+
before: wasStatus,
|
|
16503
|
+
homepage: home,
|
|
16504
|
+
check: live,
|
|
16505
|
+
warnings
|
|
16506
|
+
};
|
|
16507
|
+
}
|
|
16508
|
+
}),
|
|
16509
|
+
tool({
|
|
16510
|
+
name: "wp_site_home_set",
|
|
16511
|
+
description: "Choose the site's homepage (a published page) and, optionally, the page that lists the blog posts. Returns the previous setting so it can be put back. latest_posts: true shows the newest posts as the homepage instead.",
|
|
16512
|
+
parameters: {
|
|
16513
|
+
type: "object",
|
|
16514
|
+
properties: {
|
|
16515
|
+
page: str2("The page to show as the homepage (path, slug or id)."),
|
|
16516
|
+
posts_page: str2('The page that lists the blog posts (optional; "" to clear).'),
|
|
16517
|
+
latest_posts: bool("Show the newest posts as the homepage instead of a page.")
|
|
16518
|
+
}
|
|
16519
|
+
},
|
|
16520
|
+
group: "site",
|
|
16521
|
+
need: WRITE,
|
|
16522
|
+
risk: "W3",
|
|
16523
|
+
gates: [...GATES],
|
|
16524
|
+
confirm: (a, lang) => a.latest_posts ? say(lang, "Show your newest posts as your website's homepage.", "\u628A\u7DB2\u7AD9\u9996\u9801\u6539\u70BA\u986F\u793A\u6700\u65B0\u6587\u7AE0\u3002") : say(
|
|
16525
|
+
lang,
|
|
16526
|
+
`Make ${q2(a.page, "that page")} your website's homepage.`,
|
|
16527
|
+
`\u628A ${q2(a.page, "\u8A72\u9801\u9762")} \u8A2D\u70BA\u7DB2\u7AD9\u9996\u9801\u3002`
|
|
16528
|
+
),
|
|
16529
|
+
run: async (ctx, a) => {
|
|
16530
|
+
const site = siteOf(ctx);
|
|
16531
|
+
if (a.latest_posts) {
|
|
16532
|
+
const before = await call(site, {
|
|
16533
|
+
path: "/wp/v2/settings",
|
|
16534
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" }
|
|
16535
|
+
});
|
|
16536
|
+
await call(site, {
|
|
16537
|
+
method: "POST",
|
|
16538
|
+
path: "/wp/v2/settings",
|
|
16539
|
+
query: { _fields: "show_on_front" },
|
|
16540
|
+
body: { show_on_front: "posts" }
|
|
16541
|
+
});
|
|
16542
|
+
return { before, after: { show_on_front: "posts" } };
|
|
16543
|
+
}
|
|
16544
|
+
if (!a.page) throw new Error("Which page should be the homepage?");
|
|
16545
|
+
const p = await findPage(site, a.page);
|
|
16546
|
+
if (p.status !== "publish")
|
|
16547
|
+
throw new Error(
|
|
16548
|
+
`${path(p.link)} isn't published yet: publish it first (wp_page_publish homepage: true does both).`
|
|
16549
|
+
);
|
|
16550
|
+
let postsPage;
|
|
16551
|
+
if (typeof a.posts_page === "string")
|
|
16552
|
+
postsPage = a.posts_page === "" ? 0 : (await findPage(site, a.posts_page)).id;
|
|
16553
|
+
const r = await setHome(site, p.id, postsPage);
|
|
16554
|
+
return { ...r, check: await check(site, `${site.url ?? ""}/`, "publish") };
|
|
16555
|
+
}
|
|
16556
|
+
}),
|
|
16439
16557
|
tool({
|
|
16440
16558
|
name: "wp_page_delete",
|
|
16441
16559
|
description: "Move a page to the WordPress trash (restorable for 30 days) and redirect its address (301) to another page, by default its parent or the homepage.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
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",
|