@seldonframe/mcp 1.52.0 → 1.53.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tools.js +151 -58
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seldonframe/mcp",
3
- "version": "1.52.0",
3
+ "version": "1.53.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",
package/src/tools.js CHANGED
@@ -804,7 +804,8 @@ export const TOOLS = [
804
804
  "ONE-CALL CLOSING WRAPPER for the workspace creation flow. Bundles email collection (welcome email + lead capture via collect_operator_email) AND produces the final operator-facing summary (live URLs, what's configured, admin link). " +
805
805
  "Call this as the LAST step of every workspace creation. After create_workspace returns, ask the user 'What email should I use for your account? This is where you'll get your login link and any notifications.' Then call this tool with the email they give you. Returns a `summary` string Claude Code should paraphrase verbatim to the operator. " +
806
806
  "Use this instead of calling collect_operator_email directly when you want a single tool call to close the loop. Skipping this is the same as skipping email collection — leaves the operator with a one-shot URL and no recovery path. " +
807
- "Example: finalize_workspace({ email: 'max@precisionplumbing.com', name: 'Max' })",
807
+ "Example: finalize_workspace({ email: 'max@precisionplumbing.com', name: 'Max' }). " +
808
+ "The summary is agency-voice: addresses the operator AS an agency delivering for their SMB client, not as the workspace owner. When relaying to the operator, preserve the 'your client' framing throughout — don't rewrite to 'your workspace'.",
808
809
  inputSchema: obj(
809
810
  {
810
811
  email: str("Operator email — used as the welcome email recipient AND as the unique key for the SeldonFrame CRM lead."),
@@ -837,6 +838,10 @@ export const TOOLS = [
837
838
  const publicUrls = snapshot?.public_urls ?? {};
838
839
  const slug = snapshot?.workspace?.slug ?? null;
839
840
  const wsName = snapshot?.workspace?.name ?? "Your workspace";
841
+ const chatbot = snapshot?.chatbot ?? null;
842
+ const tier = snapshot?.tier ?? null;
843
+ const bookingInfo = snapshot?.booking ?? null;
844
+ const intakeInfo = snapshot?.intake ?? null;
840
845
  if (!publicUrls.home || !publicUrls.book || !publicUrls.intake) {
841
846
  throw new Error(
842
847
  "Snapshot did not return public_urls (home/book/intake). Re-check the workspace.",
@@ -900,65 +905,144 @@ export const TOOLS = [
900
905
  : null;
901
906
  const pipelineStages = personality?.pipeline?.stages ?? [];
902
907
 
903
- const lines = [
904
- `✅ ${wsName}'s Business OS is live.`,
905
- "",
906
- emailSent
907
- ? `📧 Welcome email sent to ${a.email}`
908
- : `⚠️ Welcome email NOT sent${emailError ? ` (${emailError})` : ""} — please retry collect_operator_email.`,
909
- "",
910
- "🌐 Public URLs:",
911
- ` • Website: ${publicUrls.home}`,
912
- ` • Booking: ${publicUrls.book}`,
913
- ` • Intake: ${publicUrls.intake}`,
914
- "",
915
- "🔐 Admin dashboard:",
916
- ` ${adminUrl}`,
917
- "",
918
- "What's configured:",
919
- ];
908
+ // 2026-05-15 Agency-voice product moment summary. See spec
909
+ // docs/superpowers/specs/2026-05-15-agency-output-product-moment-design.md
910
+ const intakeSpecialNote =
911
+ personality?.vertical === "hvac" || personality?.vertical === "plumbing"
912
+ ? "emergency-line fallback"
913
+ : "structured lead-qualification";
914
+
915
+ const tierLabel = tier?.current_tier_label ?? "Free";
916
+ const isPaid =
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:");
920
982
  if (personalityLabel) {
921
- lines.push(` • CRM personality: ${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
+ );
922
990
  }
923
- if (pipelineStages.length > 0) {
924
- const stageNames = pipelineStages
925
- .map((s) => s?.name)
926
- .filter(Boolean)
927
- .join(" ");
928
- lines.push(` • Pipeline: ${stageNames}`);
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)`);
929
996
  }
930
- lines.push(` • Booking page, intake form, CRM, AI agents — all live`);
931
997
  lines.push(
932
998
  emailSent
933
- ? ` • Welcome email sent, onboarding started`
934
- : ` • Welcome email NOT yet sent (rerun finalize_workspace to retry)`
999
+ ? ` • Welcome email + admin link sent to ${a.email}`
1000
+ : ` • Welcome email NOT yet sent (rerun finalize_workspace to retry)`,
935
1001
  );
936
- // v1.34.0 — Brief, optional next-step menu surfaced AFTER the
937
- // operator's site is live. We don't lecture; we just list what's
938
- // available. Claude Code reads this and decides whether to mention
939
- // any of it based on the conversation vibe (e.g. user says
940
- // "perfect, ship it" → skip; user says "can it look more
941
- // impressive?" → call apply_motion_preset).
942
1002
  lines.push("");
943
- lines.push("Optional upgrades (when you're ready):");
944
- lines.push(` • Tune motion: apply_motion_preset({ preset: "subtle" | "balanced" | "editorial" | "minimal" })`);
945
- lines.push(` • Apply your brand kit: apply_design_md({ design_md_content }) if you have a DESIGN.md`);
946
- lines.push(` Import a Claude Design handoff: import_claude_design_handoff({ bundle })`);
947
- lines.push(` • Add real content: describe your services, pricing, FAQs in plain English`);
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
+
948
1026
  const summary = lines.join("\n");
949
1027
 
950
1028
  return {
951
1029
  ok: emailSent || leadRecorded,
952
1030
  summary,
953
- workspace: {
954
- id: workspaceId,
955
- name: wsName,
956
- slug,
957
- },
1031
+ workspace: { id: workspaceId, name: wsName, slug },
958
1032
  website_url: publicUrls.home,
959
1033
  booking_url: publicUrls.book,
960
1034
  intake_url: publicUrls.intake,
961
1035
  admin_url: adminUrl,
1036
+ // NEW (2026-05-15): chatbot + tier surfacing
1037
+ chatbot_agent_id: chatbot?.agent_id ?? null,
1038
+ chatbot_embed_url: chatbot?.embed_url ?? null,
1039
+ chatbot_embed_snippet: chatbot?.embed_snippet ?? null,
1040
+ chatbot_status: chatbot?.status ?? null,
1041
+ client_portal_url: tier?.client_portal_url ?? null,
1042
+ client_portal_status: tier?.client_portal_status ?? null,
1043
+ current_tier: tier?.current_tier ?? "free",
1044
+ tier_features: tier?.tier_features ?? null,
1045
+ // Existing email/lead fields
962
1046
  email_sent: emailSent,
963
1047
  email_error: emailError,
964
1048
  lead_recorded: leadRecorded,
@@ -966,28 +1050,37 @@ export const TOOLS = [
966
1050
  lead_error: leadError,
967
1051
  personality: personalityLabel,
968
1052
  pipeline_stages: pipelineStages.map((s) => s?.name).filter(Boolean),
969
- // v1.34.0Structured options Claude Code can reason about
970
- // without parsing the human-facing summary string.
1053
+ // 2026-05-15agency-meaningful next-step examples
971
1054
  next_steps_available: [
972
1055
  {
973
- action: "apply_motion_preset",
974
- when: "operator says 'make it feel more premium', 'tone down animation', etc.",
975
- example: 'apply_motion_preset({ preset: "editorial" })',
1056
+ action: "publish_agent",
1057
+ when: "operator has reviewed the chatbot and is ready to take it live for the client's website",
1058
+ example: `publish_agent({ agent_id: "${chatbot?.agent_id ?? "ag_..."}", status: "live" })`,
1059
+ },
1060
+ {
1061
+ action: "update_website_chatbot",
1062
+ when: "operator wants to refine the chatbot's FAQ before publishing",
1063
+ example: `update_website_chatbot({ workspace_id, faq: [{ q: '...', a: '...' }] })`,
1064
+ },
1065
+ {
1066
+ action: "install_archetype",
1067
+ when: "operator wants to wire pre-built automations (missed-call-text-back, speed-to-lead, review-requester)",
1068
+ example: `install_archetype({ archetype: "missed-call-text-back" })`,
976
1069
  },
977
1070
  {
978
- action: "apply_design_md",
979
- when: "operator has a DESIGN.md file with their brand tokens",
980
- example: "apply_design_md({ design_md_content: <file content> })",
1071
+ action: "customize_block",
1072
+ when: "operator wants to refine landing-page hero / services / FAQ with brand voice",
1073
+ example: `customize_block({ workspace_id, block_name: "hero", prompt: "make this feel more premium" })`,
981
1074
  },
982
1075
  {
983
- action: "import_claude_design_handoff",
984
- when: "operator just exported components from Claude Design",
985
- example: "import_claude_design_handoff({ bundle: <bundle JSON> })",
1076
+ action: "connect_integration",
1077
+ when: "operator wants Google Calendar sync, Stripe payments, Twilio SMS",
1078
+ example: `connect_integration({ workspace_id, provider: "google_calendar" })`,
986
1079
  },
987
1080
  {
988
- action: "update_landing_content / configure_booking / customize_intake_form",
989
- when: "operator wants to update specific page content, prices, services",
990
- example: "(see get_workspace_state for the full surface map)",
1081
+ action: "configure_llm_provider",
1082
+ when: "operator wants to swap from the default Claude Code key to a different Anthropic key",
1083
+ example: `configure_llm_provider({ workspace_id, provider: "anthropic", api_key: "sk-ant-..." })`,
991
1084
  },
992
1085
  ],
993
1086
  };