@opennous/mcp 0.50.0 → 0.51.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 +39 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opennous/mcp",
3
- "version": "0.50.0",
3
+ "version": "0.51.0",
4
4
  "description": "Nous — the Context Graph for AI Agents.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/server.js CHANGED
@@ -16,7 +16,7 @@
16
16
  * search_notes · list_notes · get_foundation · get_insights
17
17
  * WRITE record · record_signal · save_note · propose_vault_file · merge_contacts ·
18
18
  * sync_foundation
19
- * ACT send_linkedin_message
19
+ * ACT draft_email · send_linkedin_message
20
20
  * CORRECT retract_observation · delete_note · unmerge_contacts
21
21
  * RUN get_workspace_status · whoami · list_integrations · set_workspace_profile ·
22
22
  * build_icp_model · train_icp_model · sync_icp · export_icp_model ·
@@ -28,7 +28,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
28
28
  import { z } from "zod";
29
29
  import { get, post, del } from "./client.js";
30
30
 
31
- export const SERVER_VERSION = "0.50.0";
31
+ export const SERVER_VERSION = "0.51.0";
32
32
 
33
33
  // ─── helpers ──────────────────────────────────────────────────────────────────
34
34
 
@@ -1639,6 +1639,43 @@ export function createServer() {
1639
1639
  }
1640
1640
  );
1641
1641
 
1642
+ server.tool(
1643
+ "draft_email",
1644
+ "DRAFT a follow-up email for the operator to review and SEND themselves — you draft, they send. " +
1645
+ "This does NOT send: it puts a card in front of the operator with To / Subject / Body and a Send " +
1646
+ "button; the email goes out from THEIR OWN Gmail, in their name, only when they click send. Use it " +
1647
+ "whenever the ask is to email, follow up by email, send a recap, or reply by email. Identify the " +
1648
+ "recipient with `focus` (their email, LinkedIn URL, entity id, or name); the recipient address is " +
1649
+ "read off the record unless you pass `to`. Write a real `subject` and `body` in the operator's " +
1650
+ "voice — real paragraphs, no placeholders or [brackets] — and give the `rationale`, the one line " +
1651
+ "they judge the draft against. For a LinkedIn-only contact with no email, use send_linkedin_message.",
1652
+ {
1653
+ focus: z.string().describe("The recipient — email, LinkedIn URL, entity UUID, or name."),
1654
+ subject: z.string().describe("The email subject line."),
1655
+ body: z.string().min(1).describe("The email body, in the operator's voice. Real paragraphs, no placeholders."),
1656
+ to: z.string().optional().describe("Override the recipient email address (else the entity's best email on record is used)."),
1657
+ rationale: z.string().optional().describe("One line on what the draft is based on — shown to the operator on the card."),
1658
+ },
1659
+ async ({ focus, subject, body, to, rationale }) => {
1660
+ try {
1661
+ const r = await post("/v2/drafts/email", { focus, subject, body, to, rationale });
1662
+ if (r.status === "ambiguous") {
1663
+ const opts = (r.candidates ?? []).map(c => ` • ${c.name ?? "(unnamed)"} [${c.entity_id}]`).join("\n");
1664
+ return { content: [{ type: "text", text: `"${focus}" matches several people. Re-call draft_email with one of these entity ids as focus:\n${opts}` }] };
1665
+ }
1666
+ return { content: [{ type: "text", text:
1667
+ `Email draft ready for ${r.recipient} <${r.to}> — it's in front of the operator to review and send from their own Gmail. You have not sent it.` }] };
1668
+ } catch (e) {
1669
+ const msg = /no_email/.test(e.message)
1670
+ ? "No email on file for that person. Ask the operator for the address (pass it as `to`), or draft a LinkedIn message instead."
1671
+ : /entity_not_found/.test(e.message)
1672
+ ? "Couldn't find that recipient on the record — check the focus identifier."
1673
+ : `Couldn't create the draft: ${e.message}`;
1674
+ return { content: [{ type: "text", text: msg }] };
1675
+ }
1676
+ }
1677
+ );
1678
+
1642
1679
  // ===========================================================================
1643
1680
  // TOOLS: the CORRECTION layer — unsay something recorded by mistake. `record` and
1644
1681
  // `save_note` are how you write; these are how you take it back. Both heal the