@fidacy/mcp 0.1.10 → 0.1.11
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 +10 -0
- package/dist/core.js +7 -2
- package/dist/index.js +70 -10
- package/dist/lib.js +64 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -85,3 +85,13 @@ semantic versioning.
|
|
|
85
85
|
- Onboarding: first-run `~/.fidacy/config.json` now writes the mandate template
|
|
86
86
|
explicitly (payees/categories/currency/caps) — adding a trusted payee is a
|
|
87
87
|
visible one-line edit; friendlier first-boot message (no more "dev mode" scare).
|
|
88
|
+
|
|
89
|
+
## 0.1.11 — 2026-07-02
|
|
90
|
+
|
|
91
|
+
- Upgrade micro-triggers, elegant by doctrine: fire only at value-proven moments
|
|
92
|
+
(first block, first duplicate-invoice/BEC catch, 10th gated action, one week
|
|
93
|
+
protected), each ONCE per install ever (persisted in config.json) — the free
|
|
94
|
+
tier stays fully usable in silence. The 0.1.10 every-DENY nudge is replaced.
|
|
95
|
+
- verify_mandate/get_audit_proof gain one informational closing line each;
|
|
96
|
+
assess_action's missing-key error now offers the free-key path.
|
|
97
|
+
- config.json gains created_at + nudge/decision state (preserved on read).
|
package/dist/core.js
CHANGED
|
@@ -337,7 +337,12 @@ function readConfig() {
|
|
|
337
337
|
anon_id: raw.anon_id,
|
|
338
338
|
tier: raw.tier === "paid" ? "paid" : "free",
|
|
339
339
|
api_key: typeof raw.api_key === "string" ? raw.api_key : null,
|
|
340
|
-
mandate: raw.mandate
|
|
340
|
+
mandate: raw.mandate,
|
|
341
|
+
// Install-state passthrough: dropping these on a read→write cycle would
|
|
342
|
+
// reset every once-per-install nudge into an every-time nag.
|
|
343
|
+
created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
|
|
344
|
+
nudges: raw.nudges && typeof raw.nudges === "object" ? raw.nudges : void 0,
|
|
345
|
+
decisions_count: typeof raw.decisions_count === "number" ? raw.decisions_count : void 0
|
|
341
346
|
};
|
|
342
347
|
} catch {
|
|
343
348
|
return null;
|
|
@@ -357,7 +362,7 @@ function resolveMandateRules(cfg) {
|
|
|
357
362
|
}
|
|
358
363
|
|
|
359
364
|
// src/telemetry.ts
|
|
360
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
365
|
+
var CLIENT_VERSION = true ? "0.1.11" : "dev";
|
|
361
366
|
var currentShell = "mcp";
|
|
362
367
|
function telemetryEnabled() {
|
|
363
368
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
package/dist/index.js
CHANGED
|
@@ -345,7 +345,12 @@ function readConfig() {
|
|
|
345
345
|
anon_id: raw.anon_id,
|
|
346
346
|
tier: raw.tier === "paid" ? "paid" : "free",
|
|
347
347
|
api_key: typeof raw.api_key === "string" ? raw.api_key : null,
|
|
348
|
-
mandate: raw.mandate
|
|
348
|
+
mandate: raw.mandate,
|
|
349
|
+
// Install-state passthrough: dropping these on a read→write cycle would
|
|
350
|
+
// reset every once-per-install nudge into an every-time nag.
|
|
351
|
+
created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
|
|
352
|
+
nudges: raw.nudges && typeof raw.nudges === "object" ? raw.nudges : void 0,
|
|
353
|
+
decisions_count: typeof raw.decisions_count === "number" ? raw.decisions_count : void 0
|
|
349
354
|
};
|
|
350
355
|
} catch {
|
|
351
356
|
return null;
|
|
@@ -363,7 +368,8 @@ function ensureState() {
|
|
|
363
368
|
anon_id: randomUUID2(),
|
|
364
369
|
tier: "free",
|
|
365
370
|
api_key: null,
|
|
366
|
-
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 }
|
|
371
|
+
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 },
|
|
372
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
367
373
|
};
|
|
368
374
|
try {
|
|
369
375
|
writeConfig(config);
|
|
@@ -385,7 +391,7 @@ function resolveMandateRules(cfg) {
|
|
|
385
391
|
}
|
|
386
392
|
|
|
387
393
|
// src/telemetry.ts
|
|
388
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
394
|
+
var CLIENT_VERSION = true ? "0.1.11" : "dev";
|
|
389
395
|
var currentShell = "mcp";
|
|
390
396
|
function telemetryEnabled() {
|
|
391
397
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
@@ -609,7 +615,7 @@ async function postOnce(fetchImpl, url, headers, payload, timeoutMs) {
|
|
|
609
615
|
}
|
|
610
616
|
|
|
611
617
|
// src/provision.ts
|
|
612
|
-
var CLIENT_VERSION2 = true ? "0.1.
|
|
618
|
+
var CLIENT_VERSION2 = true ? "0.1.11" : "dev";
|
|
613
619
|
function provisionEnabled() {
|
|
614
620
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
615
621
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -656,6 +662,55 @@ function requestUpgrade() {
|
|
|
656
662
|
return { url: upgradeUrl(), anonId: anonId2 };
|
|
657
663
|
}
|
|
658
664
|
|
|
665
|
+
// src/nudges.ts
|
|
666
|
+
function nudgeOnce(key) {
|
|
667
|
+
const cfg = readConfig();
|
|
668
|
+
if (!cfg) return false;
|
|
669
|
+
if (cfg.nudges?.[key]) return false;
|
|
670
|
+
cfg.nudges = { ...cfg.nudges ?? {}, [key]: true };
|
|
671
|
+
try {
|
|
672
|
+
writeConfig(cfg);
|
|
673
|
+
} catch {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
function bumpDecisionCount() {
|
|
679
|
+
const cfg = readConfig();
|
|
680
|
+
if (!cfg) return 0;
|
|
681
|
+
const n = (cfg.decisions_count ?? 0) + 1;
|
|
682
|
+
cfg.decisions_count = n;
|
|
683
|
+
try {
|
|
684
|
+
writeConfig(cfg);
|
|
685
|
+
} catch {
|
|
686
|
+
}
|
|
687
|
+
return n;
|
|
688
|
+
}
|
|
689
|
+
function installAgeDays() {
|
|
690
|
+
const t = Date.parse(readConfig()?.created_at ?? "");
|
|
691
|
+
if (Number.isNaN(t)) return 0;
|
|
692
|
+
return Math.floor((Date.now() - t) / 864e5);
|
|
693
|
+
}
|
|
694
|
+
function decisionNudge(status, violatedRule, upgradeToolName) {
|
|
695
|
+
const count = bumpDecisionCount();
|
|
696
|
+
if (status === "DENY" && violatedRule?.startsWith("duplicate_invoice") && nudgeOnce("bec_catch")) {
|
|
697
|
+
return `That was a duplicate-invoice (BEC) catch \u2014 the #1 payment fraud. On a free account every block like this is server-signed and anchored to Bitcoin: court-grade evidence. Call the ${upgradeToolName} tool to start.`;
|
|
698
|
+
}
|
|
699
|
+
if (status === "DENY" && nudgeOnce("first_deny")) {
|
|
700
|
+
return `Fidacy just blocked this for you \u2014 for server-signed, anchored proof of every block (free account, local history migrates), call the ${upgradeToolName} tool.`;
|
|
701
|
+
}
|
|
702
|
+
if (count === 10 && nudgeOnce("milestone_10")) {
|
|
703
|
+
return `That's 10 actions gated on this install. For a signed, Bitcoin-anchored history of all of them (free account), call the ${upgradeToolName} tool.`;
|
|
704
|
+
}
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
707
|
+
function weekOneBootNudge(upgradeToolName) {
|
|
708
|
+
if (installAgeDays() >= 7 && nudgeOnce("week_1")) {
|
|
709
|
+
return ` One week protected \u2014 anchor your history to Bitcoin with a free account: the ${upgradeToolName} tool starts it.`;
|
|
710
|
+
}
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
|
|
659
714
|
// src/index.ts
|
|
660
715
|
var state = ensureState();
|
|
661
716
|
var core = makeCore();
|
|
@@ -689,8 +744,10 @@ server.registerTool(
|
|
|
689
744
|
const req = args;
|
|
690
745
|
const d = await core.decide(req, subject);
|
|
691
746
|
const out = { status: d.status, decisionId: d.decisionId, grant: d.grant, violatedRule: d.violatedRule };
|
|
692
|
-
const
|
|
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
|
|
747
|
+
const base = 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:
|
|
748
|
+
${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.`;
|
|
749
|
+
const nudge = decisionNudge(d.status, d.violatedRule, "upgrade");
|
|
750
|
+
const human = nudge ? `${base} ${nudge}` : base;
|
|
694
751
|
return { content: [{ type: "text", text: human }], structuredContent: out };
|
|
695
752
|
}
|
|
696
753
|
);
|
|
@@ -705,7 +762,8 @@ server.registerTool(
|
|
|
705
762
|
async () => {
|
|
706
763
|
const m = await core.getMandate(subject);
|
|
707
764
|
const payload = { mandate: m, fidacyPublicKey: core.publicKey() };
|
|
708
|
-
|
|
765
|
+
const text = JSON.stringify(payload, null, 2) + "\n\nThis mandate is local (free tier). Hosted mandates add team governance and server-signed verdicts \u2014 the upgrade tool starts a free account.";
|
|
766
|
+
return { content: [{ type: "text", text }], structuredContent: payload };
|
|
709
767
|
}
|
|
710
768
|
);
|
|
711
769
|
server.registerTool(
|
|
@@ -719,7 +777,8 @@ server.registerTool(
|
|
|
719
777
|
async ({ decisionId }) => {
|
|
720
778
|
const proof = await core.getProof(decisionId);
|
|
721
779
|
if (!proof) return { content: [{ type: "text", text: `No proof found for ${decisionId}` }], isError: true };
|
|
722
|
-
|
|
780
|
+
const text = JSON.stringify(proof, null, 2) + "\n\nThis proof lives on this machine. On a free hosted account the chain is anchored to Bitcoin \u2014 verifiable by anyone, forever, even against Fidacy (the upgrade tool starts it).";
|
|
781
|
+
return { content: [{ type: "text", text }], structuredContent: proof };
|
|
723
782
|
}
|
|
724
783
|
);
|
|
725
784
|
server.registerTool(
|
|
@@ -745,7 +804,7 @@ server.registerTool(
|
|
|
745
804
|
content: [
|
|
746
805
|
{
|
|
747
806
|
type: "text",
|
|
748
|
-
text: "assess_action
|
|
807
|
+
text: "assess_action needs an engine key \u2014 free in about a minute: call the upgrade tool (your usage history migrates), or set FIDACY_ENGINE_API_KEY if you already have one."
|
|
749
808
|
}
|
|
750
809
|
],
|
|
751
810
|
isError: true
|
|
@@ -805,7 +864,8 @@ async function main() {
|
|
|
805
864
|
void autoProvision();
|
|
806
865
|
const verdictHint = process.env.FIDACY_ENGINE_API_KEY ? "" : " Set FIDACY_ENGINE_API_KEY to enable verdicts (assess_action).";
|
|
807
866
|
const tierHint = state.firstRun ? " First run: free local tier active (deny-unknown payee + cap). Add trusted payees in ~/.fidacy/config.json." : ` Tier: ${state.config.tier} (local-first).`;
|
|
808
|
-
|
|
867
|
+
const weekNudge = weekOneBootNudge("upgrade") ?? "";
|
|
868
|
+
console.error("[fidacy] @fidacy/mcp ready on stdio: signed verdict + payment firewall." + tierHint + verdictHint + weekNudge);
|
|
809
869
|
}
|
|
810
870
|
main().catch((e) => {
|
|
811
871
|
console.error("[fidacy] fatal:", e);
|
package/dist/lib.js
CHANGED
|
@@ -464,7 +464,12 @@ function readConfig() {
|
|
|
464
464
|
anon_id: raw.anon_id,
|
|
465
465
|
tier: raw.tier === "paid" ? "paid" : "free",
|
|
466
466
|
api_key: typeof raw.api_key === "string" ? raw.api_key : null,
|
|
467
|
-
mandate: raw.mandate
|
|
467
|
+
mandate: raw.mandate,
|
|
468
|
+
// Install-state passthrough: dropping these on a read→write cycle would
|
|
469
|
+
// reset every once-per-install nudge into an every-time nag.
|
|
470
|
+
created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
|
|
471
|
+
nudges: raw.nudges && typeof raw.nudges === "object" ? raw.nudges : void 0,
|
|
472
|
+
decisions_count: typeof raw.decisions_count === "number" ? raw.decisions_count : void 0
|
|
468
473
|
};
|
|
469
474
|
} catch {
|
|
470
475
|
return null;
|
|
@@ -482,7 +487,8 @@ function ensureState() {
|
|
|
482
487
|
anon_id: randomUUID3(),
|
|
483
488
|
tier: "free",
|
|
484
489
|
api_key: null,
|
|
485
|
-
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 }
|
|
490
|
+
mandate: { payees: [], categories: ["*"], currency: "USD", perTxMax: 2500, maxTotal: 1e4 },
|
|
491
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
486
492
|
};
|
|
487
493
|
try {
|
|
488
494
|
writeConfig(config);
|
|
@@ -504,7 +510,7 @@ function resolveMandateRules(cfg) {
|
|
|
504
510
|
}
|
|
505
511
|
|
|
506
512
|
// src/telemetry.ts
|
|
507
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
513
|
+
var CLIENT_VERSION = true ? "0.1.11" : "dev";
|
|
508
514
|
var currentShell = "mcp";
|
|
509
515
|
function setTelemetryShell(shell) {
|
|
510
516
|
currentShell = shell;
|
|
@@ -627,7 +633,7 @@ function requestUpgrade() {
|
|
|
627
633
|
}
|
|
628
634
|
|
|
629
635
|
// src/provision.ts
|
|
630
|
-
var CLIENT_VERSION2 = true ? "0.1.
|
|
636
|
+
var CLIENT_VERSION2 = true ? "0.1.11" : "dev";
|
|
631
637
|
function provisionEnabled() {
|
|
632
638
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
633
639
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -661,6 +667,55 @@ async function autoProvision() {
|
|
|
661
667
|
return "failed";
|
|
662
668
|
}
|
|
663
669
|
}
|
|
670
|
+
|
|
671
|
+
// src/nudges.ts
|
|
672
|
+
function nudgeOnce(key) {
|
|
673
|
+
const cfg = readConfig();
|
|
674
|
+
if (!cfg) return false;
|
|
675
|
+
if (cfg.nudges?.[key]) return false;
|
|
676
|
+
cfg.nudges = { ...cfg.nudges ?? {}, [key]: true };
|
|
677
|
+
try {
|
|
678
|
+
writeConfig(cfg);
|
|
679
|
+
} catch {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
return true;
|
|
683
|
+
}
|
|
684
|
+
function bumpDecisionCount() {
|
|
685
|
+
const cfg = readConfig();
|
|
686
|
+
if (!cfg) return 0;
|
|
687
|
+
const n = (cfg.decisions_count ?? 0) + 1;
|
|
688
|
+
cfg.decisions_count = n;
|
|
689
|
+
try {
|
|
690
|
+
writeConfig(cfg);
|
|
691
|
+
} catch {
|
|
692
|
+
}
|
|
693
|
+
return n;
|
|
694
|
+
}
|
|
695
|
+
function installAgeDays() {
|
|
696
|
+
const t = Date.parse(readConfig()?.created_at ?? "");
|
|
697
|
+
if (Number.isNaN(t)) return 0;
|
|
698
|
+
return Math.floor((Date.now() - t) / 864e5);
|
|
699
|
+
}
|
|
700
|
+
function decisionNudge(status, violatedRule, upgradeToolName) {
|
|
701
|
+
const count = bumpDecisionCount();
|
|
702
|
+
if (status === "DENY" && violatedRule?.startsWith("duplicate_invoice") && nudgeOnce("bec_catch")) {
|
|
703
|
+
return `That was a duplicate-invoice (BEC) catch \u2014 the #1 payment fraud. On a free account every block like this is server-signed and anchored to Bitcoin: court-grade evidence. Call the ${upgradeToolName} tool to start.`;
|
|
704
|
+
}
|
|
705
|
+
if (status === "DENY" && nudgeOnce("first_deny")) {
|
|
706
|
+
return `Fidacy just blocked this for you \u2014 for server-signed, anchored proof of every block (free account, local history migrates), call the ${upgradeToolName} tool.`;
|
|
707
|
+
}
|
|
708
|
+
if (count === 10 && nudgeOnce("milestone_10")) {
|
|
709
|
+
return `That's 10 actions gated on this install. For a signed, Bitcoin-anchored history of all of them (free account), call the ${upgradeToolName} tool.`;
|
|
710
|
+
}
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
function weekOneBootNudge(upgradeToolName) {
|
|
714
|
+
if (installAgeDays() >= 7 && nudgeOnce("week_1")) {
|
|
715
|
+
return ` One week protected \u2014 anchor your history to Bitcoin with a free account: the ${upgradeToolName} tool starts it.`;
|
|
716
|
+
}
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
664
719
|
export {
|
|
665
720
|
DevFidacyCore,
|
|
666
721
|
FileAuditStore,
|
|
@@ -669,12 +724,15 @@ export {
|
|
|
669
724
|
ReferenceRail,
|
|
670
725
|
autoProvision,
|
|
671
726
|
canonInvoice,
|
|
727
|
+
decisionNudge,
|
|
672
728
|
ensureState,
|
|
673
729
|
evaluate,
|
|
674
730
|
httpRedeem,
|
|
731
|
+
installAgeDays,
|
|
675
732
|
loadOrGenerateKeyPair,
|
|
676
733
|
lookalikePayee,
|
|
677
734
|
makeCore,
|
|
735
|
+
nudgeOnce,
|
|
678
736
|
publicKeyPem,
|
|
679
737
|
readConfig,
|
|
680
738
|
recordAgentActive,
|
|
@@ -688,5 +746,6 @@ export {
|
|
|
688
746
|
upgradeUrl,
|
|
689
747
|
validateRequest,
|
|
690
748
|
verify,
|
|
691
|
-
verifyGrant
|
|
749
|
+
verifyGrant,
|
|
750
|
+
weekOneBootNudge
|
|
692
751
|
};
|
package/package.json
CHANGED