brainchain-mcp 0.7.6 → 0.8.0
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 +12 -12
- package/dist/bonds.js +15 -12
- package/dist/config.js +1 -1
- package/dist/shipped.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Read the key without echoing it or leaving it in your shell history, then add th
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
printf 'Key: ' && read -rs BRAINCHAIN_PAYER_KEY && echo
|
|
19
|
-
claude mcp add brainchain --scope user -e BRAINCHAIN_PAYER_KEY="$BRAINCHAIN_PAYER_KEY" -- npx -y brainchain-mcp@0.
|
|
19
|
+
claude mcp add brainchain --scope user -e BRAINCHAIN_PAYER_KEY="$BRAINCHAIN_PAYER_KEY" -- npx -y brainchain-mcp@0.8.0
|
|
20
20
|
unset BRAINCHAIN_PAYER_KEY
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -27,7 +27,7 @@ unset BRAINCHAIN_PAYER_KEY
|
|
|
27
27
|
"mcpServers": {
|
|
28
28
|
"brainchain": {
|
|
29
29
|
"command": "npx",
|
|
30
|
-
"args": ["-y", "brainchain-mcp@0.
|
|
30
|
+
"args": ["-y", "brainchain-mcp@0.8.0"],
|
|
31
31
|
"env": { "BRAINCHAIN_PAYER_KEY": "${BRAINCHAIN_PAYER_KEY}" }
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -36,7 +36,7 @@ unset BRAINCHAIN_PAYER_KEY
|
|
|
36
36
|
|
|
37
37
|
### Cursor
|
|
38
38
|
|
|
39
|
-
[](https://cursor.com/en/install-mcp?name=brainchain&config=
|
|
39
|
+
[](https://cursor.com/en/install-mcp?name=brainchain&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImJyYWluY2hhaW4tbWNwQDAuOC4wIl0sImVudiI6eyJCUkFJTkNIQUlOX1BBWUVSX0tFWSI6IiR7ZW52OkJSQUlOQ0hBSU5fUEFZRVJfS0VZfSJ9fQ%3D%3D)
|
|
40
40
|
|
|
41
41
|
Or add the server to a project's `.cursor/mcp.json` (`~/.cursor/mcp.json` for every project):
|
|
42
42
|
|
|
@@ -45,7 +45,7 @@ Or add the server to a project's `.cursor/mcp.json` (`~/.cursor/mcp.json` for ev
|
|
|
45
45
|
"mcpServers": {
|
|
46
46
|
"brainchain": {
|
|
47
47
|
"command": "npx",
|
|
48
|
-
"args": ["-y", "brainchain-mcp@0.
|
|
48
|
+
"args": ["-y", "brainchain-mcp@0.8.0"],
|
|
49
49
|
"env": { "BRAINCHAIN_PAYER_KEY": "${env:BRAINCHAIN_PAYER_KEY}" }
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -63,7 +63,7 @@ Add the server to the client's `mcpServers` configuration. For Claude Desktop th
|
|
|
63
63
|
"mcpServers": {
|
|
64
64
|
"brainchain": {
|
|
65
65
|
"command": "npx",
|
|
66
|
-
"args": ["-y", "brainchain-mcp@0.
|
|
66
|
+
"args": ["-y", "brainchain-mcp@0.8.0"],
|
|
67
67
|
"env": { "BRAINCHAIN_PAYER_KEY": "0xYOUR_KEY" }
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -82,7 +82,7 @@ These clients keep the key in that file as plain text.
|
|
|
82
82
|
"brainchain": {
|
|
83
83
|
"type": "stdio",
|
|
84
84
|
"command": "npx",
|
|
85
|
-
"args": ["-y", "brainchain-mcp@0.
|
|
85
|
+
"args": ["-y", "brainchain-mcp@0.8.0"],
|
|
86
86
|
"env": { "BRAINCHAIN_PAYER_KEY": "${input:brainchain-key}" }
|
|
87
87
|
}
|
|
88
88
|
},
|
|
@@ -100,10 +100,10 @@ Save the key in a file only your account can read, then point the server at it:
|
|
|
100
100
|
mkdir -p ~/.brainchain
|
|
101
101
|
(umask 077; printf 'Key: ' && read -rs key && echo && printf '%s\n' "$key" > ~/.brainchain/payer.key)
|
|
102
102
|
chmod 600 ~/.brainchain/payer.key
|
|
103
|
-
openclaw mcp set brainchain '{"command":"npx","args":["-y","brainchain-mcp@0.
|
|
103
|
+
openclaw mcp set brainchain '{"command":"npx","args":["-y","brainchain-mcp@0.8.0"],"env":{"BRAINCHAIN_PAYER_KEY_FILE":"~/.brainchain/payer.key"}}'
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
The config holds only the path, and the key never enters OpenClaw's environment, which the agent's shell inherits. A key saved in `skills.entries.brainchain.apiKey` does not reach the server. `BRAINCHAIN_PAYER_KEY_FILE=~/.brainchain/payer.key npx -y brainchain-mcp@0.
|
|
106
|
+
The config holds only the path, and the key never enters OpenClaw's environment, which the agent's shell inherits. A key saved in `skills.entries.brainchain.apiKey` does not reach the server. `BRAINCHAIN_PAYER_KEY_FILE=~/.brainchain/payer.key npx -y brainchain-mcp@0.8.0 wallet` checks the file and prints the wallet it holds and its balance. [`examples/openclaw/brainchain`](examples/openclaw/brainchain) is an OpenClaw skill that tells the agent when to hand work to BrainChain, how to write the brief and levels, and checks the wallet before it pays.
|
|
107
107
|
|
|
108
108
|
Each setup above pays in USDG on Robinhood Chain. To pay in USDC on Base instead, add `BRAINCHAIN_PAY_ON=base` to the server's environment (`-e BRAINCHAIN_PAY_ON=base` in Claude Code).
|
|
109
109
|
|
|
@@ -117,7 +117,7 @@ Each brief is posted on BrainChain and each result is served at a public link. K
|
|
|
117
117
|
|
|
118
118
|
```bash
|
|
119
119
|
printf 'Key: ' && read -rs BRAINCHAIN_PAYER_KEY && echo && export BRAINCHAIN_PAYER_KEY
|
|
120
|
-
npx -y brainchain-mcp@0.
|
|
120
|
+
npx -y brainchain-mcp@0.8.0 approve
|
|
121
121
|
unset BRAINCHAIN_PAYER_KEY
|
|
122
122
|
```
|
|
123
123
|
|
|
@@ -166,7 +166,7 @@ Every hire and grade is recorded on BrainChain and listed at [usebrainchain.com/
|
|
|
166
166
|
| `BRAINCHAIN_STATE_DIR` | `~/.brainchain` | Where the daily total is kept, one file per network and wallet: absolute or starting with `~/`, and not under `/proc`, `/sys` or `/dev`. |
|
|
167
167
|
| `BRAINCHAIN_DESK_URL`, `BRAINCHAIN_PAY_TO`, `BRAINCHAIN_PAYMENT_NETWORK`, `BRAINCHAIN_PAYMENT_ASSET`, `BRAINCHAIN_PAYMENT_RPC` | network preset | Override a single setting. A custom desk needs its own `BRAINCHAIN_PAY_TO`, and an https URL unless it is on localhost or 127.0.0.1. |
|
|
168
168
|
|
|
169
|
-
If a setting is invalid, the server says so once on stderr when it starts, and each tool the setting stops returns that error and does nothing else. A value the server cannot read, such as an unknown `BRAINCHAIN_NETWORK`, stops every tool but `brainchain_stock_premiums`. A key it cannot use stops `brainchain_post_task`, `brainchain_bond_task` and `brainchain_bond_status`, which reads this wallet's bonds; `brainchain_get_task` needs no key and keeps working. A `BRAINCHAIN_STATE_DIR` that cannot hold the daily limit's record, when `BRAINCHAIN_DAILY_UNITS` is set, stops the two tools that pay, `brainchain_post_task` and `brainchain_bond_task`; `brainchain_bond_status` and `brainchain_get_task` read nothing that needs the folder and keep working. `npx -y brainchain-mcp@0.
|
|
169
|
+
If a setting is invalid, the server says so once on stderr when it starts, and each tool the setting stops returns that error and does nothing else. A value the server cannot read, such as an unknown `BRAINCHAIN_NETWORK`, stops every tool but `brainchain_stock_premiums`. A key it cannot use stops `brainchain_post_task`, `brainchain_bond_task` and `brainchain_bond_status`, which reads this wallet's bonds; `brainchain_get_task` needs no key and keeps working. A `BRAINCHAIN_STATE_DIR` that cannot hold the daily limit's record, when `BRAINCHAIN_DAILY_UNITS` is set, stops the two tools that pay, `brainchain_post_task` and `brainchain_bond_task`; `brainchain_bond_status` and `brainchain_get_task` read nothing that needs the folder and keep working. `npx -y brainchain-mcp@0.8.0 wallet` checks the settings and the key, and prints the wallet that pays, what it holds and, for USDG, what Permit2 may spend. `--help` lists the commands and variables, and `--version` prints the version.
|
|
170
170
|
|
|
171
171
|
## Try it on testnet
|
|
172
172
|
|
|
@@ -174,7 +174,7 @@ Set `BRAINCHAIN_NETWORK=testnet` in the server's environment. Test tokens have n
|
|
|
174
174
|
|
|
175
175
|
```bash
|
|
176
176
|
printf 'Key: ' && read -rs BRAINCHAIN_PAYER_KEY && echo
|
|
177
|
-
claude mcp add brainchain --scope user -e BRAINCHAIN_NETWORK=testnet -e BRAINCHAIN_PAYER_KEY="$BRAINCHAIN_PAYER_KEY" -- npx -y brainchain-mcp@0.
|
|
177
|
+
claude mcp add brainchain --scope user -e BRAINCHAIN_NETWORK=testnet -e BRAINCHAIN_PAYER_KEY="$BRAINCHAIN_PAYER_KEY" -- npx -y brainchain-mcp@0.8.0
|
|
178
178
|
unset BRAINCHAIN_PAYER_KEY
|
|
179
179
|
```
|
|
180
180
|
|
|
@@ -193,7 +193,7 @@ unset BRAINCHAIN_PAYER_KEY
|
|
|
193
193
|
|
|
194
194
|
```bash
|
|
195
195
|
printf 'Key: ' && read -rs BRAINCHAIN_PAYER_KEY && echo && export BRAINCHAIN_PAYER_KEY
|
|
196
|
-
BRAINCHAIN_NETWORK=testnet npx -y brainchain-mcp@0.
|
|
196
|
+
BRAINCHAIN_NETWORK=testnet npx -y brainchain-mcp@0.8.0 approve
|
|
197
197
|
unset BRAINCHAIN_PAYER_KEY
|
|
198
198
|
```
|
|
199
199
|
|
package/dist/bonds.js
CHANGED
|
@@ -85,15 +85,18 @@ export function createBondChain(bonds, account, desk, fetchImpl = fetch) {
|
|
|
85
85
|
const deeds = await client.multicall({ contracts: mine.map((id) => ({ ...registry, functionName: "getDeed", args: [id] })), allowFailure: false });
|
|
86
86
|
return mine.flatMap((deed, i) => {
|
|
87
87
|
const d = deeds[i];
|
|
88
|
-
if (d.terms.check.toLowerCase() !== bonds.check.toLowerCase()
|
|
88
|
+
if (d.terms.check.toLowerCase() !== bonds.check.toLowerCase())
|
|
89
89
|
return [];
|
|
90
|
-
|
|
90
|
+
const board = [bonds.brainchain.board, ...(bonds.brainchain.retired ?? [])].find((b) => taskOfCheck(d.terms.checkData, bonds.proofIndex, b) === task);
|
|
91
|
+
if (!board)
|
|
92
|
+
return [];
|
|
93
|
+
return [{ deed, amount: d.balance, deadline: d.terms.deadline, status: d.status, remainderBps: d.remainderBps, checkMetAt: d.checkMetAt, settledAt: d.settledAt, refundTo: d.terms.refundTo, board }];
|
|
91
94
|
});
|
|
92
95
|
}
|
|
93
96
|
return {
|
|
94
97
|
account: account.address,
|
|
95
|
-
async task(id) {
|
|
96
|
-
const t = await read("BrainChain", brainchain.readContract({ address:
|
|
98
|
+
async task(id, board = bonds.brainchain.board) {
|
|
99
|
+
const t = await read("BrainChain", brainchain.readContract({ address: board, abi: taskBoardAbi, functionName: "get", args: [id] }));
|
|
97
100
|
return t.status === 0 ? undefined : { poster: t.poster, bounty: t.bounty, deadline: t.deadline, status: t.status, model: t.model };
|
|
98
101
|
},
|
|
99
102
|
now: async () => (await read(bonds.chain, client.getBlock())).timestamp,
|
|
@@ -118,7 +121,7 @@ export function createBondChain(bonds, account, desk, fetchImpl = fetch) {
|
|
|
118
121
|
return { deed: created.args.deedId, tx: hash };
|
|
119
122
|
},
|
|
120
123
|
bondsOn: (task) => read(bonds.chain, deedsOn(task)),
|
|
121
|
-
proofOf: (task) => read(bonds.chain, client.readContract({ address: bonds.proofIndex, abi: parseAbi(["function proofOf(address board, uint256 taskId) view returns (uint256)"]), functionName: "proofOf", args: [
|
|
124
|
+
proofOf: (task, board = bonds.brainchain.board) => read(bonds.chain, client.readContract({ address: bonds.proofIndex, abi: parseAbi(["function proofOf(address board, uint256 taskId) view returns (uint256)"]), functionName: "proofOf", args: [board, task] })),
|
|
122
125
|
owed: () => read(bonds.chain, client.readContract({ ...registry, functionName: "owed", args: [account.address, bonds.usdg] })),
|
|
123
126
|
async payerOf(task) {
|
|
124
127
|
let response;
|
|
@@ -230,7 +233,8 @@ export function createBonds(options) {
|
|
|
230
233
|
throw new Error(`The bond must be at least ${formatUnits(MIN_BOND)} USDG: under that, Shipped's fee and the gas take too much of it. Nothing was bonded.`);
|
|
231
234
|
if (amount > config.maxBond)
|
|
232
235
|
throw new Error(`This server bonds at most ${formatUnits(config.maxBond)} USDG on one task. Raise BRAINCHAIN_MAX_BOND_UNITS and restart the server to allow more. Nothing was bonded.`);
|
|
233
|
-
|
|
236
|
+
// Task ids restart with each board, so a bond on a retired board's task of this number is another task's.
|
|
237
|
+
const existing = (await c.bondsOn(task)).find((b) => b.status !== DeedStatus.Settled && b.board.toLowerCase() === config.bonds.brainchain.board.toLowerCase());
|
|
234
238
|
if (existing) {
|
|
235
239
|
const page = await deedPage(existing.deed, options.fetch);
|
|
236
240
|
throw new Error(`This wallet already has ${page ? `bond No. ${page.number}` : "a bond"} open on task ${task} (registry id ${existing.deed}${page ? `, ${page.url}` : ""}). Nothing was bonded.`);
|
|
@@ -311,21 +315,20 @@ export function createBonds(options) {
|
|
|
311
315
|
return { task: task.toString(), wallet: c.account, bonds: [] };
|
|
312
316
|
const delivered = bonds.some((b) => b.status === DeedStatus.Settled && b.remainderBps === Number(BPS));
|
|
313
317
|
// Only a bond still waiting for its Proof is worded by where the task stands.
|
|
314
|
-
const
|
|
315
|
-
const [now, indexed, t, owed, pages] = await Promise.all([
|
|
318
|
+
const [now, indexed, tasks, owed, pages] = await Promise.all([
|
|
316
319
|
c.now(),
|
|
317
|
-
c.proofOf(task),
|
|
318
|
-
|
|
320
|
+
Promise.all(bonds.map((b) => c.proofOf(task, b.board))),
|
|
321
|
+
Promise.all(bonds.map((b) => (b.status !== DeedStatus.Settled && b.checkMetAt === 0n ? c.task(task, b.board) : undefined))),
|
|
319
322
|
delivered ? c.owed() : 0n,
|
|
320
323
|
Promise.all(bonds.map((b) => deedPage(b.deed, options.fetch))),
|
|
321
324
|
]);
|
|
322
325
|
return {
|
|
323
326
|
task: task.toString(),
|
|
324
327
|
wallet: c.account,
|
|
325
|
-
proofIndexed: indexed > 0n,
|
|
328
|
+
proofIndexed: indexed.some((n) => n > 0n),
|
|
326
329
|
bonds: bonds.map((b, i) => {
|
|
327
330
|
const page = pages[i];
|
|
328
|
-
return { bond: b.deed.toString(), ...(page ? { number: page.number, url: page.url } : {}), amount: `${formatUnits(b.amount)} USDG`, deadline: iso(b.deadline), ...state(b, indexed > 0n, now,
|
|
331
|
+
return { bond: b.deed.toString(), board: b.board, ...(page ? { number: page.number, url: page.url } : {}), amount: `${formatUnits(b.amount)} USDG`, deadline: iso(b.deadline), ...state(b, indexed[i] > 0n, now, tasks[i], owed) };
|
|
329
332
|
}),
|
|
330
333
|
};
|
|
331
334
|
},
|
package/dist/config.js
CHANGED
|
@@ -52,7 +52,7 @@ const BONDS = {
|
|
|
52
52
|
proofIndex: "0x0fb02559e704549794EdF3FBBBe91DB88bB849ee",
|
|
53
53
|
rpc: "https://rpc.mainnet.chain.robinhood.com",
|
|
54
54
|
chain: "Robinhood Chain",
|
|
55
|
-
brainchain: { rpc: "https://rpc.usebrainchain.com", chainId: 274663, board: "0x8385bb4b8990411CcdD8e851B2676da1A4C1f3C4" },
|
|
55
|
+
brainchain: { rpc: "https://rpc.usebrainchain.com", chainId: 274663, board: "0x44b8464342Bbfb9B565FAE494DfDefa37D33A211", retired: ["0x8385bb4b8990411CcdD8e851B2676da1A4C1f3C4"] },
|
|
56
56
|
},
|
|
57
57
|
testnet: undefined,
|
|
58
58
|
};
|
package/dist/shipped.js
CHANGED
|
@@ -25,8 +25,8 @@ export const Ruling = { None: 0, Accepted: 1, Rejected: 2, Partial: 3, Invalid:
|
|
|
25
25
|
export const TaskStatus = { Open: 1, Hired: 2, Paid: 6, Refunded: 7 };
|
|
26
26
|
export const BPS = 10000n;
|
|
27
27
|
export const FEE_BPS = 100n;
|
|
28
|
-
/** The bond's deadline is the task's plus this. */
|
|
29
|
-
export const BOND_LEAD_SEC =
|
|
28
|
+
/** The bond's deadline is the task's plus this: 48 hours for a grade, a dispute and an appealed ruling on set 3.5.0, then the worker's day to mint. */
|
|
29
|
+
export const BOND_LEAD_SEC = 72n * 3600n;
|
|
30
30
|
export const CHECK_HOLD_SEC = 3600n;
|
|
31
31
|
export const CHECK_CONFIRM_SEC = 86400n;
|
|
32
32
|
/** Under this the fee and the gas take too much of the bond. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainchain-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "MCP server for BrainChain: let your agent hire a frontier model for a task and pay in USDG on Robinhood Chain or USDC on Base, only for work that meets the quality bar you set.",
|
|
5
5
|
"mcpName": "com.usebrainchain/brainchain",
|
|
6
6
|
"license": "MIT",
|