@prismnetwork/mcp 0.8.0 → 0.8.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/README.md CHANGED
@@ -13,10 +13,14 @@ claude mcp add prism -- npx -y @prismnetwork/mcp
13
13
  Then ask what you can rent. `prism_list_gpus` answers from live capacity with
14
14
  real prices. Leasing spends money, so those tools ask for a wallet and say so.
15
15
 
16
+ Packaged for Claude Code and Codex as the [Prism plugin](https://plugins.prismnetwork.tech),
17
+ which wires this server up and prompts for the wallet at install time.
18
+
16
19
  ## Tools
17
20
 
18
21
  | Tool | Wallet |
19
22
  | --- | --- |
23
+ | `prism_budget` | no |
20
24
  | `prism_list_gpus` | no |
21
25
  | `prism_price_index` | no |
22
26
  | `prism_receipts` | no |
@@ -34,6 +38,8 @@ real prices. Leasing spends money, so those tools ask for a wallet and say so.
34
38
  | `prism_vault_delete` | yes |
35
39
  | `prism_vault_release` | yes |
36
40
 
41
+ - `prism_budget`: the spending limits in force and what has already been spent
42
+ today, with the recent charges.
37
43
  - `prism_wallet`: the agent's address and USDG/ETH balances.
38
44
  - `prism_list_gpus`: GPUs available to lease, with price per second and per hour.
39
45
  - `prism_price_index`: sourced and settled pricing per GPU model, for cost estimates.
@@ -57,6 +63,29 @@ real prices. Leasing spends money, so those tools ask for a wallet and say so.
57
63
  - `prism_vault_delete`: permanently delete an item.
58
64
  - `prism_vault_release`: authorize an item into a lease that clears its trust floor.
59
65
 
66
+ ## Spending limits
67
+
68
+ Two ceilings bound what this server can spend, and a refusal quotes both.
69
+
70
+ | Variable | Default | What it bounds |
71
+ | --- | --- | --- |
72
+ | `PRISM_MAX_USDG` | 1 | Any single lease or generation. `max_usdg` on a call may lower it, never raise it past this. |
73
+ | `PRISM_DAILY_BUDGET_USDG` | 5 | Everything in a rolling 24 hours. `0` removes the ceiling. |
74
+ | `PRISM_LEDGER_PATH` | `~/.prism/spend.json` | Where the spend is recorded. |
75
+
76
+ Spend is written before the money moves, so a crash between funding an escrow
77
+ and answering is counted rather than forgiven, and a restart does not hand back
78
+ a fresh day's allowance. Only an attempt that provably never reached the chain
79
+ is reverted. Two clients pointed at one wallet share one ceiling, because they
80
+ share the ledger file.
81
+
82
+ None of this is the real limit. Fund a dedicated wallet with what you are
83
+ willing to lose: that balance is what survives a bug in everything above.
84
+
85
+ Tools that spend are annotated `destructiveHint` and carry
86
+ `anthropic/requiresUserInteraction`, so Claude Code asks before every one of
87
+ them even in modes that otherwise approve tools automatically.
88
+
60
89
  ## Vault
61
90
 
62
91
  An agent that handles a card, an identity document or a credential should not
@@ -82,7 +111,8 @@ Point your MCP client (Claude Desktop / Code) at the published server:
82
111
  "args": ["-y", "@prismnetwork/mcp"],
83
112
  "env": {
84
113
  "PRISM_AGENT_KEY": "0x<agent wallet private key>",
85
- "PRISM_ESCROW": "0x62C042265991bEa17B07229322A01850974626dA"
114
+ "PRISM_MAX_USDG": "1",
115
+ "PRISM_DAILY_BUDGET_USDG": "5"
86
116
  }
87
117
  }
88
118
  }
@@ -95,11 +125,17 @@ Or add it to Claude Code in one line:
95
125
 
96
126
  ```sh
97
127
  claude mcp add prism \
98
- --env PRISM_ESCROW=0x62C042265991bEa17B07229322A01850974626dA \
99
128
  --env PRISM_AGENT_KEY=0x<agent wallet private key> \
129
+ --env PRISM_DAILY_BUDGET_USDG=5 \
100
130
  -- npx -y @prismnetwork/mcp
101
131
  ```
102
132
 
133
+ Codex takes the same server:
134
+
135
+ ```sh
136
+ codex mcp add prism --env PRISM_AGENT_KEY=0x<agent wallet private key> -- npx -y @prismnetwork/mcp
137
+ ```
138
+
103
139
  ## Timing
104
140
 
105
141
  `prism_lease` and `prism_lease_and_run` block while a GPU provisions (usually one to four minutes, occasionally longer on a slow host). Configure your MCP client to allow long tool calls.
package/budget.mjs CHANGED
@@ -1,16 +1,13 @@
1
1
  // What stands between a model deciding to rent a GPU and a wallet paying for it.
2
- //
3
- // The wallet balance is the real ceiling: fund the agent wallet with what you
4
- // are willing to lose, because nothing here can spend money that is not in the
5
- // account. This file is the second line, and it exists because the per-call cap
6
- // alone never was one. `max_usdg` bounds a single lease at 1 USDG by default and
7
- // says nothing about the fortieth lease in a row, which is the failure an
8
- // unattended agent actually produces.
2
+ // The real ceiling is the balance; fund the agent wallet with what you are
3
+ // willing to lose. This is the second line, and it exists because `max_usdg`
4
+ // never was one: it bounds a single lease and says nothing about the fortieth in
5
+ // a row, which is what an unattended agent actually does.
9
6
  //
10
7
  // Spend is written before the money moves and reverted only when the attempt
11
8
  // provably cost nothing, so a crash between funding and reply is counted rather
12
9
  // than forgiven. The file is shared across clients on purpose: one wallet gets
13
- // one daily ceiling whether Claude, Codex, or a script is holding it.
10
+ // one daily ceiling whoever is holding it.
14
11
  import { mkdirSync, readFileSync, renameSync, writeFileSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
15
12
  import { homedir } from "node:os";
16
13
  import { dirname, join } from "node:path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismnetwork/mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "MCP server for leasing and running on Prism Network GPUs.",
5
5
  "mcpName": "io.github.prismnetwork-tech/mcp",
6
6
  "type": "module",
package/server.mjs CHANGED
@@ -67,7 +67,7 @@ function requireWallet(tool, reason = "spends money") {
67
67
 
68
68
  function requireLedger(tool) {
69
69
  if (!ledger) {
70
- throw new Error(`${tool} spends money and the spend limits are unusable: ${budgetProblem}`);
70
+ throw new Error(`${tool} needs the spend limits, and they are unusable: ${budgetProblem}`);
71
71
  }
72
72
  return ledger;
73
73
  }
@@ -79,14 +79,25 @@ function requireLedger(tool) {
79
79
  async function spending(tool, micros, run) {
80
80
  const book = requireLedger(tool);
81
81
  const id = book.commit({ tool, micros });
82
+ // Reconciling is bookkeeping and must never be the reason a caller loses a
83
+ // machine it paid for, or the reason a failure is reported as the wrong
84
+ // failure. A ledger that cannot be written says so on stderr and the
85
+ // committed figure stands, which errs towards counting the spend.
86
+ const reconcile = (action, ...args) => {
87
+ try {
88
+ book[action](id, ...args);
89
+ } catch (err) {
90
+ console.error(`prism mcp: could not ${action} the ledger entry for ${tool}: ${err?.message ?? err}`);
91
+ }
92
+ };
82
93
  try {
83
94
  const { value, settledMicros, reference } = await run();
84
- book.settle(id, { micros: settledMicros, reference });
95
+ reconcile("settle", { micros: settledMicros, reference });
85
96
  return value;
86
97
  } catch (err) {
87
98
  const funded = err?.body?.funding_hash;
88
- if (funded) book.settle(id, { reference: funded });
89
- else book.revert(id);
99
+ if (funded) reconcile("settle", { reference: funded });
100
+ else reconcile("revert");
90
101
  throw err;
91
102
  }
92
103
  }
@@ -104,8 +115,8 @@ function requireCommand(value) {
104
115
  // The per-call ceiling is the operator's, not the model's: an omitted max_usdg
105
116
  // takes the configured cap rather than a hardcoded one, and a stated max_usdg
106
117
  // above it is refused when the ledger checks the commit.
107
- function maxDeposit(args) {
108
- if (args.max_usdg === undefined) return requireLedger("this tool").maxPerCallMicros;
118
+ function maxDeposit(tool, args) {
119
+ if (args.max_usdg === undefined) return requireLedger(tool).maxPerCallMicros;
109
120
  const cap = args.max_usdg;
110
121
  if (typeof cap !== "number" || !Number.isFinite(cap) || cap <= 0) {
111
122
  throw new Error("max_usdg must be a positive number of USDG.");
@@ -473,7 +484,7 @@ async function handle(name, args) {
473
484
  if (name === "prism_batch_run") {
474
485
  requireCommand(args.command);
475
486
  requireWallet(name);
476
- const cap = maxDeposit(args);
487
+ const cap = maxDeposit(name, args);
477
488
  return spending(name, cap, async () => {
478
489
  const batch = await agent.lease({
479
490
  image: IMAGE,
@@ -571,7 +582,7 @@ async function handle(name, args) {
571
582
  if (name === "prism_lease_and_run" || name === "prism_lease") {
572
583
  if (name === "prism_lease_and_run") requireCommand(args.command);
573
584
  requireWallet(name);
574
- const cap = maxDeposit(args);
585
+ const cap = maxDeposit(name, args);
575
586
  sweepExpiredLeases();
576
587
  const lease = await spending(name, cap, async () => {
577
588
  const funded = await agent.lease({
@@ -679,7 +690,7 @@ async function handleVault(name, args) {
679
690
  throw new Error(`unknown tool ${name}`);
680
691
  }
681
692
 
682
- const server = new Server({ name: "prism", version: "0.8.0" }, { capabilities: { tools: {} } });
693
+ const server = new Server({ name: "prism", version: "0.8.2" }, { capabilities: { tools: {} } });
683
694
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
684
695
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
685
696
  try {