@rel-time/mcp-server 1.2.0 → 1.2.2
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/index.js +91 -10
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -20,18 +20,63 @@ const { exec } = require("child_process");
|
|
|
20
20
|
const { PDFDocument } = require("pdf-lib");
|
|
21
21
|
const sharp = require("sharp");
|
|
22
22
|
|
|
23
|
-
const API_BASE = (process.env.RELTIME_API_URL || "https://
|
|
23
|
+
const API_BASE = (process.env.RELTIME_API_URL || "https://rel-time.com/api/v1").replace(/\/+$/, "");
|
|
24
24
|
const WEB_BASE = (process.env.RELTIME_WEB_URL || "https://rel-time.com").replace(/\/+$/, "");
|
|
25
25
|
let CURRENT_API_KEY = process.env.RELTIME_API_KEY || "";
|
|
26
26
|
|
|
27
27
|
const PASSKEY_CONFIG_DIR = path.join(os.homedir(), ".reltime");
|
|
28
28
|
const PASSKEY_CONFIG_PATH = path.join(PASSKEY_CONFIG_DIR, "passkey.json");
|
|
29
|
+
const API_KEY_CONFIG_PATH = path.join(PASSKEY_CONFIG_DIR, "api_key.json");
|
|
30
|
+
let LAST_INVOICE_PACK = null;
|
|
29
31
|
|
|
30
32
|
const SERVER_INFO = {
|
|
31
33
|
name: "rel-time-mcp-server",
|
|
32
|
-
version: "1.2.
|
|
34
|
+
version: "1.2.2",
|
|
33
35
|
};
|
|
34
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Loads saved API key from ~/.reltime/api_key.json if not provided via env/args.
|
|
39
|
+
*/
|
|
40
|
+
function loadSavedApiKey() {
|
|
41
|
+
if (CURRENT_API_KEY && CURRENT_API_KEY.trim()) {
|
|
42
|
+
return CURRENT_API_KEY.trim();
|
|
43
|
+
}
|
|
44
|
+
if (process.env.RELTIME_API_KEY && process.env.RELTIME_API_KEY.trim()) {
|
|
45
|
+
return process.env.RELTIME_API_KEY.trim();
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
if (fs.existsSync(API_KEY_CONFIG_PATH)) {
|
|
49
|
+
const parsed = JSON.parse(fs.readFileSync(API_KEY_CONFIG_PATH, "utf8"));
|
|
50
|
+
if (parsed.api_key && parsed.api_key.trim()) {
|
|
51
|
+
CURRENT_API_KEY = parsed.api_key.trim();
|
|
52
|
+
return CURRENT_API_KEY;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
// Ignore corrupted file
|
|
57
|
+
}
|
|
58
|
+
return "";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Saves provisioned API key to ~/.reltime/api_key.json with 0600 permissions.
|
|
63
|
+
*/
|
|
64
|
+
function saveApiKeyConfig(apiKey, pack) {
|
|
65
|
+
if (!fs.existsSync(PASSKEY_CONFIG_DIR)) {
|
|
66
|
+
fs.mkdirSync(PASSKEY_CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
67
|
+
}
|
|
68
|
+
const payload = {
|
|
69
|
+
api_key: apiKey.trim(),
|
|
70
|
+
pack: pack || "standard",
|
|
71
|
+
saved_at: new Date().toISOString(),
|
|
72
|
+
};
|
|
73
|
+
fs.writeFileSync(API_KEY_CONFIG_PATH, JSON.stringify(payload, null, 2), {
|
|
74
|
+
encoding: "utf8",
|
|
75
|
+
mode: 0o600,
|
|
76
|
+
});
|
|
77
|
+
return payload;
|
|
78
|
+
}
|
|
79
|
+
|
|
35
80
|
/**
|
|
36
81
|
* Loads linked Passkey credentials from env vars or ~/.reltime/passkey.json.
|
|
37
82
|
*/
|
|
@@ -397,7 +442,7 @@ const TOOLS = [
|
|
|
397
442
|
{
|
|
398
443
|
name: "reltime_provision_agent_key",
|
|
399
444
|
description:
|
|
400
|
-
"Self-onboarding & Top-Up for Autonomous AI Agents
|
|
445
|
+
"Self-onboarding & Top-Up for Autonomous AI Agents via Bitcoin Lightning (`POST /v1/agent/invoice` & `POST /v1/agent/claim`). IMPORTANT: Before calling `create_invoice` for a new key, ALWAYS ask the user which pack they want first:\n1. **Agent Launch Pack (`pack: 'launch'`, $5 / 50 Hashes):** Priority 10-Minute Bitcoin Queue · Standard Mode only (Data Integrity + Biometric or Anonymous) · Includes Sun-Stamp, 1-Click Stamped Copy (.PDF/.PNG), and .JSON Doomsday Proof.\n2. **Autonomous Agents (`pack: 'standard'`, $50 / 500 Hashes):** Dynamic 6-Hour Batch Queue · Supports both Temporal Mode (`T_index` sub-second sequencing) and Standard Mode · Reloadable anytime (+500 credits / $50) with zero key rotation.",
|
|
401
446
|
inputSchema: {
|
|
402
447
|
type: "object",
|
|
403
448
|
properties: {
|
|
@@ -411,7 +456,7 @@ const TOOLS = [
|
|
|
411
456
|
type: "string",
|
|
412
457
|
enum: ["launch", "standard"],
|
|
413
458
|
description:
|
|
414
|
-
"
|
|
459
|
+
"Which key pack the user selected: 'launch' (Agent Launch Pack — $5 for 50 Hash Credits, 10-Min Queue, Standard Mode only) or 'standard' (Autonomous Agents — $50 for 500 Hash Credits, 6-Hr Queue, Temporal & Standard Modes, reloadable). If omitted on 'create_invoice', the tool returns the two options so you can ask the user which pack they prefer.",
|
|
415
460
|
},
|
|
416
461
|
invoice_id: {
|
|
417
462
|
type: "string",
|
|
@@ -434,7 +479,7 @@ const TOOLS = [
|
|
|
434
479
|
];
|
|
435
480
|
|
|
436
481
|
async function executeTool(name, args = {}) {
|
|
437
|
-
const key = (args.api_key ||
|
|
482
|
+
const key = (args.api_key || loadSavedApiKey() || "").trim();
|
|
438
483
|
|
|
439
484
|
if (name === "reltime_link_passkey") {
|
|
440
485
|
if (args.public_key_hex && args.passkey_signature) {
|
|
@@ -467,7 +512,7 @@ async function executeTool(name, args = {}) {
|
|
|
467
512
|
}
|
|
468
513
|
if (!key) {
|
|
469
514
|
throw new Error(
|
|
470
|
-
"Missing RELTIME_API_KEY.
|
|
515
|
+
"Missing RELTIME_API_KEY. Please ask the user which API key pack they would like to provision first before calling `reltime_provision_agent_key`:\n1. **Agent Launch Pack (`pack: \"launch\"`, $5 / 50 Hashes):** Priority 10-Min Bitcoin Queue · Standard Mode only (Data Integrity + Biometric or Anonymous)\n2. **Autonomous Agents (`pack: \"standard\"`, $50 / 500 Hashes):** Dynamic 6-Hr Batch Queue · Temporal Mode (T_index sequencing) + Standard Mode · Reloadable anytime"
|
|
471
516
|
);
|
|
472
517
|
}
|
|
473
518
|
|
|
@@ -614,7 +659,9 @@ async function executeTool(name, args = {}) {
|
|
|
614
659
|
|
|
615
660
|
if (name === "reltime_anchor_hash") {
|
|
616
661
|
if (!key) {
|
|
617
|
-
throw new Error(
|
|
662
|
+
throw new Error(
|
|
663
|
+
"Missing RELTIME_API_KEY. Please ask the user which API key pack they would like to provision first before calling `reltime_provision_agent_key`: 1) Agent Launch Pack (`pack: \"launch\"`, $5 / 50 Hashes · 10-Min Queue · Standard Mode only) or 2) Autonomous Agents (`pack: \"standard\"`, $50 / 500 Hashes · 6-Hr Queue · Temporal & Standard Modes)."
|
|
664
|
+
);
|
|
618
665
|
}
|
|
619
666
|
const clientHash = (args.client_hash || "").trim().toLowerCase();
|
|
620
667
|
if (!/^[0-9a-f]{64}$/.test(clientHash)) {
|
|
@@ -713,22 +760,54 @@ async function executeTool(name, args = {}) {
|
|
|
713
760
|
|
|
714
761
|
if (name === "reltime_provision_agent_key") {
|
|
715
762
|
if (args.action === "create_invoice") {
|
|
763
|
+
if (args.pack !== "launch" && args.pack !== "standard") {
|
|
764
|
+
return {
|
|
765
|
+
status: "pack_selection_required",
|
|
766
|
+
message:
|
|
767
|
+
"Please ask the user which Rel-Time Agent API Key pack they would like to provision before generating the Lightning invoice:",
|
|
768
|
+
available_packs: [
|
|
769
|
+
{
|
|
770
|
+
pack: "launch",
|
|
771
|
+
name: "Agent Launch Pack",
|
|
772
|
+
price_usd: "$5.00",
|
|
773
|
+
credits: 50,
|
|
774
|
+
settlement_queue: "Priority 10-Minute Bitcoin Queue",
|
|
775
|
+
hashing_modes: "Standard Mode only (Data Integrity + Biometric or Anonymous)",
|
|
776
|
+
outputs: "64-Ray Sun-Stamp SVG + 1-Click Stamped Copy (.PDF/.PNG) + .JSON Doomsday Proof",
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
pack: "standard",
|
|
780
|
+
name: "Autonomous Agents",
|
|
781
|
+
price_usd: "$50.00",
|
|
782
|
+
credits: 500,
|
|
783
|
+
settlement_queue: "Dynamic 6-Hour Batch Queue",
|
|
784
|
+
hashing_modes: "Temporal Mode (T_index sub-second VDF sequencing) + Standard Mode (Biometric or Anonymous)",
|
|
785
|
+
outputs: "64-Ray Sun-Stamp SVG + 1-Click Stamped Copy (.PDF/.PNG) + .JSON Doomsday Proof + Reloadable anytime (+500 credits / $50)",
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
next_step:
|
|
789
|
+
"Once the user chooses, call `reltime_provision_agent_key` with `action: 'create_invoice'` and `pack: 'launch'` or `pack: 'standard'`.",
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
LAST_INVOICE_PACK = args.pack;
|
|
716
794
|
const res = await fetch(`${API_BASE}/agent/invoice`, {
|
|
717
795
|
method: "POST",
|
|
718
796
|
headers: { "Content-Type": "application/json" },
|
|
719
797
|
body: JSON.stringify({
|
|
720
798
|
accept_terms: true,
|
|
721
|
-
pack: args.pack
|
|
799
|
+
pack: args.pack,
|
|
722
800
|
}),
|
|
723
801
|
});
|
|
724
802
|
return await res.json();
|
|
725
803
|
} else if (args.action === "claim_invoice") {
|
|
726
804
|
if (!args.invoice_id) throw new Error("invoice_id is required when action is 'claim_invoice'.");
|
|
805
|
+
const resolvedPack = args.pack || LAST_INVOICE_PACK || undefined;
|
|
727
806
|
const claimPayload = {
|
|
728
807
|
invoice_id: args.invoice_id,
|
|
729
|
-
pack:
|
|
808
|
+
pack: resolvedPack === "launch" ? "launch" : undefined,
|
|
730
809
|
};
|
|
731
|
-
const targetReloadKey = args.api_key || (args.reload_existing ?
|
|
810
|
+
const targetReloadKey = args.api_key || (args.reload_existing ? loadSavedApiKey() : "");
|
|
732
811
|
if (targetReloadKey && targetReloadKey.trim()) {
|
|
733
812
|
claimPayload.api_key = targetReloadKey.trim();
|
|
734
813
|
}
|
|
@@ -740,6 +819,8 @@ async function executeTool(name, args = {}) {
|
|
|
740
819
|
const data = await res.json();
|
|
741
820
|
if (data.api_key) {
|
|
742
821
|
CURRENT_API_KEY = data.api_key;
|
|
822
|
+
saveApiKeyConfig(data.api_key, resolvedPack || "standard");
|
|
823
|
+
data.saved_to_config = API_KEY_CONFIG_PATH;
|
|
743
824
|
}
|
|
744
825
|
return data;
|
|
745
826
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rel-time/mcp-server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Official Model Context Protocol (MCP) server for Rel-Time (rel-time.com) — Zero-Knowledge Bitcoin & VDF Provenance, Local File Hashing, and Sun-Stamp Generation for Claude, Cursor, Windsurf, and Antigravity.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|