@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.
- package/package.json +4 -3
- package/src/server.js +35 -15
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opennous/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Nous
|
|
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
|
|
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.
|
|
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
|
|
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
|
|