@fidacy/mcp 0.1.9 → 0.1.10
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/CHANGELOG.md +11 -0
- package/dist/core.js +4 -3
- package/dist/index.js +12 -6
- package/dist/lib.js +87 -3
- package/package.json +9 -10
package/CHANGELOG.md
CHANGED
|
@@ -74,3 +74,14 @@ semantic versioning.
|
|
|
74
74
|
- One install delivers both the signed verdict (assess_action) and the
|
|
75
75
|
non-custodial payment firewall (request_payment), with the same signed,
|
|
76
76
|
publicly verifiable proof as the SDK.
|
|
77
|
+
|
|
78
|
+
## 0.1.10 — 2026-07-02
|
|
79
|
+
|
|
80
|
+
- Telemetry: `shell` channel attribution (mcp | openclaw-plugin | crabtrap | sdk)
|
|
81
|
+
and `client_version` injected from package.json at build time (0.1.5 had shipped
|
|
82
|
+
stale through 0.1.9 in telemetry AND provision).
|
|
83
|
+
- DENY responses now point to the `upgrade` tool (free account, signed anchored
|
|
84
|
+
proof of every block).
|
|
85
|
+
- Onboarding: first-run `~/.fidacy/config.json` now writes the mandate template
|
|
86
|
+
explicitly (payees/categories/currency/caps) — adding a trusted payee is a
|
|
87
|
+
visible one-line edit; friendlier first-boot message (no more "dev mode" scare).
|
package/dist/core.js
CHANGED
|
@@ -213,7 +213,7 @@ var DevFidacyCore = class {
|
|
|
213
213
|
this.priv = kp.privateKey;
|
|
214
214
|
this.pubPem = publicKeyPem(kp.publicKey);
|
|
215
215
|
if (kp.ephemeral)
|
|
216
|
-
console.error("[fidacy]
|
|
216
|
+
console.error("[fidacy] local firewall active, deny-by-default. Grants are signed with a per-session key (fine for local use); set FIDACY_SIGNING_KEY_B64 for a stable key, or FIDACY_MODE=http to use the hosted core.");
|
|
217
217
|
this.mandate = opts.mandate;
|
|
218
218
|
this.store = new FileAuditStore(opts.auditLogPath ?? "./fidacy-audit.log");
|
|
219
219
|
this.onDecision = opts.onDecision;
|
|
@@ -357,7 +357,8 @@ function resolveMandateRules(cfg) {
|
|
|
357
357
|
}
|
|
358
358
|
|
|
359
359
|
// src/telemetry.ts
|
|
360
|
-
var CLIENT_VERSION = "0.1.
|
|
360
|
+
var CLIENT_VERSION = true ? "0.1.10" : "dev";
|
|
361
|
+
var currentShell = "mcp";
|
|
361
362
|
function telemetryEnabled() {
|
|
362
363
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
363
364
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -383,7 +384,7 @@ function resultOf(status, violatedRule) {
|
|
|
383
384
|
}
|
|
384
385
|
function record(type, result) {
|
|
385
386
|
if (!telemetryEnabled()) return;
|
|
386
|
-
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, ...result ? { result } : {} });
|
|
387
|
+
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, shell: currentShell, ...result ? { result } : {} });
|
|
387
388
|
if (!flushTimer) {
|
|
388
389
|
flushTimer = setTimeout(() => {
|
|
389
390
|
void flush();
|
package/dist/index.js
CHANGED
|
@@ -220,7 +220,7 @@ var DevFidacyCore = class {
|
|
|
220
220
|
this.priv = kp.privateKey;
|
|
221
221
|
this.pubPem = publicKeyPem(kp.publicKey);
|
|
222
222
|
if (kp.ephemeral)
|
|
223
|
-
console.error("[fidacy]
|
|
223
|
+
console.error("[fidacy] local firewall active, deny-by-default. Grants are signed with a per-session key (fine for local use); set FIDACY_SIGNING_KEY_B64 for a stable key, or FIDACY_MODE=http to use the hosted core.");
|
|
224
224
|
this.mandate = opts.mandate;
|
|
225
225
|
this.store = new FileAuditStore(opts.auditLogPath ?? "./fidacy-audit.log");
|
|
226
226
|
this.onDecision = opts.onDecision;
|
|
@@ -359,7 +359,12 @@ function writeConfig(cfg) {
|
|
|
359
359
|
function ensureState() {
|
|
360
360
|
const existing = readConfig();
|
|
361
361
|
if (existing) return { config: existing, firstRun: false };
|
|
362
|
-
const config = {
|
|
362
|
+
const config = {
|
|
363
|
+
anon_id: randomUUID2(),
|
|
364
|
+
tier: "free",
|
|
365
|
+
api_key: null,
|
|
366
|
+
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 }
|
|
367
|
+
};
|
|
363
368
|
try {
|
|
364
369
|
writeConfig(config);
|
|
365
370
|
} catch {
|
|
@@ -380,7 +385,8 @@ function resolveMandateRules(cfg) {
|
|
|
380
385
|
}
|
|
381
386
|
|
|
382
387
|
// src/telemetry.ts
|
|
383
|
-
var CLIENT_VERSION = "0.1.
|
|
388
|
+
var CLIENT_VERSION = true ? "0.1.10" : "dev";
|
|
389
|
+
var currentShell = "mcp";
|
|
384
390
|
function telemetryEnabled() {
|
|
385
391
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
386
392
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -406,7 +412,7 @@ function resultOf(status, violatedRule) {
|
|
|
406
412
|
}
|
|
407
413
|
function record(type, result) {
|
|
408
414
|
if (!telemetryEnabled()) return;
|
|
409
|
-
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, ...result ? { result } : {} });
|
|
415
|
+
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, shell: currentShell, ...result ? { result } : {} });
|
|
410
416
|
if (!flushTimer) {
|
|
411
417
|
flushTimer = setTimeout(() => {
|
|
412
418
|
void flush();
|
|
@@ -603,7 +609,7 @@ async function postOnce(fetchImpl, url, headers, payload, timeoutMs) {
|
|
|
603
609
|
}
|
|
604
610
|
|
|
605
611
|
// src/provision.ts
|
|
606
|
-
var CLIENT_VERSION2 = "0.1.
|
|
612
|
+
var CLIENT_VERSION2 = true ? "0.1.10" : "dev";
|
|
607
613
|
function provisionEnabled() {
|
|
608
614
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
609
615
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -684,7 +690,7 @@ server.registerTool(
|
|
|
684
690
|
const d = await core.decide(req, subject);
|
|
685
691
|
const out = { status: d.status, decisionId: d.decisionId, grant: d.grant, violatedRule: d.violatedRule };
|
|
686
692
|
const human = d.status === "ALLOW" ? `ALLOW (decision ${d.decisionId})${req.invoiceRef ? ` for invoice ${req.invoiceRef}` : ""}. To settle, call execute_payment with the SAME payee, amount, currency, and idempotencyKey, and set "grant" to EXACTLY this signed value:
|
|
687
|
-
${d.grant}` : `DENY (decision ${d.decisionId}). Rule violated: ${d.violatedRule}. No grant issued, this payment cannot proceed. The denial itself is recorded in the tamper-evident, hash-chained audit: call get_audit_proof with decisionId ${d.decisionId} for the proof of what was blocked.`;
|
|
693
|
+
${d.grant}` : `DENY (decision ${d.decisionId}). Rule violated: ${d.violatedRule}. No grant issued, this payment cannot proceed. The denial itself is recorded in the tamper-evident, hash-chained audit: call get_audit_proof with decisionId ${d.decisionId} for the proof of what was blocked. Fidacy just blocked this for you \u2014 for server-signed, anchored proof of every block (free account, local history migrates), call the upgrade tool.`;
|
|
688
694
|
return { content: [{ type: "text", text: human }], structuredContent: out };
|
|
689
695
|
}
|
|
690
696
|
);
|
package/dist/lib.js
CHANGED
|
@@ -339,7 +339,7 @@ var DevFidacyCore = class {
|
|
|
339
339
|
this.priv = kp.privateKey;
|
|
340
340
|
this.pubPem = publicKeyPem(kp.publicKey);
|
|
341
341
|
if (kp.ephemeral)
|
|
342
|
-
console.error("[fidacy]
|
|
342
|
+
console.error("[fidacy] local firewall active, deny-by-default. Grants are signed with a per-session key (fine for local use); set FIDACY_SIGNING_KEY_B64 for a stable key, or FIDACY_MODE=http to use the hosted core.");
|
|
343
343
|
this.mandate = opts.mandate;
|
|
344
344
|
this.store = new FileAuditStore(opts.auditLogPath ?? "./fidacy-audit.log");
|
|
345
345
|
this.onDecision = opts.onDecision;
|
|
@@ -430,6 +430,7 @@ var HttpFidacyCore = class {
|
|
|
430
430
|
};
|
|
431
431
|
|
|
432
432
|
// src/config.ts
|
|
433
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
433
434
|
import { homedir } from "node:os";
|
|
434
435
|
import { join } from "node:path";
|
|
435
436
|
import {
|
|
@@ -469,6 +470,26 @@ function readConfig() {
|
|
|
469
470
|
return null;
|
|
470
471
|
}
|
|
471
472
|
}
|
|
473
|
+
function writeConfig(cfg) {
|
|
474
|
+
const dir = configDir();
|
|
475
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
476
|
+
writeFileSync(configPath(), JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
477
|
+
}
|
|
478
|
+
function ensureState() {
|
|
479
|
+
const existing = readConfig();
|
|
480
|
+
if (existing) return { config: existing, firstRun: false };
|
|
481
|
+
const config = {
|
|
482
|
+
anon_id: randomUUID3(),
|
|
483
|
+
tier: "free",
|
|
484
|
+
api_key: null,
|
|
485
|
+
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 }
|
|
486
|
+
};
|
|
487
|
+
try {
|
|
488
|
+
writeConfig(config);
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
return { config, firstRun: true };
|
|
492
|
+
}
|
|
472
493
|
function resolveMandateRules(cfg) {
|
|
473
494
|
const m = cfg?.mandate ?? {};
|
|
474
495
|
const envList = (v) => v === void 0 ? void 0 : v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -483,7 +504,11 @@ function resolveMandateRules(cfg) {
|
|
|
483
504
|
}
|
|
484
505
|
|
|
485
506
|
// src/telemetry.ts
|
|
486
|
-
var CLIENT_VERSION = "0.1.
|
|
507
|
+
var CLIENT_VERSION = true ? "0.1.10" : "dev";
|
|
508
|
+
var currentShell = "mcp";
|
|
509
|
+
function setTelemetryShell(shell) {
|
|
510
|
+
currentShell = shell;
|
|
511
|
+
}
|
|
487
512
|
function telemetryEnabled() {
|
|
488
513
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
489
514
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -509,7 +534,7 @@ function resultOf(status, violatedRule) {
|
|
|
509
534
|
}
|
|
510
535
|
function record(type, result) {
|
|
511
536
|
if (!telemetryEnabled()) return;
|
|
512
|
-
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, ...result ? { result } : {} });
|
|
537
|
+
buffer.push({ type, ts: (/* @__PURE__ */ new Date()).toISOString(), client_version: CLIENT_VERSION, shell: currentShell, ...result ? { result } : {} });
|
|
513
538
|
if (!flushTimer) {
|
|
514
539
|
flushTimer = setTimeout(() => {
|
|
515
540
|
void flush();
|
|
@@ -517,7 +542,10 @@ function record(type, result) {
|
|
|
517
542
|
if (typeof flushTimer.unref === "function") flushTimer.unref();
|
|
518
543
|
}
|
|
519
544
|
}
|
|
545
|
+
var recordInstall = () => record("install");
|
|
546
|
+
var recordAgentActive = () => record("agent_active");
|
|
520
547
|
var recordDecision = (status, violatedRule) => record("decision", resultOf(status, violatedRule));
|
|
548
|
+
var recordUpgradeIntent = () => record("upgrade_intent");
|
|
521
549
|
async function flush() {
|
|
522
550
|
if (flushTimer) {
|
|
523
551
|
clearTimeout(flushTimer);
|
|
@@ -585,23 +613,79 @@ function makeCore() {
|
|
|
585
613
|
onDecision: (d) => recordDecision(d.status, d.violatedRule)
|
|
586
614
|
});
|
|
587
615
|
}
|
|
616
|
+
|
|
617
|
+
// src/upgrade.ts
|
|
618
|
+
function upgradeUrl() {
|
|
619
|
+
const base = (process.env.FIDACY_APP_URL ?? "https://app.fidacy.com").replace(/\/$/, "");
|
|
620
|
+
const anon = readConfig()?.anon_id ?? "";
|
|
621
|
+
return `${base}/upgrade?anon=${encodeURIComponent(anon)}`;
|
|
622
|
+
}
|
|
623
|
+
function requestUpgrade() {
|
|
624
|
+
recordUpgradeIntent();
|
|
625
|
+
const anonId2 = readConfig()?.anon_id ?? "";
|
|
626
|
+
return { url: upgradeUrl(), anonId: anonId2 };
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/provision.ts
|
|
630
|
+
var CLIENT_VERSION2 = true ? "0.1.10" : "dev";
|
|
631
|
+
function provisionEnabled() {
|
|
632
|
+
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
633
|
+
return !(v === "1" || v === "true" || v === "yes");
|
|
634
|
+
}
|
|
635
|
+
function endpoint2() {
|
|
636
|
+
const base = (process.env.FIDACY_ENGINE_URL ?? "https://api.fidacy.com").replace(/\/$/, "");
|
|
637
|
+
return `${base}/v1/provision`;
|
|
638
|
+
}
|
|
639
|
+
async function autoProvision() {
|
|
640
|
+
if (!provisionEnabled()) return "skipped";
|
|
641
|
+
const cfg = readConfig();
|
|
642
|
+
if (!cfg) return "skipped";
|
|
643
|
+
if (cfg.api_key) return "skipped";
|
|
644
|
+
try {
|
|
645
|
+
const res = await fetch(endpoint2(), {
|
|
646
|
+
method: "POST",
|
|
647
|
+
headers: { "content-type": "application/json" },
|
|
648
|
+
body: JSON.stringify({ anon_id: cfg.anon_id, client_version: CLIENT_VERSION2 })
|
|
649
|
+
});
|
|
650
|
+
if (res.status === 429) return "rate_limited";
|
|
651
|
+
if (!res.ok) return "failed";
|
|
652
|
+
const data = await res.json();
|
|
653
|
+
if (typeof data.api_key !== "string" || !data.api_key) return "failed";
|
|
654
|
+
writeConfig({
|
|
655
|
+
...cfg,
|
|
656
|
+
api_key: data.api_key,
|
|
657
|
+
tier: data.tier === "paid" ? "paid" : "free"
|
|
658
|
+
});
|
|
659
|
+
return "provisioned";
|
|
660
|
+
} catch {
|
|
661
|
+
return "failed";
|
|
662
|
+
}
|
|
663
|
+
}
|
|
588
664
|
export {
|
|
589
665
|
DevFidacyCore,
|
|
590
666
|
FileAuditStore,
|
|
591
667
|
GrantEnforcingExecutor,
|
|
592
668
|
HttpFidacyCore,
|
|
593
669
|
ReferenceRail,
|
|
670
|
+
autoProvision,
|
|
594
671
|
canonInvoice,
|
|
672
|
+
ensureState,
|
|
595
673
|
evaluate,
|
|
596
674
|
httpRedeem,
|
|
597
675
|
loadOrGenerateKeyPair,
|
|
598
676
|
lookalikePayee,
|
|
599
677
|
makeCore,
|
|
600
678
|
publicKeyPem,
|
|
679
|
+
readConfig,
|
|
680
|
+
recordAgentActive,
|
|
681
|
+
recordInstall,
|
|
682
|
+
requestUpgrade,
|
|
601
683
|
requireHttpsBase,
|
|
684
|
+
setTelemetryShell,
|
|
602
685
|
sha256,
|
|
603
686
|
sign,
|
|
604
687
|
stableStringify,
|
|
688
|
+
upgradeUrl,
|
|
605
689
|
validateRequest,
|
|
606
690
|
verify,
|
|
607
691
|
verifyGrant
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fidacy/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Fidacy action firewall for AI agents. Mandate-gated payment authorization as an MCP server.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://fidacy.com",
|
|
@@ -36,12 +36,6 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "node scripts/bundle.mjs",
|
|
41
|
-
"dev": "tsx watch src/index.ts",
|
|
42
|
-
"start": "node dist/index.js",
|
|
43
|
-
"prepublishOnly": "npm run build"
|
|
44
|
-
},
|
|
45
39
|
"engines": {
|
|
46
40
|
"node": ">=18"
|
|
47
41
|
},
|
|
@@ -50,14 +44,19 @@
|
|
|
50
44
|
"zod": "^3.25.0"
|
|
51
45
|
},
|
|
52
46
|
"devDependencies": {
|
|
53
|
-
"@fidacy/firewall": "workspace:*",
|
|
54
47
|
"@types/node": "^22.10.0",
|
|
55
48
|
"tsx": "^4.19.2",
|
|
56
|
-
"typescript": "^5.7.2"
|
|
49
|
+
"typescript": "^5.7.2",
|
|
50
|
+
"@fidacy/firewall": "0.1.0"
|
|
57
51
|
},
|
|
58
52
|
"mcpName": "com.fidacy/mcp",
|
|
59
53
|
"repository": {
|
|
60
54
|
"type": "git",
|
|
61
55
|
"url": "git+https://github.com/lucaslubi/fidacy-mcp.git"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "node scripts/bundle.mjs",
|
|
59
|
+
"dev": "tsx watch src/index.ts",
|
|
60
|
+
"start": "node dist/index.js"
|
|
62
61
|
}
|
|
63
|
-
}
|
|
62
|
+
}
|