@elisym/mcp 0.3.2 → 0.3.3
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 +9 -9
- package/dist/index.js +60 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -106,15 +106,15 @@ The bootstrap step is unchanged - the wizard collects the passphrase interactive
|
|
|
106
106
|
|
|
107
107
|
## Environment Variables
|
|
108
108
|
|
|
109
|
-
| Variable | Description
|
|
110
|
-
| --------------------------- |
|
|
111
|
-
| `ELISYM_AGENT` | Load agent from `~/.elisym/agents/<name>/`
|
|
112
|
-
| `ELISYM_NOSTR_SECRET` | Nostr secret key (hex or nsec) for ephemeral mode
|
|
113
|
-
| `ELISYM_AGENT_NAME` | Agent display name (default: mcp-agent)
|
|
114
|
-
| `ELISYM_NETWORK` | Solana network for ephemeral mode
|
|
115
|
-
| `ELISYM_PASSPHRASE` | Passphrase for encrypted agent configs (optional)
|
|
116
|
-
| `ELISYM_ALLOW_WITHDRAWAL` | Set to `1` to override per-agent `security.withdrawals_enabled` flag (CI use)
|
|
117
|
-
| `ELISYM_ALLOW_AGENT_SWITCH` | Set to `1` to override per-agent `security.agent_switch_enabled` flag
|
|
109
|
+
| Variable | Description |
|
|
110
|
+
| --------------------------- | ------------------------------------------------------------------------------- |
|
|
111
|
+
| `ELISYM_AGENT` | Load agent from `~/.elisym/agents/<name>/` |
|
|
112
|
+
| `ELISYM_NOSTR_SECRET` | Nostr secret key (hex or nsec) for ephemeral mode |
|
|
113
|
+
| `ELISYM_AGENT_NAME` | Agent display name (default: mcp-agent) |
|
|
114
|
+
| `ELISYM_NETWORK` | Solana network for ephemeral mode. Only `devnet` is supported (default: devnet) |
|
|
115
|
+
| `ELISYM_PASSPHRASE` | Passphrase for encrypted agent configs (optional) |
|
|
116
|
+
| `ELISYM_ALLOW_WITHDRAWAL` | Set to `1` to override per-agent `security.withdrawals_enabled` flag (CI use) |
|
|
117
|
+
| `ELISYM_ALLOW_AGENT_SWITCH` | Set to `1` to override per-agent `security.agent_switch_enabled` flag |
|
|
118
118
|
|
|
119
119
|
## Usage Examples
|
|
120
120
|
|
package/dist/index.js
CHANGED
|
@@ -42,8 +42,16 @@ function agentsDir() {
|
|
|
42
42
|
function agentConfigPath(name) {
|
|
43
43
|
return join(agentsDir(), name, "config.json");
|
|
44
44
|
}
|
|
45
|
-
function coerceNetwork(raw) {
|
|
46
|
-
|
|
45
|
+
function coerceNetwork(raw, agentName) {
|
|
46
|
+
if (raw === void 0 || raw === "devnet") {
|
|
47
|
+
return "devnet";
|
|
48
|
+
}
|
|
49
|
+
if (raw === "mainnet") {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Agent "${agentName}" is configured for mainnet, which is not supported until the elisym-config program is deployed there. Re-create the agent with --network devnet: rm -rf ~/.elisym/agents/${agentName} && elisym-mcp init ${agentName} --network devnet`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Agent "${agentName}" has unsupported network "${raw}". Expected "devnet".`);
|
|
47
55
|
}
|
|
48
56
|
async function loadAgentConfig(name, passphrase) {
|
|
49
57
|
validateAgentName(name);
|
|
@@ -65,7 +73,7 @@ async function loadAgentConfig(name, passphrase) {
|
|
|
65
73
|
`Failed to load agent "${name}": ${msg}. If this config was created by an earlier version, delete ~/.elisym/agents/${name} and run "elisym-mcp init ${name}" again.`
|
|
66
74
|
);
|
|
67
75
|
}
|
|
68
|
-
const network = coerceNetwork(config.wallet?.network ?? config.payments?.[0]?.network);
|
|
76
|
+
const network = coerceNetwork(config.wallet?.network ?? config.payments?.[0]?.network, name);
|
|
69
77
|
return {
|
|
70
78
|
nostrSecretKey: config.identity.secret_key,
|
|
71
79
|
solanaSecretKey: config.wallet?.secret_key,
|
|
@@ -160,18 +168,17 @@ async function listAgentNames() {
|
|
|
160
168
|
return [];
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
|
-
function rpcUrlFor(
|
|
164
|
-
return
|
|
171
|
+
function rpcUrlFor(_network) {
|
|
172
|
+
return "https://api.devnet.solana.com";
|
|
165
173
|
}
|
|
166
|
-
async function fetchProtocolConfig(
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
const rpc = createSolanaRpc(rpcUrlFor(cluster));
|
|
174
|
+
async function fetchProtocolConfig(_network) {
|
|
175
|
+
const programId = getProtocolProgramId("devnet");
|
|
176
|
+
const rpc = createSolanaRpc(rpcUrlFor());
|
|
170
177
|
const config = await getProtocolConfig(rpc, programId, { forceRefresh: true });
|
|
171
178
|
return { feeBps: config.feeBps, treasury: config.treasury };
|
|
172
179
|
}
|
|
173
|
-
function explorerClusterFor(
|
|
174
|
-
return
|
|
180
|
+
function explorerClusterFor(_network) {
|
|
181
|
+
return "devnet";
|
|
175
182
|
}
|
|
176
183
|
var RateLimiter = class {
|
|
177
184
|
constructor(maxCalls, windowSecs) {
|
|
@@ -632,7 +639,10 @@ var CreateAgentSchema = z.object({
|
|
|
632
639
|
// customer-mode in 0.1.x and never publishes a NIP-89 capability card,
|
|
633
640
|
// so an advertised capability list would be misleading. Provider-mode
|
|
634
641
|
// (0.2.0) will reintroduce this field.
|
|
635
|
-
|
|
642
|
+
// Only devnet is supported until the elisym-config program ships on mainnet.
|
|
643
|
+
// Mainnet was previously advertised here but every paid flow then crashed at
|
|
644
|
+
// payment time - rejecting at schema level surfaces the error up front.
|
|
645
|
+
network: z.enum(["devnet"]).default("devnet"),
|
|
636
646
|
passphrase: z.string().optional().describe("Optional passphrase; if set, secret keys are encrypted at rest."),
|
|
637
647
|
activate: z.boolean().default(true)
|
|
638
648
|
});
|
|
@@ -1193,18 +1203,34 @@ function makePaymentFeedbackHandler(opts) {
|
|
|
1193
1203
|
);
|
|
1194
1204
|
return;
|
|
1195
1205
|
}
|
|
1196
|
-
|
|
1206
|
+
let parsedRequest;
|
|
1207
|
+
try {
|
|
1208
|
+
parsedRequest = JSON.parse(paymentRequest);
|
|
1209
|
+
} catch {
|
|
1210
|
+
opts.rejectPayment(new Error("Provider sent a malformed payment_request (not valid JSON)."));
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
const signedAmount = typeof parsedRequest.amount === "number" && Number.isInteger(parsedRequest.amount) && parsedRequest.amount > 0 ? parsedRequest.amount : void 0;
|
|
1214
|
+
if (amount !== void 0 && amount > 0 && signedAmount !== void 0 && amount !== signedAmount) {
|
|
1197
1215
|
opts.rejectPayment(
|
|
1198
1216
|
new Error(
|
|
1199
|
-
`Payment
|
|
1217
|
+
`Payment request mismatch: feedback tag amount=${amount} differs from signed amount=${signedAmount}. Refusing to proceed.`
|
|
1200
1218
|
)
|
|
1201
1219
|
);
|
|
1202
1220
|
return;
|
|
1203
1221
|
}
|
|
1204
|
-
if (opts.maxPriceLamports
|
|
1222
|
+
if (opts.maxPriceLamports === void 0 && signedAmount !== void 0) {
|
|
1205
1223
|
opts.rejectPayment(
|
|
1206
1224
|
new Error(
|
|
1207
|
-
`
|
|
1225
|
+
`Payment of ${formatSol(BigInt(signedAmount))} required but no max_price_lamports set. Retry with max_price_lamports to approve.`
|
|
1226
|
+
)
|
|
1227
|
+
);
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
if (opts.maxPriceLamports !== void 0 && signedAmount !== void 0 && signedAmount > opts.maxPriceLamports) {
|
|
1231
|
+
opts.rejectPayment(
|
|
1232
|
+
new Error(
|
|
1233
|
+
`Price ${formatSol(BigInt(signedAmount))} exceeds max ${formatSol(BigInt(opts.maxPriceLamports))}`
|
|
1208
1234
|
)
|
|
1209
1235
|
);
|
|
1210
1236
|
return;
|
|
@@ -1212,7 +1238,7 @@ function makePaymentFeedbackHandler(opts) {
|
|
|
1212
1238
|
if (!opts.agent.solanaKeypair) {
|
|
1213
1239
|
opts.resolveNoWallet(
|
|
1214
1240
|
`Payment required but no Solana wallet configured.
|
|
1215
|
-
Amount: ${
|
|
1241
|
+
Amount: ${signedAmount !== void 0 ? formatSol(BigInt(signedAmount)) : "unknown"}
|
|
1216
1242
|
Payment request: ${paymentRequest}`
|
|
1217
1243
|
);
|
|
1218
1244
|
return;
|
|
@@ -1642,7 +1668,7 @@ ${result}`);
|
|
|
1642
1668
|
var GetDashboardSchema = z.object({
|
|
1643
1669
|
top_n: z.number().int().min(1).max(100).default(10),
|
|
1644
1670
|
chain: z.enum(["solana"]).default("solana"),
|
|
1645
|
-
network: z.enum(["devnet"
|
|
1671
|
+
network: z.enum(["devnet"]).optional(),
|
|
1646
1672
|
timeout_secs: z.number().int().min(1).max(60).default(15)
|
|
1647
1673
|
});
|
|
1648
1674
|
var dashboardTools = [
|
|
@@ -2411,9 +2437,14 @@ program.action(async () => {
|
|
|
2411
2437
|
}
|
|
2412
2438
|
const client = new ElisymClient({ relays: RELAYS });
|
|
2413
2439
|
const name = process.env.ELISYM_AGENT_NAME ?? "mcp-agent";
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2440
|
+
if (process.env.ELISYM_NETWORK && process.env.ELISYM_NETWORK !== "devnet") {
|
|
2441
|
+
console.error(
|
|
2442
|
+
`ELISYM_NETWORK="${process.env.ELISYM_NETWORK}" is not supported. Only "devnet" is available until the on-chain protocol program ships on mainnet.`
|
|
2443
|
+
);
|
|
2444
|
+
process.exit(1);
|
|
2445
|
+
}
|
|
2446
|
+
ctx.register({ client, identity, name, network: "devnet", security: {} });
|
|
2447
|
+
console.error(`Ephemeral agent: ${name} (devnet)`);
|
|
2417
2448
|
} else {
|
|
2418
2449
|
const names = (await listAgentNames()).slice().sort();
|
|
2419
2450
|
if (names.length > 0) {
|
|
@@ -2436,7 +2467,7 @@ program.action(async () => {
|
|
|
2436
2467
|
}
|
|
2437
2468
|
await startServer(ctx);
|
|
2438
2469
|
});
|
|
2439
|
-
program.command("init [name]").description("Create a new agent identity").option("-d, --description <desc>", "Agent description", "Elisym MCP agent").option("-n, --network <network>", "Solana network (devnet
|
|
2470
|
+
program.command("init [name]").description("Create a new agent identity").option("-d, --description <desc>", "Agent description", "Elisym MCP agent").option("-n, --network <network>", "Solana network (devnet only)", "devnet").option("--install", "Also install into MCP clients").action(async (name, options) => {
|
|
2440
2471
|
const { default: inquirer } = await import('inquirer');
|
|
2441
2472
|
if (!name) {
|
|
2442
2473
|
const answers = await inquirer.prompt([
|
|
@@ -2456,8 +2487,8 @@ program.command("init [name]").description("Create a new agent identity").option
|
|
|
2456
2487
|
type: "list",
|
|
2457
2488
|
name: "network",
|
|
2458
2489
|
message: "Solana network:",
|
|
2459
|
-
//
|
|
2460
|
-
choices: ["devnet"
|
|
2490
|
+
// Only devnet is supported until the elisym-config program ships on mainnet.
|
|
2491
|
+
choices: ["devnet"],
|
|
2461
2492
|
default: "devnet"
|
|
2462
2493
|
}
|
|
2463
2494
|
]);
|
|
@@ -2465,8 +2496,10 @@ program.command("init [name]").description("Create a new agent identity").option
|
|
|
2465
2496
|
options.description = answers.description;
|
|
2466
2497
|
options.network = answers.network;
|
|
2467
2498
|
}
|
|
2468
|
-
if (options.network !== "devnet"
|
|
2469
|
-
console.error(
|
|
2499
|
+
if (options.network !== "devnet") {
|
|
2500
|
+
console.error(
|
|
2501
|
+
`Network must be "devnet", got "${options.network}". Mainnet is not supported until the on-chain protocol program is deployed.`
|
|
2502
|
+
);
|
|
2470
2503
|
process.exit(1);
|
|
2471
2504
|
}
|
|
2472
2505
|
const { passphrase } = await inquirer.prompt([
|
|
@@ -2488,7 +2521,7 @@ program.command("init [name]").description("Create a new agent identity").option
|
|
|
2488
2521
|
nostrSecretKey: Buffer.from(nostrSecretKey).toString("hex"),
|
|
2489
2522
|
solanaSecretKey: bs58.encode(solanaSecretBytes),
|
|
2490
2523
|
solanaAddress: solanaSigner.address,
|
|
2491
|
-
network:
|
|
2524
|
+
network: "devnet",
|
|
2492
2525
|
security: { withdrawals_enabled: false, agent_switch_enabled: false },
|
|
2493
2526
|
passphrase: passphrase || void 0
|
|
2494
2527
|
});
|