carpool-mcp 0.1.0 → 0.2.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 +13 -0
- package/dist/cli.js +126 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,19 @@ Requires Node 20.19 or newer.
|
|
|
15
15
|
|
|
16
16
|
## Install in Claude Code
|
|
17
17
|
|
|
18
|
+
One command:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx carpool-mcp setup
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It asks for a Hedera ECDSA testnet account id and key (press Enter to skip and search only),
|
|
25
|
+
associates the account with test USDC if needed, and adds Carpool to Claude Code for every project.
|
|
26
|
+
The same account buys and earns. To buy, top it up with test USDC at https://faucet.circle.com.
|
|
27
|
+
No account yet? Create one at https://portal.hedera.com.
|
|
28
|
+
|
|
29
|
+
### Or add it by hand
|
|
30
|
+
|
|
18
31
|
Search only (no keys, nothing is paid):
|
|
19
32
|
|
|
20
33
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,14 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// apps/registry/src/scripts/associate-account-lib.ts
|
|
18
|
+
var associate_account_lib_exports = {};
|
|
19
|
+
__export(associate_account_lib_exports, {
|
|
20
|
+
InputError: () => InputError,
|
|
21
|
+
USDC_TESTNET: () => USDC_TESTNET,
|
|
22
|
+
checkAccountKeyType: () => checkAccountKeyType,
|
|
23
|
+
parseAccountId: () => parseAccountId,
|
|
24
|
+
parsePrivateKey: () => parsePrivateKey
|
|
25
|
+
});
|
|
18
26
|
function parseAccountId(value) {
|
|
19
27
|
const v = (value ?? "").trim();
|
|
20
28
|
if (!v) throw new InputError("HEDERA_ACCOUNT_ID is not set. Pass it as an environment variable, e.g. HEDERA_ACCOUNT_ID=0.0.12345");
|
|
@@ -147,6 +155,109 @@ var init_associate_account_run = __esm({
|
|
|
147
155
|
}
|
|
148
156
|
});
|
|
149
157
|
|
|
158
|
+
// apps/mcp/scripts/npm-setup.ts
|
|
159
|
+
var npm_setup_exports = {};
|
|
160
|
+
__export(npm_setup_exports, {
|
|
161
|
+
setup: () => setup
|
|
162
|
+
});
|
|
163
|
+
import { spawnSync } from "node:child_process";
|
|
164
|
+
import { createInterface } from "node:readline";
|
|
165
|
+
function ask(question, hidden = false) {
|
|
166
|
+
return new Promise((resolve) => {
|
|
167
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
168
|
+
if (hidden) {
|
|
169
|
+
const out = rl;
|
|
170
|
+
let prompted = false;
|
|
171
|
+
out._writeToOutput = (s) => {
|
|
172
|
+
if (!prompted) {
|
|
173
|
+
process.stdout.write(s);
|
|
174
|
+
prompted = true;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
rl.question(question, (answer) => {
|
|
179
|
+
rl.close();
|
|
180
|
+
if (hidden) process.stdout.write("\n");
|
|
181
|
+
resolve(answer.trim());
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
async function usdcBalance(id) {
|
|
186
|
+
try {
|
|
187
|
+
const res = await fetch(`${MIRROR2}/api/v1/accounts/${id}/tokens?token.id=${USDC}`);
|
|
188
|
+
if (!res.ok) return null;
|
|
189
|
+
const json = await res.json();
|
|
190
|
+
return json.tokens?.[0]?.balance ?? null;
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function hasClaude() {
|
|
196
|
+
return spawnSync("claude", ["--version"], { stdio: "ignore" }).status === 0;
|
|
197
|
+
}
|
|
198
|
+
async function setup() {
|
|
199
|
+
const registry2 = process.env.CARPOOL_REGISTRY_URL?.trim() || DEFAULT_REGISTRY;
|
|
200
|
+
console.log("Carpool setup\n");
|
|
201
|
+
console.log("A Hedera ECDSA testnet account lets your agent buy research and get paid for its own.");
|
|
202
|
+
console.log("No account yet? Create one at https://portal.hedera.com, or press Enter to search only.\n");
|
|
203
|
+
const id = process.env.HEDERA_ACCOUNT_ID?.trim() || await ask("Account id (0.0.x, Enter to skip): ");
|
|
204
|
+
const env = [["CARPOOL_REGISTRY_URL", registry2]];
|
|
205
|
+
if (id) {
|
|
206
|
+
const key = process.env.HEDERA_PRIVATE_KEY?.trim() || await ask("Private key (hex, hidden): ", true);
|
|
207
|
+
process.env.HEDERA_ACCOUNT_ID = id;
|
|
208
|
+
process.env.HEDERA_PRIVATE_KEY = key;
|
|
209
|
+
const { associateAccount: associateAccount2 } = await Promise.resolve().then(() => (init_associate_account_run(), associate_account_run_exports));
|
|
210
|
+
console.log("\nChecking the account and USDC association...");
|
|
211
|
+
await associateAccount2();
|
|
212
|
+
env.push(
|
|
213
|
+
["CARPOOL_BUYER_ACCOUNT_ID", id],
|
|
214
|
+
["CARPOOL_BUYER_PRIVATE_KEY", key],
|
|
215
|
+
["CARPOOL_AUTHOR_ACCOUNT_ID", id],
|
|
216
|
+
["CARPOOL_AUTHOR_PRIVATE_KEY", key]
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
const args = ["mcp", "add", "carpool", "-s", "user"];
|
|
220
|
+
for (const [k, v] of env) args.push("-e", `${k}=${v}`);
|
|
221
|
+
args.push("--", "npx", "-y", "carpool-mcp");
|
|
222
|
+
if (!hasClaude()) {
|
|
223
|
+
const shown = args.map((a) => a.includes("PRIVATE_KEY=") ? a.replace(/=.*/, "=<your key>") : a);
|
|
224
|
+
console.log("\nClaude Code (the `claude` command) was not found. Once installed, run:\n");
|
|
225
|
+
console.log(` claude ${shown.join(" ")}`);
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
228
|
+
spawnSync("claude", ["mcp", "remove", "carpool", "-s", "user"], { stdio: "ignore" });
|
|
229
|
+
const added = spawnSync("claude", args, { stdio: ["ignore", "ignore", "inherit"] });
|
|
230
|
+
if (added.status !== 0) {
|
|
231
|
+
console.error("\n`claude mcp add` failed; see the message above.");
|
|
232
|
+
return 1;
|
|
233
|
+
}
|
|
234
|
+
console.log("\nDone. Carpool is added to Claude Code for every project. Restart Claude Code to load it.");
|
|
235
|
+
if (!id) {
|
|
236
|
+
console.log("Search only. Run `npx carpool-mcp setup` again with an account to buy and publish.");
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
const bal = await usdcBalance(id);
|
|
240
|
+
if (bal === 0) {
|
|
241
|
+
console.log(`
|
|
242
|
+
${id} holds no USDC yet. To buy, get test USDC (Hedera testnet) at https://faucet.circle.com`);
|
|
243
|
+
console.log("Publishing needs none: royalties arrive in this account.");
|
|
244
|
+
} else if (bal !== null) {
|
|
245
|
+
console.log(`
|
|
246
|
+
${id} holds $${(bal / 1e6).toFixed(2)} test USDC. Ready to buy and publish.`);
|
|
247
|
+
}
|
|
248
|
+
console.log("Keys given to `claude mcp add` are stored in plaintext in its config. Use a testnet key.");
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
var DEFAULT_REGISTRY, MIRROR2, USDC;
|
|
252
|
+
var init_npm_setup = __esm({
|
|
253
|
+
"apps/mcp/scripts/npm-setup.ts"() {
|
|
254
|
+
"use strict";
|
|
255
|
+
DEFAULT_REGISTRY = "https://carpool-registry-production.up.railway.app";
|
|
256
|
+
MIRROR2 = "https://testnet.mirrornode.hedera.com";
|
|
257
|
+
USDC = "0.0.429274";
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
150
261
|
// apps/mcp/src/consent.ts
|
|
151
262
|
var consent_exports = {};
|
|
152
263
|
__export(consent_exports, {
|
|
@@ -1174,7 +1285,19 @@ function emitDeny(reason) {
|
|
|
1174
1285
|
);
|
|
1175
1286
|
process.exit(0);
|
|
1176
1287
|
}
|
|
1177
|
-
if (sub === "
|
|
1288
|
+
if (sub === "setup") {
|
|
1289
|
+
const { setup: setup2 } = await Promise.resolve().then(() => (init_npm_setup(), npm_setup_exports));
|
|
1290
|
+
const { InputError: InputError2 } = await Promise.resolve().then(() => (init_associate_account_lib(), associate_account_lib_exports));
|
|
1291
|
+
setup2().then(
|
|
1292
|
+
(code) => process.exit(code),
|
|
1293
|
+
(e) => {
|
|
1294
|
+
console.error(e instanceof InputError2 ? `
|
|
1295
|
+
${e.message}` : `
|
|
1296
|
+
setup failed: ${e.message}`);
|
|
1297
|
+
process.exit(1);
|
|
1298
|
+
}
|
|
1299
|
+
);
|
|
1300
|
+
} else if (sub === "associate") {
|
|
1178
1301
|
const { associateAccount: associateAccount2, InputError: InputError2 } = await Promise.resolve().then(() => (init_associate_account_run(), associate_account_run_exports));
|
|
1179
1302
|
associateAccount2().then(
|
|
1180
1303
|
(code) => process.exit(code),
|
|
@@ -1202,11 +1325,12 @@ if (sub === "associate") {
|
|
|
1202
1325
|
const { server: server2 } = await init_server().then(() => server_exports);
|
|
1203
1326
|
await server2.connect(new StdioServerTransport2());
|
|
1204
1327
|
} else if (sub === "--version" || sub === "-v") {
|
|
1205
|
-
console.log("carpool-mcp 0.
|
|
1328
|
+
console.log("carpool-mcp 0.2.0");
|
|
1206
1329
|
} else {
|
|
1207
1330
|
console.error(
|
|
1208
1331
|
`carpool-mcp: unknown command "${sub}".
|
|
1209
1332
|
Usage: carpool-mcp start the MCP server on stdio
|
|
1333
|
+
carpool-mcp setup associate an account and add Carpool to Claude Code
|
|
1210
1334
|
carpool-mcp associate associate HEDERA_ACCOUNT_ID with test USDC (key from HEDERA_PRIVATE_KEY env)
|
|
1211
1335
|
carpool-mcp consent-hook PreToolUse hook for carpool_publish`
|
|
1212
1336
|
);
|