@suveren/gateway 0.34.0 → 0.35.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/content/integrations/erp.json +75 -8
- package/content/integrations/gmail.json +8 -1
- package/content/integrations/mail.json +9 -2
- package/content/integrations/mollie.json +8 -0
- package/dist/control-plane/index.mjs +79 -0
- package/dist/mcp-server/http.mjs +841 -98
- package/dist/ui/assets/index-M1sLTJjt.js +123 -0
- package/dist/ui/assets/{index-BiGnI2Tk.css → index-c8cmIEPx.css} +1 -1
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/profiles/email/0.9.profile.json +252 -0
- package/profiles/index.json +2 -1
- package/dist/ui/assets/index-DKBwi4Yw.js +0 -123
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"icon": "briefcase",
|
|
7
7
|
"profile": "sales",
|
|
8
8
|
"npmPackage": "@humanagencyp/erp-mcp",
|
|
9
|
-
"npmVersion": "0.
|
|
9
|
+
"npmVersion": "0.9.0",
|
|
10
10
|
"mcp": {
|
|
11
11
|
"command": "erp-mcp",
|
|
12
12
|
"args": [],
|
|
@@ -27,11 +27,35 @@
|
|
|
27
27
|
"type": "text",
|
|
28
28
|
"placeholder": "simulation (default) — live needs an adapter for your ERP",
|
|
29
29
|
"optional": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"key": "liveAdapter",
|
|
33
|
+
"label": "Live adapter (optional)",
|
|
34
|
+
"type": "text",
|
|
35
|
+
"placeholder": "local — your own company's invoicing. Leave empty unless Mode is \"live\"",
|
|
36
|
+
"optional": true
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"key": "companyFile",
|
|
40
|
+
"label": "Company data file (optional)",
|
|
41
|
+
"type": "text",
|
|
42
|
+
"placeholder": "Path to your company file (name, address, UID, bank, VAT mode) — required when the live adapter is \"local\"",
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"key": "invoiceTemplate",
|
|
47
|
+
"label": "Invoice template (optional)",
|
|
48
|
+
"type": "text",
|
|
49
|
+
"placeholder": "Path to an invoice template file — leave empty for the bundled German template",
|
|
50
|
+
"optional": true
|
|
30
51
|
}
|
|
31
52
|
],
|
|
32
53
|
"envMapping": {
|
|
33
54
|
"DATABASE_URL": "databaseUrl",
|
|
34
|
-
"ERP_MODE": "mode"
|
|
55
|
+
"ERP_MODE": "mode",
|
|
56
|
+
"ERP_LIVE_ADAPTER": "liveAdapter",
|
|
57
|
+
"ERP_LIVE_COMPANY_FILE": "companyFile",
|
|
58
|
+
"ERP_INVOICE_TEMPLATE": "invoiceTemplate"
|
|
35
59
|
}
|
|
36
60
|
},
|
|
37
61
|
"simulation": {
|
|
@@ -40,6 +64,18 @@
|
|
|
40
64
|
},
|
|
41
65
|
"personalDefault": true,
|
|
42
66
|
"oauth": null,
|
|
67
|
+
"documents": {
|
|
68
|
+
"invoice-pdf": {
|
|
69
|
+
"tool": "get_document",
|
|
70
|
+
"args": { "kind": "invoice-pdf", "id": "$id" },
|
|
71
|
+
"label": "issued invoice {id}"
|
|
72
|
+
},
|
|
73
|
+
"credit-note-pdf": {
|
|
74
|
+
"tool": "get_document",
|
|
75
|
+
"args": { "kind": "credit-note-pdf", "id": "$id" },
|
|
76
|
+
"label": "issued credit note {id}"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
43
79
|
"context": {
|
|
44
80
|
"recordKeys": {
|
|
45
81
|
"customer": {
|
|
@@ -202,7 +238,7 @@
|
|
|
202
238
|
},
|
|
203
239
|
"create_invoice": {
|
|
204
240
|
"profile": "invoicing",
|
|
205
|
-
"summary": "Invoice of {net_total|money} net to {customer_id}[ for order {order_id}]",
|
|
241
|
+
"summary": "Invoice[ {number}] of {net_total|money} net to {customer_id}[ for order {order_id}]",
|
|
206
242
|
"executionMapping": {
|
|
207
243
|
"net_total": "net_total",
|
|
208
244
|
"currency": "currency"
|
|
@@ -213,15 +249,33 @@
|
|
|
213
249
|
"actionLabel": "Invoice issued",
|
|
214
250
|
"contextKeys": { "customer": "customer_id" },
|
|
215
251
|
"preview": [
|
|
216
|
-
{ "tool": "get_customer", "args": { "id": "customer_id" }, "attach": "customer_id" }
|
|
252
|
+
{ "tool": "get_customer", "args": { "id": "customer_id" }, "attach": "customer_id" },
|
|
253
|
+
{
|
|
254
|
+
"tool": "preview_invoice",
|
|
255
|
+
"args": {
|
|
256
|
+
"customer_id": "customer_id",
|
|
257
|
+
"number": "number",
|
|
258
|
+
"document_date": "document_date",
|
|
259
|
+
"service_period": "service_period",
|
|
260
|
+
"lines": "lines",
|
|
261
|
+
"net_total": "net_total",
|
|
262
|
+
"currency": "currency",
|
|
263
|
+
"payment_term_days": "payment_term_days",
|
|
264
|
+
"memo": "memo"
|
|
265
|
+
},
|
|
266
|
+
"kind": "document"
|
|
267
|
+
}
|
|
217
268
|
],
|
|
218
269
|
"display": {
|
|
219
|
-
"order": ["customer_id", "order_id", "lines", "net_total", "currency", "payment_term_days", "memo"],
|
|
270
|
+
"order": ["customer_id", "order_id", "number", "document_date", "service_period", "lines", "net_total", "currency", "payment_term_days", "memo"],
|
|
220
271
|
"money": ["net_total", "customer_id.credit_limit", "customer_id.open_balance", "customer_id.available_credit"],
|
|
221
272
|
"currencyField": "currency",
|
|
222
273
|
"labels": {
|
|
223
274
|
"customer_id": "Customer",
|
|
224
275
|
"order_id": "Order",
|
|
276
|
+
"number": "Invoice number",
|
|
277
|
+
"document_date": "Invoice date",
|
|
278
|
+
"service_period": "Service period",
|
|
225
279
|
"net_total": "Total (net)",
|
|
226
280
|
"payment_term_days": "Payment terms (days)",
|
|
227
281
|
"memo": "Memo",
|
|
@@ -233,7 +287,7 @@
|
|
|
233
287
|
},
|
|
234
288
|
"create_credit_note": {
|
|
235
289
|
"profile": "invoicing",
|
|
236
|
-
"summary": "Credit note of {credit_total|money} net for invoice {invoice_id}: {reason|short}",
|
|
290
|
+
"summary": "Credit note[ {number}] of {credit_total|money} net for invoice {invoice_id}: {reason|short}",
|
|
237
291
|
"executionMapping": {
|
|
238
292
|
"credit_total": "credit_total",
|
|
239
293
|
"currency": "currency"
|
|
@@ -248,16 +302,29 @@
|
|
|
248
302
|
"fields": ["number", "customer_id", "net_total", "currency", "status"]
|
|
249
303
|
},
|
|
250
304
|
"display": {
|
|
251
|
-
"order": ["invoice_id", "credit_total", "currency", "reason", "lines"],
|
|
305
|
+
"order": ["invoice_id", "number", "document_date", "credit_total", "currency", "reason", "service_period", "lines"],
|
|
252
306
|
"money": ["credit_total"],
|
|
253
307
|
"currencyField": "currency",
|
|
254
308
|
"labels": {
|
|
255
309
|
"invoice_id": "Invoice",
|
|
310
|
+
"number": "Credit note number",
|
|
311
|
+
"document_date": "Credit note date",
|
|
256
312
|
"credit_total": "Total (net)",
|
|
257
|
-
"reason": "Reason"
|
|
313
|
+
"reason": "Reason",
|
|
314
|
+
"service_period": "Service period"
|
|
258
315
|
}
|
|
259
316
|
}
|
|
260
317
|
},
|
|
318
|
+
"preview_invoice": {
|
|
319
|
+
"profile": "invoicing",
|
|
320
|
+
"category": "read",
|
|
321
|
+
"internal": true
|
|
322
|
+
},
|
|
323
|
+
"get_document": {
|
|
324
|
+
"profile": "invoicing",
|
|
325
|
+
"category": "read",
|
|
326
|
+
"internal": true
|
|
327
|
+
},
|
|
261
328
|
"list_invoices": {
|
|
262
329
|
"profile": "invoicing",
|
|
263
330
|
"category": "read",
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"REFRESH_TOKEN": "refreshToken"
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
|
+
"attachments": {
|
|
42
|
+
"transport": "mime-raw",
|
|
43
|
+
"arg": "raw"
|
|
44
|
+
},
|
|
41
45
|
"context": {
|
|
42
46
|
"sources": {
|
|
43
47
|
"message": {
|
|
@@ -106,7 +110,10 @@
|
|
|
106
110
|
"argEncoding": {
|
|
107
111
|
"subject": "rfc2047"
|
|
108
112
|
},
|
|
109
|
-
"actionLabel": "Email sent"
|
|
113
|
+
"actionLabel": "Email sent",
|
|
114
|
+
"attachmentsArg": "attachments",
|
|
115
|
+
"insertFields": ["body"],
|
|
116
|
+
"display": { "aiText": "body" }
|
|
110
117
|
},
|
|
111
118
|
"create_draft": {
|
|
112
119
|
"summary": "Draft email to {to|list}[: {subject|short}]",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"icon": "mail",
|
|
7
7
|
"profile": "email",
|
|
8
8
|
"npmPackage": "@humanagencyp/email-mcp",
|
|
9
|
-
"npmVersion": "0.
|
|
9
|
+
"npmVersion": "0.4.0",
|
|
10
10
|
"readPolicy": {
|
|
11
11
|
"defaultAgeDays": 30
|
|
12
12
|
},
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
},
|
|
43
43
|
"personalDefault": false,
|
|
44
44
|
"oauth": null,
|
|
45
|
+
"attachments": {
|
|
46
|
+
"transport": "field",
|
|
47
|
+
"arg": "attachments"
|
|
48
|
+
},
|
|
45
49
|
"context": {
|
|
46
50
|
"sources": {
|
|
47
51
|
"message": {
|
|
@@ -101,7 +105,10 @@
|
|
|
101
105
|
},
|
|
102
106
|
"actionLabel": "Email sent",
|
|
103
107
|
"sourceFromArg": { "kind": "message", "arg": "in_reply_to" },
|
|
104
|
-
"contextKeys": { "email": "to" }
|
|
108
|
+
"contextKeys": { "email": "to" },
|
|
109
|
+
"attachmentsArg": "attachments",
|
|
110
|
+
"insertFields": ["body"],
|
|
111
|
+
"display": { "aiText": "body" }
|
|
105
112
|
},
|
|
106
113
|
"load_simulation": {
|
|
107
114
|
"executionMapping": {},
|
|
@@ -29,6 +29,14 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"oauth": null,
|
|
32
|
+
"values": {
|
|
33
|
+
"payment-link": {
|
|
34
|
+
"tool": "GetPaymentLink",
|
|
35
|
+
"args": { "paymentLinkId": "$id" },
|
|
36
|
+
"path": "_links.paymentLink.href",
|
|
37
|
+
"allowedHosts": ["payment-links.mollie.com"]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
32
40
|
"toolGating": {
|
|
33
41
|
"default": {
|
|
34
42
|
"executionMapping": {},
|
|
@@ -759,6 +759,25 @@ async function getToolRequestContext(data) {
|
|
|
759
759
|
clearTimeout(timeout);
|
|
760
760
|
}
|
|
761
761
|
}
|
|
762
|
+
async function getAttachmentPreview(ref) {
|
|
763
|
+
const controller = new AbortController();
|
|
764
|
+
const timeout = setTimeout(() => controller.abort(), 12e3);
|
|
765
|
+
try {
|
|
766
|
+
const res = await fetch(`${MCP_BASE}/internal/document-preview`, {
|
|
767
|
+
method: "POST",
|
|
768
|
+
headers: internalHeaders(),
|
|
769
|
+
body: JSON.stringify(ref),
|
|
770
|
+
signal: controller.signal
|
|
771
|
+
});
|
|
772
|
+
if (!res.ok) {
|
|
773
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
774
|
+
throw new Error(`MCP document-preview failed: ${err.error ?? res.status}`);
|
|
775
|
+
}
|
|
776
|
+
return res.json();
|
|
777
|
+
} finally {
|
|
778
|
+
clearTimeout(timeout);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
762
781
|
async function getAgentContact() {
|
|
763
782
|
const res = await fetch(`${MCP_BASE}/internal/agent-contact`, {
|
|
764
783
|
headers: internalHeaders()
|
|
@@ -3713,6 +3732,24 @@ function createEvidenceExportRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2)
|
|
|
3713
3732
|
// src/routes/proposal-preview.ts
|
|
3714
3733
|
import { Router as Router10 } from "express";
|
|
3715
3734
|
|
|
3735
|
+
// src/lib/attachment-preview-types.ts
|
|
3736
|
+
var ATTACHMENTS_SEALED_META_KEY = "_attachmentsSealed";
|
|
3737
|
+
function findSealedAttachment(toolArgs, sha256) {
|
|
3738
|
+
if (!toolArgs) return null;
|
|
3739
|
+
const raw = toolArgs[ATTACHMENTS_SEALED_META_KEY];
|
|
3740
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
3741
|
+
const attachments = raw.attachments;
|
|
3742
|
+
if (!Array.isArray(attachments)) return null;
|
|
3743
|
+
for (const a of attachments) {
|
|
3744
|
+
if (a === null || typeof a !== "object") continue;
|
|
3745
|
+
const r = a;
|
|
3746
|
+
if (r.sha256 === sha256 && typeof r.connector === "string" && typeof r.kind === "string" && typeof r.id === "string") {
|
|
3747
|
+
return { connector: r.connector, kind: r.kind, id: r.id, sha256 };
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
return null;
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3716
3753
|
// src/lib/content-crypto.ts
|
|
3717
3754
|
import { createHash as createHash5 } from "crypto";
|
|
3718
3755
|
import { canonicalize as canonicalize3 } from "@hap/core";
|
|
@@ -3911,6 +3948,23 @@ function createProposalStatusRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2,
|
|
|
3911
3948
|
res.status(502).json({ error: `MCP server unavailable: ${err instanceof Error ? err.message : String(err)}` });
|
|
3912
3949
|
}
|
|
3913
3950
|
});
|
|
3951
|
+
router.get("/:id/attachment-preview/:sha256", async (req, res) => {
|
|
3952
|
+
const proposalId = req.params.id;
|
|
3953
|
+
const sha256 = req.params.sha256;
|
|
3954
|
+
const resolved = await resolveProposalToolArgsForRoute(spUrl, vault2, dataDir, lockAsTlsMismatch2, proposalId, res);
|
|
3955
|
+
if (!resolved) return;
|
|
3956
|
+
const ref = findSealedAttachment(resolved.toolArgs, sha256);
|
|
3957
|
+
if (!ref) {
|
|
3958
|
+
res.status(404).json({ status: "error", message: "No sealed attachment with this fingerprint on this proposal." });
|
|
3959
|
+
return;
|
|
3960
|
+
}
|
|
3961
|
+
try {
|
|
3962
|
+
const result = await getAttachmentPreview(ref);
|
|
3963
|
+
res.json(result);
|
|
3964
|
+
} catch (err) {
|
|
3965
|
+
res.status(502).json({ status: "error", message: `MCP server unavailable: ${err instanceof Error ? err.message : String(err)}` });
|
|
3966
|
+
}
|
|
3967
|
+
});
|
|
3914
3968
|
router.get("/:id/request-context", async (req, res) => {
|
|
3915
3969
|
const proposalId = req.params.id;
|
|
3916
3970
|
const resolved = await resolveProposalToolArgsForRoute(spUrl, vault2, dataDir, lockAsTlsMismatch2, proposalId, res);
|
|
@@ -4138,6 +4192,31 @@ function createEvidenceRouter() {
|
|
|
4138
4192
|
});
|
|
4139
4193
|
}
|
|
4140
4194
|
});
|
|
4195
|
+
router.get("/receipt/:id/attachment-preview/:sha256", async (req, res) => {
|
|
4196
|
+
const id = String(req.params.id);
|
|
4197
|
+
const sha256 = String(req.params.sha256);
|
|
4198
|
+
try {
|
|
4199
|
+
const evidence = await getLocalEvidence();
|
|
4200
|
+
const entry = (evidence.receipts ?? []).find(
|
|
4201
|
+
(r) => r.receipt?.id === id
|
|
4202
|
+
);
|
|
4203
|
+
if (!entry) {
|
|
4204
|
+
res.status(404).json({ status: "error", message: "No local copy of this receipt" });
|
|
4205
|
+
return;
|
|
4206
|
+
}
|
|
4207
|
+
const e = entry;
|
|
4208
|
+
const candidate = e.sentArgs ?? e.proposal?.toolArgs ?? (e.boundContent && typeof e.boundContent === "object" && !Array.isArray(e.boundContent) ? e.boundContent : void 0);
|
|
4209
|
+
const ref = findSealedAttachment(candidate, sha256);
|
|
4210
|
+
if (!ref) {
|
|
4211
|
+
res.status(404).json({ status: "error", message: "No sealed attachment with this fingerprint on this ticket." });
|
|
4212
|
+
return;
|
|
4213
|
+
}
|
|
4214
|
+
const result = await getAttachmentPreview(ref);
|
|
4215
|
+
res.json(result);
|
|
4216
|
+
} catch (err) {
|
|
4217
|
+
res.status(502).json({ status: "error", message: `MCP server unavailable: ${err instanceof Error ? err.message : String(err)}` });
|
|
4218
|
+
}
|
|
4219
|
+
});
|
|
4141
4220
|
router.get("/headlines", async (_req, res) => {
|
|
4142
4221
|
try {
|
|
4143
4222
|
res.json({ headlines: await getTicketHeadlines() });
|