@opennous/mcp 0.61.0 → 0.63.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 +4 -3
  2. package/src/server.js +35 -15
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opennous/mcp",
3
- "version": "0.61.0",
4
- "description": "Nous the Context Graph for AI Agents.",
3
+ "version": "0.63.0",
4
+ "description": "Nous \u2014 the Context Graph for AI Agents.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -21,7 +21,8 @@
21
21
  "start": "node src/index.js",
22
22
  "dev:http": "node --watch src/http.js",
23
23
  "start:http": "node src/http.js",
24
- "typecheck": "echo 'no ts in mcp skipping'"
24
+ "typecheck": "echo 'no ts in mcp \u2014 skipping'",
25
+ "test": "node --test tests/*.test.mjs"
25
26
  },
26
27
  "keywords": [
27
28
  "mcp",
package/src/server.js CHANGED
@@ -29,7 +29,7 @@ const APP_URL = () => (process.env.NOUS_APP_URL || "https://app.opennous.cloud")
29
29
  const OAUTH_CONNECT = { gmail: "gmail", gmail_oauth: "gmail", google: "gmail", "google-mail": "gmail", googlemail: "gmail", linkedin: "linkedin" };
30
30
  const connectLink = (slug) => `${APP_URL()}/settings?section=integrations&connect=${slug}`;
31
31
 
32
- export const SERVER_VERSION = "0.60.0";
32
+ export const SERVER_VERSION = "0.62.0";
33
33
 
34
34
  // ─── helpers ──────────────────────────────────────────────────────────────────
35
35
 
@@ -91,6 +91,24 @@ const pct = (c) => `${Math.round((c ?? 0) * 100)}%`;
91
91
 
92
92
  // ─── factory ──────────────────────────────────────────────────────────────────
93
93
 
94
+ // A closed deal as the agent may supply it. A bare domain is the original shape and still
95
+ // works; the object form carries the money and the date, which the forecast needs. Widened
96
+ // rather than replaced so nothing that already calls this breaks.
97
+ //
98
+ // Module scope, not inside createServer(). It was declared below its own first use, and a
99
+ // `const` in the temporal dead zone throws on every request — the hosted server crashed on
100
+ // each call with "Cannot access 'CLOSED_DEAL' before initialization". Out here it is also
101
+ // built once instead of per request, since createServer() runs for every incoming call.
102
+ const CLOSED_DEAL = z.union([
103
+ z.string(),
104
+ z.object({
105
+ domain: z.string().describe("Company domain, e.g. 'acme.com' — no scheme."),
106
+ amount: z.number().optional().describe("Deal value in major units (48000, not 4800000)."),
107
+ currency: z.string().optional().describe("ISO code or symbol. Defaults to the workspace currency."),
108
+ closed_at: z.string().optional().describe("When it actually closed, ISO date. Drives every cycle-time measurement, so pass the real date rather than today's."),
109
+ }),
110
+ ]);
111
+
94
112
  export function createServer() {
95
113
  const server = new McpServer({
96
114
  name: "nous",
@@ -282,6 +300,17 @@ export function createServer() {
282
300
  lines.push(`ICP FIT: ${rec.icp.score}/100 — ${label}${rec.icp.reason ? ` (${rec.icp.reason})` : ""}`);
283
301
  lines.push("");
284
302
  }
303
+ if (rec.scorecard) {
304
+ // The latest call scorecard the app computed (Coaching v2). The after-call skill writes the
305
+ // coaching review out of THIS — it does not re-score. Each dimension carries its exact moment.
306
+ const sc = rec.scorecard;
307
+ lines.push(`LAST CALL SCORE: ${sc.overall}/100 · ${sc.next_step_secured ? "next step secured" : "no next step secured"}${sc.occurred_at ? ` (${relAge(sc.occurred_at)})` : ""}`);
308
+ for (const d of (sc.scores ?? [])) {
309
+ lines.push(` [${d.score}] ${d.label}${d.note ? ` — ${d.note}` : ""}`);
310
+ if (d.moment) lines.push(` "${d.moment}"`);
311
+ }
312
+ lines.push("");
313
+ }
285
314
  if (rec.facts?.length) {
286
315
  // Atomic memory — the durable, decision-relevant facts learned about them.
287
316
  lines.push(`FACTS (${rec.facts.length} — durable memory about them):`);
@@ -390,8 +419,12 @@ export function createServer() {
390
419
  "Insights about YOUR OWN business (product/positioning/market/buyer) go to record_insight, not here. " +
391
420
  "CLOSING THE LOOP — when you RECOMMEND an action, write the recommendation down before it happens: " +
392
421
  "{kind:'state',property:'decision.proposed',value:{decision_id:'<your id>',proposal:'send a follow-up " +
393
- "naming the security objection',rationale:'the security review is the real blocker at this stage', " +
422
+ "naming the security objection',proposal_body:'<the exact draft>',rationale:'the security review " +
423
+ "is the real blocker at this stage', " +
394
424
  "evidence_ids:['<claim/note id you reasoned from>'],action_type:'email_send',category:'outreach'}}. " +
425
+ "`proposal_body` is the draft itself — hashed and discarded, never stored, and the only way to tell " +
426
+ "later whether the human sent it as written or rewrote it first. Omit it and the decision reports as " +
427
+ "sent-verbatim whatever happened. " +
395
428
  "Keep `proposal` (WHAT you are doing) apart from `rationale` (WHY you think it works), and list the " +
396
429
  "facts you actually reasoned from in `evidence_ids` — that is what lets Nous learn which KINDS of " +
397
430
  "evidence are worth acting on, not just which actions worked. When the human answers, " +
@@ -745,19 +778,6 @@ export function createServer() {
745
778
 
746
779
 
747
780
 
748
- // ===========================================================================
749
- // A closed deal as the agent may supply it. A bare domain is the original shape and still
750
- // works; the object form carries the money and the date, which the forecast needs. Widened
751
- // rather than replaced so nothing that already calls this breaks.
752
- const CLOSED_DEAL = z.union([
753
- z.string(),
754
- z.object({
755
- domain: z.string().describe("Company domain, e.g. 'acme.com' — no scheme."),
756
- amount: z.number().optional().describe("Deal value in major units (48000, not 4800000)."),
757
- currency: z.string().optional().describe("ISO code or symbol. Defaults to the workspace currency."),
758
- closed_at: z.string().optional().describe("When it actually closed, ISO date. Drives every cycle-time measurement, so pass the real date rather than today's."),
759
- }),
760
- ]);
761
781
 
762
782
 
763
783