@edda-business/mcp 0.75.1 → 0.76.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 +62 -0
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -222,6 +222,9 @@ export function createServer() {
|
|
|
222
222
|
const label = String(c.predicate ?? "").replace(/[_:]/g, " ");
|
|
223
223
|
lines.push(`[claim] ${c.subject ? `${c.subject} · ` : ""}${label}${mark}${infer}: ${c.object}`);
|
|
224
224
|
lines.push(` as of ${String(c.as_of ?? "").slice(0, 10)} · evidence ${c.source?.kind}:${c.source?.id}`);
|
|
225
|
+
// The id is what opens the evidence. Without it the agent can repeat what the company
|
|
226
|
+
// believes and cannot say why — the gap explain_claim exists to close.
|
|
227
|
+
if (c.id) lines.push(` claim id: ${c.id} ← pass this to explain_claim`);
|
|
225
228
|
}
|
|
226
229
|
lines.push("");
|
|
227
230
|
}
|
|
@@ -245,6 +248,65 @@ export function createServer() {
|
|
|
245
248
|
},
|
|
246
249
|
);
|
|
247
250
|
|
|
251
|
+
// ===========================================================================
|
|
252
|
+
// TOOL: explain_claim — GET /v2/company/claims/:id/evidence
|
|
253
|
+
// "Why does Edda believe this?", for an agent. The browser has had this since EDDA-153; a seat
|
|
254
|
+
// could only repeat the claim.
|
|
255
|
+
// ===========================================================================
|
|
256
|
+
server.tool(
|
|
257
|
+
"explain_claim",
|
|
258
|
+
"WHY the company believes a claim: how firm it is, when it became true vs when Edda recorded " +
|
|
259
|
+
"it, the sources you may open, how it was approved, and what it replaced. Take the `claim id` " +
|
|
260
|
+
"from a search result. " +
|
|
261
|
+
"Use it before repeating a company fact that carries weight — a figure in a document you are " +
|
|
262
|
+
"drafting, anything a person will act on, or when a claim looks stale or surprising. " +
|
|
263
|
+
"Say what it says: if it reports no excerpt, the wording has NOT been checked against the " +
|
|
264
|
+
"source, and you must not present the claim as quoted. Never invent supporting text.",
|
|
265
|
+
{ claim_id: z.string().describe("The claim id, printed as `claim id:` in search results.") },
|
|
266
|
+
async ({ claim_id }) => {
|
|
267
|
+
try {
|
|
268
|
+
const r = await get(`/v2/company/claims/${encodeURIComponent(claim_id)}/evidence`);
|
|
269
|
+
const c = r?.claim ?? {};
|
|
270
|
+
const day = (d) => (d ? String(d).slice(0, 10) : "—");
|
|
271
|
+
const lines = [
|
|
272
|
+
`${c.subject?.name ? `${c.subject.name} · ` : ""}${String(c.predicate ?? "").replace(/[_:]/g, " ")}: ${c.object}`,
|
|
273
|
+
`standing: ${c.standing}${c.confidence === "inferred" ? " · inferred (read between the lines, not stated)" : ""} · ${c.state === "superseded" ? "NO LONGER CURRENT" : "current"}`,
|
|
274
|
+
`true as of ${day(c.as_of)} · recorded by Edda ${day(c.recorded_at)}`,
|
|
275
|
+
"",
|
|
276
|
+
];
|
|
277
|
+
lines.push(r?.excerpt?.text
|
|
278
|
+
? `Supporting passage (checked word for word against the source):\n "${r.excerpt.text}"`
|
|
279
|
+
: "Supporting passage: NONE RECORDED — the source below is where it came from, but nobody checked that it says this in these words. Do not quote it.");
|
|
280
|
+
if (r?.excerpt_rejected && !r?.excerpt?.text) lines.push(" (a quotation was proposed and was not found in the document, so it was dropped)");
|
|
281
|
+
lines.push("");
|
|
282
|
+
const sources = r?.sources ?? [];
|
|
283
|
+
lines.push(sources.length ? "Sources:" : "Sources: none you can open.");
|
|
284
|
+
for (const s of sources) {
|
|
285
|
+
if (s.available === false && s.reason === "missing") { lines.push(" · a cited document that no longer exists"); continue; }
|
|
286
|
+
lines.push(` · ${s.name}${s.primary ? " (primary)" : ""}${s.changed_since === true ? " — EDITED since this claim was recorded" : ""}`);
|
|
287
|
+
if (s.id) lines.push(` id: ${s.id} ← pass this to read`);
|
|
288
|
+
}
|
|
289
|
+
const a = r?.approval ?? {};
|
|
290
|
+
const who = (p) => p?.name || (p?.id ? "a team member" : null);
|
|
291
|
+
lines.push("", a.kind === "inbox_approval"
|
|
292
|
+
? `Approved in the Inbox${a.auto_filed ? " automatically" : ` by ${who(a.by) ?? "an admin"}`} on ${day(a.at)}${who(a.submitted_by) ? `, proposed by ${who(a.submitted_by)}` : ""}.`
|
|
293
|
+
: a.kind === "direct_write"
|
|
294
|
+
? `Written directly into the project's knowledge by ${who(a.by) ?? "an admin"} on ${day(a.at)}.`
|
|
295
|
+
: `Recorded ${day(a.at)}. No approval record exists.`);
|
|
296
|
+
const h = r?.history ?? {};
|
|
297
|
+
if (h.replaced?.length) lines.push(`Replaced: ${h.replaced.map((x) => `"${x.object}"`).join(", ")}`);
|
|
298
|
+
if (h.replaced_by?.length) lines.push(`Replaced by: ${h.replaced_by.map((x) => `"${x.object}"`).join(" → ")}`);
|
|
299
|
+
if (h.alongside?.length) lines.push(`Also current at a different standing: ${h.alongside.map((x) => `"${x.object}" (${x.standing})`).join(", ")}`);
|
|
300
|
+
return text(lines.join("\n"));
|
|
301
|
+
} catch (e) {
|
|
302
|
+
const msg = String(e?.message || e);
|
|
303
|
+
if (msg.includes("(404)")) return text("No such claim, or it is not one this seat may read. Claims about people and companies are admin-only for now.");
|
|
304
|
+
if (msg.includes("(403)")) return text("This seat cannot read company claims.");
|
|
305
|
+
throw e;
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
);
|
|
309
|
+
|
|
248
310
|
// ===========================================================================
|
|
249
311
|
// TOOL: read — GET /v2/company/pages/:id
|
|
250
312
|
// Read one full wiki page. Take the `path:` from a search result, or an id.
|