@cmo-so/mcp 0.7.1 → 0.7.3
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 -3
- 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.7.
|
|
7202
|
+
version: "0.7.3",
|
|
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",
|
|
@@ -7410,6 +7410,14 @@ function createApi({ baseUrl, session: session2, fetch: fetchImpl = globalThis.f
|
|
|
7410
7410
|
apps: () => request("/v1/me/apps"),
|
|
7411
7411
|
revokeApp: (grantId) => request(`/v1/me/apps/${encodeURIComponent(grantId)}`, { method: "DELETE" }),
|
|
7412
7412
|
invoices: () => request("/v1/me/invoices"),
|
|
7413
|
+
/**
|
|
7414
|
+
* Take a website off your own list (archives your claim; reversible on ai.cmo.so). Nothing changes for
|
|
7415
|
+
* anyone else; a team member also leaves the team.
|
|
7416
|
+
*/
|
|
7417
|
+
removeWebsite: (domain) => request(
|
|
7418
|
+
`/v1/me/websites/${encodeURIComponent(domain)}/remove`,
|
|
7419
|
+
{ method: "POST" }
|
|
7420
|
+
),
|
|
7413
7421
|
/** Delete the account (only from the person's own sign-in). Websites stay, unclaimed; plans stop renewing. */
|
|
7414
7422
|
delete: () => request("/v1/me/delete", {
|
|
7415
7423
|
method: "POST",
|
|
@@ -7697,6 +7705,11 @@ function domainApi(api2, domain) {
|
|
|
7697
7705
|
wordpressPlugin: () => api2.request(`${base}/wordpress-plugin`),
|
|
7698
7706
|
// Writes (need autopilot write on the domain).
|
|
7699
7707
|
addIdea: (input) => post(`${base}/ideas`, input),
|
|
7708
|
+
/**
|
|
7709
|
+
* Up to 100 ideas exactly as given (no AI, no generation used): they wait in the pool, not the plan, and count
|
|
7710
|
+
* toward the 100 waiting ideas a person may add. Duplicates (title or page) are skipped and listed.
|
|
7711
|
+
*/
|
|
7712
|
+
addIdeas: (ideas) => post(`${base}/ideas/bulk`, { ideas }),
|
|
7700
7713
|
/** Ideas built on up to 10 photos (base64 JPEG). The server keeps no copy. */
|
|
7701
7714
|
ideasFromPhotos: (photos, count, brief2 = "") => post(`${base}/ideas/from-photos`, { photos, count, brief: brief2 }),
|
|
7702
7715
|
generateIdeas: (count, brief2 = "") => post(`${base}/ideas/generate`, { count, brief: brief2 }),
|
|
@@ -8146,6 +8159,18 @@ function domainApi(api2, domain) {
|
|
|
8146
8159
|
body: JSON.stringify(r)
|
|
8147
8160
|
}
|
|
8148
8161
|
),
|
|
8162
|
+
/** Competitors Maggie found with Google Search, waiting for the user to add or dismiss (docs/25). */
|
|
8163
|
+
competitorSuggestions: () => api2.request(
|
|
8164
|
+
`${base}/competitors/suggestions`
|
|
8165
|
+
),
|
|
8166
|
+
/** Put a suggestion in the business profile's competitors. */
|
|
8167
|
+
addCompetitorSuggestion: (id) => post(
|
|
8168
|
+
`${base}/competitors/suggestions/${encodeURIComponent(id)}/add`
|
|
8169
|
+
),
|
|
8170
|
+
/** Not a competitor: never suggested or read for ideas again. */
|
|
8171
|
+
dismissCompetitorSuggestion: (id) => post(`${base}/competitors/suggestions/${encodeURIComponent(id)}/dismiss`),
|
|
8172
|
+
/** Look for new competitors now (once a day; subscribed websites only, else 402). */
|
|
8173
|
+
refreshCompetitorSuggestions: () => post(`${base}/competitors/suggestions/refresh`),
|
|
8149
8174
|
/** The last time posts delivered by API pull were found in the website's sitemap (gives them their address). */
|
|
8150
8175
|
sitemapMatch: () => api2.request(`${base}/rewrites/sitemap-match`),
|
|
8151
8176
|
/** Read the sitemap (found on its own when blank) and match API-pull posts to their live address. */
|
|
@@ -9339,6 +9364,41 @@ var blogTools = [
|
|
|
9339
9364
|
return ws(ctx).addIdea(url ? { url } : { text: text3 });
|
|
9340
9365
|
}
|
|
9341
9366
|
}),
|
|
9367
|
+
tool({
|
|
9368
|
+
name: "ideas_add_list",
|
|
9369
|
+
description: "Add up to 100 ideas exactly as given (a researched list): title, description, primary keyword, up to 5 more keywords, a benchmark URL (read as research, never linked), priority 1-10 and optionally one of the website's topics. No AI rewrites them and no generation is used; they wait in the idea pool, not the plan. Duplicates are skipped and listed; at most 100 of a person's own ideas can wait at once.",
|
|
9370
|
+
parameters: {
|
|
9371
|
+
type: "object",
|
|
9372
|
+
properties: {
|
|
9373
|
+
ideas: {
|
|
9374
|
+
type: "array",
|
|
9375
|
+
items: {
|
|
9376
|
+
type: "object",
|
|
9377
|
+
properties: {
|
|
9378
|
+
title: { type: "string" },
|
|
9379
|
+
description: { type: "string" },
|
|
9380
|
+
keyword: { type: "string", description: "The primary keyword" },
|
|
9381
|
+
keywords: { type: "array", items: { type: "string" } },
|
|
9382
|
+
url: { type: "string", description: "A benchmark page" },
|
|
9383
|
+
priority: { type: "integer", minimum: 1, maximum: 10 },
|
|
9384
|
+
topic: { type: "string", description: "One of topics_list, if it fits" }
|
|
9385
|
+
},
|
|
9386
|
+
required: ["title"]
|
|
9387
|
+
}
|
|
9388
|
+
}
|
|
9389
|
+
},
|
|
9390
|
+
required: ["ideas"]
|
|
9391
|
+
},
|
|
9392
|
+
group: "blog",
|
|
9393
|
+
need: write,
|
|
9394
|
+
risk: "W1",
|
|
9395
|
+
run: async (ctx, { ideas }) => {
|
|
9396
|
+
if (!ideas?.length) throw new Error("Give at least one idea.");
|
|
9397
|
+
if (ideas.length > 100) throw new Error("Up to 100 ideas at a time.");
|
|
9398
|
+
const out = await ws(ctx).addIdeas(ideas);
|
|
9399
|
+
return { added: out.added, skipped: out.skipped, room_left: out.room_left };
|
|
9400
|
+
}
|
|
9401
|
+
}),
|
|
9342
9402
|
tool({
|
|
9343
9403
|
name: "ideas_generate",
|
|
9344
9404
|
description: "Let Maggie come up with new ideas (1\u201310) with AI, optionally about a theme.",
|
|
@@ -9410,7 +9470,7 @@ var blogTools = [
|
|
|
9410
9470
|
}),
|
|
9411
9471
|
tool({
|
|
9412
9472
|
name: "idea_plan",
|
|
9413
|
-
description: "Add a waiting idea to the end of the plan (the plan holds
|
|
9473
|
+
description: "Add a waiting idea to the end of the plan (the plan holds up to 100).",
|
|
9414
9474
|
parameters: {
|
|
9415
9475
|
type: "object",
|
|
9416
9476
|
properties: {
|
|
@@ -9701,6 +9761,60 @@ var brandTools = [
|
|
|
9701
9761
|
return { competitors: out.competitors?.map((x) => x.name) };
|
|
9702
9762
|
}
|
|
9703
9763
|
}),
|
|
9764
|
+
tool({
|
|
9765
|
+
name: "competitor_suggestions_list",
|
|
9766
|
+
description: "Competitors Maggie found on the web (each website checked) that the user hasn't added to the profile or dismissed yet: name, website, one line, and how many ideas came from their site. Their sitemaps are already used for blog ideas while they wait.",
|
|
9767
|
+
parameters: none,
|
|
9768
|
+
group: "brand",
|
|
9769
|
+
need: { resource: "overview", level: "read" },
|
|
9770
|
+
risk: "R0",
|
|
9771
|
+
run: async (ctx) => {
|
|
9772
|
+
const out = await ws(ctx).competitorSuggestions();
|
|
9773
|
+
return {
|
|
9774
|
+
searched_at: out.searched_at,
|
|
9775
|
+
suggestions: out.items.map(({ id, name, website, description: description2, ideas_found }) => ({
|
|
9776
|
+
id,
|
|
9777
|
+
name,
|
|
9778
|
+
website,
|
|
9779
|
+
description: description2,
|
|
9780
|
+
ideas_found
|
|
9781
|
+
}))
|
|
9782
|
+
};
|
|
9783
|
+
}
|
|
9784
|
+
}),
|
|
9785
|
+
tool({
|
|
9786
|
+
name: "competitor_suggestion_add",
|
|
9787
|
+
description: "Add one of Maggie's competitor suggestions (id from competitor_suggestions_list) to the business profile.",
|
|
9788
|
+
parameters: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
9789
|
+
group: "brand",
|
|
9790
|
+
need: write2,
|
|
9791
|
+
risk: "W1",
|
|
9792
|
+
run: async (ctx, { id }) => {
|
|
9793
|
+
const out = await ws(ctx).addCompetitorSuggestion(id);
|
|
9794
|
+
return { competitors: out.competitors.map((c) => c.name) };
|
|
9795
|
+
}
|
|
9796
|
+
}),
|
|
9797
|
+
tool({
|
|
9798
|
+
name: "competitor_suggestion_dismiss",
|
|
9799
|
+
description: "Not a competitor after all: the suggestion is never made again and its site is no longer read for ideas.",
|
|
9800
|
+
parameters: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
9801
|
+
group: "brand",
|
|
9802
|
+
need: write2,
|
|
9803
|
+
risk: "W1",
|
|
9804
|
+
run: async (ctx, { id }) => ws(ctx).dismissCompetitorSuggestion(id)
|
|
9805
|
+
}),
|
|
9806
|
+
tool({
|
|
9807
|
+
name: "competitor_suggestions_find",
|
|
9808
|
+
description: "Look for new competitors on the web now (once a day per website, subscribed websites only; Maggie also looks on her own once the website and its known competitors have no new pages left). New ones come back as suggestions; nothing is added to the profile.",
|
|
9809
|
+
parameters: none,
|
|
9810
|
+
group: "brand",
|
|
9811
|
+
need: write2,
|
|
9812
|
+
risk: "W1",
|
|
9813
|
+
run: async (ctx) => {
|
|
9814
|
+
const out = await ws(ctx).refreshCompetitorSuggestions();
|
|
9815
|
+
return { found: out.found, suggestions: out.items.map(({ id, name, website }) => ({ id, name, website })) };
|
|
9816
|
+
}
|
|
9817
|
+
}),
|
|
9704
9818
|
tool({
|
|
9705
9819
|
name: "brand_research_update",
|
|
9706
9820
|
description: "Change the profile's market notes: market_research (text), additional_information (anything else Maggie should know) or the SWOT list (each {name: Strengths|Weaknesses|Opportunities|Threats, description}). A list replaces the whole list.",
|
|
@@ -22086,12 +22200,14 @@ var OPEN_WORLD = /* @__PURE__ */ new Set([
|
|
|
22086
22200
|
"social_video_add",
|
|
22087
22201
|
"seo_audit_run",
|
|
22088
22202
|
"ai_visibility_prompt_check",
|
|
22089
|
-
"idea_add"
|
|
22203
|
+
"idea_add",
|
|
22204
|
+
"competitor_suggestions_find"
|
|
22090
22205
|
]);
|
|
22091
22206
|
var OVERWRITES = /* @__PURE__ */ new Set([
|
|
22092
22207
|
"ai_visibility_keywords_set",
|
|
22093
22208
|
"brand_research_update",
|
|
22094
22209
|
"brand_update",
|
|
22210
|
+
"competitor_suggestion_dismiss",
|
|
22095
22211
|
"draft_rewrite",
|
|
22096
22212
|
"draft_rewrite_save",
|
|
22097
22213
|
"draft_update",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
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",
|