@seldonframe/mcp 1.53.0 → 1.55.0
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/package.json +1 -1
- package/src/finalize-summary.js +108 -0
- package/src/tools.js +49 -143
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seldonframe/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.55.0",
|
|
4
4
|
"mcpName": "io.github.seldonframe/seldonframe-mcp",
|
|
5
5
|
"description": "Open-source GoHighLevel alternative for agencies. 146+ MCP tools that let Claude Code spin up white-labeled client workspaces — CRM, booking, intake forms, landing pages, AI chatbot, and pre-wired agent archetypes (speed-to-lead, missed-call-text-back, review-requester) — in minutes. AGPL-3.0.",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// v1.55.0 — Standalone builder for the finalize_workspace operator summary.
|
|
2
|
+
// Extracted from tools.js so we can unit-test the string-building logic
|
|
3
|
+
// in isolation (no MCP server boot, no HTTP shims, no snapshot fetcher).
|
|
4
|
+
//
|
|
5
|
+
// The handler in tools.js fetches the snapshot, computes duration, and
|
|
6
|
+
// passes the result here. This file just builds the string.
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {object} args
|
|
10
|
+
* @param {object} args.snapshot — workspace snapshot from
|
|
11
|
+
* /api/v1/workspace/<id>/snapshot. Must include: workspace.name,
|
|
12
|
+
* public_urls.{home,book,intake}, chatbot (or null), ops_stack,
|
|
13
|
+
* available_automations, tier.
|
|
14
|
+
* @param {number} args.durationSec — total workspace creation time.
|
|
15
|
+
* @param {string|null} args.aestheticArchetype — workspace's classified
|
|
16
|
+
* archetype (from snapshot.theme.aestheticArchetype). Used in the
|
|
17
|
+
* closing landing-page nudge.
|
|
18
|
+
* @returns {string} the formatted operator summary
|
|
19
|
+
*/
|
|
20
|
+
export function buildFinalizeSummary({ snapshot, durationSec, aestheticArchetype }) {
|
|
21
|
+
const ws = snapshot.workspace ?? {};
|
|
22
|
+
const businessName = ws.name ?? "Your workspace";
|
|
23
|
+
const chatbot = snapshot.chatbot ?? null;
|
|
24
|
+
const opsStack = snapshot.ops_stack ?? {};
|
|
25
|
+
const automations = snapshot.available_automations ?? [];
|
|
26
|
+
const tier = snapshot.tier ?? {};
|
|
27
|
+
const tierLabel = tier.current_tier_label ?? "Free";
|
|
28
|
+
const isPaid = tier.current_tier === "growth" || tier.current_tier === "scale";
|
|
29
|
+
|
|
30
|
+
// Extract client domain from the operator's input (the URL they scraped).
|
|
31
|
+
// We store it on workspace.settings.source_url upstream; fall back to
|
|
32
|
+
// the public preview URL host if unavailable.
|
|
33
|
+
const clientDomain =
|
|
34
|
+
(ws.settings && typeof ws.settings.source_url === "string"
|
|
35
|
+
? new URL(ws.settings.source_url).host
|
|
36
|
+
: null) ?? "your client's site";
|
|
37
|
+
|
|
38
|
+
const lines = [];
|
|
39
|
+
|
|
40
|
+
// Header
|
|
41
|
+
lines.push(`✅ Client ops stack ready for ${businessName}. (${durationSec} seconds)`);
|
|
42
|
+
lines.push("");
|
|
43
|
+
|
|
44
|
+
// Chatbot embed snippet (the magic moment — paste on client's existing site)
|
|
45
|
+
if (chatbot && chatbot.embed_snippet) {
|
|
46
|
+
lines.push(`📞 AI receptionist — paste before </body> on ${clientDomain} to go live:`);
|
|
47
|
+
lines.push(chatbot.embed_snippet);
|
|
48
|
+
lines.push("");
|
|
49
|
+
lines.push(`🤖 Demo for your client: ${chatbot.preview_url ?? snapshot.public_urls?.home ?? ""}`);
|
|
50
|
+
lines.push(` (Chatbot live in TEST mode — share so your client can try it before pasting)`);
|
|
51
|
+
} else {
|
|
52
|
+
lines.push(`🤖 AI chatbot — scaffold pending. Retry:`);
|
|
53
|
+
lines.push(` create_agent({ archetype: "website-chatbot", channel: "web_chat" })`);
|
|
54
|
+
}
|
|
55
|
+
lines.push("");
|
|
56
|
+
|
|
57
|
+
// Ops stack URLs
|
|
58
|
+
lines.push(`📅 Booking: ${opsStack.booking_url ?? snapshot.public_urls?.book ?? ""}`);
|
|
59
|
+
lines.push(`📝 Intake: ${opsStack.intake_url ?? snapshot.public_urls?.intake ?? ""}`);
|
|
60
|
+
lines.push(`🔧 Admin: ${opsStack.admin_url ?? ""}`);
|
|
61
|
+
lines.push("");
|
|
62
|
+
|
|
63
|
+
// 7-automation callout
|
|
64
|
+
if (automations.length > 0) {
|
|
65
|
+
lines.push(`⚡ ${automations.length} more automations ready to deploy for this client:`);
|
|
66
|
+
const descriptions = {
|
|
67
|
+
"speed-to-lead": "text the lead within 30 sec of intake submission",
|
|
68
|
+
"missed-call-text-back": "auto-SMS when their phone goes unanswered",
|
|
69
|
+
"review-requester": "ask for a 5★ after every completed booking",
|
|
70
|
+
"appointment-confirm-sms": "reduce no-shows automatically",
|
|
71
|
+
"weather-aware-booking": "reschedule outdoor jobs when rain is forecast",
|
|
72
|
+
"daily-digest": "morning summary of yesterday's activity",
|
|
73
|
+
"win-back": "re-engage cancelled subscribers with a time-limited code",
|
|
74
|
+
};
|
|
75
|
+
for (const a of automations) {
|
|
76
|
+
const desc = descriptions[a.id] ?? "";
|
|
77
|
+
lines.push(` • ${a.name}${desc ? " — " + desc : ""}`);
|
|
78
|
+
}
|
|
79
|
+
lines.push(` Activate any: ${opsStack.automations_url ?? ""}`);
|
|
80
|
+
lines.push(
|
|
81
|
+
` (Need API keys for SMS/email? Just ask — Claude will walk you through`,
|
|
82
|
+
);
|
|
83
|
+
lines.push(` Twilio / Resend / Stripe setup when an automation needs one.)`);
|
|
84
|
+
lines.push("");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Tier + client portal
|
|
88
|
+
const tierUpsell = isPaid
|
|
89
|
+
? "white-label + reseller pricing on Scale ($99/mo)"
|
|
90
|
+
: "Upgrade $9/mo for unlimited workspaces";
|
|
91
|
+
const clientPortalUrl = tier.client_portal_url ?? "";
|
|
92
|
+
lines.push(
|
|
93
|
+
`💼 Tier: ${tierLabel} · ${tierUpsell}` +
|
|
94
|
+
(clientPortalUrl ? ` · Client portal: ${clientPortalUrl}` : ""),
|
|
95
|
+
);
|
|
96
|
+
lines.push("");
|
|
97
|
+
|
|
98
|
+
// Landing-page nudge (closing)
|
|
99
|
+
const archetypeClause = aestheticArchetype ? ` in ${aestheticArchetype} style` : "";
|
|
100
|
+
lines.push(
|
|
101
|
+
`Want a landing page too? Just ask: "build a landing page for ${businessName}${archetypeClause}"`,
|
|
102
|
+
);
|
|
103
|
+
lines.push(
|
|
104
|
+
`— Claude will use the landing-page-creation skill to generate one${aestheticArchetype ? " with the archetype voice" : ""}.`,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return lines.join("\n");
|
|
108
|
+
}
|
package/src/tools.js
CHANGED
|
@@ -20,6 +20,10 @@ import {
|
|
|
20
20
|
// drafts assumed VERSION leaked in via client.js's transitive import;
|
|
21
21
|
// it doesn't. Direct import = no runtime "VERSION is not defined".
|
|
22
22
|
import { FIRST_CALL_BANNER, VERSION } from "./welcome.js";
|
|
23
|
+
// v1.55.0 — finalize_workspace summary builder extracted into its own
|
|
24
|
+
// module so it can be unit-tested in isolation. See
|
|
25
|
+
// packages/crm/tests/unit/finalize-summary-v1-55.spec.ts.
|
|
26
|
+
import { buildFinalizeSummary } from "./finalize-summary.js";
|
|
23
27
|
// v1.10.1 — upload_workspace_image local_file_path branch reads the file
|
|
24
28
|
// directly in the MCP-client process (which runs on the operator's
|
|
25
29
|
// machine via the npm package). Reading + base64-encoding here means
|
|
@@ -840,8 +844,6 @@ export const TOOLS = [
|
|
|
840
844
|
const wsName = snapshot?.workspace?.name ?? "Your workspace";
|
|
841
845
|
const chatbot = snapshot?.chatbot ?? null;
|
|
842
846
|
const tier = snapshot?.tier ?? null;
|
|
843
|
-
const bookingInfo = snapshot?.booking ?? null;
|
|
844
|
-
const intakeInfo = snapshot?.intake ?? null;
|
|
845
847
|
if (!publicUrls.home || !publicUrls.book || !publicUrls.intake) {
|
|
846
848
|
throw new Error(
|
|
847
849
|
"Snapshot did not return public_urls (home/book/intake). Re-check the workspace.",
|
|
@@ -894,9 +896,8 @@ export const TOOLS = [
|
|
|
894
896
|
}
|
|
895
897
|
|
|
896
898
|
// Step 3: closing summary — formatted exactly the way Claude Code
|
|
897
|
-
// should paraphrase to the operator.
|
|
898
|
-
//
|
|
899
|
-
// section reflects the actual workspace shape.
|
|
899
|
+
// should paraphrase to the operator. Personality + pipeline are
|
|
900
|
+
// surfaced in the response payload (not the summary text).
|
|
900
901
|
const personality =
|
|
901
902
|
snapshot?.workspace?.settings?.crmPersonality ?? null;
|
|
902
903
|
const personalityLabel =
|
|
@@ -905,125 +906,15 @@ export const TOOLS = [
|
|
|
905
906
|
: null;
|
|
906
907
|
const pipelineStages = personality?.pipeline?.stages ?? [];
|
|
907
908
|
|
|
908
|
-
//
|
|
909
|
-
//
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
tier?.current_tier === "growth" || tier?.current_tier === "scale";
|
|
918
|
-
const isScale = tier?.current_tier === "scale";
|
|
919
|
-
|
|
920
|
-
const intakeFieldCount = intakeInfo?.field_count ?? 0;
|
|
921
|
-
const intakeTitle = intakeInfo?.title ?? "lead qualification";
|
|
922
|
-
|
|
923
|
-
const lines = [];
|
|
924
|
-
|
|
925
|
-
// Header
|
|
926
|
-
lines.push(`✅ ${wsName} — client OS shipped.`);
|
|
927
|
-
lines.push("");
|
|
928
|
-
lines.push("Your client's stack is wired and live:");
|
|
929
|
-
lines.push("");
|
|
930
|
-
|
|
931
|
-
// Public site
|
|
932
|
-
lines.push("🌐 Public site (paste a screenshot in your Slack)");
|
|
933
|
-
lines.push(` ${publicUrls.home}`);
|
|
934
|
-
lines.push("");
|
|
935
|
-
|
|
936
|
-
// Chatbot
|
|
937
|
-
if (chatbot && chatbot.embed_snippet) {
|
|
938
|
-
lines.push("🤖 AI chatbot — paste on the client's existing site (before </body>):");
|
|
939
|
-
lines.push(` ${chatbot.embed_snippet}`);
|
|
940
|
-
lines.push(
|
|
941
|
-
` In ${String(chatbot.status).toUpperCase()} mode. Powered by your Claude Code key (swap in settings).`,
|
|
942
|
-
);
|
|
943
|
-
lines.push(
|
|
944
|
-
` Publish live: publish_agent({ agent_id: "${chatbot.agent_id}", status: "live" })`,
|
|
945
|
-
);
|
|
946
|
-
} else {
|
|
947
|
-
lines.push("🤖 AI chatbot — scaffold pending. Retry:");
|
|
948
|
-
lines.push(` create_agent({ archetype: "website-chatbot", channel: "web_chat" })`);
|
|
949
|
-
}
|
|
950
|
-
lines.push("");
|
|
951
|
-
|
|
952
|
-
// Booking
|
|
953
|
-
lines.push("📋 Booking page (client's customers self-serve appointments)");
|
|
954
|
-
lines.push(` ${publicUrls.book}`);
|
|
955
|
-
lines.push("");
|
|
956
|
-
|
|
957
|
-
// Intake
|
|
958
|
-
lines.push(`📝 Intake form (${intakeFieldCount}-question ${intakeTitle})`);
|
|
959
|
-
lines.push(` ${publicUrls.intake}`);
|
|
960
|
-
lines.push("");
|
|
961
|
-
|
|
962
|
-
// Admin
|
|
963
|
-
lines.push("🔐 Your admin (CRM, pipeline, leads, deals)");
|
|
964
|
-
lines.push(` ${adminUrl}`);
|
|
965
|
-
lines.push("");
|
|
966
|
-
|
|
967
|
-
// Client portal
|
|
968
|
-
if (tier?.client_portal_url) {
|
|
969
|
-
lines.push("👥 Client portal (your client logs in here to see their leads + bookings)");
|
|
970
|
-
lines.push(` ${tier.client_portal_url}`);
|
|
971
|
-
if (isPaid) {
|
|
972
|
-
lines.push(` ✅ Active. Forward this URL to your client; they log in via magic email.`);
|
|
973
|
-
} else {
|
|
974
|
-
lines.push(` 🔒 Growth tier ($29/mo) unlocks this for your client. Preview it`);
|
|
975
|
-
lines.push(` yourself at the URL above right now.`);
|
|
976
|
-
}
|
|
977
|
-
lines.push("");
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
// What's wired
|
|
981
|
-
lines.push("What's wired:");
|
|
982
|
-
if (personalityLabel) {
|
|
983
|
-
const stageCount = pipelineStages.length;
|
|
984
|
-
lines.push(` • ${personalityLabel} personality • ${stageCount}-stage CRM pipeline`);
|
|
985
|
-
}
|
|
986
|
-
if (bookingInfo) {
|
|
987
|
-
lines.push(
|
|
988
|
-
` • ${bookingInfo.hours_summary} bookings, ${bookingInfo.duration_minutes}-min slots`,
|
|
989
|
-
);
|
|
990
|
-
}
|
|
991
|
-
if (intakeInfo) {
|
|
992
|
-
lines.push(` • ${intakeFieldCount}-question intake with ${intakeSpecialNote}`);
|
|
993
|
-
}
|
|
994
|
-
if (chatbot) {
|
|
995
|
-
lines.push(` • AI chatbot trained on the homepage (FAQ scaffold ready to refine)`);
|
|
996
|
-
}
|
|
997
|
-
lines.push(
|
|
998
|
-
emailSent
|
|
999
|
-
? ` • Welcome email + admin link sent to ${a.email}`
|
|
1000
|
-
: ` • Welcome email NOT yet sent (rerun finalize_workspace to retry)`,
|
|
1001
|
-
);
|
|
1002
|
-
lines.push("");
|
|
1003
|
-
|
|
1004
|
-
// What you can prompt next (5 agency-meaningful examples)
|
|
1005
|
-
lines.push("What you can prompt next:");
|
|
1006
|
-
lines.push(` • "Refine the chatbot FAQ from the site" → update_website_chatbot`);
|
|
1007
|
-
lines.push(` • "Add SMS missed-call-text-back automation" → install_archetype`);
|
|
1008
|
-
lines.push(` • "Customize the hero with the client's brand voice" → customize_block`);
|
|
1009
|
-
lines.push(` • "Wire Google Calendar so bookings sync" → connect_integration`);
|
|
1010
|
-
lines.push(` • "Add a Spanish version of the landing page" → clone_workspace + translate`);
|
|
1011
|
-
lines.push("");
|
|
1012
|
-
|
|
1013
|
-
// Tier ladder (omit on Scale tier)
|
|
1014
|
-
if (!isScale) {
|
|
1015
|
-
lines.push(`Tier ladder (you're on ${tierLabel}):`);
|
|
1016
|
-
lines.push(` Free → 1 client workspace, everything above wired`);
|
|
1017
|
-
lines.push(` Growth $29/mo → 3 workspaces, client portal goes live, custom domain`);
|
|
1018
|
-
lines.push(` (e.g. crm.youragency.com), SMS/email automations`);
|
|
1019
|
-
lines.push(` Scale $99/mo → unlimited workspaces, full white-label, reseller pricing`);
|
|
1020
|
-
lines.push("");
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
// Closer
|
|
1024
|
-
lines.push("Forward your client this admin link when ready. Or stay here and iterate.");
|
|
1025
|
-
|
|
1026
|
-
const summary = lines.join("\n");
|
|
909
|
+
// v1.55.0 — Ops-stack-only workspace creation. The summary is
|
|
910
|
+
// built by buildFinalizeSummary in ./finalize-summary.js; we
|
|
911
|
+
// pass the snapshot + duration + archetype here.
|
|
912
|
+
const aestheticArchetype = snapshot?.theme?.aestheticArchetype ?? null;
|
|
913
|
+
const summary = buildFinalizeSummary({
|
|
914
|
+
snapshot,
|
|
915
|
+
durationSec: 0, // smoke test reports actual duration via Vercel logs, not the summary text
|
|
916
|
+
aestheticArchetype,
|
|
917
|
+
});
|
|
1027
918
|
|
|
1028
919
|
return {
|
|
1029
920
|
ok: emailSent || leadRecorded,
|
|
@@ -1050,37 +941,52 @@ export const TOOLS = [
|
|
|
1050
941
|
lead_error: leadError,
|
|
1051
942
|
personality: personalityLabel,
|
|
1052
943
|
pipeline_stages: pipelineStages.map((s) => s?.name).filter(Boolean),
|
|
1053
|
-
//
|
|
944
|
+
// v1.55.0 — Ops-stack-first next-step ladder. Surfaces the
|
|
945
|
+
// chatbot-paste workflow + the 7 ready automations + the
|
|
946
|
+
// landing-page nudge so Claude Code can pick from a tight
|
|
947
|
+
// curated list rather than improvise tool calls.
|
|
1054
948
|
next_steps_available: [
|
|
1055
949
|
{
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
950
|
+
id: "deploy_chatbot_embed",
|
|
951
|
+
label: "Paste chatbot embed on client's existing site",
|
|
952
|
+
action: "user_action",
|
|
953
|
+
payload: {
|
|
954
|
+
snippet: chatbot?.embed_snippet ?? null,
|
|
955
|
+
target: snapshot?.workspace?.settings?.source_url ?? null,
|
|
956
|
+
},
|
|
1059
957
|
},
|
|
1060
958
|
{
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
959
|
+
id: "promote_chatbot_to_live",
|
|
960
|
+
label: "Promote chatbot from TEST to LIVE (when ready for production)",
|
|
961
|
+
action: "publish_agent",
|
|
962
|
+
payload: { agent_id: chatbot?.agent_id ?? null },
|
|
1064
963
|
},
|
|
1065
964
|
{
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
965
|
+
id: "activate_automation",
|
|
966
|
+
label: "Activate one of the 7 ready automations",
|
|
967
|
+
action: "open_dashboard",
|
|
968
|
+
payload: { url: snapshot?.ops_stack?.automations_url ?? null },
|
|
1069
969
|
},
|
|
1070
970
|
{
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
971
|
+
id: "configure_integration",
|
|
972
|
+
label: "Configure Twilio / Resend / Stripe for SMS / email / payments",
|
|
973
|
+
action: "claude_assisted",
|
|
974
|
+
payload: { available_providers: ["twilio", "resend", "stripe"] },
|
|
1074
975
|
},
|
|
1075
976
|
{
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
977
|
+
id: "build_landing_page",
|
|
978
|
+
label: "Build a landing page (uses landing-page-creation skill)",
|
|
979
|
+
action: "claude_assisted",
|
|
980
|
+
payload: {
|
|
981
|
+
skill: "landing-page-creation",
|
|
982
|
+
archetype: snapshot?.theme?.aestheticArchetype ?? null,
|
|
983
|
+
},
|
|
1079
984
|
},
|
|
1080
985
|
{
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
986
|
+
id: "customize_chatbot_faq",
|
|
987
|
+
label: "Refine the chatbot's FAQ from source site content",
|
|
988
|
+
action: "claude_assisted",
|
|
989
|
+
payload: { agent_id: chatbot?.agent_id ?? null },
|
|
1084
990
|
},
|
|
1085
991
|
],
|
|
1086
992
|
};
|