@opennous/mcp 0.22.0 → 0.24.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/server.js +32 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opennous/mcp",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Nous MCP Server — Customer graph for GTM agents.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
package/src/server.js CHANGED
@@ -37,7 +37,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
37
37
  import { z } from "zod";
38
38
  import { get, post } from "./client.js";
39
39
 
40
- export const SERVER_VERSION = "0.22.0";
40
+ export const SERVER_VERSION = "0.24.0";
41
41
 
42
42
  // ─── helpers ──────────────────────────────────────────────────────────────────
43
43
 
@@ -506,13 +506,21 @@ export function createServer() {
506
506
  // ===========================================================================
507
507
  server.tool(
508
508
  "get_workspace_status",
509
- "See the whole setup state of this workspace in one call and what to set up next. Nous is " +
510
- "operated by you, the agent, not by a human clicking through the app: call this at the start of " +
511
- "a session to learn whether the workspace is onboarded, whether the GTM playbook (ICP model) is " +
512
- "built, which integrations are connected, whether CRM sync is configured, and whether webhooks/" +
513
- "triggers are live. Returns a ranked NEXT STEPS list walk the user through whatever is missing " +
514
- "(onboard them with set_workspace_profile, build the playbook with update_gtm_profile, connect " +
515
- "their tools). Use this before offering to set anything up.",
509
+ "See the whole setup state of this workspace in one call, and what to do next. Nous is operated " +
510
+ "by you, the agent: call this at the start of a session. It returns a ranked NEXT STEPS list — " +
511
+ "walk the user through it top-down. The onboarding sequence, in order: " +
512
+ "(1) profile (set_workspace_profile); " +
513
+ "(2) connect core channelsGmail/email, LinkedIn, and a meeting note-taker (Fireflies/Fathom/" +
514
+ "Calendly); (3) connect enrichment/outbound (Prospeo/Apollo/Instantly); (4) set up webhooks for " +
515
+ "the connected tools so their events flow in; (5) import first records (CSV from the CRM) on the " +
516
+ "Accounts page, then backfill enrichment; (6) build the GTM playbook (update_gtm_profile + " +
517
+ "build_scoring_model, asking for closed-won/lost domains). " +
518
+ "KNOW THE CONSTRAINTS: Gmail uses Google OAuth and LinkedIn has NO public API (Nous connects it " +
519
+ "natively via Unipile) — you CANNOT connect those yourself; tell the user to set them up on the " +
520
+ "Integrations page. Key-based tools (Prospeo, Apollo, Instantly, HubSpot token) you CAN connect " +
521
+ "with connect_integration. CSV import and CRM-page actions are done by the user in the app — guide " +
522
+ "them. Respect PLAN: never push a feature the plan doesn't include (e.g. CRM sync on free). " +
523
+ "Recommend, don't dump — surface the next 1-2 steps, not all of them at once.",
516
524
  {},
517
525
  async () => {
518
526
  const s = await get("/v2/workspace/status");
@@ -521,6 +529,8 @@ export function createServer() {
521
529
 
522
530
  const ws = s.workspace ?? {};
523
531
  lines.push(`WORKSPACE: ${ws.name || "(unnamed)"}${ws.website ? ` · ${ws.website}` : ""}${ws.business_type ? ` · ${ws.business_type}` : ""}`);
532
+ const pl = s.plan ?? {};
533
+ lines.push(`PLAN: ${pl.name || pl.id || "free"}${pl.crm_sync === false ? " (CRM sync not included — do not offer it)" : ""}`);
524
534
  lines.push("");
525
535
 
526
536
  const mark = (b) => (b ? "✓" : "✗");
@@ -530,9 +540,18 @@ export function createServer() {
530
540
  const ints = setup.integrations?.connected ?? [];
531
541
  lines.push(` ${mark((setup.integrations?.count ?? 0) > 0)} Integrations (${setup.integrations?.count ?? 0})${ints.length ? `: ${ints.map((i) => i.name).join(", ")}` : ""}`);
532
542
  const crm = setup.crm_sync ?? {};
533
- lines.push(` ${mark(crm.configured)} CRM sync${crm.configured ? `: ${(crm.providers ?? []).map((p) => p.provider).join(", ")}` : ""}${crm.pending_hygiene_proposals ? ` · ${crm.pending_hygiene_proposals} hygiene proposal(s) to review` : ""}`);
543
+ if (crm.available === false) {
544
+ lines.push(` – CRM sync (not on the ${pl.name || pl.id || "current"} plan)`);
545
+ } else {
546
+ lines.push(` ${mark(crm.configured)} CRM sync${crm.configured ? `: ${(crm.providers ?? []).map((p) => p.provider).join(", ")}` : ""}${crm.pending_hygiene_proposals ? ` · ${crm.pending_hygiene_proposals} hygiene proposal(s) to review` : ""}`);
547
+ }
534
548
  lines.push(` ${mark(setup.enrichment?.connected)} Enrichment${setup.enrichment?.provider ? `: ${setup.enrichment.provider}` : ""}`);
535
549
  lines.push(` ${mark((setup.webhooks?.count ?? 0) > 0 || (setup.triggers?.count ?? 0) > 0)} Events — ${setup.webhooks?.count ?? 0} webhook(s), ${setup.triggers?.count ?? 0} trigger(s)`);
550
+ const rec = setup.recommended ?? {};
551
+ lines.push("");
552
+ lines.push("RECOMMENDED CHANNELS (connect these first):");
553
+ lines.push(` ${mark(rec.email)} Email / Gmail ${mark(rec.linkedin)} LinkedIn ${mark(rec.meeting_notetaker)} Meeting note-taker`);
554
+ lines.push(` Records imported: ${setup.records?.count ?? 0}`);
536
555
 
537
556
  if (s.next_steps?.length) {
538
557
  lines.push("");
@@ -607,7 +626,10 @@ export function createServer() {
607
626
  "update_gtm_profile, then call this to translate that context into a weighted set of scoring " +
608
627
  "signals so accounts get scored for fit. If a model already exists it is left alone unless you " +
609
628
  "pass force:true (use that when the GTM context has changed and the model should be rebuilt). If " +
610
- "it reports no GTM context yet, record some with update_gtm_profile first, then call this again.",
629
+ "it reports no GTM context yet, record some with update_gtm_profile first, then call this again. " +
630
+ "When building the playbook during onboarding, also ASK the user for a few closed-WON customer " +
631
+ "domains and closed-LOST domains — real outcomes sharpen the ICP. Record them with update_gtm_profile " +
632
+ "(e.g. section 'ICP': 'Closed-won: acme.com, globex.com; closed-lost: tinyco.io') so the model reflects who actually buys.",
611
633
  {
612
634
  force: z.boolean().optional()
613
635
  .describe("Rebuild the model even if one already exists — use when the GTM context has changed."),