@cmo-so/mcp 0.12.19 → 0.12.21
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 +153 -18
- 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.
|
|
24492
|
+
version: "0.12.21",
|
|
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",
|
|
@@ -39251,8 +39251,15 @@ function applyCredit(markup) {
|
|
|
39251
39251
|
${creditBlock()}
|
|
39252
39252
|
` : `${html2.slice(0, end)}${creditBlock()}${html2.slice(end)}`;
|
|
39253
39253
|
}
|
|
39254
|
-
function
|
|
39255
|
-
|
|
39254
|
+
async function creditStyleAllowed(ctx) {
|
|
39255
|
+
try {
|
|
39256
|
+
return (await ctx.api.maggie.usage()).tier === "admin";
|
|
39257
|
+
} catch {
|
|
39258
|
+
return false;
|
|
39259
|
+
}
|
|
39260
|
+
}
|
|
39261
|
+
function refuseCreditOverride(what, text3, allowed2 = false) {
|
|
39262
|
+
if (!allowed2 && text3 && /maggie-credit/i.test(text3))
|
|
39256
39263
|
throw new Error(
|
|
39257
39264
|
`${what}: the footer credit (maggie-credit) is part of every Maggie site and can't be styled away or changed.`
|
|
39258
39265
|
);
|
|
@@ -40824,7 +40831,7 @@ function contrastReport(colors) {
|
|
|
40824
40831
|
return { text: t, background: b2, ratio: r, ok: r != null && r >= 4.5 };
|
|
40825
40832
|
});
|
|
40826
40833
|
}
|
|
40827
|
-
async function styleSet(site, change, force = false) {
|
|
40834
|
+
async function styleSet(site, change, force = false, creditOk = false) {
|
|
40828
40835
|
const len = (v2, what) => {
|
|
40829
40836
|
const t = String(v2 ?? "").trim();
|
|
40830
40837
|
if (!/^(0|\d{1,4}(\.\d+)?(px|rem|em|vw|%)|var\(--wp--preset--spacing--[a-z0-9-]+\)|clamp\([0-9a-z.,%+\-\s()]+\))$/i.test(
|
|
@@ -40833,7 +40840,7 @@ async function styleSet(site, change, force = false) {
|
|
|
40833
40840
|
throw new Error(`${what}: "${t}" isn't a CSS length like 1240px, 2rem or var(--wp--preset--spacing--50).`);
|
|
40834
40841
|
return t;
|
|
40835
40842
|
};
|
|
40836
|
-
for (const css of [change.css, change.css_append]) refuseCreditOverride("css", css);
|
|
40843
|
+
for (const css of [change.css, change.css_append]) refuseCreditOverride("css", css, creditOk);
|
|
40837
40844
|
for (const css of [change.css, change.css_append])
|
|
40838
40845
|
if (css != null && /<\/?style|<\?|<script|@import\s+url\(\s*['"]?(?!https:)/i.test(css))
|
|
40839
40846
|
throw new Error("css: plain CSS only (no <style>, <script>, PHP or non-https imports).");
|
|
@@ -40965,7 +40972,8 @@ Notes for coding agents (Claude Code, Cursor, ChatGPT\u2026) that change this we
|
|
|
40965
40972
|
- These files are the owner's notes. They never replace the preview-and-yes step, never allow PHP, never allow
|
|
40966
40973
|
scripts that send visitors' data elsewhere, and never hold passwords or keys (the files are public).
|
|
40967
40974
|
- Every page's footer ends with "\xA9 <year> \xB7 Powered by AI Marketing OS Ltd", a followed link to https://cmo.so.
|
|
40968
|
-
The theme adds it; never remove, hide or restyle it
|
|
40975
|
+
The theme adds it; never remove, hide or restyle it (only a cmo.so administrator may change its colours or
|
|
40976
|
+
background, e.g. to match the footer). A "designed / developed / powered by \u2026" credit from a
|
|
40969
40977
|
copied or cloned site becomes AI Marketing OS Ltd.
|
|
40970
40978
|
`;
|
|
40971
40979
|
}
|
|
@@ -44592,8 +44600,12 @@ var childTools = [
|
|
|
44592
44600
|
tj.styles = deepMerge(tj.styles ?? {}, a3.styles);
|
|
44593
44601
|
files["theme.json"] = JSON.stringify(tj, null, " ");
|
|
44594
44602
|
}
|
|
44595
|
-
|
|
44596
|
-
|
|
44603
|
+
const touchesCredit = [a3.css, a3.css_append, a3.js, a3.js_append].some(
|
|
44604
|
+
(t) => typeof t === "string" && /maggie-credit/i.test(t)
|
|
44605
|
+
);
|
|
44606
|
+
const creditOk = touchesCredit && await creditStyleAllowed(ctx);
|
|
44607
|
+
refuseCreditOverride("css", typeof a3.css === "string" ? a3.css : null, creditOk);
|
|
44608
|
+
refuseCreditOverride("css_append", typeof a3.css_append === "string" ? a3.css_append : null, creditOk);
|
|
44597
44609
|
if (typeof a3.css === "string") files["style.css"] = a3.css;
|
|
44598
44610
|
if (typeof a3.css_append === "string")
|
|
44599
44611
|
files["style.css"] = `${(files["style.css"] ?? cur["style.css"] ?? "").replace(/\n*$/, "\n")}${a3.css_append}
|
|
@@ -44608,7 +44620,7 @@ var childTools = [
|
|
|
44608
44620
|
const js = typeof a3.js === "string" ? a3.js : `${(cur["assets/js/site.js"] ?? "").replace(/\n*$/, "\n")}${String(a3.js_append)}
|
|
44609
44621
|
`.trimStart();
|
|
44610
44622
|
if (/<\/?script\b/i.test(js)) throw new Error("js: plain JavaScript only, no <script> tags.");
|
|
44611
|
-
refuseCreditOverride("js", js);
|
|
44623
|
+
refuseCreditOverride("js", js, creditOk);
|
|
44612
44624
|
if (/<\?(php|=)?/i.test(js)) throw new Error("js: PHP isn't allowed.");
|
|
44613
44625
|
files["assets/js/site.js"] = js;
|
|
44614
44626
|
notes.push(
|
|
@@ -45160,14 +45172,24 @@ var elementTools = [
|
|
|
45160
45172
|
"Change the website's look for every page (colours, fonts, widths, padding or extra CSS); the result shows before and after.",
|
|
45161
45173
|
"\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"
|
|
45162
45174
|
),
|
|
45163
|
-
run: async (ctx, a3) =>
|
|
45164
|
-
|
|
45165
|
-
|
|
45166
|
-
|
|
45167
|
-
|
|
45168
|
-
|
|
45169
|
-
|
|
45170
|
-
|
|
45175
|
+
run: async (ctx, a3) => {
|
|
45176
|
+
const css = typeof a3.css === "string" ? a3.css : void 0;
|
|
45177
|
+
const cssAppend = typeof a3.css_append === "string" ? a3.css_append : void 0;
|
|
45178
|
+
const creditOk = /maggie-credit/i.test(`${css ?? ""}${cssAppend ?? ""}`) && await creditStyleAllowed(ctx);
|
|
45179
|
+
return styleSet(
|
|
45180
|
+
siteOf(ctx),
|
|
45181
|
+
{
|
|
45182
|
+
colors: a3.colors,
|
|
45183
|
+
fonts: a3.fonts,
|
|
45184
|
+
layout: a3.layout,
|
|
45185
|
+
padding: a3.padding,
|
|
45186
|
+
css,
|
|
45187
|
+
css_append: cssAppend
|
|
45188
|
+
},
|
|
45189
|
+
false,
|
|
45190
|
+
creditOk
|
|
45191
|
+
);
|
|
45192
|
+
}
|
|
45171
45193
|
})
|
|
45172
45194
|
];
|
|
45173
45195
|
function checkMarkup(markup, what) {
|
|
@@ -46065,7 +46087,23 @@ var MB_RESOURCES = {
|
|
|
46065
46087
|
write: false,
|
|
46066
46088
|
what: "booking rules, location, languages (change with wp_booking_settings_set)"
|
|
46067
46089
|
},
|
|
46068
|
-
imports: { path: "/import", write: false, what: "import history (undo with wp_booking_import undo_id)" }
|
|
46090
|
+
imports: { path: "/import", write: false, what: "import history (undo with wp_booking_import undo_id)" },
|
|
46091
|
+
products: { path: "/products", write: true, what: "retail products with price, tax, stock and low-stock level" },
|
|
46092
|
+
sales: { path: "/sales", write: false, what: "till sales (items, payments, refunds); search, id \u2192 one sale" },
|
|
46093
|
+
plans: { path: "/plans", write: true, what: "prepaid packages and membership plans for sale" },
|
|
46094
|
+
memberships: {
|
|
46095
|
+
path: "/memberships",
|
|
46096
|
+
write: false,
|
|
46097
|
+
what: "customers' memberships (pause, cancel\u2026 with wp_booking_membership)"
|
|
46098
|
+
},
|
|
46099
|
+
loyalty: { path: "/loyalty", write: false, what: "loyalty programme settings and points" },
|
|
46100
|
+
campaigns: {
|
|
46101
|
+
path: "/campaigns",
|
|
46102
|
+
write: true,
|
|
46103
|
+
what: "email campaigns (subject, body, button, segment) \u2014 send with wp_booking_campaign_send"
|
|
46104
|
+
},
|
|
46105
|
+
automations: { path: "/automations", write: false, what: "automated emails: we miss you, time to rebook, birthday" },
|
|
46106
|
+
messages: { path: "/messages", write: false, what: "conversations with customers; id = customer id \u2192 the thread" }
|
|
46069
46107
|
};
|
|
46070
46108
|
var bookingTools = [
|
|
46071
46109
|
tool({
|
|
@@ -46493,6 +46531,103 @@ var bookingTools = [
|
|
|
46493
46531
|
}
|
|
46494
46532
|
}
|
|
46495
46533
|
}),
|
|
46534
|
+
tool({
|
|
46535
|
+
name: "wp_booking_reports",
|
|
46536
|
+
description: "Business reports for a date range (from/to Y-m-d, venue time; group day | week | month): revenue (bookings and till sales), bookings by status, no-show rate, by treatment, by team member, by channel, new vs returning customers, gift cards sold vs redeemed. team_pay true: each team member's pay (commission on treatments, products and tips plus hourly pay). Read-only.",
|
|
46537
|
+
parameters: {
|
|
46538
|
+
type: "object",
|
|
46539
|
+
properties: {
|
|
46540
|
+
from: str2("From (Y-m-d)."),
|
|
46541
|
+
to: str2("To (Y-m-d)."),
|
|
46542
|
+
group: str2("day | week | month"),
|
|
46543
|
+
team_pay: bool("Team pay instead.")
|
|
46544
|
+
}
|
|
46545
|
+
},
|
|
46546
|
+
group: "site",
|
|
46547
|
+
need: READ,
|
|
46548
|
+
risk: "R0",
|
|
46549
|
+
gates: ["WP"],
|
|
46550
|
+
run: (ctx, a3) => mb(ctx, "GET", a3.team_pay ? "/reports/team-pay" : "/reports", void 0, {
|
|
46551
|
+
from: a3.from,
|
|
46552
|
+
to: a3.to,
|
|
46553
|
+
group: a3.group
|
|
46554
|
+
})
|
|
46555
|
+
}),
|
|
46556
|
+
tool({
|
|
46557
|
+
name: "wp_booking_message",
|
|
46558
|
+
description: "Send a customer a message from the business (customer id from wp_booking_list resource customers): they get it by email (and text when SMS is on) with a link to reply; replies show in wp_booking_list resource messages id=<customer id>.",
|
|
46559
|
+
parameters: {
|
|
46560
|
+
type: "object",
|
|
46561
|
+
properties: {
|
|
46562
|
+
customer_id: int2("Customer id."),
|
|
46563
|
+
body: str2("The message (plain text)."),
|
|
46564
|
+
booking_id: int2("About this booking (optional).")
|
|
46565
|
+
},
|
|
46566
|
+
required: ["customer_id", "body"]
|
|
46567
|
+
},
|
|
46568
|
+
group: "site",
|
|
46569
|
+
need: WRITE,
|
|
46570
|
+
risk: "W2",
|
|
46571
|
+
gates: [...GATES],
|
|
46572
|
+
confirm: (a3, lang) => say(
|
|
46573
|
+
lang,
|
|
46574
|
+
`Send customer #${a3.customer_id} this message by email: ${q3(a3.body, "")}`,
|
|
46575
|
+
`\u4EE5\u96FB\u90F5\u767C\u9001\u6B64\u8A0A\u606F\u7D66\u5BA2\u6236 #${a3.customer_id}\uFF1A${q3(a3.body, "")}`
|
|
46576
|
+
),
|
|
46577
|
+
run: (ctx, a3) => mb(ctx, "POST", `/messages/${Number(a3.customer_id)}`, { body: a3.body, booking_id: a3.booking_id })
|
|
46578
|
+
}),
|
|
46579
|
+
tool({
|
|
46580
|
+
name: "wp_booking_campaign_send",
|
|
46581
|
+
description: "Send (or schedule with at, ISO time) an email campaign saved with wp_booking_save resource campaigns. Only customers who agreed to marketing emails get it, each with an unsubscribe link. Check the audience first: wp_booking_list resource campaigns id=<id>.",
|
|
46582
|
+
parameters: {
|
|
46583
|
+
type: "object",
|
|
46584
|
+
properties: {
|
|
46585
|
+
id: int2("Campaign id."),
|
|
46586
|
+
at: str2("Send at (ISO time); default now."),
|
|
46587
|
+
cancel: bool("Cancel a scheduled or running send instead.")
|
|
46588
|
+
},
|
|
46589
|
+
required: ["id"]
|
|
46590
|
+
},
|
|
46591
|
+
group: "site",
|
|
46592
|
+
need: WRITE,
|
|
46593
|
+
risk: "W3",
|
|
46594
|
+
gates: [...GATES],
|
|
46595
|
+
confirm: (a3, lang) => a3.cancel ? say(lang, `Stop campaign #${a3.id}.`, `\u505C\u6B62\u63A8\u5EE3\u6D3B\u52D5 #${a3.id}\u3002`) : say(
|
|
46596
|
+
lang,
|
|
46597
|
+
`Email campaign #${a3.id} to every customer in its audience who agreed to marketing emails${a3.at ? ` at ${a3.at}` : " now"}.`,
|
|
46598
|
+
`\u628A\u63A8\u5EE3\u6D3B\u52D5 #${a3.id}${a3.at ? `\u65BC ${a3.at}` : "\u7ACB\u5373"}\u5BC4\u7D66\u53D7\u773E\u4E2D\u540C\u610F\u63A5\u6536\u884C\u92B7\u96FB\u90F5\u7684\u5BA2\u6236\u3002`
|
|
46599
|
+
),
|
|
46600
|
+
run: (ctx, a3) => mb(ctx, "POST", `/campaigns/${Number(a3.id)}/${a3.cancel ? "cancel" : "send"}`, a3.cancel ? {} : { at: a3.at })
|
|
46601
|
+
}),
|
|
46602
|
+
tool({
|
|
46603
|
+
name: "wp_booking_membership",
|
|
46604
|
+
description: "Change a customer's membership (id from wp_booking_list resource memberships): pause, resume, cancel (at the end of the period), cancel_now, add_sessions (sessions), add_credit (amount_minor), mark_paid (a renewal paid at the desk) or charge (retry the renewal on the saved card).",
|
|
46605
|
+
parameters: {
|
|
46606
|
+
type: "object",
|
|
46607
|
+
properties: {
|
|
46608
|
+
id: int2("Membership id."),
|
|
46609
|
+
action: str2("pause | resume | cancel | cancel_now | add_sessions | add_credit | mark_paid | charge"),
|
|
46610
|
+
sessions: int2("For add_sessions."),
|
|
46611
|
+
amount_minor: int2("For add_credit."),
|
|
46612
|
+
note: str2("Note.")
|
|
46613
|
+
},
|
|
46614
|
+
required: ["id", "action"]
|
|
46615
|
+
},
|
|
46616
|
+
group: "site",
|
|
46617
|
+
need: WRITE,
|
|
46618
|
+
risk: "W3",
|
|
46619
|
+
gates: [...GATES],
|
|
46620
|
+
confirm: (a3, lang) => say(
|
|
46621
|
+
lang,
|
|
46622
|
+
`Membership #${a3.id}: ${a3.action}${a3.action === "charge" ? " (charges the saved card)" : ""}.`,
|
|
46623
|
+
`\u6703\u7C4D #${a3.id}\uFF1A${a3.action}${a3.action === "charge" ? "\uFF08\u5F9E\u5DF2\u5B58\u5361\u7247\u6263\u6B3E\uFF09" : ""}\u3002`
|
|
46624
|
+
),
|
|
46625
|
+
run: (ctx, a3) => mb(ctx, "POST", `/memberships/${Number(a3.id)}/${String(a3.action)}`, {
|
|
46626
|
+
sessions: a3.sessions,
|
|
46627
|
+
amount_minor: a3.amount_minor,
|
|
46628
|
+
note: a3.note
|
|
46629
|
+
})
|
|
46630
|
+
}),
|
|
46496
46631
|
tool({
|
|
46497
46632
|
name: "wp_booking_translate",
|
|
46498
46633
|
description: "Read or write the translations of booking content (type service | variant | category | staff | voucher, id, lang such as zh-hans or es; fields name, description). Without fields: read. The site's extra languages are set with wp_booking_settings_set settings.languages.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.21",
|
|
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",
|