@edda-business/mcp 0.73.0 → 0.75.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 +29 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edda-business/mcp",
3
- "version": "0.73.0",
3
+ "version": "0.75.0",
4
4
  "description": "Edda — the company data layer for AI agents.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
package/src/server.js CHANGED
@@ -128,6 +128,28 @@ async function uploadLocalFile(filePath, { sourceId } = {}) {
128
128
  return { originalId: r?.original?.id ?? null, name, sha256, bytes: r?.original?.byte_size ?? bytes.length };
129
129
  }
130
130
 
131
+ // A submit-only seat has no `inbox` tool, so the submit response is the ONLY place it can learn
132
+ // what happened to anything it sent. Render it there or the loop never closes.
133
+ function loopLines(r) {
134
+ const out = [];
135
+ const d = r?.recent_decisions;
136
+ if (d && d.total) {
137
+ const bits = [];
138
+ if (d.filed) bits.push(`${d.filed} filed`);
139
+ if (d.rejected) bits.push(`${d.rejected} rejected`);
140
+ out.push("", `Since ${String(d.since).slice(0, 10)}, of what you sent: ${bits.join(", ") || `${d.total} decided`}.`);
141
+ for (const e of d.examples ?? []) {
142
+ out.push(e.status === "rejected"
143
+ ? ` ✗ ${e.name} — rejected${e.reason ? ` — ${e.reason}` : " (no reason given)"}`
144
+ : ` ✓ ${e.name} → ${e.location}`);
145
+ }
146
+ }
147
+ if (typeof r?.pending_mine === "number" && r.pending_mine > 0) {
148
+ out.push(`${r.pending_mine} of your submissions ${r.pending_mine === 1 ? "is" : "are"} still waiting for review.`);
149
+ }
150
+ return out;
151
+ }
152
+
131
153
  export function createServer() {
132
154
  // EfB seat boundary: with EDDA_MCP_READONLY set (the flag Hermes EfB box profiles use),
133
155
  // the personal agent gets EXACTLY search + read — the write tools (push/update/create) are
@@ -362,6 +384,7 @@ export function createServer() {
362
384
  subject_kind: z.enum(["project", "person", "company", "page"]).optional().describe("Default project — the project this is filed into."),
363
385
  subject_id: z.string().optional().describe("Only when the subject is NOT the destination project."),
364
386
  confidence: z.enum(["stated", "inferred"]).optional().describe("stated = the source says it outright; inferred = you read it between the lines."),
387
+ excerpt: z.string().max(600).optional().describe("A short passage copied WORD FOR WORD from the document that supports this claim (one or two sentences). Shown to people as the evidence. It is kept only if it is actually found in the filed document; never paraphrase."),
365
388
  })).optional().describe(
366
389
  "What this material CHANGES about what the company believes — the point of sharing an update rather than a document. " +
367
390
  "'The term sheet arrived and Tom is unhappy with it' is not a document, it is two claims. " +
@@ -388,10 +411,11 @@ export function createServer() {
388
411
  const n = Array.isArray(claims) ? claims.length : 0;
389
412
  // Say what is waiting, including the belief change — the person needs to know a claim is
390
413
  // pending a human decision, not quietly applied.
391
- return text(
414
+ return text([
392
415
  `Staged "${name}" into the company Inbox (${rc?.location ?? "Inbox"}). The company will route it to the right folder on the next reconcile.`
393
416
  + (n ? `\n${n} proposed knowledge update${n === 1 ? "" : "s"} rides with it — shown in the review gate as a belief change and applied only on approval.` : ""),
394
- );
417
+ ...loopLines(r),
418
+ ].join("\n"));
395
419
  } catch (e) {
396
420
  const msg = String(e?.message || e);
397
421
  if (msg.includes("read_only") || msg.includes("admins_only") || msg.includes("(403)")) return text("This seat is read-only on the company Edda, so it can search and read but not contribute. Ask an admin for a write role.");
@@ -439,6 +463,7 @@ export function createServer() {
439
463
  subject_kind: z.enum(["project", "person", "company", "page"]).optional(),
440
464
  subject_id: z.string().optional(),
441
465
  confidence: z.enum(["stated", "inferred"]).optional(),
466
+ excerpt: z.string().max(600).optional().describe("A short passage copied WORD FOR WORD from the document that supports this claim (one or two sentences). Shown to people as the evidence. It is kept only if it is actually found in the filed document; never paraphrase."),
442
467
  })).optional().describe("What THIS item changes about what the company believes."),
443
468
  })).max(100).describe("The items from one ingest run."),
444
469
  },
@@ -469,6 +494,7 @@ export function createServer() {
469
494
  else if (rec.suggestion_dropped) lines.push(` • ${rec.name} — staged; your suggested destination was dropped (not visible to you)`);
470
495
  }
471
496
  lines.push("", "They wait for a person to review and file them. Nothing has been placed in a project yet.");
497
+ lines.push(...loopLines(r));
472
498
  return text(lines.join("\n"));
473
499
  } catch (e) {
474
500
  const msg = String(e?.message || e);
@@ -507,6 +533,7 @@ export function createServer() {
507
533
  standing: z.enum(["committed", "reported", "indicative", "contested"]).optional().describe("committed = signed/agreed/done · reported = a source states it · indicative = non-binding, draft, conditional · contested = disputed. A weaker claim never retires a firmer one."),
508
534
  as_of: z.string().optional().describe("When it became TRUE (YYYY-MM-DD), not when you learned it."),
509
535
  confidence: z.enum(["stated", "inferred"]).optional(),
536
+ excerpt: z.string().max(600).optional().describe("A short passage copied WORD FOR WORD from one of the cited source_refs documents that supports this claim. Kept only if found in that document; never paraphrase."),
510
537
  })).max(25).describe("The beliefs that changed. One per fact — do not pack two facts into one sentence."),
511
538
  source_refs: z.array(z.object({
512
539
  kind: z.enum(["company_file", "river_original", "river_receipt"]),