@elisym/mcp 0.15.2 → 0.15.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 +2 -1
- package/dist/index.js +138 -104
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,8 @@ npx @elisym/mcp install --agent <agent-name>
|
|
|
24
24
|
# List detected MCP clients
|
|
25
25
|
npx @elisym/mcp install --list
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# Installs pin to @latest, so npx pulls the newest build on each restart.
|
|
28
|
+
# Run update only to force a refresh (clears the npx cache; preserves agent + env).
|
|
28
29
|
npx @elisym/mcp update
|
|
29
30
|
|
|
30
31
|
# Remove from MCP clients
|
package/dist/index.js
CHANGED
|
@@ -5,19 +5,19 @@ import { createIrohTransport, loadGlobalConfig, writeGlobalConfig } from '@elisy
|
|
|
5
5
|
import { getBase58Encoder, getBase58Decoder, generateKeyPairSigner, createSolanaRpc, address, createSolanaRpcSubscriptions, sendAndConfirmTransactionFactory, getSignatureFromTransaction, pipe, createTransactionMessage, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, signTransactionMessageWithSigners, createKeyPairSignerFromBytes, isAddress } from '@solana/kit';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import { generateSecretKey, nip19, getPublicKey } from 'nostr-tools';
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
8
9
|
import { realpath, readFile, stat, mkdir, rm, writeFile, rename, unlink } from 'node:fs/promises';
|
|
9
10
|
import { tmpdir, platform, homedir } from 'node:os';
|
|
10
11
|
import { dirname, join, resolve, isAbsolute, basename, relative } from 'node:path';
|
|
11
|
-
import {
|
|
12
|
-
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { promisify } from 'node:util';
|
|
13
13
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
14
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
15
|
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
16
16
|
import { z, ZodError } from 'zod';
|
|
17
17
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
18
|
+
import { readFileSync, mkdtempSync } from 'node:fs';
|
|
18
19
|
import pino from 'pino';
|
|
19
|
-
import {
|
|
20
|
-
import { promisify } from 'node:util';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
21
|
import { randomBytes } from 'node:crypto';
|
|
22
22
|
import { getTransferSolInstruction } from '@solana-program/system';
|
|
23
23
|
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS, getCreateAssociatedTokenIdempotentInstruction, ASSOCIATED_TOKEN_PROGRAM_ADDRESS, getTransferCheckedInstruction } from '@solana-program/token';
|
|
@@ -271,108 +271,40 @@ async function writeFileAtomic(path, content, mode = 384) {
|
|
|
271
271
|
throw err;
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
|
-
var LAMPORTS_PER_SOL = 1000000000n;
|
|
275
|
-
function readPackageVersion() {
|
|
276
|
-
try {
|
|
277
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
278
|
-
const pkg = JSON.parse(readFileSync(join(here, "..", "package.json"), "utf-8"));
|
|
279
|
-
return pkg.version;
|
|
280
|
-
} catch {
|
|
281
|
-
return "0.0.0";
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
var PACKAGE_VERSION = readPackageVersion();
|
|
285
|
-
function formatSol(lamports) {
|
|
286
|
-
return `${formatSolNumeric(lamports)} SOL`;
|
|
287
|
-
}
|
|
288
|
-
function formatSolNumeric(lamports) {
|
|
289
|
-
const sign = lamports < 0n ? "-" : "";
|
|
290
|
-
const abs = lamports < 0n ? -lamports : lamports;
|
|
291
|
-
const whole = abs / LAMPORTS_PER_SOL;
|
|
292
|
-
const frac = abs % LAMPORTS_PER_SOL;
|
|
293
|
-
return `${sign}${whole}.${frac.toString().padStart(9, "0")}`;
|
|
294
|
-
}
|
|
295
|
-
function assetFromCardPayment(payment2) {
|
|
296
|
-
if (!payment2) {
|
|
297
|
-
return NATIVE_SOL;
|
|
298
|
-
}
|
|
299
|
-
const known = resolveKnownAsset(payment2.chain, payment2.token ?? "sol", payment2.mint);
|
|
300
|
-
if (known) {
|
|
301
|
-
return known;
|
|
302
|
-
}
|
|
303
|
-
if (payment2.token && payment2.symbol && typeof payment2.decimals === "number") {
|
|
304
|
-
return {
|
|
305
|
-
chain: payment2.chain,
|
|
306
|
-
token: payment2.token,
|
|
307
|
-
mint: payment2.mint,
|
|
308
|
-
symbol: payment2.symbol,
|
|
309
|
-
decimals: payment2.decimals
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
return NATIVE_SOL;
|
|
313
|
-
}
|
|
314
|
-
function parseSolToLamports(s) {
|
|
315
|
-
const trimmed = s.trim();
|
|
316
|
-
if (!trimmed) {
|
|
317
|
-
throw new Error("amount is empty");
|
|
318
|
-
}
|
|
319
|
-
if (trimmed.startsWith("-")) {
|
|
320
|
-
throw new Error("amount cannot be negative");
|
|
321
|
-
}
|
|
322
|
-
if (!/^(\d+\.\d*|\d*\.\d+|\d+)$/.test(trimmed)) {
|
|
323
|
-
throw new Error(
|
|
324
|
-
'amount must be a non-negative decimal number (e.g. "0.5", "1", "0.000000001")'
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
const dotPos = trimmed.indexOf(".");
|
|
328
|
-
if (dotPos === -1) {
|
|
329
|
-
const whole = BigInt(trimmed);
|
|
330
|
-
return whole * LAMPORTS_PER_SOL;
|
|
331
|
-
}
|
|
332
|
-
const wholePart = dotPos === 0 ? 0n : BigInt(trimmed.slice(0, dotPos));
|
|
333
|
-
const fracStr = trimmed.slice(dotPos + 1);
|
|
334
|
-
if (fracStr.length > 9) {
|
|
335
|
-
throw new Error("too many decimal places (max 9)");
|
|
336
|
-
}
|
|
337
|
-
const padded = fracStr.padEnd(9, "0");
|
|
338
|
-
const frac = BigInt(padded);
|
|
339
|
-
return wholePart * LAMPORTS_PER_SOL + frac;
|
|
340
|
-
}
|
|
341
|
-
function checkLen(field, value, max) {
|
|
342
|
-
if (new TextEncoder().encode(value).length > max) {
|
|
343
|
-
throw new Error(`${field} too long (max ${max} bytes)`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
var MAX_INPUT_LEN = LIMITS.MAX_INPUT_LENGTH;
|
|
347
|
-
var MAX_CAPABILITIES = LIMITS.MAX_CAPABILITIES;
|
|
348
|
-
var MAX_TIMEOUT_SECS = LIMITS.MAX_TIMEOUT_SECS;
|
|
349
|
-
LIMITS.NIP44_MAX_PLAINTEXT_BYTES;
|
|
350
|
-
LIMITS.MAX_ENCRYPTED_INLINE_BYTES;
|
|
351
|
-
LIMITS.MAX_REINLINE_TEXT_BYTES;
|
|
352
|
-
var MAX_NPUB_LEN = 128;
|
|
353
|
-
var MAX_EVENT_ID_LEN = 128;
|
|
354
|
-
var MAX_PAYMENT_REQ_LEN = 1e4;
|
|
355
|
-
var MAX_SOLANA_ADDR_LEN = 64;
|
|
356
|
-
var _paymentStrategy = null;
|
|
357
|
-
function payment() {
|
|
358
|
-
_paymentStrategy ??= new SolanaPaymentStrategy();
|
|
359
|
-
return _paymentStrategy;
|
|
360
|
-
}
|
|
361
|
-
function decodeNpub(npub) {
|
|
362
|
-
const decoded = nip19.decode(npub);
|
|
363
|
-
if (decoded.type !== "npub") {
|
|
364
|
-
throw new Error(`Expected npub, got ${decoded.type}`);
|
|
365
|
-
}
|
|
366
|
-
return decoded.data;
|
|
367
|
-
}
|
|
368
274
|
|
|
369
275
|
// src/install.ts
|
|
276
|
+
var execFileAsync = promisify(execFile);
|
|
370
277
|
function elisymPackageArgs() {
|
|
371
|
-
return ["-y",
|
|
278
|
+
return ["-y", "@elisym/mcp@latest"];
|
|
372
279
|
}
|
|
373
280
|
function userHome() {
|
|
374
281
|
return process.env.HOME ?? homedir();
|
|
375
282
|
}
|
|
283
|
+
async function resolveNpmCacheDir() {
|
|
284
|
+
const fromEnv = process.env.npm_config_cache;
|
|
285
|
+
if (fromEnv && fromEnv.trim() !== "") {
|
|
286
|
+
return fromEnv.trim();
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const { stdout } = await execFileAsync("npm", ["config", "get", "cache"]);
|
|
290
|
+
const value = stdout.trim();
|
|
291
|
+
if (value && value !== "undefined" && value !== "null") {
|
|
292
|
+
return value;
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
if (platform() === "win32") {
|
|
297
|
+
const localAppData = process.env.LOCALAPPDATA ?? join(userHome(), "AppData", "Local");
|
|
298
|
+
return join(localAppData, "npm-cache");
|
|
299
|
+
}
|
|
300
|
+
return join(userHome(), ".npm");
|
|
301
|
+
}
|
|
302
|
+
async function clearNpxCache() {
|
|
303
|
+
const cacheDir = await resolveNpmCacheDir();
|
|
304
|
+
const npxDir = join(cacheDir, "_npx");
|
|
305
|
+
await rm(npxDir, { recursive: true, force: true });
|
|
306
|
+
console.log(`Cleared npx cache: ${npxDir}`);
|
|
307
|
+
}
|
|
376
308
|
function validateClientName(name) {
|
|
377
309
|
if (name === void 0) {
|
|
378
310
|
return;
|
|
@@ -539,7 +471,7 @@ async function runUpdate(options) {
|
|
|
539
471
|
try {
|
|
540
472
|
const result = await updateCodexConfig(path, options.agent);
|
|
541
473
|
if (result === "updated") {
|
|
542
|
-
console.log(`Updated ${client.name}: ${path} -> @elisym/mcp
|
|
474
|
+
console.log(`Updated ${client.name}: ${path} -> @elisym/mcp@latest`);
|
|
543
475
|
updated++;
|
|
544
476
|
}
|
|
545
477
|
} catch (err) {
|
|
@@ -614,12 +546,15 @@ async function runUpdate(options) {
|
|
|
614
546
|
console.log(`Skipped ${client.name}: ${err.message}`);
|
|
615
547
|
continue;
|
|
616
548
|
}
|
|
617
|
-
console.log(`Updated ${client.name}: ${path} -> @elisym/mcp
|
|
549
|
+
console.log(`Updated ${client.name}: ${path} -> @elisym/mcp@latest`);
|
|
618
550
|
updated++;
|
|
619
551
|
}
|
|
620
552
|
if (updated === 0) {
|
|
621
553
|
console.log("No existing elisym MCP installs found to update.");
|
|
622
554
|
}
|
|
555
|
+
{
|
|
556
|
+
await clearNpxCache();
|
|
557
|
+
}
|
|
623
558
|
}
|
|
624
559
|
async function runUninstall(options) {
|
|
625
560
|
validateClientName(options.client);
|
|
@@ -914,7 +849,10 @@ function updateCodexPackagePin(body) {
|
|
|
914
849
|
if (section !== "elisym" || !/^\s*args\s*=/.test(line)) {
|
|
915
850
|
continue;
|
|
916
851
|
}
|
|
917
|
-
const packageSpec =
|
|
852
|
+
const packageSpec = elisymPackageArgs()[1];
|
|
853
|
+
if (packageSpec === void 0) {
|
|
854
|
+
throw new Error("Internal error: missing package argument for elisym MCP install.");
|
|
855
|
+
}
|
|
918
856
|
const assignmentEndIndex = findTomlAssignmentEnd(lines, lineIndex);
|
|
919
857
|
const assignmentLines = lines.slice(lineIndex, assignmentEndIndex + 1);
|
|
920
858
|
const packageLineOffset = assignmentLines.findIndex(
|
|
@@ -1526,6 +1464,102 @@ Solana: ${solanaSigner.address}
|
|
|
1526
1464
|
}
|
|
1527
1465
|
})
|
|
1528
1466
|
];
|
|
1467
|
+
var LAMPORTS_PER_SOL = 1000000000n;
|
|
1468
|
+
function readPackageVersion() {
|
|
1469
|
+
try {
|
|
1470
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
1471
|
+
const pkg = JSON.parse(readFileSync(join(here, "..", "package.json"), "utf-8"));
|
|
1472
|
+
return pkg.version;
|
|
1473
|
+
} catch {
|
|
1474
|
+
return "0.0.0";
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
var PACKAGE_VERSION = readPackageVersion();
|
|
1478
|
+
function formatSol(lamports) {
|
|
1479
|
+
return `${formatSolNumeric(lamports)} SOL`;
|
|
1480
|
+
}
|
|
1481
|
+
function formatSolNumeric(lamports) {
|
|
1482
|
+
const sign = lamports < 0n ? "-" : "";
|
|
1483
|
+
const abs = lamports < 0n ? -lamports : lamports;
|
|
1484
|
+
const whole = abs / LAMPORTS_PER_SOL;
|
|
1485
|
+
const frac = abs % LAMPORTS_PER_SOL;
|
|
1486
|
+
return `${sign}${whole}.${frac.toString().padStart(9, "0")}`;
|
|
1487
|
+
}
|
|
1488
|
+
function assetFromCardPayment(payment2) {
|
|
1489
|
+
if (!payment2) {
|
|
1490
|
+
return NATIVE_SOL;
|
|
1491
|
+
}
|
|
1492
|
+
const known = resolveKnownAsset(payment2.chain, payment2.token ?? "sol", payment2.mint);
|
|
1493
|
+
if (known) {
|
|
1494
|
+
return known;
|
|
1495
|
+
}
|
|
1496
|
+
if (payment2.token && payment2.symbol && typeof payment2.decimals === "number") {
|
|
1497
|
+
return {
|
|
1498
|
+
chain: payment2.chain,
|
|
1499
|
+
token: payment2.token,
|
|
1500
|
+
mint: payment2.mint,
|
|
1501
|
+
symbol: payment2.symbol,
|
|
1502
|
+
decimals: payment2.decimals
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
return NATIVE_SOL;
|
|
1506
|
+
}
|
|
1507
|
+
function parseSolToLamports(s) {
|
|
1508
|
+
const trimmed = s.trim();
|
|
1509
|
+
if (!trimmed) {
|
|
1510
|
+
throw new Error("amount is empty");
|
|
1511
|
+
}
|
|
1512
|
+
if (trimmed.startsWith("-")) {
|
|
1513
|
+
throw new Error("amount cannot be negative");
|
|
1514
|
+
}
|
|
1515
|
+
if (!/^(\d+\.\d*|\d*\.\d+|\d+)$/.test(trimmed)) {
|
|
1516
|
+
throw new Error(
|
|
1517
|
+
'amount must be a non-negative decimal number (e.g. "0.5", "1", "0.000000001")'
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
const dotPos = trimmed.indexOf(".");
|
|
1521
|
+
if (dotPos === -1) {
|
|
1522
|
+
const whole = BigInt(trimmed);
|
|
1523
|
+
return whole * LAMPORTS_PER_SOL;
|
|
1524
|
+
}
|
|
1525
|
+
const wholePart = dotPos === 0 ? 0n : BigInt(trimmed.slice(0, dotPos));
|
|
1526
|
+
const fracStr = trimmed.slice(dotPos + 1);
|
|
1527
|
+
if (fracStr.length > 9) {
|
|
1528
|
+
throw new Error("too many decimal places (max 9)");
|
|
1529
|
+
}
|
|
1530
|
+
const padded = fracStr.padEnd(9, "0");
|
|
1531
|
+
const frac = BigInt(padded);
|
|
1532
|
+
return wholePart * LAMPORTS_PER_SOL + frac;
|
|
1533
|
+
}
|
|
1534
|
+
function checkLen(field, value, max) {
|
|
1535
|
+
if (new TextEncoder().encode(value).length > max) {
|
|
1536
|
+
throw new Error(`${field} too long (max ${max} bytes)`);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
var MAX_INPUT_LEN = LIMITS.MAX_INPUT_LENGTH;
|
|
1540
|
+
var MAX_CAPABILITIES = LIMITS.MAX_CAPABILITIES;
|
|
1541
|
+
var MAX_TIMEOUT_SECS = LIMITS.MAX_TIMEOUT_SECS;
|
|
1542
|
+
LIMITS.NIP44_MAX_PLAINTEXT_BYTES;
|
|
1543
|
+
LIMITS.MAX_ENCRYPTED_INLINE_BYTES;
|
|
1544
|
+
LIMITS.MAX_REINLINE_TEXT_BYTES;
|
|
1545
|
+
var MAX_NPUB_LEN = 128;
|
|
1546
|
+
var MAX_EVENT_ID_LEN = 128;
|
|
1547
|
+
var MAX_PAYMENT_REQ_LEN = 1e4;
|
|
1548
|
+
var MAX_SOLANA_ADDR_LEN = 64;
|
|
1549
|
+
var _paymentStrategy = null;
|
|
1550
|
+
function payment() {
|
|
1551
|
+
_paymentStrategy ??= new SolanaPaymentStrategy();
|
|
1552
|
+
return _paymentStrategy;
|
|
1553
|
+
}
|
|
1554
|
+
function decodeNpub(npub) {
|
|
1555
|
+
const decoded = nip19.decode(npub);
|
|
1556
|
+
if (decoded.type !== "npub") {
|
|
1557
|
+
throw new Error(`Expected npub, got ${decoded.type}`);
|
|
1558
|
+
}
|
|
1559
|
+
return decoded.data;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/job-input.ts
|
|
1529
1563
|
var execFileP = promisify(execFile);
|
|
1530
1564
|
var MAX_INPUT_PATH_LEN = 4096;
|
|
1531
1565
|
var SENSITIVE_NAME_RE = /(^|[/\\])(\.secrets\.json|\.env(\..+)?|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*-keypair\.json|.*\.pem|.*\.key|\.bashrc|\.bash_profile|\.bash_login|\.bash_logout|\.bash_aliases|\.profile|\.zshrc|\.zprofile|\.zshenv|\.zlogin|\.zlogout|config\.fish|\.gitconfig|\.npmrc|\.netrc|crontab|sudoers|bash\.bashrc|.*\.service|.*\.desktop)$/i;
|
|
@@ -4948,12 +4982,12 @@ program.command("install").description("Install elisym MCP server into client co
|
|
|
4948
4982
|
}
|
|
4949
4983
|
})
|
|
4950
4984
|
);
|
|
4951
|
-
program.command("update").description("
|
|
4985
|
+
program.command("update").description("Force-refresh installed elisym MCP entries to @latest and clear the npx cache").option(
|
|
4952
4986
|
"--client <name>",
|
|
4953
4987
|
"Specific client (claude-desktop, claude-code, cursor, codex, windsurf)"
|
|
4954
4988
|
).option("--agent <name>", "Override the agent binding").action(
|
|
4955
4989
|
safe(async (options) => {
|
|
4956
|
-
await runUpdate({ client: options.client, agent: options.agent });
|
|
4990
|
+
await runUpdate({ client: options.client, agent: options.agent, clearCache: true });
|
|
4957
4991
|
})
|
|
4958
4992
|
);
|
|
4959
4993
|
program.command("uninstall").description("Remove elisym from MCP client configs").option("--client <name>", "Specific client").action(
|