@cmo-so/mcp 0.12.24 → 0.12.25
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 +330 -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.
|
|
24492
|
+
version: "0.12.25",
|
|
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",
|
|
@@ -46183,7 +46183,33 @@ var MB_RESOURCES = {
|
|
|
46183
46183
|
what: "email campaigns (subject, body, button, segment) \u2014 send with wp_booking_campaign_send"
|
|
46184
46184
|
},
|
|
46185
46185
|
automations: { path: "/automations", write: false, what: "automated emails: we miss you, time to rebook, birthday" },
|
|
46186
|
-
messages: { path: "/messages", write: false, what: "conversations with customers; id = customer id \u2192 the thread" }
|
|
46186
|
+
messages: { path: "/messages", write: false, what: "conversations with customers; id = customer id \u2192 the thread" },
|
|
46187
|
+
portfolio: {
|
|
46188
|
+
path: "/portfolio",
|
|
46189
|
+
write: true,
|
|
46190
|
+
what: "portfolio photos of finished work (image_id, staff_id, service_id, caption)"
|
|
46191
|
+
},
|
|
46192
|
+
"form-responses": {
|
|
46193
|
+
path: "/form-responses",
|
|
46194
|
+
write: false,
|
|
46195
|
+
what: "customers' answers to intake / consultation forms"
|
|
46196
|
+
}
|
|
46197
|
+
};
|
|
46198
|
+
var MB_OWNER_ONLY = /^\/(gateways|payments\/settings|stripe|terminal|pay-links|pin|sms$|sms\/test|webhooks)|\/cards(\/|$)/;
|
|
46199
|
+
var mbPath = (raw) => {
|
|
46200
|
+
const p2 = `/${String(raw ?? "").trim().replace(/^\/+/, "").replace(/^maggie-booking\/v1\/admin\/?/, "")}`.replace(/\/+$/, "");
|
|
46201
|
+
if (p2 === "/" || /\.\.|[?#\s]/.test(p2) || !/^[\w\-/.]+$/.test(p2))
|
|
46202
|
+
throw new Error("path: a route under /admin, such as /services or /sales/12/close (see wp_booking_routes).");
|
|
46203
|
+
return p2;
|
|
46204
|
+
};
|
|
46205
|
+
var TILL_METHODS = ["cash", "card_reader", "gift_card", "credit", "pay_link", "other"];
|
|
46206
|
+
var escHtml = (t) => String(t ?? "").replace(/[&<>"]/g, (c2) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c2] ?? c2);
|
|
46207
|
+
var mbBlock = (name, attrs) => {
|
|
46208
|
+
const n2 = name.startsWith("maggie/") ? name : `maggie/${name}`;
|
|
46209
|
+
if (!/^maggie\/[a-z0-9-]+$/.test(n2))
|
|
46210
|
+
throw new Error(`block: ${name} is not a booking block (see wp_booking_blocks).`);
|
|
46211
|
+
const json = attrs && Object.keys(attrs).length ? ` ${JSON.stringify(attrs).replace(/--/g, "\\u002d\\u002d")}` : "";
|
|
46212
|
+
return `<!-- wp:${n2}${json} /-->`;
|
|
46187
46213
|
};
|
|
46188
46214
|
var bookingTools = [
|
|
46189
46215
|
tool({
|
|
@@ -46727,6 +46753,308 @@ var bookingTools = [
|
|
|
46727
46753
|
gates: [...GATES],
|
|
46728
46754
|
confirm: (a3, lang) => say(lang, `Save the ${a3.lang} translation of ${a3.type} #${a3.id}.`, `\u5132\u5B58 ${a3.type} #${a3.id} \u7684 ${a3.lang} \u7FFB\u8B6F\u3002`),
|
|
46729
46755
|
run: (ctx, a3) => a3.fields ? mb(ctx, "POST", "/translations", { type: a3.type, id: a3.id, lang: a3.lang, fields: a3.fields }) : mb(ctx, "GET", "/translations", void 0, { type: a3.type, id: a3.id })
|
|
46756
|
+
}),
|
|
46757
|
+
tool({
|
|
46758
|
+
name: "wp_booking_routes",
|
|
46759
|
+
description: "Every Maggie Booking admin route on the site (the whole wp-admin \u2192 Bookings dashboard: calendar, till, team, roles, clock, pay runs, goals, stock, finance, loyalty, automations, upsells, safety, client files\u2026): path under /admin, methods, arguments, and owner_only for the payment / SMS / card set-up that only the owner does in wp-admin. filter: text to match in the path. Use with wp_booking_get and wp_booking_post for anything the other wp_booking_* tools don't cover. Read-only.",
|
|
46760
|
+
parameters: { type: "object", properties: { filter: str2("Text in the path, e.g. sales, team, loyalty.") } },
|
|
46761
|
+
group: "site",
|
|
46762
|
+
need: READ,
|
|
46763
|
+
risk: "R0",
|
|
46764
|
+
gates: ["WP"],
|
|
46765
|
+
run: async (ctx, a3) => {
|
|
46766
|
+
const out = await mb(ctx, "GET", "/routes");
|
|
46767
|
+
const f2 = String(a3.filter ?? "").toLowerCase();
|
|
46768
|
+
const routes = f2 ? out.routes.filter((r) => r.path.toLowerCase().includes(f2)) : out.routes;
|
|
46769
|
+
return {
|
|
46770
|
+
count: routes.length,
|
|
46771
|
+
routes,
|
|
46772
|
+
note: "Write with wp_booking_post; owner_only routes are set up by the owner in wp-admin."
|
|
46773
|
+
};
|
|
46774
|
+
}
|
|
46775
|
+
}),
|
|
46776
|
+
tool({
|
|
46777
|
+
name: "wp_booking_get",
|
|
46778
|
+
description: "Read any Maggie Booking admin route (GET path under /admin, e.g. /overview, /sales/today, /sales/close?date=, /team/members, /clock, /pay-runs, /goals, /stock, /loyalty, /automations/rebook, /upsells, /patch-tests, /customers/12/wallet, /finance/accounts, /tools/settings) with an optional query. Find paths with wp_booking_routes. Money in minor units. Read-only.",
|
|
46779
|
+
parameters: {
|
|
46780
|
+
type: "object",
|
|
46781
|
+
properties: { path: str2("Route under /admin."), query: obj("Query parameters, e.g. { date: '2026-11-06' }.") },
|
|
46782
|
+
required: ["path"]
|
|
46783
|
+
},
|
|
46784
|
+
group: "site",
|
|
46785
|
+
need: READ,
|
|
46786
|
+
risk: "R0",
|
|
46787
|
+
gates: ["WP"],
|
|
46788
|
+
run: (ctx, a3) => mb(ctx, "GET", mbPath(a3.path), void 0, a3.query ?? void 0)
|
|
46789
|
+
}),
|
|
46790
|
+
tool({
|
|
46791
|
+
name: "wp_booking_post",
|
|
46792
|
+
description: "Change anything in the Maggie Booking dashboard that the other wp_booking_* tools don't cover: method POST | PATCH | DELETE, path under /admin (from wp_booking_routes), body. Examples: team roles and permissions (/team/roles), clock in/out (/clock), pay runs (/pay-runs), goals (/goals), stock moves (/stock), loyalty programme (/loyalty), automated emails (/automations/{kind}), upsells (/upsells), patch tests (/patch-tests), client files (/customers/{id}/files), finance accounts (/finance/accounts), AI polish (/ai/polish), tool settings (/tools/settings), till settings (/sales/settings). Read the item first with wp_booking_get. Refused: owner_only routes (payment, card reader, saved card, SMS and PIN set-up) and charging a saved card.",
|
|
46793
|
+
parameters: {
|
|
46794
|
+
type: "object",
|
|
46795
|
+
properties: {
|
|
46796
|
+
method: str2("POST | PATCH | DELETE"),
|
|
46797
|
+
path: str2("Route under /admin."),
|
|
46798
|
+
body: obj("Fields to send.")
|
|
46799
|
+
},
|
|
46800
|
+
required: ["method", "path"]
|
|
46801
|
+
},
|
|
46802
|
+
group: "site",
|
|
46803
|
+
need: WRITE,
|
|
46804
|
+
risk: "W3",
|
|
46805
|
+
gates: [...GATES],
|
|
46806
|
+
confirm: (a3, lang) => {
|
|
46807
|
+
const m = String(a3.method ?? "").toUpperCase();
|
|
46808
|
+
const verb = m === "DELETE" ? ["Delete", "\u522A\u9664"] : m === "PATCH" ? ["Change", "\u4FEE\u6539"] : ["Send", "\u9001\u51FA"];
|
|
46809
|
+
const body = a3.body ? ` ${JSON.stringify(a3.body).slice(0, 300)}` : "";
|
|
46810
|
+
return say(lang, `${verb[0]} booking ${String(a3.path)}${body}.`, `${verb[1]}\u9810\u7D04 ${String(a3.path)}${body}\u3002`);
|
|
46811
|
+
},
|
|
46812
|
+
run: (ctx, a3) => {
|
|
46813
|
+
const m = String(a3.method ?? "").toUpperCase();
|
|
46814
|
+
if (!["POST", "PATCH", "DELETE"].includes(m)) throw new Error("method: POST, PATCH or DELETE.");
|
|
46815
|
+
const p2 = mbPath(a3.path);
|
|
46816
|
+
if (MB_OWNER_ONLY.test(p2))
|
|
46817
|
+
throw new Error(
|
|
46818
|
+
"Payment, card reader, saved card, SMS and PIN set-up is the owner's, in wp-admin \u2192 Bookings. Nothing was changed."
|
|
46819
|
+
);
|
|
46820
|
+
if (/^\/sales\/\d+\/payments$/.test(p2) && !TILL_METHODS.includes(String(a3.body?.method ?? "")))
|
|
46821
|
+
throw new Error(`method: ${TILL_METHODS.join(", ")} (a saved card is charged by a person at the till).`);
|
|
46822
|
+
if (/^\/(routes|blocks)$/.test(p2)) throw new Error("That route is read-only.");
|
|
46823
|
+
return mb(ctx, m, p2, m === "DELETE" ? void 0 : a3.body ?? {});
|
|
46824
|
+
}
|
|
46825
|
+
}),
|
|
46826
|
+
tool({
|
|
46827
|
+
name: "wp_booking_till",
|
|
46828
|
+
description: "The till (point of sale): action start (new sale: customer_id, items, note) | from_booking (booking_id \u2192 its sale with treatments and what was already paid) | items (sale id, items [{kind service|product|gift_card|custom, service_id, variant_id, product_id, name, quantity, unit_minor, staff_id}], discount, tips \u2014 replaces the lines) | pay (sale id, method cash|card_reader|gift_card|credit|pay_link|other, amount_minor (default: what is due), tendered_minor for cash, reference) | close (sale id) | receipt (sale id, email) | refund (sale id, all true or payments [{id, amount_minor}], reason, restock) | void (sale id, reason). Read sales with wp_booking_list resource sales and today's takings with wp_booking_daily_close. A saved card is never charged by an agent.",
|
|
46829
|
+
parameters: {
|
|
46830
|
+
type: "object",
|
|
46831
|
+
properties: {
|
|
46832
|
+
action: str2("start | from_booking | items | pay | close | receipt | refund | void"),
|
|
46833
|
+
id: int2("Sale id."),
|
|
46834
|
+
booking_id: int2("For from_booking."),
|
|
46835
|
+
customer_id: int2("For start."),
|
|
46836
|
+
items: arr("Sale lines.", obj("")),
|
|
46837
|
+
discount: obj("For items: { percent } or { amount_minor }."),
|
|
46838
|
+
tips: arr("For items: tips per team member.", obj("")),
|
|
46839
|
+
note: str2("For start."),
|
|
46840
|
+
method: str2("For pay."),
|
|
46841
|
+
amount_minor: int2("For pay."),
|
|
46842
|
+
tendered_minor: int2("For pay in cash."),
|
|
46843
|
+
reference: str2("For pay."),
|
|
46844
|
+
email: str2("For receipt (default: the customer's)."),
|
|
46845
|
+
all: bool("For refund: everything."),
|
|
46846
|
+
payments: arr("For refund: [{ id, amount_minor }].", obj("")),
|
|
46847
|
+
restock: bool("For refund: put products back in stock."),
|
|
46848
|
+
reason: str2("For refund / void.")
|
|
46849
|
+
},
|
|
46850
|
+
required: ["action"]
|
|
46851
|
+
},
|
|
46852
|
+
group: "site",
|
|
46853
|
+
need: WRITE,
|
|
46854
|
+
risk: "W3",
|
|
46855
|
+
gates: [...GATES],
|
|
46856
|
+
confirm: (a3, lang) => {
|
|
46857
|
+
const money = (n2) => typeof n2 === "number" ? (n2 / 100).toFixed(2) : "";
|
|
46858
|
+
switch (a3.action) {
|
|
46859
|
+
case "pay":
|
|
46860
|
+
return say(
|
|
46861
|
+
lang,
|
|
46862
|
+
`Take ${a3.amount_minor ? money(a3.amount_minor) : "what is due"} by ${a3.method} on sale #${a3.id}.`,
|
|
46863
|
+
`\u5728\u92B7\u552E #${a3.id} \u4EE5 ${a3.method} \u6536\u53D6${a3.amount_minor ? ` ${money(a3.amount_minor)}` : "\u61C9\u4ED8\u91D1\u984D"}\u3002`
|
|
46864
|
+
);
|
|
46865
|
+
case "refund":
|
|
46866
|
+
return say(
|
|
46867
|
+
lang,
|
|
46868
|
+
`Refund sale #${a3.id}${a3.all ? " in full" : ""}: money goes back to the customer.`,
|
|
46869
|
+
`\u9000\u6B3E\u92B7\u552E #${a3.id}${a3.all ? "\uFF08\u5168\u984D\uFF09" : ""}\uFF1A\u6B3E\u9805\u6703\u9000\u56DE\u7D66\u5BA2\u4EBA\u3002`
|
|
46870
|
+
);
|
|
46871
|
+
case "void":
|
|
46872
|
+
return say(lang, `Void sale #${a3.id}.`, `\u4F5C\u5EE2\u92B7\u552E #${a3.id}\u3002`);
|
|
46873
|
+
case "close":
|
|
46874
|
+
return say(lang, `Close sale #${a3.id}.`, `\u7D50\u675F\u92B7\u552E #${a3.id}\u3002`);
|
|
46875
|
+
case "receipt":
|
|
46876
|
+
return say(lang, `Email the receipt for sale #${a3.id}.`, `\u5BC4\u51FA\u92B7\u552E #${a3.id} \u7684\u6536\u64DA\u3002`);
|
|
46877
|
+
case "from_booking":
|
|
46878
|
+
return say(lang, `Open the till for booking #${a3.booking_id}.`, `\u70BA\u9810\u7D04 #${a3.booking_id} \u958B\u555F\u6536\u9280\u3002`);
|
|
46879
|
+
case "items":
|
|
46880
|
+
return say(lang, `Change the lines of sale #${a3.id}.`, `\u4FEE\u6539\u92B7\u552E #${a3.id} \u7684\u9805\u76EE\u3002`);
|
|
46881
|
+
default:
|
|
46882
|
+
return say(lang, "Start a new till sale.", "\u958B\u59CB\u4E00\u7B46\u65B0\u7684\u6536\u9280\u92B7\u552E\u3002");
|
|
46883
|
+
}
|
|
46884
|
+
},
|
|
46885
|
+
run: (ctx, a3) => {
|
|
46886
|
+
const id = Number(a3.id);
|
|
46887
|
+
const need = () => {
|
|
46888
|
+
if (!id) throw new Error("id: the sale id.");
|
|
46889
|
+
};
|
|
46890
|
+
switch (a3.action) {
|
|
46891
|
+
case "start":
|
|
46892
|
+
return mb(ctx, "POST", "/sales", { customer_id: a3.customer_id, items: a3.items, note: a3.note });
|
|
46893
|
+
case "from_booking":
|
|
46894
|
+
if (!a3.booking_id) throw new Error("booking_id is needed.");
|
|
46895
|
+
return mb(ctx, "POST", `/sales/from-booking/${Number(a3.booking_id)}`, {});
|
|
46896
|
+
case "items":
|
|
46897
|
+
need();
|
|
46898
|
+
return mb(ctx, "PATCH", `/sales/${id}`, {
|
|
46899
|
+
...a3.items ? { items: a3.items } : {},
|
|
46900
|
+
...a3.discount ? { discount: a3.discount } : {},
|
|
46901
|
+
...a3.tips ? { tips: a3.tips } : {}
|
|
46902
|
+
});
|
|
46903
|
+
case "pay":
|
|
46904
|
+
need();
|
|
46905
|
+
if (!TILL_METHODS.includes(String(a3.method)))
|
|
46906
|
+
throw new Error(`method: ${TILL_METHODS.join(", ")} (a saved card is charged by a person at the till).`);
|
|
46907
|
+
return mb(ctx, "POST", `/sales/${id}/payments`, {
|
|
46908
|
+
method: a3.method,
|
|
46909
|
+
amount_minor: a3.amount_minor,
|
|
46910
|
+
tendered_minor: a3.tendered_minor,
|
|
46911
|
+
reference: a3.reference,
|
|
46912
|
+
key: `mcp-${id}-${a3.method}-${a3.amount_minor ?? "due"}-${Date.now()}`
|
|
46913
|
+
});
|
|
46914
|
+
case "close":
|
|
46915
|
+
need();
|
|
46916
|
+
return mb(ctx, "POST", `/sales/${id}/close`, {});
|
|
46917
|
+
case "receipt":
|
|
46918
|
+
need();
|
|
46919
|
+
return mb(ctx, "POST", `/sales/${id}/receipt`, a3.email ? { email: a3.email } : {});
|
|
46920
|
+
case "refund":
|
|
46921
|
+
need();
|
|
46922
|
+
return mb(ctx, "POST", `/sales/${id}/refund`, {
|
|
46923
|
+
all: !!a3.all,
|
|
46924
|
+
payments: a3.payments,
|
|
46925
|
+
reason: a3.reason ?? "",
|
|
46926
|
+
restock: a3.restock,
|
|
46927
|
+
key: `mcp-refund-${id}-${Date.now()}`
|
|
46928
|
+
});
|
|
46929
|
+
case "void":
|
|
46930
|
+
need();
|
|
46931
|
+
return mb(ctx, "POST", `/sales/${id}/void`, { reason: a3.reason ?? "" });
|
|
46932
|
+
default:
|
|
46933
|
+
throw new Error("action: start, from_booking, items, pay, close, receipt, refund or void.");
|
|
46934
|
+
}
|
|
46935
|
+
}
|
|
46936
|
+
}),
|
|
46937
|
+
tool({
|
|
46938
|
+
name: "wp_booking_daily_close",
|
|
46939
|
+
description: "The day's till close (end-of-day report): takings by payment method, cash expected in the drawer, refunds, tips, open sales still to settle. date (Y-m-d, venue time; default today). Read-only.",
|
|
46940
|
+
parameters: { type: "object", properties: { date: str2("Y-m-d") } },
|
|
46941
|
+
group: "site",
|
|
46942
|
+
need: READ,
|
|
46943
|
+
risk: "R0",
|
|
46944
|
+
gates: ["WP"],
|
|
46945
|
+
run: (ctx, a3) => mb(ctx, "GET", "/sales/close", void 0, { date: a3.date })
|
|
46946
|
+
}),
|
|
46947
|
+
tool({
|
|
46948
|
+
name: "wp_booking_blocks",
|
|
46949
|
+
description: "The booking blocks visitors see (services menu, Book button, team, gift cards and balance check, manage booking, reviews, my bookings, products, plans and memberships, portfolio, AI receptionist chat) with their attributes, the Book page, booking links (#book, #book:<service_id>:<variant_id>) and the current visitor design. Use before wp_booking_page, wp_booking_design or adding a block to a page with wp_section_add / wp_page_markup_set. Read-only.",
|
|
46950
|
+
parameters: { type: "object", properties: {} },
|
|
46951
|
+
group: "site",
|
|
46952
|
+
need: READ,
|
|
46953
|
+
risk: "R0",
|
|
46954
|
+
gates: ["WP"],
|
|
46955
|
+
run: (ctx) => mb(ctx, "GET", "/blocks")
|
|
46956
|
+
}),
|
|
46957
|
+
tool({
|
|
46958
|
+
name: "wp_booking_page",
|
|
46959
|
+
description: "Make or rebuild a booking page from sections, in the theme's full width (template page-wide): sections in order, each { heading, text } (a heading and/or a paragraph) or { block, attrs } with a booking block from wp_booking_blocks (e.g. booking-services {layout: cards, category}, booking-team, gift-cards, gift-card-check, plans {kind}, portfolio, booking-reviews, my-bookings, products, booking-manage). page_id: rebuild that page (it keeps its address; the earlier version stays in revisions); else a new page (title, slug). book_page true: make it the page the booking links open. status draft (default) or publish. preview true: show the markup only.",
|
|
46960
|
+
parameters: {
|
|
46961
|
+
type: "object",
|
|
46962
|
+
properties: {
|
|
46963
|
+
title: str2("Page title (new page)."),
|
|
46964
|
+
slug: str2("Address (new page)."),
|
|
46965
|
+
page_id: int2("Page to rebuild."),
|
|
46966
|
+
sections: arr(
|
|
46967
|
+
"Sections in order.",
|
|
46968
|
+
obj("", { heading: str2(""), text: str2(""), block: str2(""), attrs: obj("") })
|
|
46969
|
+
),
|
|
46970
|
+
book_page: bool("Use it as the Book page."),
|
|
46971
|
+
status: str2("draft | publish"),
|
|
46972
|
+
preview: bool("Markup only.")
|
|
46973
|
+
},
|
|
46974
|
+
required: ["sections"]
|
|
46975
|
+
},
|
|
46976
|
+
group: "site",
|
|
46977
|
+
need: WRITE,
|
|
46978
|
+
risk: "W2",
|
|
46979
|
+
gates: [...GATES],
|
|
46980
|
+
confirm: (a3, lang) => a3.page_id ? say(lang, `Rebuild page #${a3.page_id} as a booking page.`, `\u628A\u9801\u9762 #${a3.page_id} \u91CD\u5EFA\u70BA\u9810\u7D04\u9801\u9762\u3002`) : say(lang, `Create the booking page "${a3.title}".`, `\u5EFA\u7ACB\u9810\u7D04\u9801\u9762\u300C${a3.title}\u300D\u3002`),
|
|
46981
|
+
run: async (ctx, a3) => {
|
|
46982
|
+
const site = siteOf(ctx);
|
|
46983
|
+
const sections = Array.isArray(a3.sections) ? a3.sections : [];
|
|
46984
|
+
if (!sections.length) throw new Error("sections: at least one.");
|
|
46985
|
+
const parts = [];
|
|
46986
|
+
for (const s of sections) {
|
|
46987
|
+
if (s.heading)
|
|
46988
|
+
parts.push(
|
|
46989
|
+
`<!-- wp:heading -->
|
|
46990
|
+
<h2 class="wp-block-heading">${escHtml(s.heading)}</h2>
|
|
46991
|
+
<!-- /wp:heading -->`
|
|
46992
|
+
);
|
|
46993
|
+
if (s.text) parts.push(`<!-- wp:paragraph -->
|
|
46994
|
+
<p>${escHtml(s.text)}</p>
|
|
46995
|
+
<!-- /wp:paragraph -->`);
|
|
46996
|
+
if (s.block) parts.push(mbBlock(String(s.block), s.attrs ?? void 0));
|
|
46997
|
+
}
|
|
46998
|
+
const content = parts.join("\n\n");
|
|
46999
|
+
if (a3.preview) return { preview: true, template: "page-wide", content };
|
|
47000
|
+
if (!a3.page_id && !a3.title) throw new Error("title: needed for a new page.");
|
|
47001
|
+
const page = await call(site, {
|
|
47002
|
+
method: "POST",
|
|
47003
|
+
path: a3.page_id ? `/wp/v2/pages/${Number(a3.page_id)}` : "/wp/v2/pages",
|
|
47004
|
+
query: { _fields: "id,link,status" },
|
|
47005
|
+
body: {
|
|
47006
|
+
...a3.title ? { title: a3.title } : {},
|
|
47007
|
+
...a3.slug && !a3.page_id ? { slug: a3.slug } : {},
|
|
47008
|
+
...a3.status ? { status: a3.status === "publish" ? "publish" : "draft" } : a3.page_id ? {} : { status: "draft" },
|
|
47009
|
+
template: "page-wide",
|
|
47010
|
+
content
|
|
47011
|
+
}
|
|
47012
|
+
});
|
|
47013
|
+
if (!page || typeof page.id !== "number") throw new Error("WordPress didn't save the page; nothing was changed.");
|
|
47014
|
+
const book = a3.book_page ? await mb(ctx, "POST", "/settings", { settings: { booking_page_id: page.id } }).then(
|
|
47015
|
+
() => true,
|
|
47016
|
+
(e2) => ({ error: e2.message })
|
|
47017
|
+
) : false;
|
|
47018
|
+
return {
|
|
47019
|
+
saved: true,
|
|
47020
|
+
id: page.id,
|
|
47021
|
+
path: path(page.link),
|
|
47022
|
+
status: page.status,
|
|
47023
|
+
book_page: book,
|
|
47024
|
+
sections: sections.length
|
|
47025
|
+
};
|
|
47026
|
+
}
|
|
47027
|
+
}),
|
|
47028
|
+
tool({
|
|
47029
|
+
name: "wp_booking_design",
|
|
47030
|
+
description: "The look of the booking blocks, booking sheet, gift cards, plans and account pages for visitors (Maggie Core 0.20.1+): design { accent, accent_deep, ink, muted, line, surface, panel (hex colours), radius 0-40 (px, cards and sheet), button_radius 0-99 (px), density comfortable | compact }. Send only what changes; reset true goes back to the theme's colours. Without design or reset: read the current design. The footer credit is not part of it.",
|
|
47031
|
+
parameters: {
|
|
47032
|
+
type: "object",
|
|
47033
|
+
properties: { design: obj("Design values."), reset: bool("Back to the theme look.") }
|
|
47034
|
+
},
|
|
47035
|
+
group: "site",
|
|
47036
|
+
need: WRITE,
|
|
47037
|
+
risk: "W2",
|
|
47038
|
+
gates: [...GATES],
|
|
47039
|
+
confirm: (a3, lang) => a3.reset ? say(lang, "Reset the booking look to the theme's.", "\u628A\u9810\u7D04\u5916\u89C0\u91CD\u8A2D\u70BA\u4E3B\u984C\u9810\u8A2D\u3002") : say(
|
|
47040
|
+
lang,
|
|
47041
|
+
`Change the booking look: ${JSON.stringify(a3.design ?? {})}.`,
|
|
47042
|
+
`\u4FEE\u6539\u9810\u7D04\u5916\u89C0\uFF1A${JSON.stringify(a3.design ?? {})}\u3002`
|
|
47043
|
+
),
|
|
47044
|
+
run: async (ctx, a3) => {
|
|
47045
|
+
if (!a3.design && !a3.reset) {
|
|
47046
|
+
const b2 = await mb(ctx, "GET", "/blocks");
|
|
47047
|
+
return { design: b2.design ?? {} };
|
|
47048
|
+
}
|
|
47049
|
+
let next = {};
|
|
47050
|
+
if (!a3.reset) {
|
|
47051
|
+
const b2 = await mb(ctx, "GET", "/blocks");
|
|
47052
|
+
const cur = b2.design && !Array.isArray(b2.design) ? b2.design : {};
|
|
47053
|
+
next = { ...cur, ...a3.design };
|
|
47054
|
+
}
|
|
47055
|
+
await mb(ctx, "POST", "/settings", { settings: { design: next } });
|
|
47056
|
+
return { saved: true, design: next };
|
|
47057
|
+
}
|
|
46730
47058
|
})
|
|
46731
47059
|
];
|
|
46732
47060
|
var RESTYLE = /* @__PURE__ */ new Set([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.25",
|
|
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",
|