@opennous/mcp 0.42.0 → 0.43.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 +1 -1
- package/src/server.js +74 -11
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -89,9 +89,9 @@ const pct = (c) => `${Math.round((c ?? 0) * 100)}%`;
|
|
|
89
89
|
// Gong/Granola). Returned by get_routing_preferences; the agent writes it into
|
|
90
90
|
// the user's CLAUDE.md (Claude Code) or the user pastes it into claude.ai org
|
|
91
91
|
// preferences. Mirrors the Install page's "short" version.
|
|
92
|
-
const ROUTING_PREFERENCES = `# Nous is this workspace's
|
|
92
|
+
const ROUTING_PREFERENCES = `# Nous is this workspace's GTM context graph
|
|
93
93
|
|
|
94
|
-
Nous is our
|
|
94
|
+
Nous is our context graph for GTM. It resolves every person, conversation, and
|
|
95
95
|
touchpoint across our GTM tool stack into one account record, with each fact's
|
|
96
96
|
confidence and freshness, the full interaction timeline, a 0-100 ICP fit score on
|
|
97
97
|
every account, plus our own ICP, positioning, and pricing. Agents read engineered
|
|
@@ -249,11 +249,27 @@ export function createServer() {
|
|
|
249
249
|
"get_account",
|
|
250
250
|
"Get the full account record for a person or company — the durable FACTS we've learned about them " +
|
|
251
251
|
"(their atomic memory: budget, authority, pain, stack, plans), every attribute (claim) with its " +
|
|
252
|
-
"confidence and freshness, plus
|
|
253
|
-
"
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
"confidence and freshness, plus what they actually SAID and did, ranked by how much it tells you. " +
|
|
253
|
+
"Pass an email or entity UUID, and the intent you're working toward so the record is shaped for it.",
|
|
254
|
+
{
|
|
255
|
+
id: z.string().describe("Email address or entity UUID"),
|
|
256
|
+
intent: z
|
|
257
|
+
.enum(["meeting_prep", "call_prep", "account_review", "follow_up", "draft_email"])
|
|
258
|
+
.optional()
|
|
259
|
+
.describe(
|
|
260
|
+
"What you're about to do. Shapes how much of their history comes back: a meeting brief wants " +
|
|
261
|
+
"the conversation in detail, an email draft wants one hook. Defaults to account_review.",
|
|
262
|
+
),
|
|
263
|
+
},
|
|
264
|
+
async ({ id, intent }) => {
|
|
265
|
+
// Ask for the RANKED record, not the raw one.
|
|
266
|
+
//
|
|
267
|
+
// The timeline this tool used to print was chronological and contentless —
|
|
268
|
+
// "3d ago email_sent" — which tells an agent that something happened and
|
|
269
|
+
// nothing about what. Ranked activity carries the source and the substance,
|
|
270
|
+
// so the model reads what was actually said instead of a list of event names.
|
|
271
|
+
const q = new URLSearchParams({ intent: intent ?? "account_review", compress: "1" });
|
|
272
|
+
const rec = await get(`/v2/accounts/${encodeURIComponent(id)}?${q}`);
|
|
257
273
|
const lines = [`${rec.type} · ${rec.entity_id}`, ""];
|
|
258
274
|
|
|
259
275
|
if (rec.icp) {
|
|
@@ -275,13 +291,37 @@ export function createServer() {
|
|
|
275
291
|
}
|
|
276
292
|
lines.push("");
|
|
277
293
|
}
|
|
278
|
-
|
|
279
|
-
|
|
294
|
+
// What they actually said and did — the most telling first, each with the
|
|
295
|
+
// system it came from, so a claim in the answer can always be traced back.
|
|
296
|
+
const activity = rec.key_activity ?? [];
|
|
297
|
+
if (activity.length) {
|
|
298
|
+
lines.push(`WHAT HAPPENED (${activity.length} most telling):`);
|
|
299
|
+
for (const a of activity) {
|
|
300
|
+
const when = a.when ? relAge(a.when) : "";
|
|
301
|
+
const head = ` ${a.what}${a.source ? ` · ${a.source}` : ""}${when ? ` · ${when}` : ""}`;
|
|
302
|
+
lines.push(a.detail ? `${head}\n ${a.detail}` : head);
|
|
303
|
+
}
|
|
304
|
+
lines.push("");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Say what was left out, and why. An agent that is handed 18 of 300
|
|
308
|
+
// interactions and does not know it will happily conclude that nothing else
|
|
309
|
+
// ever happened.
|
|
310
|
+
const sum = rec.activity_summary;
|
|
311
|
+
if (sum?.note) lines.push(sum.note);
|
|
312
|
+
else if (sum?.total_observations) {
|
|
313
|
+
lines.push(`${sum.total_observations} interactions on record.`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Fall back to the raw timeline if an older API didn't rank anything.
|
|
317
|
+
if (!activity.length && rec.recent_observations?.length) {
|
|
318
|
+
const obs = rec.recent_observations;
|
|
280
319
|
lines.push(`TIMELINE (${obs.length}):`);
|
|
281
320
|
for (const o of obs.slice(0, 30)) {
|
|
282
321
|
lines.push(` ${whenLabel(o.property, o.observed_at)} ${fmtType(o.property)}`);
|
|
283
322
|
}
|
|
284
323
|
}
|
|
324
|
+
|
|
285
325
|
return { content: [{ type: "text", text: lines.join("\n").trim() }] };
|
|
286
326
|
}
|
|
287
327
|
);
|
|
@@ -507,9 +547,15 @@ export function createServer() {
|
|
|
507
547
|
return { content: [{ type: "text", text: "Nothing needs attention right now." }] };
|
|
508
548
|
}
|
|
509
549
|
// Upcoming meetings carry a `when` — render the absolute local date+time.
|
|
550
|
+
//
|
|
551
|
+
// Each item also names where it came from: the calendar holding the call, the
|
|
552
|
+
// transcript the promise was captured from. An agent that can cite the call
|
|
553
|
+
// someone made a promise ON is making an argument; one that just asserts the
|
|
554
|
+
// promise is asking to be trusted.
|
|
510
555
|
const lines = r.items.map(it => {
|
|
511
556
|
const when = it.when ? `${fmtWhen(it.when)} — ` : "";
|
|
512
|
-
|
|
557
|
+
const from = it.source ? ` [${it.source}]` : "";
|
|
558
|
+
return ` ${when}${it.entity_name ?? it.entity_id} — ${it.what}${from}\n → ${it.suggested_action}`;
|
|
513
559
|
});
|
|
514
560
|
return { content: [{ type: "text", text: `Needs attention (${r.items.length}):\n${lines.join("\n")}` }] };
|
|
515
561
|
}
|
|
@@ -638,6 +684,11 @@ export function createServer() {
|
|
|
638
684
|
"whenever you edit a policy file in the repo (e.g. references/voice.md, outreach rules), passing the " +
|
|
639
685
|
"file's new content and its path, so Nous mirrors it and every other agent obeys the same rules. An " +
|
|
640
686
|
"edited playbook file that isn't synced is silently inert — other agents keep reading the old rules. " +
|
|
687
|
+
"MIRROR, DO NOT REWRITE: when the user already has a playbook file, sync it AS-IS. Their file is the " +
|
|
688
|
+
"author and Nous is the mirror — always pass file_path so the next sync knows where an in-app edit " +
|
|
689
|
+
"lands. 'Improving' their wording on the way through means the copy in Nous silently disagrees with " +
|
|
690
|
+
"the copy in their repo, and they will trust neither. If a file looks wrong, SAY SO; don't fix it in " +
|
|
691
|
+
"transit. " +
|
|
641
692
|
"(For the ICP/context files specifically, sync_icp is the sync — use that one.)",
|
|
642
693
|
syncPlaybookSchema, syncPlaybookHandler);
|
|
643
694
|
|
|
@@ -752,7 +803,19 @@ export function createServer() {
|
|
|
752
803
|
|
|
753
804
|
const mark = (b) => (b ? "✓" : "✗");
|
|
754
805
|
lines.push("SETUP:");
|
|
755
|
-
|
|
806
|
+
// The ICP first, because it IS the gate — a workspace without one is not set up, no
|
|
807
|
+
// matter how many integrations are green. If it's mirrored from a file in their repo,
|
|
808
|
+
// say so and say where: that file is the author, and editing anything else is a way of
|
|
809
|
+
// losing their work on the next sync.
|
|
810
|
+
const icp = setup.icp ?? {};
|
|
811
|
+
lines.push(
|
|
812
|
+
` ${mark(icp.done)} ICP${icp.done
|
|
813
|
+
? (icp.source === "claude_code" && icp.file_path
|
|
814
|
+
? ` — mirrored from ${icp.file_path} (their repo is the author; edit the FILE, then sync)`
|
|
815
|
+
: " — authored in Nous")
|
|
816
|
+
: " — MISSING. The workspace is not set up until this exists. Scan their repo before you ask them anything."}`
|
|
817
|
+
);
|
|
818
|
+
lines.push(` ${mark(setup.onboarding?.done)} Profile${setup.onboarding?.done ? "" : ` — missing ${(setup.onboarding?.missing ?? []).join(", ") || "details"}`}`);
|
|
756
819
|
lines.push(` ${mark(setup.gtm_playbook?.done)} GTM playbook${setup.gtm_playbook?.model ? " (scoring model live)" : ""}${setup.gtm_playbook?.stale_facts ? ` · ${setup.gtm_playbook.stale_facts} stale fact(s)` : ""}`);
|
|
757
820
|
if (setup.icp_sync) {
|
|
758
821
|
const sy = setup.icp_sync;
|