@opennous/mcp 0.21.0 → 0.22.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 +43 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opennous/mcp",
3
- "version": "0.21.0",
3
+ "version": "0.22.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
@@ -30,13 +30,14 @@
30
30
  * list_triggers — list the workspace's event triggers + available events
31
31
  * lead_list_operations — the operations trail of a lead list (imports/enrich/push/replies), filterable
32
32
  * check_leads — pre-spend coverage check: which candidates you already own / should re-enrich
33
+ * lead_coverage — attribute coverage estimate ("how many agency founders do we have, by freshness")
33
34
  */
34
35
 
35
36
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
36
37
  import { z } from "zod";
37
38
  import { get, post } from "./client.js";
38
39
 
39
- export const SERVER_VERSION = "0.21.0";
40
+ export const SERVER_VERSION = "0.22.0";
40
41
 
41
42
  // ─── helpers ──────────────────────────────────────────────────────────────────
42
43
 
@@ -867,5 +868,46 @@ export function createServer() {
867
868
  }
868
869
  );
869
870
 
871
+ // ===========================================================================
872
+ // TOOL: lead_coverage — GET /v2/people/coverage
873
+ // The attribute-based planning check: "how many <agency founders> do we already
874
+ // have, and how fresh?" — answered WITHOUT pasting identifiers. Use it before
875
+ // building a list elsewhere to see how much you already cover.
876
+ // ===========================================================================
877
+ server.tool(
878
+ "lead_coverage",
879
+ "Estimate how many people you ALREADY have matching a role/keyword, bucketed by enrichment " +
880
+ "freshness — the planning question before building a list (no identifiers to paste). E.g. " +
881
+ "title='founder', keyword='agency' → how many agency founders are already in your workspace, " +
882
+ "how many were never enriched or are stale (>90d, so re-enrich), and how many have a fresh " +
883
+ "verified email. Rough by design (title is precise; keyword matches title/company/department). " +
884
+ "For an exact net-new check against specific candidates, use check_leads with their identifiers.",
885
+ {
886
+ title: z.string().optional().describe("Role match, e.g. 'founder', 'VP Sales' (matches job_title)."),
887
+ keyword: z.string().optional().describe("Extra match across title/company/department, e.g. 'agency'."),
888
+ stale_days: z.number().optional().describe("Days after which enrichment counts as stale (default 90)."),
889
+ },
890
+ async ({ title, keyword, stale_days }) => {
891
+ if (!title && !keyword) {
892
+ return { content: [{ type: "text", text: "Pass a title and/or keyword, e.g. title='founder', keyword='agency'." }] };
893
+ }
894
+ const r = await get("/v2/people/coverage", { title, keyword, stale_days });
895
+ const lines = [
896
+ `COVERAGE — ${[title && `title~"${title}"`, keyword && `keyword~"${keyword}"`].filter(Boolean).join(" + ")}`,
897
+ ` ${r.total ?? 0} already in your workspace`,
898
+ ` ${r.needs_enrichment ?? 0} need (re-)enrichment (${r.never_enriched ?? 0} never enriched · ${r.stale ?? 0} stale >90d)`,
899
+ ` ${r.fresh_verified ?? 0} have a fresh verified email`,
900
+ ];
901
+ const sample = r.sample || [];
902
+ if (sample.length) {
903
+ lines.push("", "SAMPLE (oldest first):");
904
+ for (const s of sample.slice(0, 12)) {
905
+ lines.push(` ${[s.job_title, s.company].filter(Boolean).join(" @ ") || s.entity_id} [${s.enriched_at ? `enriched ${relAge(s.enriched_at)}` : "never enriched"}]`);
906
+ }
907
+ }
908
+ return { content: [{ type: "text", text: lines.join("\n") }] };
909
+ }
910
+ );
911
+
870
912
  return server;
871
913
  }