@suveren/gateway 0.34.0 → 0.35.1
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/crm.json +18 -2
- package/content/integrations/erp.json +83 -8
- package/content/integrations/gmail.json +8 -1
- package/content/integrations/mail.json +13 -3
- package/content/integrations/mollie.json +8 -0
- package/dist/control-plane/index.mjs +79 -0
- package/dist/mcp-server/http.mjs +944 -117
- package/dist/ui/assets/index-BHxzXFpf.js +123 -0
- package/dist/ui/assets/{index-BiGnI2Tk.css → index-XiOgY6b5.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": "users",
|
|
7
7
|
"profile": "customers",
|
|
8
8
|
"npmPackage": "@humanagencyp/crm-mcp",
|
|
9
|
-
"npmVersion": "1.
|
|
9
|
+
"npmVersion": "1.6.0",
|
|
10
10
|
"mcp": {
|
|
11
11
|
"command": "crm-mcp",
|
|
12
12
|
"args": []
|
|
@@ -26,17 +26,33 @@
|
|
|
26
26
|
"type": "text",
|
|
27
27
|
"placeholder": "simulation (default) — live needs an adapter for your CRM",
|
|
28
28
|
"optional": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"key": "liveAdapter",
|
|
32
|
+
"label": "Live adapter (optional)",
|
|
33
|
+
"type": "text",
|
|
34
|
+
"placeholder": "local — your own company's CRM data. Leave empty unless Mode is \"live\"",
|
|
35
|
+
"optional": true
|
|
29
36
|
}
|
|
30
37
|
],
|
|
31
38
|
"envMapping": {
|
|
32
39
|
"DATABASE_URL": "databaseUrl",
|
|
33
|
-
"CRM_MODE": "mode"
|
|
40
|
+
"CRM_MODE": "mode",
|
|
41
|
+
"CRM_LIVE_ADAPTER": "liveAdapter"
|
|
34
42
|
}
|
|
35
43
|
},
|
|
36
44
|
"simulation": {
|
|
37
45
|
"field": "mode",
|
|
38
46
|
"default": "simulation"
|
|
39
47
|
},
|
|
48
|
+
"modeLabels": {
|
|
49
|
+
"simulation": "Test data",
|
|
50
|
+
"live": { "local": "Local" }
|
|
51
|
+
},
|
|
52
|
+
"modeNotes": {
|
|
53
|
+
"live": { "local": "On this computer — no shared access" }
|
|
54
|
+
},
|
|
55
|
+
"adapterField": "liveAdapter",
|
|
40
56
|
"personalDefault": true,
|
|
41
57
|
"oauth": null,
|
|
42
58
|
"context": {
|
|
@@ -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.1",
|
|
10
10
|
"mcp": {
|
|
11
11
|
"command": "erp-mcp",
|
|
12
12
|
"args": [],
|
|
@@ -27,19 +27,63 @@
|
|
|
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": {
|
|
38
62
|
"field": "mode",
|
|
39
63
|
"default": "simulation"
|
|
40
64
|
},
|
|
65
|
+
"modeLabels": {
|
|
66
|
+
"simulation": "Test data",
|
|
67
|
+
"live": { "local": "Local" }
|
|
68
|
+
},
|
|
69
|
+
"modeNotes": {
|
|
70
|
+
"live": { "local": "On this computer — no shared access" }
|
|
71
|
+
},
|
|
72
|
+
"adapterField": "liveAdapter",
|
|
41
73
|
"personalDefault": true,
|
|
42
74
|
"oauth": null,
|
|
75
|
+
"documents": {
|
|
76
|
+
"invoice-pdf": {
|
|
77
|
+
"tool": "get_document",
|
|
78
|
+
"args": { "kind": "invoice-pdf", "id": "$id" },
|
|
79
|
+
"label": "issued invoice {id}"
|
|
80
|
+
},
|
|
81
|
+
"credit-note-pdf": {
|
|
82
|
+
"tool": "get_document",
|
|
83
|
+
"args": { "kind": "credit-note-pdf", "id": "$id" },
|
|
84
|
+
"label": "issued credit note {id}"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
43
87
|
"context": {
|
|
44
88
|
"recordKeys": {
|
|
45
89
|
"customer": {
|
|
@@ -202,7 +246,7 @@
|
|
|
202
246
|
},
|
|
203
247
|
"create_invoice": {
|
|
204
248
|
"profile": "invoicing",
|
|
205
|
-
"summary": "Invoice of {net_total|money} net to {customer_id}[ for order {order_id}]",
|
|
249
|
+
"summary": "Invoice[ {number}] of {net_total|money} net to {customer_id}[ for order {order_id}]",
|
|
206
250
|
"executionMapping": {
|
|
207
251
|
"net_total": "net_total",
|
|
208
252
|
"currency": "currency"
|
|
@@ -213,15 +257,33 @@
|
|
|
213
257
|
"actionLabel": "Invoice issued",
|
|
214
258
|
"contextKeys": { "customer": "customer_id" },
|
|
215
259
|
"preview": [
|
|
216
|
-
{ "tool": "get_customer", "args": { "id": "customer_id" }, "attach": "customer_id" }
|
|
260
|
+
{ "tool": "get_customer", "args": { "id": "customer_id" }, "attach": "customer_id" },
|
|
261
|
+
{
|
|
262
|
+
"tool": "preview_invoice",
|
|
263
|
+
"args": {
|
|
264
|
+
"customer_id": "customer_id",
|
|
265
|
+
"number": "number",
|
|
266
|
+
"document_date": "document_date",
|
|
267
|
+
"service_period": "service_period",
|
|
268
|
+
"lines": "lines",
|
|
269
|
+
"net_total": "net_total",
|
|
270
|
+
"currency": "currency",
|
|
271
|
+
"payment_term_days": "payment_term_days",
|
|
272
|
+
"memo": "memo"
|
|
273
|
+
},
|
|
274
|
+
"kind": "document"
|
|
275
|
+
}
|
|
217
276
|
],
|
|
218
277
|
"display": {
|
|
219
|
-
"order": ["customer_id", "order_id", "lines", "net_total", "currency", "payment_term_days", "memo"],
|
|
278
|
+
"order": ["customer_id", "order_id", "number", "document_date", "service_period", "lines", "net_total", "currency", "payment_term_days", "memo"],
|
|
220
279
|
"money": ["net_total", "customer_id.credit_limit", "customer_id.open_balance", "customer_id.available_credit"],
|
|
221
280
|
"currencyField": "currency",
|
|
222
281
|
"labels": {
|
|
223
282
|
"customer_id": "Customer",
|
|
224
283
|
"order_id": "Order",
|
|
284
|
+
"number": "Invoice number",
|
|
285
|
+
"document_date": "Invoice date",
|
|
286
|
+
"service_period": "Service period",
|
|
225
287
|
"net_total": "Total (net)",
|
|
226
288
|
"payment_term_days": "Payment terms (days)",
|
|
227
289
|
"memo": "Memo",
|
|
@@ -233,7 +295,7 @@
|
|
|
233
295
|
},
|
|
234
296
|
"create_credit_note": {
|
|
235
297
|
"profile": "invoicing",
|
|
236
|
-
"summary": "Credit note of {credit_total|money} net for invoice {invoice_id}: {reason|short}",
|
|
298
|
+
"summary": "Credit note[ {number}] of {credit_total|money} net for invoice {invoice_id}: {reason|short}",
|
|
237
299
|
"executionMapping": {
|
|
238
300
|
"credit_total": "credit_total",
|
|
239
301
|
"currency": "currency"
|
|
@@ -248,16 +310,29 @@
|
|
|
248
310
|
"fields": ["number", "customer_id", "net_total", "currency", "status"]
|
|
249
311
|
},
|
|
250
312
|
"display": {
|
|
251
|
-
"order": ["invoice_id", "credit_total", "currency", "reason", "lines"],
|
|
313
|
+
"order": ["invoice_id", "number", "document_date", "credit_total", "currency", "reason", "service_period", "lines"],
|
|
252
314
|
"money": ["credit_total"],
|
|
253
315
|
"currencyField": "currency",
|
|
254
316
|
"labels": {
|
|
255
317
|
"invoice_id": "Invoice",
|
|
318
|
+
"number": "Credit note number",
|
|
319
|
+
"document_date": "Credit note date",
|
|
256
320
|
"credit_total": "Total (net)",
|
|
257
|
-
"reason": "Reason"
|
|
321
|
+
"reason": "Reason",
|
|
322
|
+
"service_period": "Service period"
|
|
258
323
|
}
|
|
259
324
|
}
|
|
260
325
|
},
|
|
326
|
+
"preview_invoice": {
|
|
327
|
+
"profile": "invoicing",
|
|
328
|
+
"category": "read",
|
|
329
|
+
"internal": true
|
|
330
|
+
},
|
|
331
|
+
"get_document": {
|
|
332
|
+
"profile": "invoicing",
|
|
333
|
+
"category": "read",
|
|
334
|
+
"internal": true
|
|
335
|
+
},
|
|
261
336
|
"list_invoices": {
|
|
262
337
|
"profile": "invoicing",
|
|
263
338
|
"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}]",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "mail",
|
|
3
|
-
"name": "Email
|
|
3
|
+
"name": "Email",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"description": "Simulated inbox for testing an agent's email replies — nothing leaves the laptop",
|
|
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
|
},
|
|
@@ -40,8 +40,15 @@
|
|
|
40
40
|
"field": "mode",
|
|
41
41
|
"default": "simulation"
|
|
42
42
|
},
|
|
43
|
+
"modeLabels": {
|
|
44
|
+
"simulation": "Test mailbox"
|
|
45
|
+
},
|
|
43
46
|
"personalDefault": false,
|
|
44
47
|
"oauth": null,
|
|
48
|
+
"attachments": {
|
|
49
|
+
"transport": "field",
|
|
50
|
+
"arg": "attachments"
|
|
51
|
+
},
|
|
45
52
|
"context": {
|
|
46
53
|
"sources": {
|
|
47
54
|
"message": {
|
|
@@ -101,7 +108,10 @@
|
|
|
101
108
|
},
|
|
102
109
|
"actionLabel": "Email sent",
|
|
103
110
|
"sourceFromArg": { "kind": "message", "arg": "in_reply_to" },
|
|
104
|
-
"contextKeys": { "email": "to" }
|
|
111
|
+
"contextKeys": { "email": "to" },
|
|
112
|
+
"attachmentsArg": "attachments",
|
|
113
|
+
"insertFields": ["body"],
|
|
114
|
+
"display": { "aiText": "body" }
|
|
105
115
|
},
|
|
106
116
|
"load_simulation": {
|
|
107
117
|
"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() });
|