@cmo-so/mcp 0.12.7 → 0.12.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/dist/cmo-mcp.mjs +227 -18
- 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.9",
|
|
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",
|
|
@@ -14718,6 +14718,54 @@ function replace(blocks, ref, next, synced = {}) {
|
|
|
14718
14718
|
function sectionAt(blocks, ref, synced = {}) {
|
|
14719
14719
|
return pick(locate(blocks), ref, synced);
|
|
14720
14720
|
}
|
|
14721
|
+
function widthValue(width) {
|
|
14722
|
+
const w = String(width ?? "").trim();
|
|
14723
|
+
if (w === "content") return null;
|
|
14724
|
+
if (w === "wide") return "var(--wp--style--global--wide-size)";
|
|
14725
|
+
if (/^\d{2,4}(\.\d+)?(px|rem|em|vw|%)$/.test(w)) return w;
|
|
14726
|
+
throw new Error('width: "content", "wide" or a CSS length such as 1240px.');
|
|
14727
|
+
}
|
|
14728
|
+
var NARROW_PX = 700;
|
|
14729
|
+
var sizePx = (v) => {
|
|
14730
|
+
const m = /^(\d+(?:\.\d+)?)(px|rem|em)$/.exec(v);
|
|
14731
|
+
return m ? Number(m[1]) * (m[2] === "px" ? 1 : 16) : null;
|
|
14732
|
+
};
|
|
14733
|
+
function setSectionWidth(b, width) {
|
|
14734
|
+
const size = widthValue(width);
|
|
14735
|
+
const before = [];
|
|
14736
|
+
const visit = (x, top) => {
|
|
14737
|
+
let changed = false;
|
|
14738
|
+
for (const c of x.inner) if (visit(c, false)) changed = true;
|
|
14739
|
+
const lay = x.attrs.layout;
|
|
14740
|
+
const constrained = lay?.type === "constrained";
|
|
14741
|
+
const cur = lay?.contentSize;
|
|
14742
|
+
const px = cur ? sizePx(cur) : null;
|
|
14743
|
+
const eligible = constrained && (!cur || cur.includes("--wp--style--global") || px == null || px >= NARROW_PX);
|
|
14744
|
+
if (eligible || top && !lay && (x.name === "core/group" || x.name === "core/cover")) {
|
|
14745
|
+
if ((cur ?? null) !== size) {
|
|
14746
|
+
before.push(cur ?? "content");
|
|
14747
|
+
const next = { ...lay ?? {}, type: "constrained" };
|
|
14748
|
+
if (size) next.contentSize = size;
|
|
14749
|
+
else delete next.contentSize;
|
|
14750
|
+
x.attrs = { ...x.attrs, layout: next };
|
|
14751
|
+
changed = true;
|
|
14752
|
+
}
|
|
14753
|
+
}
|
|
14754
|
+
if (changed) delete x.raw;
|
|
14755
|
+
return changed;
|
|
14756
|
+
};
|
|
14757
|
+
visit(b, true);
|
|
14758
|
+
return { containers: before.length, before };
|
|
14759
|
+
}
|
|
14760
|
+
function refreshRaw(list3) {
|
|
14761
|
+
let any = false;
|
|
14762
|
+
for (const b of list3) {
|
|
14763
|
+
const inner = refreshRaw(b.inner);
|
|
14764
|
+
if (inner) delete b.raw;
|
|
14765
|
+
if (inner || b.raw == null) any = true;
|
|
14766
|
+
}
|
|
14767
|
+
return any;
|
|
14768
|
+
}
|
|
14721
14769
|
var escRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14722
14770
|
function applyEdits(b, e) {
|
|
14723
14771
|
let m = serializeBlock(b);
|
|
@@ -15155,6 +15203,15 @@ async function styleGet(site) {
|
|
|
15155
15203
|
fonts: (user.settings?.typography?.fontFamilies?.theme ?? []).map((f) => f.slug)
|
|
15156
15204
|
},
|
|
15157
15205
|
contrast: contrastReport(Object.fromEntries([...palette.values()].map((c) => [c.slug, c.color]))),
|
|
15206
|
+
layout: {
|
|
15207
|
+
content: user.settings?.layout?.contentSize ?? base.settings?.layout?.contentSize ?? null,
|
|
15208
|
+
wide: user.settings?.layout?.wideSize ?? base.settings?.layout?.wideSize ?? null,
|
|
15209
|
+
padding: {
|
|
15210
|
+
left: user.styles?.spacing?.padding?.left ?? base.styles?.spacing?.padding?.left ?? null,
|
|
15211
|
+
right: user.styles?.spacing?.padding?.right ?? base.styles?.spacing?.padding?.right ?? null
|
|
15212
|
+
}
|
|
15213
|
+
},
|
|
15214
|
+
css: user.styles?.css ?? "",
|
|
15158
15215
|
_palette: [...palette.values()],
|
|
15159
15216
|
_fonts: [...fonts.values()],
|
|
15160
15217
|
_user: user
|
|
@@ -15195,6 +15252,17 @@ function contrastReport(colors) {
|
|
|
15195
15252
|
});
|
|
15196
15253
|
}
|
|
15197
15254
|
async function styleSet(site, change, force = false) {
|
|
15255
|
+
const len = (v, what) => {
|
|
15256
|
+
const t = String(v ?? "").trim();
|
|
15257
|
+
if (!/^(0|\d{1,4}(\.\d+)?(px|rem|em|vw|%)|var\(--wp--preset--spacing--[a-z0-9-]+\)|clamp\([0-9a-z.,%+\-\s()]+\))$/i.test(
|
|
15258
|
+
t
|
|
15259
|
+
))
|
|
15260
|
+
throw new Error(`${what}: "${t}" isn't a CSS length like 1240px, 2rem or var(--wp--preset--spacing--50).`);
|
|
15261
|
+
return t;
|
|
15262
|
+
};
|
|
15263
|
+
for (const css of [change.css, change.css_append])
|
|
15264
|
+
if (css != null && /<\/?style|<\?|<script|@import\s+url\(\s*['"]?(?!https:)/i.test(css))
|
|
15265
|
+
throw new Error("css: plain CSS only (no <style>, <script>, PHP or non-https imports).");
|
|
15198
15266
|
const cur = await styleGet(site);
|
|
15199
15267
|
const palette = cur._palette.map((c) => ({ ...c }));
|
|
15200
15268
|
for (const [slug, color] of Object.entries(change.colors ?? {})) {
|
|
@@ -15219,15 +15287,48 @@ async function styleSet(site, change, force = false) {
|
|
|
15219
15287
|
);
|
|
15220
15288
|
const user = cur._user;
|
|
15221
15289
|
const settings = { ...user.settings ?? {} };
|
|
15290
|
+
const styles = { ...user.styles ?? {} };
|
|
15222
15291
|
if (change.colors) settings.color = { ...settings.color ?? {}, palette: { theme: palette } };
|
|
15223
15292
|
if (change.fonts)
|
|
15224
15293
|
settings.typography = { ...settings.typography ?? {}, fontFamilies: { theme: fonts } };
|
|
15294
|
+
if (change.layout) {
|
|
15295
|
+
const layout = { ...settings.layout ?? {} };
|
|
15296
|
+
if (change.layout.content != null) layout.contentSize = len(change.layout.content, "layout.content");
|
|
15297
|
+
if (change.layout.wide != null) layout.wideSize = len(change.layout.wide, "layout.wide");
|
|
15298
|
+
settings.layout = layout;
|
|
15299
|
+
}
|
|
15300
|
+
if (change.padding) {
|
|
15301
|
+
const spacing = { ...styles.spacing ?? {} };
|
|
15302
|
+
const pad = { ...spacing.padding ?? {} };
|
|
15303
|
+
if (change.padding.left != null) pad.left = len(change.padding.left, "padding.left");
|
|
15304
|
+
if (change.padding.right != null) pad.right = len(change.padding.right, "padding.right");
|
|
15305
|
+
styles.spacing = { ...spacing, padding: pad };
|
|
15306
|
+
settings.useRootPaddingAwareAlignments = true;
|
|
15307
|
+
}
|
|
15308
|
+
if (change.css != null) styles.css = change.css;
|
|
15309
|
+
if (change.css_append)
|
|
15310
|
+
styles.css = `${String(styles.css ?? "").trimEnd()}
|
|
15311
|
+
|
|
15312
|
+
${change.css_append.trim()}
|
|
15313
|
+
`.trimStart();
|
|
15225
15314
|
await call(site, {
|
|
15226
15315
|
method: "POST",
|
|
15227
15316
|
path: `/wp/v2/global-styles/${cur.id}`,
|
|
15228
|
-
body: { settings, styles
|
|
15317
|
+
body: { settings, styles }
|
|
15229
15318
|
});
|
|
15319
|
+
const changedLayout = change.layout || change.padding;
|
|
15230
15320
|
return {
|
|
15321
|
+
...changedLayout ? {
|
|
15322
|
+
layout: {
|
|
15323
|
+
before: cur.layout,
|
|
15324
|
+
after: {
|
|
15325
|
+
content: settings.layout?.contentSize ?? cur.layout.content,
|
|
15326
|
+
wide: settings.layout?.wideSize ?? cur.layout.wide,
|
|
15327
|
+
padding: change.padding ? { ...cur.layout.padding, ...change.padding } : cur.layout.padding
|
|
15328
|
+
}
|
|
15329
|
+
}
|
|
15330
|
+
} : {},
|
|
15331
|
+
...change.css != null || change.css_append ? { css: { before: cur.css.length, after: String(styles.css ?? "").length, before_text: cur.css } } : {},
|
|
15231
15332
|
colors: Object.fromEntries(
|
|
15232
15333
|
Object.entries(change.colors ?? {}).map(([k, v]) => [k, { before: cur.colors[k], after: v }])
|
|
15233
15334
|
),
|
|
@@ -16269,7 +16370,7 @@ var siteTools = [
|
|
|
16269
16370
|
}),
|
|
16270
16371
|
tool({
|
|
16271
16372
|
name: "wp_style_get",
|
|
16272
|
-
description: "The
|
|
16373
|
+
description: "The site's look: colours (by name: canvas, panel, soft, ink, muted, olive, accent\u2026), fonts (display, body), layout widths (content, wide) and page padding, the extra CSS, and the text contrast of each colour pair.",
|
|
16273
16374
|
parameters: { type: "object", properties: {} },
|
|
16274
16375
|
group: "site",
|
|
16275
16376
|
need: READ,
|
|
@@ -16277,7 +16378,14 @@ var siteTools = [
|
|
|
16277
16378
|
gates: ["WP"],
|
|
16278
16379
|
run: async (ctx) => {
|
|
16279
16380
|
const s = await styleGet(siteOf(ctx));
|
|
16280
|
-
return {
|
|
16381
|
+
return {
|
|
16382
|
+
colors: s.colors,
|
|
16383
|
+
fonts: s.fonts,
|
|
16384
|
+
layout: s.layout,
|
|
16385
|
+
css: s.css,
|
|
16386
|
+
customized: s.customized,
|
|
16387
|
+
contrast: s.contrast
|
|
16388
|
+
};
|
|
16281
16389
|
}
|
|
16282
16390
|
})
|
|
16283
16391
|
];
|
|
@@ -16719,12 +16827,15 @@ var sectionTools = [
|
|
|
16719
16827
|
}),
|
|
16720
16828
|
tool({
|
|
16721
16829
|
name: "wp_section_update",
|
|
16722
|
-
description:
|
|
16830
|
+
description: 'Change one section. width: line its content up with the header and footer ("wide") or another width, one section or all. edits: change text, links or pictures inside it and keep its design (works on any section, the homepage too). slots: write the section again from new content (generated types; give the complete content). faq: add, remove (1-based numbers) or replace questions.',
|
|
16723
16831
|
parameters: {
|
|
16724
16832
|
type: "object",
|
|
16725
16833
|
properties: {
|
|
16726
16834
|
page: PAGE,
|
|
16727
|
-
section: str2(
|
|
16835
|
+
section: str2('Section id from wp_page_get (s2, m4) or its type (faq); "all" with width only.'),
|
|
16836
|
+
width: str2(
|
|
16837
|
+
`The section's inner width: "content" (the site's content width), "wide" (the site's wide width, as the header and footer) or a CSS length (1240px). Changes the section and its containers wider than 700px; with section "all", every section on the page.`
|
|
16838
|
+
),
|
|
16728
16839
|
edits: EDITS,
|
|
16729
16840
|
slots: obj("Complete new content for the section (same type unless type is given)."),
|
|
16730
16841
|
markup: str2(
|
|
@@ -16753,6 +16864,19 @@ var sectionTools = [
|
|
|
16753
16864
|
),
|
|
16754
16865
|
run: (ctx, a) => changePage(ctx, a, (blocks, kit) => {
|
|
16755
16866
|
const ref = String(a.section);
|
|
16867
|
+
if (a.width != null && a.width !== "") {
|
|
16868
|
+
const targets = ref === "all" ? locate(blocks) : [sectionAt(blocks, ref, kit.syncedTitles)];
|
|
16869
|
+
const changed = {};
|
|
16870
|
+
for (const t of targets) {
|
|
16871
|
+
if (t.block.name === "core/block") continue;
|
|
16872
|
+
const r = setSectionWidth(t.block, a.width);
|
|
16873
|
+
if (r.containers) changed[t.id] = r;
|
|
16874
|
+
}
|
|
16875
|
+
refreshRaw(blocks);
|
|
16876
|
+
if (!Object.keys(changed).length) throw new Error("Those sections already have that width.");
|
|
16877
|
+
return { blocks, note: { width: String(a.width), sections: changed } };
|
|
16878
|
+
}
|
|
16879
|
+
if (ref === "all") throw new Error('section "all" works with width only.');
|
|
16756
16880
|
const target = sectionAt(blocks, ref, kit.syncedTitles);
|
|
16757
16881
|
const type = classify(target.block, target.region, kit.syncedTitles);
|
|
16758
16882
|
let next;
|
|
@@ -17187,7 +17311,7 @@ var childTools = [
|
|
|
17187
17311
|
files[`assets/fonts/${name}`] = btoa(bin);
|
|
17188
17312
|
let fam = fams.find((x) => x.slug === f.slug);
|
|
17189
17313
|
const stack = `"${f.family}", ${f.fallback || "sans-serif"}`;
|
|
17190
|
-
if (!fam
|
|
17314
|
+
if (!fam?.fontFamily.includes(`"${f.family}"`)) {
|
|
17191
17315
|
const keep = fam ? fams.indexOf(fam) : -1;
|
|
17192
17316
|
fam = { slug: f.slug, name: f.family, fontFamily: stack, fontFace: [] };
|
|
17193
17317
|
if (keep >= 0) fams[keep] = fam;
|
|
@@ -17658,23 +17782,41 @@ var elementTools = [
|
|
|
17658
17782
|
}),
|
|
17659
17783
|
tool({
|
|
17660
17784
|
name: "wp_style_set",
|
|
17661
|
-
description: "Change brand colours (by name, hex)
|
|
17785
|
+
description: "Change the whole site's look: brand colours (by name, hex), fonts (by name, CSS font-family), layout widths (content: the width sections and text use; wide: the header, footer and wide blocks), the left and right page padding, and extra CSS. Saved in the site's Global Styles (works on any block theme; returns before and after). Refuses colours that would make text hard to read (contrast under 4.5:1). One section's width: wp_section_update width.",
|
|
17662
17786
|
parameters: {
|
|
17663
17787
|
type: "object",
|
|
17664
17788
|
properties: {
|
|
17665
17789
|
colors: obj('e.g. { "olive": "#4F5B48", "accent": "#A8834F" }.'),
|
|
17666
|
-
fonts: obj('e.g. { "display": "\\"Playfair Display\\", Georgia, serif" }.')
|
|
17790
|
+
fonts: obj('e.g. { "display": "\\"Playfair Display\\", Georgia, serif" }.'),
|
|
17791
|
+
layout: obj('Widths, e.g. { "content": "1240px", "wide": "1240px" }.', {
|
|
17792
|
+
content: str2("Content width (CSS length)."),
|
|
17793
|
+
wide: str2("Wide width (CSS length).")
|
|
17794
|
+
}),
|
|
17795
|
+
padding: obj('Left and right page padding, e.g. { "left": "24px", "right": "24px" }.', {
|
|
17796
|
+
left: str2(""),
|
|
17797
|
+
right: str2("")
|
|
17798
|
+
}),
|
|
17799
|
+
css: str2("Replace the site's extra CSS (Global Styles \u2192 Additional CSS); plain CSS only."),
|
|
17800
|
+
css_append: str2("Add this CSS after the site's extra CSS.")
|
|
17667
17801
|
}
|
|
17668
17802
|
},
|
|
17669
17803
|
group: "site",
|
|
17670
17804
|
need: WRITE,
|
|
17671
17805
|
risk: "W3",
|
|
17672
17806
|
gates: [...GATES],
|
|
17673
|
-
confirm: (_a3, lang) => say(
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17807
|
+
confirm: (_a3, lang) => say(
|
|
17808
|
+
lang,
|
|
17809
|
+
"Change the website's look for every page (colours, fonts, widths, padding or extra CSS); the result shows before and after.",
|
|
17810
|
+
"\u4FEE\u6539\u7DB2\u7AD9\u6240\u6709\u9801\u9762\u7684\u5916\u89C0\uFF08\u984F\u8272\u3001\u5B57\u9AD4\u3001\u5BEC\u5EA6\u3001\u908A\u8DDD\u6216\u984D\u5916 CSS\uFF09\uFF1B\u7D50\u679C\u6703\u5217\u51FA\u4FEE\u6539\u524D\u5F8C\u3002"
|
|
17811
|
+
),
|
|
17812
|
+
run: async (ctx, a) => styleSet(siteOf(ctx), {
|
|
17813
|
+
colors: a.colors,
|
|
17814
|
+
fonts: a.fonts,
|
|
17815
|
+
layout: a.layout,
|
|
17816
|
+
padding: a.padding,
|
|
17817
|
+
css: typeof a.css === "string" ? a.css : void 0,
|
|
17818
|
+
css_append: typeof a.css_append === "string" ? a.css_append : void 0
|
|
17819
|
+
})
|
|
17678
17820
|
})
|
|
17679
17821
|
];
|
|
17680
17822
|
function checkMarkup(markup, what) {
|
|
@@ -18006,6 +18148,49 @@ var fullTools = [
|
|
|
18006
18148
|
});
|
|
18007
18149
|
}
|
|
18008
18150
|
}),
|
|
18151
|
+
tool({
|
|
18152
|
+
name: "wp_term_delete",
|
|
18153
|
+
description: "Delete a category or tag by id. Posts keep their other terms; posts left without a category go to the default category, which can't be deleted. Terms have no trash: the result gives name, slug and description to recreate it with wp_term_save.",
|
|
18154
|
+
parameters: {
|
|
18155
|
+
type: "object",
|
|
18156
|
+
properties: {
|
|
18157
|
+
taxonomy: { type: "string", enum: ["categories", "tags"], description: "Default categories." },
|
|
18158
|
+
id: int2("The term to delete (from wp_terms_list).")
|
|
18159
|
+
},
|
|
18160
|
+
required: ["id"]
|
|
18161
|
+
},
|
|
18162
|
+
group: "site",
|
|
18163
|
+
need: WRITE,
|
|
18164
|
+
risk: "W3",
|
|
18165
|
+
gates: [...GATES],
|
|
18166
|
+
confirm: (a, lang) => say(
|
|
18167
|
+
lang,
|
|
18168
|
+
`Delete the ${a.taxonomy === "tags" ? "tag" : "category"} #${String(a.id)} from your website (posts stay; it can be recreated, not restored).`,
|
|
18169
|
+
`\u522A\u9664\u7DB2\u7AD9\u7684${a.taxonomy === "tags" ? "\u6A19\u7C64" : "\u5206\u985E"} #${String(a.id)}\uFF08\u6587\u7AE0\u4FDD\u7559\uFF1B\u53EF\u91CD\u65B0\u5EFA\u7ACB\uFF0C\u7121\u6CD5\u9084\u539F\uFF09\u3002`
|
|
18170
|
+
),
|
|
18171
|
+
run: async (ctx, a) => {
|
|
18172
|
+
const site = siteOf(ctx);
|
|
18173
|
+
const tax = a.taxonomy === "tags" ? "tags" : "categories";
|
|
18174
|
+
const id = Number(a.id);
|
|
18175
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error("id: the term id from wp_terms_list.");
|
|
18176
|
+
if (tax === "categories") {
|
|
18177
|
+
const st = await call(site, {
|
|
18178
|
+
path: "/wp/v2/settings",
|
|
18179
|
+
query: { _fields: "default_category" }
|
|
18180
|
+
});
|
|
18181
|
+
if (Number(st.default_category ?? 1) === id)
|
|
18182
|
+
throw new Error("That is the default category; it can't be deleted.");
|
|
18183
|
+
}
|
|
18184
|
+
const before = await call(site, { path: `/wp/v2/${tax}/${id}`, query: { _fields: "id,name,slug,description,count,parent" } });
|
|
18185
|
+
await call(site, { method: "DELETE", path: `/wp/v2/${tax}/${id}`, query: { force: "true" } });
|
|
18186
|
+
return {
|
|
18187
|
+
deleted: true,
|
|
18188
|
+
taxonomy: tax,
|
|
18189
|
+
...before,
|
|
18190
|
+
undo: `wp_term_save ${tax} name "${before.name}" slug ${before.slug}`
|
|
18191
|
+
};
|
|
18192
|
+
}
|
|
18193
|
+
}),
|
|
18009
18194
|
tool({
|
|
18010
18195
|
name: "wp_settings_get",
|
|
18011
18196
|
description: "The site's general settings: title, tagline, search-engine visibility, language, timezone, date and time formats, start of week, posts per page, homepage and posts page, logo and icon.",
|
|
@@ -18091,7 +18276,7 @@ var fullTools = [
|
|
|
18091
18276
|
}),
|
|
18092
18277
|
tool({
|
|
18093
18278
|
name: "wp_plugin_set",
|
|
18094
|
-
description: "Install a plugin from WordPress.org by its slug (e.g. wpforms-lite), and/or activate or
|
|
18279
|
+
description: "Install a plugin from WordPress.org by its slug (e.g. wpforms-lite), and/or activate, deactivate or delete an installed one (plugin id from wp_plugins_list, e.g. akismet/akismet; only an inactive plugin can be deleted, and its settings may go with it). Installing runs the plugin's code on the site: only well-known plugins the owner asked for.",
|
|
18095
18280
|
parameters: {
|
|
18096
18281
|
type: "object",
|
|
18097
18282
|
properties: {
|
|
@@ -18099,8 +18284,8 @@ var fullTools = [
|
|
|
18099
18284
|
plugin: str2("Installed plugin id (folder/file) to change."),
|
|
18100
18285
|
status: {
|
|
18101
18286
|
type: "string",
|
|
18102
|
-
enum: ["active", "inactive"],
|
|
18103
|
-
description: "Activate
|
|
18287
|
+
enum: ["active", "inactive", "deleted"],
|
|
18288
|
+
description: "Activate, deactivate (after installing, default inactive), or deleted: remove an inactive plugin's files (deactivate it first; Maggie Press can't be removed here)."
|
|
18104
18289
|
}
|
|
18105
18290
|
}
|
|
18106
18291
|
},
|
|
@@ -18112,6 +18297,10 @@ var fullTools = [
|
|
|
18112
18297
|
lang,
|
|
18113
18298
|
`Install the plugin ${q2(a.install, "")} from WordPress.org on your website${a.status === "active" ? " and activate it" : ""}.`,
|
|
18114
18299
|
`\u5728\u7DB2\u7AD9\u4E0A\u5B89\u88DD WordPress.org \u63D2\u4EF6 ${q2(a.install, "")}${a.status === "active" ? "\u4E26\u555F\u7528" : ""}\u3002`
|
|
18300
|
+
) : a.status === "deleted" ? say(
|
|
18301
|
+
lang,
|
|
18302
|
+
`Delete the plugin ${q2(a.plugin, "")} from your website (its files are removed; reinstall it from WordPress.org to undo, its settings may be lost).`,
|
|
18303
|
+
`\u5F9E\u7DB2\u7AD9\u522A\u9664\u63D2\u4EF6 ${q2(a.plugin, "")}\uFF08\u6A94\u6848\u6703\u88AB\u79FB\u9664\uFF1B\u53EF\u5F9E WordPress.org \u91CD\u65B0\u5B89\u88DD\uFF0C\u8A2D\u5B9A\u53EF\u80FD\u907A\u5931\uFF09\u3002`
|
|
18115
18304
|
) : say(
|
|
18116
18305
|
lang,
|
|
18117
18306
|
`${a.status === "active" ? "Activate" : "Deactivate"} the plugin ${q2(a.plugin, "")} on your website.`,
|
|
@@ -18132,9 +18321,29 @@ var fullTools = [
|
|
|
18132
18321
|
if (!a.plugin || !a.status) throw new Error("Give install (a slug), or plugin and status.");
|
|
18133
18322
|
if (!/^[a-z0-9._-]+(\/[a-z0-9._-]+)?$/i.test(String(a.plugin)))
|
|
18134
18323
|
throw new Error("plugin: the id from wp_plugins_list, e.g. akismet/akismet.");
|
|
18324
|
+
const id = String(a.plugin).replace(/\.php$/, "");
|
|
18325
|
+
if (a.status === "deleted") {
|
|
18326
|
+
if (/^maggie-?press\//i.test(id))
|
|
18327
|
+
throw new Error("Maggie Press runs the site's styles; it can't be deleted here.");
|
|
18328
|
+
const cur = await call(site, {
|
|
18329
|
+
path: `/wp/v2/plugins/${id}`,
|
|
18330
|
+
query: { _fields: "plugin,name,version,status" }
|
|
18331
|
+
});
|
|
18332
|
+
if (cur.status !== "inactive")
|
|
18333
|
+
throw new Error(`${cur.name} is ${cur.status}: deactivate it first (status inactive), then delete it.`);
|
|
18334
|
+
await call(site, { method: "DELETE", path: `/wp/v2/plugins/${id}` });
|
|
18335
|
+
const slug = id.split("/")[0];
|
|
18336
|
+
return {
|
|
18337
|
+
deleted: true,
|
|
18338
|
+
plugin: cur.plugin,
|
|
18339
|
+
name: cur.name,
|
|
18340
|
+
version: cur.version,
|
|
18341
|
+
undo: `wp_plugin_set install ${slug}`
|
|
18342
|
+
};
|
|
18343
|
+
}
|
|
18135
18344
|
return call(site, {
|
|
18136
18345
|
method: "POST",
|
|
18137
|
-
path: `/wp/v2/plugins/${
|
|
18346
|
+
path: `/wp/v2/plugins/${id}`,
|
|
18138
18347
|
query: { _fields: "plugin,name,version,status" },
|
|
18139
18348
|
body: { status: a.status }
|
|
18140
18349
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.9",
|
|
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",
|