@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 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] dev mode: ephemeral signing key. Production: set FIDACY_SIGNING_KEY_B64, or FIDACY_MODE=http + FIDACY_API_URL + FIDACY_API_KEY to use the live core.");
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.5";
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] dev mode: ephemeral signing key. Production: set FIDACY_SIGNING_KEY_B64, or FIDACY_MODE=http + FIDACY_API_URL + FIDACY_API_KEY to use the live core.");
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 = { anon_id: randomUUID2(), tier: "free", api_key: null };
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.5";
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.5";
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] dev mode: ephemeral signing key. Production: set FIDACY_SIGNING_KEY_B64, or FIDACY_MODE=http + FIDACY_API_URL + FIDACY_API_KEY to use the live core.");
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.5";
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.9",
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
+ }