@edda-business/mcp 0.67.0 → 0.68.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 +42 -6
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -278,6 +278,36 @@ export function createServer() {
|
|
|
278
278
|
},
|
|
279
279
|
);
|
|
280
280
|
|
|
281
|
+
// ===========================================================================
|
|
282
|
+
// TOOL: inbox — GET /v2/company/inbox
|
|
283
|
+
// The waiting room the agent-run ingest reads (Decision Log 2026-09-04: the agent is
|
|
284
|
+
// the analyst; the app is the filing clerk).
|
|
285
|
+
// ===========================================================================
|
|
286
|
+
server.tool(
|
|
287
|
+
"inbox",
|
|
288
|
+
"LIST what is waiting in the company Inbox — each staged item with its id, submitter, the " +
|
|
289
|
+
"submitter's suggested destination (if any), and a content preview. This is the start of the " +
|
|
290
|
+
"company ingest: read each item (use `read` for the full text if the preview is not enough), " +
|
|
291
|
+
"decide where it belongs among the real projects, then file it with " +
|
|
292
|
+
"reconcile { stagingId, path }. Admin/ambassador only.",
|
|
293
|
+
{},
|
|
294
|
+
async () => {
|
|
295
|
+
try {
|
|
296
|
+
const r = await get("/v2/company/inbox");
|
|
297
|
+
const pending = r?.pending ?? [];
|
|
298
|
+
if (!pending.length) return text("The company Inbox is empty — nothing waiting.");
|
|
299
|
+
const lines = pending.map((f) =>
|
|
300
|
+
`• ${f.name} (stagingId: ${f.id})\n staged ${String(f.created_at).slice(0, 10)}` +
|
|
301
|
+
`${f.suggested ? ` · suggested: ${f.suggested}` : ""}\n ${String(f.preview || "").replace(/\s+/g, " ").slice(0, 240)}`);
|
|
302
|
+
return text(`${pending.length} item(s) waiting in the company Inbox:\n\n${lines.join("\n\n")}`);
|
|
303
|
+
} catch (e) {
|
|
304
|
+
const msg = String(e?.message || e);
|
|
305
|
+
if (msg.includes("admins_only") || msg.includes("(403)")) return text("Only an admin or ambassador can read the company Inbox.");
|
|
306
|
+
throw e;
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
);
|
|
310
|
+
|
|
281
311
|
// ===========================================================================
|
|
282
312
|
// TOOL: reconcile — POST /v2/company/river/reconcile
|
|
283
313
|
// Process the company Edda's Inbox: the River classifies + places each staged item into the
|
|
@@ -285,14 +315,20 @@ export function createServer() {
|
|
|
285
315
|
// ===========================================================================
|
|
286
316
|
server.tool(
|
|
287
317
|
"reconcile",
|
|
288
|
-
"PROCESS the company Inbox
|
|
289
|
-
"
|
|
290
|
-
"
|
|
318
|
+
"PROCESS the company Inbox. Two modes. (1) Sweep: no arguments — the company auto-files items " +
|
|
319
|
+
"with a clear destination and leaves ambiguous ones waiting. (2) ANALYZED FILING — the ingest " +
|
|
320
|
+
"flow: list waiting items with `inbox`, read and analyze each one, then call this with that " +
|
|
321
|
+
"item's `stagingId` AND an explicit `path` (e.g. 'Projects/Whitehay AI/Working Documents') to " +
|
|
322
|
+
"file it exactly there. YOU are the analyst; the company only files what you tell it. " +
|
|
291
323
|
"Returns where each item landed.",
|
|
292
|
-
{
|
|
293
|
-
|
|
324
|
+
{
|
|
325
|
+
stagingId: z.string().optional().describe("Id of one staged item to file (from an `inbox` row or a submit receipt). Omit to sweep the whole Inbox."),
|
|
326
|
+
path: z.string().optional().describe("Explicit destination folder path for THAT item (requires stagingId). Missing folders are created."),
|
|
327
|
+
},
|
|
328
|
+
async ({ stagingId, path }) => {
|
|
294
329
|
try {
|
|
295
|
-
|
|
330
|
+
if (path && !stagingId) return text("An explicit `path` files ONE analyzed item — pass its stagingId too.");
|
|
331
|
+
const r = await post("/v2/company/river/reconcile", { stagingId, forcePath: path });
|
|
296
332
|
const receipts = r?.receipts ?? [];
|
|
297
333
|
if (!receipts.length) return text("Nothing waiting in the company Inbox.");
|
|
298
334
|
const lines = receipts.map((x) => ` ${x.filed ? "✓ filed" : x.status} → ${x.location}${x.audience && x.audience !== "company" ? ` [${x.audience}]` : ""} (${x.reason})`);
|