@fidacy/mcp 0.1.15 → 0.1.17
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 +20 -0
- package/dist/core.js +39 -2
- package/dist/index.js +43 -5
- package/dist/lib.js +40 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to `@fidacy/mcp` are documented here. This project follows
|
|
4
4
|
semantic versioning.
|
|
5
5
|
|
|
6
|
+
## 0.1.17 — 2026-07-03
|
|
7
|
+
|
|
8
|
+
- Config HOT-RELOAD: editing `~/.fidacy/config.json` (payees, caps) takes effect
|
|
9
|
+
on the next call, no host restart. Spend and invoice-dedup state is rebuilt
|
|
10
|
+
from the audit log on reload, so a reload never weakens the firewall.
|
|
11
|
+
- The `payee_not_in_allowlist` DENY now tells the agent exactly how to allow a
|
|
12
|
+
trusted payee (friction fix from a clean-room install test).
|
|
13
|
+
|
|
14
|
+
## 0.1.16 — 2026-07-03
|
|
15
|
+
|
|
16
|
+
- `anchor_artifact`/`check_artifact`: new kind `conversation` — anchor chatbot
|
|
17
|
+
session digests produced by `@fidacy/session` (conversation receipts).
|
|
18
|
+
|
|
19
|
+
## 0.1.15 — 2026-07-03
|
|
20
|
+
|
|
21
|
+
- New tools: `anchor_artifact` and `check_artifact` — Bitcoin-anchored integrity
|
|
22
|
+
proof for any artifact (contracts, invoices, prescriptions, claims, images,
|
|
23
|
+
audio, video). The file is hashed locally and never uploaded; only the SHA-256
|
|
24
|
+
joins the tamper-evident audit chain. Signed JWS receipt verifies offline.
|
|
25
|
+
|
|
6
26
|
## 0.1.4
|
|
7
27
|
|
|
8
28
|
### Fixed
|
package/dist/core.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/core.ts
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
|
|
1
4
|
// ../firewall/dist/util.js
|
|
2
5
|
function stableStringify(obj) {
|
|
3
6
|
if (obj === null || typeof obj !== "object")
|
|
@@ -189,6 +192,19 @@ var DevFidacyCore = class {
|
|
|
189
192
|
this.spent += r.amount;
|
|
190
193
|
}
|
|
191
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Swap the active mandate (shell config hot-reload: edit config.json, the next
|
|
197
|
+
* call picks it up, no host restart). Decision state is REBUILT from the audit
|
|
198
|
+
* log under the new window/currency, so a reload can never reset the BEC
|
|
199
|
+
* invoice dedup or undercount spend: a paid invoice stays paid, spent is
|
|
200
|
+
* recomputed.
|
|
201
|
+
*/
|
|
202
|
+
setMandate(m) {
|
|
203
|
+
this.mandate = m;
|
|
204
|
+
this.spent = 0;
|
|
205
|
+
this.claimedInvoices.clear();
|
|
206
|
+
this.rehydrate();
|
|
207
|
+
}
|
|
192
208
|
async getMandate() {
|
|
193
209
|
return this.mandate;
|
|
194
210
|
}
|
|
@@ -423,7 +439,7 @@ function resolveMandateRules(cfg) {
|
|
|
423
439
|
}
|
|
424
440
|
|
|
425
441
|
// src/telemetry.ts
|
|
426
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
442
|
+
var CLIENT_VERSION = true ? "0.1.17" : "dev";
|
|
427
443
|
var currentShell = "mcp";
|
|
428
444
|
function telemetryEnabled() {
|
|
429
445
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
@@ -525,11 +541,32 @@ function makeCore() {
|
|
|
525
541
|
if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
|
|
526
542
|
return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
|
|
527
543
|
}
|
|
528
|
-
|
|
544
|
+
const dev = new DevFidacyCore({
|
|
529
545
|
mandate: buildMandate(),
|
|
530
546
|
auditLogPath: auditLogPath(),
|
|
531
547
|
onDecision: (d) => recordDecision(d.status, d.violatedRule)
|
|
532
548
|
});
|
|
549
|
+
const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
|
|
550
|
+
let seenMtime = mtimeOf();
|
|
551
|
+
const maybeReload = () => {
|
|
552
|
+
const m = mtimeOf();
|
|
553
|
+
if (m !== seenMtime) {
|
|
554
|
+
seenMtime = m;
|
|
555
|
+
dev.setMandate(buildMandate());
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
return {
|
|
559
|
+
getMandate: () => {
|
|
560
|
+
maybeReload();
|
|
561
|
+
return dev.getMandate();
|
|
562
|
+
},
|
|
563
|
+
decide: (req, subject) => {
|
|
564
|
+
maybeReload();
|
|
565
|
+
return dev.decide(req, subject);
|
|
566
|
+
},
|
|
567
|
+
getProof: (decisionId) => dev.getProof(decisionId),
|
|
568
|
+
publicKey: () => dev.publicKey()
|
|
569
|
+
};
|
|
533
570
|
}
|
|
534
571
|
export {
|
|
535
572
|
makeCore
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
|
|
8
|
+
// src/core.ts
|
|
9
|
+
import { statSync } from "node:fs";
|
|
10
|
+
|
|
8
11
|
// ../firewall/dist/util.js
|
|
9
12
|
function stableStringify(obj) {
|
|
10
13
|
if (obj === null || typeof obj !== "object")
|
|
@@ -196,6 +199,19 @@ var DevFidacyCore = class {
|
|
|
196
199
|
this.spent += r.amount;
|
|
197
200
|
}
|
|
198
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Swap the active mandate (shell config hot-reload: edit config.json, the next
|
|
204
|
+
* call picks it up, no host restart). Decision state is REBUILT from the audit
|
|
205
|
+
* log under the new window/currency, so a reload can never reset the BEC
|
|
206
|
+
* invoice dedup or undercount spend: a paid invoice stays paid, spent is
|
|
207
|
+
* recomputed.
|
|
208
|
+
*/
|
|
209
|
+
setMandate(m) {
|
|
210
|
+
this.mandate = m;
|
|
211
|
+
this.spent = 0;
|
|
212
|
+
this.claimedInvoices.clear();
|
|
213
|
+
this.rehydrate();
|
|
214
|
+
}
|
|
199
215
|
async getMandate() {
|
|
200
216
|
return this.mandate;
|
|
201
217
|
}
|
|
@@ -452,7 +468,7 @@ function resolveMandateRules(cfg) {
|
|
|
452
468
|
}
|
|
453
469
|
|
|
454
470
|
// src/telemetry.ts
|
|
455
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
471
|
+
var CLIENT_VERSION = true ? "0.1.17" : "dev";
|
|
456
472
|
var currentShell = "mcp";
|
|
457
473
|
function telemetryEnabled() {
|
|
458
474
|
const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
|
|
@@ -557,11 +573,32 @@ function makeCore() {
|
|
|
557
573
|
if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
|
|
558
574
|
return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
|
|
559
575
|
}
|
|
560
|
-
|
|
576
|
+
const dev = new DevFidacyCore({
|
|
561
577
|
mandate: buildMandate(),
|
|
562
578
|
auditLogPath: auditLogPath(),
|
|
563
579
|
onDecision: (d) => recordDecision(d.status, d.violatedRule)
|
|
564
580
|
});
|
|
581
|
+
const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
|
|
582
|
+
let seenMtime = mtimeOf();
|
|
583
|
+
const maybeReload = () => {
|
|
584
|
+
const m = mtimeOf();
|
|
585
|
+
if (m !== seenMtime) {
|
|
586
|
+
seenMtime = m;
|
|
587
|
+
dev.setMandate(buildMandate());
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
return {
|
|
591
|
+
getMandate: () => {
|
|
592
|
+
maybeReload();
|
|
593
|
+
return dev.getMandate();
|
|
594
|
+
},
|
|
595
|
+
decide: (req, subject2) => {
|
|
596
|
+
maybeReload();
|
|
597
|
+
return dev.decide(req, subject2);
|
|
598
|
+
},
|
|
599
|
+
getProof: (decisionId) => dev.getProof(decisionId),
|
|
600
|
+
publicKey: () => dev.publicKey()
|
|
601
|
+
};
|
|
565
602
|
}
|
|
566
603
|
|
|
567
604
|
// src/assess.ts
|
|
@@ -693,6 +730,7 @@ var ARTIFACT_KINDS = [
|
|
|
693
730
|
"image",
|
|
694
731
|
"audio",
|
|
695
732
|
"video",
|
|
733
|
+
"conversation",
|
|
696
734
|
"custom"
|
|
697
735
|
];
|
|
698
736
|
async function hashFile(path) {
|
|
@@ -745,7 +783,7 @@ async function findArtifacts(sha2562, cfg) {
|
|
|
745
783
|
}
|
|
746
784
|
|
|
747
785
|
// src/provision.ts
|
|
748
|
-
var CLIENT_VERSION2 = true ? "0.1.
|
|
786
|
+
var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
|
|
749
787
|
function provisionEnabled() {
|
|
750
788
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
751
789
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -845,7 +883,7 @@ function weekOneBootNudge(upgradeToolName) {
|
|
|
845
883
|
var state = ensureState();
|
|
846
884
|
var core = makeCore();
|
|
847
885
|
var subject = process.env.FIDACY_SUBJECT ?? "agent:demo";
|
|
848
|
-
var SERVER_VERSION = true ? "0.1.
|
|
886
|
+
var SERVER_VERSION = true ? "0.1.17" : "dev";
|
|
849
887
|
var server = new McpServer({ name: "fidacy", version: SERVER_VERSION });
|
|
850
888
|
server.registerTool(
|
|
851
889
|
"request_payment",
|
|
@@ -876,7 +914,7 @@ server.registerTool(
|
|
|
876
914
|
const d = await core.decide(req, subject);
|
|
877
915
|
const out = { status: d.status, decisionId: d.decisionId, grant: d.grant, violatedRule: d.violatedRule };
|
|
878
916
|
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:
|
|
879
|
-
${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
|
|
917
|
+
${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.${d.violatedRule?.startsWith("payee_not_in_allowlist") ? ` If the user trusts this payee, add "${req.payee}" to mandate.payees in ~/.fidacy/config.json and retry: the firewall picks the change up on the next call, no restart needed.` : ""}`;
|
|
880
918
|
const nudge = decisionNudge(d.status, d.violatedRule, "upgrade");
|
|
881
919
|
const human = nudge ? `${base} ${nudge}` : base;
|
|
882
920
|
return { content: [{ type: "text", text: human }], structuredContent: out };
|
package/dist/lib.js
CHANGED
|
@@ -230,6 +230,19 @@ var DevFidacyCore = class {
|
|
|
230
230
|
this.spent += r.amount;
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Swap the active mandate (shell config hot-reload: edit config.json, the next
|
|
235
|
+
* call picks it up, no host restart). Decision state is REBUILT from the audit
|
|
236
|
+
* log under the new window/currency, so a reload can never reset the BEC
|
|
237
|
+
* invoice dedup or undercount spend: a paid invoice stays paid, spent is
|
|
238
|
+
* recomputed.
|
|
239
|
+
*/
|
|
240
|
+
setMandate(m) {
|
|
241
|
+
this.mandate = m;
|
|
242
|
+
this.spent = 0;
|
|
243
|
+
this.claimedInvoices.clear();
|
|
244
|
+
this.rehydrate();
|
|
245
|
+
}
|
|
233
246
|
async getMandate() {
|
|
234
247
|
return this.mandate;
|
|
235
248
|
}
|
|
@@ -490,6 +503,9 @@ var GrantEnforcingExecutor = class {
|
|
|
490
503
|
}
|
|
491
504
|
};
|
|
492
505
|
|
|
506
|
+
// src/core.ts
|
|
507
|
+
import { statSync } from "node:fs";
|
|
508
|
+
|
|
493
509
|
// src/config.ts
|
|
494
510
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
495
511
|
import { homedir } from "node:os";
|
|
@@ -571,7 +587,7 @@ function resolveMandateRules(cfg) {
|
|
|
571
587
|
}
|
|
572
588
|
|
|
573
589
|
// src/telemetry.ts
|
|
574
|
-
var CLIENT_VERSION = true ? "0.1.
|
|
590
|
+
var CLIENT_VERSION = true ? "0.1.17" : "dev";
|
|
575
591
|
var currentShell = "mcp";
|
|
576
592
|
function setTelemetryShell(shell) {
|
|
577
593
|
currentShell = shell;
|
|
@@ -679,11 +695,32 @@ function makeCore() {
|
|
|
679
695
|
if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
|
|
680
696
|
return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
|
|
681
697
|
}
|
|
682
|
-
|
|
698
|
+
const dev = new DevFidacyCore({
|
|
683
699
|
mandate: buildMandate(),
|
|
684
700
|
auditLogPath: auditLogPath(),
|
|
685
701
|
onDecision: (d) => recordDecision(d.status, d.violatedRule)
|
|
686
702
|
});
|
|
703
|
+
const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
|
|
704
|
+
let seenMtime = mtimeOf();
|
|
705
|
+
const maybeReload = () => {
|
|
706
|
+
const m = mtimeOf();
|
|
707
|
+
if (m !== seenMtime) {
|
|
708
|
+
seenMtime = m;
|
|
709
|
+
dev.setMandate(buildMandate());
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
return {
|
|
713
|
+
getMandate: () => {
|
|
714
|
+
maybeReload();
|
|
715
|
+
return dev.getMandate();
|
|
716
|
+
},
|
|
717
|
+
decide: (req, subject) => {
|
|
718
|
+
maybeReload();
|
|
719
|
+
return dev.decide(req, subject);
|
|
720
|
+
},
|
|
721
|
+
getProof: (decisionId) => dev.getProof(decisionId),
|
|
722
|
+
publicKey: () => dev.publicKey()
|
|
723
|
+
};
|
|
687
724
|
}
|
|
688
725
|
|
|
689
726
|
// src/upgrade.ts
|
|
@@ -699,7 +736,7 @@ function requestUpgrade() {
|
|
|
699
736
|
}
|
|
700
737
|
|
|
701
738
|
// src/provision.ts
|
|
702
|
-
var CLIENT_VERSION2 = true ? "0.1.
|
|
739
|
+
var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
|
|
703
740
|
function provisionEnabled() {
|
|
704
741
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
705
742
|
return !(v === "1" || v === "true" || v === "yes");
|
package/package.json
CHANGED