@zypheragent/mcp 0.3.0 → 0.5.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 +16 -7
- package/dist/index.js +183 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -63,29 +63,38 @@ Generic stdio client, with optional environment:
|
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
With a valid token the server registers
|
|
66
|
+
With a valid token the server registers eleven more tools (28 in total) and its ready line says `read + EXECUTION`. A malformed token prints a clear error on stderr and execution stays disabled; the 17 read tools keep working.
|
|
67
67
|
|
|
68
68
|
| Tool | What it does | Arguments |
|
|
69
69
|
| --- | --- | --- |
|
|
70
70
|
| `agent_status` | Your Agent Wallet: address, balances, positions, caps. Does not move funds. | none |
|
|
71
71
|
| `agent_swap` | Exact-in swap on HyperEVM from the Agent Wallet. | `tokenIn`, `tokenOut` (symbol or 0x address), `amountIn`, optional `slippageBps` |
|
|
72
|
+
| `agent_elysium_swap` | Swap on Elysium 99901 (native HYPE <-> a Boxa-indexed token) from the Agent Wallet. | `tokenIn`, `tokenOut` (HYPE on one side; symbol or 0x address), `amountIn`, optional `slippageBps` |
|
|
73
|
+
| `agent_elysium_launch` | **Launch a token on Elysium** through Boxa's V3 launcher from the Agent Wallet (1B supply in locked liquidity, no creation fee). | `name`, `symbol`, optional `description`, `image`/`website`/`twitter`/`telegram` (https URLs), `allocation` (`balanced`, `creator`, `holders`, `buyback`, `liquidity` or four basis-point shares summing to 10000), `antiSnipe`, `firstBuyHype` |
|
|
74
|
+
| `agent_bridge_elysium` | Move native HYPE HyperEVM <-> Elysium for the Agent Wallet (fund it before an Elysium swap or launch). | `direction` (`deposit`\|`withdraw`), `amount` |
|
|
75
|
+
| `agent_bridge` | Bridge with Relay between chains (name or id, tokens by symbol/address) from the Agent Wallet. Recipient: the wallet itself or an address on your send allow-list. | `originChain`, `destinationChain`, `amount`, optional `originToken`, `destinationToken`, `recipient` |
|
|
76
|
+
| `upload_token_image` | Upload a token image (PNG/JPEG/GIF/WebP, up to 4 MB, base64 or data URL) and get an https URL for `agent_elysium_launch`. No funds, API token not sent. | `imageBase64` |
|
|
72
77
|
| `agent_perp_order` | Open/add a Hyperliquid perp position. | `coin` (`BTC`, `xyz:NVDA`), `side` long\|short, `notionalUsd`, `leverage`, optional `tpPrice`, `slPrice`, `reduceOnly` |
|
|
73
78
|
| `agent_close` | Close a perp position (all or a percentage). | `coin`, optional `fractionPct` (0-100) |
|
|
74
79
|
| `agent_send` | Send funds from the Agent Wallet to an external 0x address. | `asset`, `amount`, `to` (0x address) |
|
|
75
80
|
| `agent_transfer_out` | Move funds from the Agent Wallet back to your own main wallet. | `asset`, `amount` |
|
|
76
81
|
|
|
77
|
-
**These tools move real funds on mainnet.** Every call executes immediately from your Agent Wallet, inside the caps set by you / the operator in the app. There is **no confirmation step** in the MCP, so the assistant is told to ask you first; do not auto-approve these tools in your client. No tool accepts a wallet, owner, URL or path argument: the package can only call the
|
|
82
|
+
**These tools move real funds on mainnet.** Every call executes immediately from your Agent Wallet, inside the caps set by you / the operator in the app. There is **no confirmation step** in the MCP, so the assistant is told to ask you first; do not auto-approve these tools in your client. No tool accepts a wallet, owner, URL or path argument: the package can only call the ten fixed paths `/api/agent-api/{status,swap,elysium-swap,elysium-launch,bridge-boxa,bridge,perp-order,close,send,transfer-out}` (plus the public image upload route of the same host for `upload_token_image`, which never receives the token) under `ZYPHER_API_URL`.
|
|
78
83
|
|
|
79
84
|
Each write call carries a fresh random `Idempotency-Key`. Timeouts are 15 s (45 s for swaps); redirects are refused and responses over 100 KB are refused. After a timeout or a 5xx on a write, the outcome is unknown: call `agent_status` before retrying.
|
|
80
85
|
|
|
81
|
-
## Tools (
|
|
86
|
+
## Tools (17 read tools, always on)
|
|
82
87
|
|
|
83
88
|
| Tool | What it does |
|
|
84
89
|
| --- | --- |
|
|
85
90
|
| `get_policy` | Shows this server's fixed read-only policy (network, no trading, no keys). |
|
|
86
91
|
| `analyze_ticker` | Hyperliquid perp analysis for any listed market, crypto or trade.xyz stocks/indices/metals (`BTC`, `xyz:NVDA`, or the bare symbol `NVDA`): price, 24h volume, open interest, funding, orderbook depth. |
|
|
87
92
|
| `get_strong_volume` | Perp tickers with the highest 24h volume, with volume/OI ratio and price change. |
|
|
88
|
-
| `get_new_pairs` |
|
|
93
|
+
| `get_new_pairs` | Newest token launches on Elysium 99901 (all launchpads), newest first. Elysium only; `chain=hyperevm` returns an explicit error. |
|
|
94
|
+
| `get_elysium_market` | The Elysium market / launchpad feed (like the app's Market and Launch tabs): sort `newest`, `fdv` (top), `volume` (trending), `change` (gainers), `trades`, `holders`; filter by launchpad (`boxa`, `kleos`, `ascend`, `montra`, `volta`, `elyspump`, `uniswap`, `stockium`, `stocks`...), search `q`, `tradable`. Read from the Zypher public API. |
|
|
95
|
+
| `get_elysium_activity` | Recent swaps (or transfers) of an Elysium token, newest first, from chain logs (side, amounts, wallet, block); page backwards with `before`. Times are approximate. |
|
|
96
|
+
| `get_elysium_holders` | Largest holders of an Elysium token seen in recent activity (not a full ranking) plus the index holder count. |
|
|
97
|
+
| `get_elysium_token` | One Elysium token by address: launchpad, pool, price, FDV, 24h change/volume, holders, tradable flag. |
|
|
89
98
|
| `analyze_token_health` | Bytecode/ABI check of a token contract (mint, pause, blacklist, owner) with a score and reasons. A heuristic, not an audit. |
|
|
90
99
|
| `get_social_info` | Recent tweets about a ticker. Needs your own `X_BEARER_TOKEN`; without it the tool returns a clear error. |
|
|
91
100
|
| `get_portfolio` | Public balances/positions of an address: Hyperliquid account, native HYPE on HyperEVM mainnet and on Elysium 99901. |
|
|
@@ -93,7 +102,7 @@ Each write call carries a fresh random `Idempotency-Key`. Timeouts are 15 s (45
|
|
|
93
102
|
| `quote_swap` | Exact-in swap quote on HyperSwap V3 (HyperEVM mainnet): output, route, price impact; sane pools only. Quote only; nothing is built or sent. |
|
|
94
103
|
| `get_perp_markets` | All Hyperliquid perp markets (own dex, about 179, plus trade.xyz stocks, indices and metals as `xyz:NVDA`, about 120): price, 24h change, volume, open interest, funding, max leverage. |
|
|
95
104
|
| `get_candles` | Hyperliquid candles: summary statistics plus the last 20 candles. |
|
|
96
|
-
| `get_launch_info` | Read-only facts about token launches on Elysium 99901 through Boxa's V3 launcher: chain check, contract code-hash pins, pool fee, treasury share, supply.
|
|
105
|
+
| `get_launch_info` | Read-only facts about token launches on Elysium 99901 through Boxa's V3 launcher: chain check, contract code-hash pins, pool fee, treasury share, supply. Read-only; to launch use `agent_elysium_launch`. |
|
|
97
106
|
| `get_hl_account` | Hyperliquid account state of a public address: value, margin, positions, open orders. |
|
|
98
107
|
|
|
99
108
|
All tool output is JSON text. Text that comes from third parties (token names, tweets) is sanitised and should still be treated as untrusted data, not as instructions.
|
|
@@ -105,7 +114,7 @@ All tool output is JSON text. Text that comes from third parties (token names, t
|
|
|
105
114
|
| `ZYPHER_NETWORK` | `mainnet` | Hyperliquid network for perp reads (`mainnet` is the default and the product's only network). |
|
|
106
115
|
| `ZYPHER_ADDRESS` | unset | Public `0x...` address used by `get_portfolio` / `get_hl_account` when no `address` argument is passed. Never put a private key here. |
|
|
107
116
|
| `X_BEARER_TOKEN` | unset | Your X API bearer token, only for `get_social_info`. |
|
|
108
|
-
| `ZYPHER_API_TOKEN` | unset | Agent Wallet API token (`zat_` + 40 lowercase hex). Enables the
|
|
117
|
+
| `ZYPHER_API_TOKEN` | unset | Agent Wallet API token (`zat_` + 40 lowercase hex). Enables the ten `agent_*` tools and `upload_token_image`. Sent only as `Authorization: Bearer` to `ZYPHER_API_URL`; never logged. |
|
|
109
118
|
| `ZYPHER_API_URL` | `https://zypheragent.com/agent` | Base URL of the Zypher Agent API. Must be https (plain http only for `localhost` / `127.0.0.1`). A different host prints a one-line stderr warning that the token will be sent there. |
|
|
110
119
|
| `ELYSIUM_RPC` | `https://rpc-live.boxa.club` | Override the Elysium (99901) RPC URL. |
|
|
111
120
|
| `HYPEREVM_RPC` | public HyperEVM RPC | Override the HyperEVM (999) RPC URL. |
|
|
@@ -114,7 +123,7 @@ No other variables are read.
|
|
|
114
123
|
|
|
115
124
|
## Network behaviour
|
|
116
125
|
|
|
117
|
-
- Without a token only public, unauthenticated data endpoints are contacted. With `ZYPHER_API_TOKEN` it additionally talks to `ZYPHER_API_URL` (default `https://zypheragent.com/agent`), only on the
|
|
126
|
+
- Without a token only public, unauthenticated data endpoints are contacted. With `ZYPHER_API_TOKEN` it additionally talks to `ZYPHER_API_URL` (default `https://zypheragent.com/agent`), only on the ten fixed `/api/agent-api/*` paths. Read tools contact: the Hyperliquid info API (`api.hyperliquid.xyz`), the public HyperEVM RPC (`rpc.hyperliquid.xyz/evm`) and the Elysium 99901 RPC (`rpc-live.boxa.club`, run by Boxa) and, for the Elysium market tools, the public Zypher API (`zypheragent.com/agent`). `get_social_info` contacts `api.x.com` only with your own token.
|
|
118
127
|
- Requests carry the header `User-Agent: zypher-mcp/<version>`.
|
|
119
128
|
- No telemetry, no analytics, no phone-home. The package writes nothing to disk.
|
|
120
129
|
- Default is **mainnet** (real markets): Hyperliquid mainnet, HyperEVM 999 and Elysium 99901. **Elysium 99901 is a community-run chain served by Boxa (rpc-live.boxa.club), not the official Kinetiq mainnet**; `get_launch_info` checks that the chain id and the pinned contract code hashes still match and says so when they do not. Its RPC and contracts are third-party; a lying or lagging RPC cannot be detected from here.
|
package/dist/index.js
CHANGED
|
@@ -454,7 +454,7 @@ async function boxaLaunchInfo() {
|
|
|
454
454
|
creationFee: "none: the only HYPE a launch sends is the first buy",
|
|
455
455
|
note: "Fees go 30% to the Boxa treasury; the rest by the creator's choice (creator / holders / buyback and burn / locked liquidity)."
|
|
456
456
|
},
|
|
457
|
-
launching: "
|
|
457
|
+
launching: "Read tools cannot launch. With ZYPHER_API_TOKEN set, the agent_elysium_launch tool launches from the user's Agent Wallet (real funds, no confirmation step); otherwise launch in the Zypher Agent app, signed in your own wallet.",
|
|
458
458
|
parentChain: { id: 999, inbox: PARENT.inbox }
|
|
459
459
|
};
|
|
460
460
|
}
|
|
@@ -517,6 +517,100 @@ async function searchRecentPosts(bearerToken, query, timeoutMs = 15e3) {
|
|
|
517
517
|
return { count: j.data?.length ?? 0, tweets: (j.data ?? []).map((x) => untrusted(x.text, 280)) };
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
+
// src/providers/zypher.ts
|
|
521
|
+
var BASE = () => (process.env.ZYPHER_API_URL?.trim() || "https://zypheragent.com/agent").replace(/\/+$/, "");
|
|
522
|
+
async function getJson(path, q) {
|
|
523
|
+
const u = new URL(BASE() + path);
|
|
524
|
+
for (const [k, v] of Object.entries(q)) if (v !== void 0 && v !== "") u.searchParams.set(k, String(v));
|
|
525
|
+
const r = await fetch(u, { headers: { accept: "application/json" }, redirect: "error", signal: AbortSignal.timeout(2e4) });
|
|
526
|
+
const text = await r.text();
|
|
527
|
+
if (text.length > 4e5) throw new Error("Response from the Zypher API is too large; refused.");
|
|
528
|
+
let j;
|
|
529
|
+
try {
|
|
530
|
+
j = JSON.parse(text);
|
|
531
|
+
} catch {
|
|
532
|
+
j = null;
|
|
533
|
+
}
|
|
534
|
+
if (!r.ok || !j || j.ok === false) throw new Error(`Zypher API ${r.status}: ${cleanLabel(String(j?.error ?? "request failed"), 200)}`);
|
|
535
|
+
return j;
|
|
536
|
+
}
|
|
537
|
+
var num = (x, d = 6) => typeof x === "number" && Number.isFinite(x) ? Number(x.toPrecision(d)) : null;
|
|
538
|
+
var row = (t, hypeUsd2) => ({
|
|
539
|
+
address: t.address,
|
|
540
|
+
symbol: cleanLabel(String(t.symbol ?? "?"), 12),
|
|
541
|
+
name: cleanLabel(String(t.name ?? ""), 40),
|
|
542
|
+
launchpad: t.launchpad,
|
|
543
|
+
pool: t.poolVersion,
|
|
544
|
+
createdAt: t.createdAt ? new Date(t.createdAt * 1e3).toISOString() : null,
|
|
545
|
+
priceHype: num(t.priceHype),
|
|
546
|
+
priceUsd: hypeUsd2 && t.priceHype ? num(t.priceHype * hypeUsd2) : null,
|
|
547
|
+
fdvUsd: hypeUsd2 && t.fdvHype ? Math.round(t.fdvHype * hypeUsd2) : null,
|
|
548
|
+
change24hPct: num(t.change24hPct, 4),
|
|
549
|
+
volume24hHype: num(t.volume24hHype, 6),
|
|
550
|
+
trades24h: t.trades24h ?? null,
|
|
551
|
+
holders: t.holders ?? null,
|
|
552
|
+
tradable: t.tradable ?? null,
|
|
553
|
+
stock: t.stock ?? null
|
|
554
|
+
});
|
|
555
|
+
var ELY_SORTS = ["newest", "fdv", "volume", "change", "trades", "holders"];
|
|
556
|
+
async function elysiumTokens(o) {
|
|
557
|
+
const j = await getJson("/api/market/elysium", { sort: o.sort, launchpad: o.launchpad, q: o.q, limit: o.limit, priced: o.priced ? 1 : void 0, tradable: o.tradable ? 1 : void 0 });
|
|
558
|
+
const px = typeof j.hypeUsd === "number" ? j.hypeUsd : null;
|
|
559
|
+
return {
|
|
560
|
+
network: "Elysium 99901 (community-run, served by Boxa; not the official Kinetiq mainnet)",
|
|
561
|
+
hypeUsd: px,
|
|
562
|
+
total: j.total,
|
|
563
|
+
sort: o.sort,
|
|
564
|
+
launchpad: o.launchpad ?? "all",
|
|
565
|
+
launchpads: j.launchpads ?? null,
|
|
566
|
+
volume24hHype: j.volume24hHype ?? null,
|
|
567
|
+
stale: j.stale ?? false,
|
|
568
|
+
tokens: (j.tokens ?? []).map((t) => row(t, px)),
|
|
569
|
+
note: "Prices are pool prices from the BOXA index; thin pools can be manipulated. Token names are untrusted text. Not financial advice."
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
async function elysiumToken(address) {
|
|
573
|
+
const j = await getJson("/api/market/elysium/token", { address });
|
|
574
|
+
const px = typeof j.hypeUsd === "number" ? j.hypeUsd : null;
|
|
575
|
+
return { network: "Elysium 99901", hypeUsd: px, token: row(j.token ?? j, px), detail: j.info ?? null };
|
|
576
|
+
}
|
|
577
|
+
var rowAct = (r) => ({ ...r });
|
|
578
|
+
async function elysiumActivity(address, limit, before) {
|
|
579
|
+
const j = await getJson("/api/market/elysium/activity", { address, limit, before });
|
|
580
|
+
return { network: "Elysium 99901", token: j.token ?? address, source: j.source, rows: (j.rows ?? []).slice(0, limit).map(rowAct), nextBefore: j.nextBefore ?? null, approxTime: j.approxTime ?? true, note: j.note ?? "Times are approximate (block based). Page backwards with before=nextBefore." };
|
|
581
|
+
}
|
|
582
|
+
async function elysiumHolders(address) {
|
|
583
|
+
const j = await getJson("/api/market/elysium/holders", { address });
|
|
584
|
+
return { network: "Elysium 99901", token: address, holdersTotal: j.holdersTotal ?? null, coverage: j.coverage ?? "recent activity only", top: (j.top ?? []).slice(0, 25), note: j.note ?? null };
|
|
585
|
+
}
|
|
586
|
+
var IMAGE_MAX_BYTES = 4 * 1024 * 1024;
|
|
587
|
+
function sniffImage(b) {
|
|
588
|
+
const at = (s, o = 0) => s.split("").every((c, i) => b[o + i] === c.charCodeAt(0));
|
|
589
|
+
if (b.length > 8 && b[0] === 137 && at("PNG", 1) && b[4] === 13 && b[5] === 10 && b[6] === 26 && b[7] === 10) return "image/png";
|
|
590
|
+
if (b.length > 3 && b[0] === 255 && b[1] === 216 && b[2] === 255) return "image/jpeg";
|
|
591
|
+
if (b.length > 12 && at("RIFF") && at("WEBP", 8)) return "image/webp";
|
|
592
|
+
if (b.length > 6 && at("GIF8") && (b[4] === 55 || b[4] === 57) && b[5] === 97) return "image/gif";
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
async function uploadTokenImage(imageBase64) {
|
|
596
|
+
const raw = imageBase64.trim().replace(/^data:[^,]*;base64,/i, "").replace(/\s+/g, "");
|
|
597
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(raw) || raw.length < 16) throw new Error("imageBase64 must be a base64 encoded PNG, JPEG, GIF or WebP image.");
|
|
598
|
+
if (raw.length > Math.ceil(IMAGE_MAX_BYTES / 3) * 4 + 8) throw new Error("That image is too large. The limit is 4 MB.");
|
|
599
|
+
const bytes = Buffer.from(raw, "base64");
|
|
600
|
+
if (bytes.length > IMAGE_MAX_BYTES) throw new Error("That image is too large. The limit is 4 MB.");
|
|
601
|
+
const type = sniffImage(bytes);
|
|
602
|
+
if (!type) throw new Error("The data is not a PNG, JPEG, GIF or WebP image (checked by its first bytes).");
|
|
603
|
+
const r = await fetch(BASE() + "/api/launch-mainnet/upload", { method: "POST", headers: { "content-type": type, accept: "application/json" }, body: new Uint8Array(bytes), redirect: "error", signal: AbortSignal.timeout(3e4) });
|
|
604
|
+
const text = await r.text();
|
|
605
|
+
let j = null;
|
|
606
|
+
try {
|
|
607
|
+
j = JSON.parse(text);
|
|
608
|
+
} catch {
|
|
609
|
+
}
|
|
610
|
+
if (!r.ok || !j?.ok || typeof j.url !== "string" || !/^https:\/\//.test(j.url)) throw new Error(`Image upload refused (HTTP ${r.status}): ${cleanLabel(String(j?.error ?? "unexpected answer"), 160)}`);
|
|
611
|
+
return { url: j.url, type, bytes: bytes.length, next: "Pass this url as `image` to agent_elysium_launch." };
|
|
612
|
+
}
|
|
613
|
+
|
|
520
614
|
// src/market/reads.ts
|
|
521
615
|
import { formatUnits as formatUnits3, getAddress as getAddress4, isAddress as isAddress2, parseUnits } from "viem";
|
|
522
616
|
|
|
@@ -917,12 +1011,37 @@ var tools = [
|
|
|
917
1011
|
},
|
|
918
1012
|
{
|
|
919
1013
|
name: "get_new_pairs",
|
|
920
|
-
description: "
|
|
921
|
-
shape: { chain, limit: z.number().int().min(1).max(50).default(20) },
|
|
922
|
-
handler: async () => {
|
|
923
|
-
throw new Error("get_new_pairs
|
|
1014
|
+
description: "Newest token launches on Elysium 99901 (all launchpads: Boxa, Kleos, Ascend, Montra, Volta ...), newest first, with price, FDV, holders and tradable flag. HyperEVM has no indexer here: chain=hyperevm returns an error.",
|
|
1015
|
+
shape: { chain: z.enum(["elysium", "hyperevm"]).default("elysium"), limit: z.number().int().min(1).max(50).default(20), launchpad: z.string().regex(/^[a-z0-9]{2,20}$/).optional() },
|
|
1016
|
+
handler: async (a) => {
|
|
1017
|
+
if (a.chain !== "elysium") throw new Error("get_new_pairs only supports chain=elysium (HyperEVM would need a pool event indexer).");
|
|
1018
|
+
return elysiumTokens({ sort: "newest", launchpad: a.launchpad, limit: a.limit });
|
|
924
1019
|
}
|
|
925
1020
|
},
|
|
1021
|
+
{
|
|
1022
|
+
name: "get_elysium_market",
|
|
1023
|
+
description: "The Elysium 99901 market / launchpad feed like the app's Market and Launch tabs: sort newest | fdv (top) | volume (trending) | change (gainers) | trades | holders; filter by launchpad (boxa, kleos, ascend, montra, volta, elyspump, uniswap, stockium, obol, stocks, other); optional search q; tradable=true hides tokens the app cannot swap.",
|
|
1024
|
+
shape: { sort: z.enum(ELY_SORTS).default("volume"), launchpad: z.string().regex(/^[a-z0-9]{2,20}$/).optional(), q: z.string().min(1).max(40).optional(), limit: z.number().int().min(1).max(50).default(20), priced: z.boolean().default(true), tradable: z.boolean().default(false) },
|
|
1025
|
+
handler: async (a) => elysiumTokens({ sort: a.sort, launchpad: a.launchpad, q: a.q, limit: a.limit, priced: a.priced, tradable: a.tradable })
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
name: "get_elysium_token",
|
|
1029
|
+
description: "One Elysium 99901 token by contract address: launchpad, pool, price, FDV, 24h change/volume, holders and whether the Zypher app can swap it.",
|
|
1030
|
+
shape: { address: evmAddr },
|
|
1031
|
+
handler: async (a) => elysiumToken(a.address)
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
name: "get_elysium_activity",
|
|
1035
|
+
description: "Recent swaps (or transfers) of an Elysium 99901 token, newest first, read from chain logs: side, amounts, wallet, block. Times are approximate. Page backwards with before = nextBefore of the previous answer.",
|
|
1036
|
+
shape: { address: evmAddr, limit: z.number().int().min(1).max(60).default(30), before: z.number().int().min(0).max(1e9).optional() },
|
|
1037
|
+
handler: async (a) => elysiumActivity(a.address, a.limit, a.before)
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
name: "get_elysium_holders",
|
|
1041
|
+
description: "Largest holders of an Elysium 99901 token SEEN IN RECENT ACTIVITY (not a full ranking), plus the total holder count from the index.",
|
|
1042
|
+
shape: { address: evmAddr },
|
|
1043
|
+
handler: async (a) => elysiumHolders(a.address)
|
|
1044
|
+
},
|
|
926
1045
|
{
|
|
927
1046
|
name: "analyze_token_health",
|
|
928
1047
|
description: "Check a token contract (mint/pause/blacklist/owner) on HyperEVM mainnet (default) or Elysium 99901 and give a score with reasons. Bytecode heuristic, not a safety guarantee.",
|
|
@@ -976,7 +1095,7 @@ var tools = [
|
|
|
976
1095
|
},
|
|
977
1096
|
{
|
|
978
1097
|
name: "get_launch_info",
|
|
979
|
-
description: "Read-only facts about token launches on Elysium 99901 through Boxa's V3 launcher: chain check, contract code-hash pins, pool fee, treasury share, supply.
|
|
1098
|
+
description: "Read-only facts about token launches on Elysium 99901 through Boxa's V3 launcher: chain check, contract code-hash pins, pool fee, treasury share, supply. Read-only (launching is the agent_elysium_launch tool, which needs ZYPHER_API_TOKEN). Elysium 99901 is community-run, not the official Kinetiq mainnet.",
|
|
980
1099
|
shape: {},
|
|
981
1100
|
handler: async () => boxaLaunchInfo()
|
|
982
1101
|
},
|
|
@@ -1005,7 +1124,7 @@ var MAX_RESPONSE_BYTES = 100 * 1024;
|
|
|
1005
1124
|
var TIMEOUT_MS = 15e3;
|
|
1006
1125
|
var SWAP_TIMEOUT_MS = 45e3;
|
|
1007
1126
|
var DEFAULT_HOST = "zypheragent.com";
|
|
1008
|
-
var ALLOWED_PATHS = ["/api/agent-api/status", "/api/agent-api/swap", "/api/agent-api/perp-order", "/api/agent-api/close", "/api/agent-api/send", "/api/agent-api/transfer-out"];
|
|
1127
|
+
var ALLOWED_PATHS = ["/api/agent-api/status", "/api/agent-api/swap", "/api/agent-api/elysium-swap", "/api/agent-api/elysium-launch", "/api/agent-api/bridge-boxa", "/api/agent-api/bridge", "/api/agent-api/perp-order", "/api/agent-api/close", "/api/agent-api/send", "/api/agent-api/transfer-out"];
|
|
1009
1128
|
function loadExecConfig(e2 = process.env) {
|
|
1010
1129
|
const token = e2.ZYPHER_API_TOKEN?.trim();
|
|
1011
1130
|
if (!token) return { enabled: false };
|
|
@@ -1043,6 +1162,8 @@ var usd = (max) => z2.union([z2.string().regex(/^\d{1,12}(\.\d{1,8})?$/), z2.num
|
|
|
1043
1162
|
return n3;
|
|
1044
1163
|
});
|
|
1045
1164
|
var tokenRef = z2.union([ticker, evmAddr]);
|
|
1165
|
+
var chainRef = z2.union([z2.string().regex(/^[A-Za-z0-9._-]{1,30}$/), z2.number().int().positive()]);
|
|
1166
|
+
var httpsUrl = z2.string().max(400).regex(/^https:\/\/\S+$/, "must be an https:// URL");
|
|
1046
1167
|
var slippageBps = z2.number().int().min(1).max(5e3).optional();
|
|
1047
1168
|
var HONEST = "REAL FUNDS, MAINNET: this executes IMMEDIATELY from the user's Agent Wallet, inside the caps set by the user/operator in the Zypher Agent app. There is NO confirmation step and this MCP never holds keys. Ask the human for explicit approval of the exact parameters BEFORE calling.";
|
|
1048
1169
|
var SPECS = [
|
|
@@ -1061,6 +1182,49 @@ var SPECS = [
|
|
|
1061
1182
|
shape: { tokenIn: tokenRef, tokenOut: tokenRef, amountIn: amount, slippageBps },
|
|
1062
1183
|
description: `Swap tokens (exact-in) on HyperEVM from the user's Agent Wallet. ${HONEST}`
|
|
1063
1184
|
},
|
|
1185
|
+
{
|
|
1186
|
+
name: "agent_elysium_swap",
|
|
1187
|
+
method: "POST",
|
|
1188
|
+
path: "/api/agent-api/elysium-swap",
|
|
1189
|
+
swap: true,
|
|
1190
|
+
shape: { tokenIn: tokenRef, tokenOut: tokenRef, amountIn: amount, slippageBps },
|
|
1191
|
+
description: `Swap on ELYSIUM 99901 (community-run chain by Boxa) from the user's Agent Wallet: native HYPE <-> a token listed in the Boxa index (use HYPE on one side; token by symbol or 0x address, prefer the 0x address from get_elysium_market). Signed server-side, delivered through the HyperEVM Inbox, so it can take a minute. ${HONEST}`
|
|
1192
|
+
},
|
|
1193
|
+
{
|
|
1194
|
+
name: "agent_elysium_launch",
|
|
1195
|
+
method: "POST",
|
|
1196
|
+
path: "/api/agent-api/elysium-launch",
|
|
1197
|
+
swap: true,
|
|
1198
|
+
shape: {
|
|
1199
|
+
name: z2.string().min(1).max(32),
|
|
1200
|
+
symbol: z2.string().regex(/^[A-Za-z0-9][A-Za-z0-9._$-]{0,9}$/),
|
|
1201
|
+
description: z2.string().max(280).optional(),
|
|
1202
|
+
image: httpsUrl.optional(),
|
|
1203
|
+
website: httpsUrl.optional(),
|
|
1204
|
+
twitter: httpsUrl.optional(),
|
|
1205
|
+
telegram: httpsUrl.optional(),
|
|
1206
|
+
allocation: z2.union([z2.enum(["balanced", "creator", "holders", "buyback", "liquidity"]), z2.object({ creatorBps: z2.number().int().min(0).max(1e4), holdersBps: z2.number().int().min(0).max(1e4), buybackBps: z2.number().int().min(0).max(1e4), liquidityBps: z2.number().int().min(0).max(1e4) }).strict()]).optional(),
|
|
1207
|
+
antiSnipe: z2.boolean().optional(),
|
|
1208
|
+
firstBuyHype: amount.optional()
|
|
1209
|
+
},
|
|
1210
|
+
description: `LAUNCH a new token on ELYSIUM 99901 through Boxa's V3 launcher (1B supply, all in locked liquidity, 1% pool fee, 30% of fees to the Boxa treasury; the rest by 'allocation': balanced = 25% each to creator / holders / buyback-burn / liquidity, or four basis-point shares adding up to 10000). No creation fee; the only HYPE spent is the optional firstBuyHype (anti-snipe ON caps the first buy at about 0.6 HYPE) plus gas, paid from the Agent Wallet's HYPE ON ELYSIUM (and a little on HyperEVM for delivery). image/website/twitter/telegram must be https URLs. The token is created at once and cannot be deleted. ${HONEST}`
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
name: "agent_bridge_elysium",
|
|
1214
|
+
method: "POST",
|
|
1215
|
+
path: "/api/agent-api/bridge-boxa",
|
|
1216
|
+
swap: true,
|
|
1217
|
+
shape: { direction: z2.enum(["deposit", "withdraw"]), amount },
|
|
1218
|
+
description: `Move native HYPE between HyperEVM and ELYSIUM 99901 for the user's Agent Wallet (Boxa bridge): deposit = HyperEVM -> Elysium (needed before agent_elysium_swap / agent_elysium_launch), withdraw = Elysium -> HyperEVM (can take a while). ${HONEST}`
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
name: "agent_bridge",
|
|
1222
|
+
method: "POST",
|
|
1223
|
+
path: "/api/agent-api/bridge",
|
|
1224
|
+
swap: true,
|
|
1225
|
+
shape: { originChain: chainRef, destinationChain: chainRef, originToken: z2.string().min(1).max(60).optional(), destinationToken: z2.string().min(1).max(70).optional(), amount, recipient: evmAddr.optional() },
|
|
1226
|
+
description: `Bridge funds with Relay between chains (any supported chain to any, e.g. ethereum -> hyperevm, arbitrum -> base) from the user's Agent Wallet. originChain/destinationChain = a chain name or numeric id; tokens by symbol or 0x address (default: the native token). With an API token the recipient can only be the Agent Wallet itself (leave it out) or an EVM address on the owner's send allow-list; Solana recipients are not possible. For HYPE between HyperEVM and Elysium use agent_bridge_elysium instead. ${HONEST}`
|
|
1227
|
+
},
|
|
1064
1228
|
{
|
|
1065
1229
|
name: "agent_perp_order",
|
|
1066
1230
|
method: "POST",
|
|
@@ -1169,11 +1333,14 @@ function execTools(cfg) {
|
|
|
1169
1333
|
}));
|
|
1170
1334
|
}
|
|
1171
1335
|
|
|
1336
|
+
// src/index.ts
|
|
1337
|
+
import { z as z3 } from "zod";
|
|
1338
|
+
|
|
1172
1339
|
// package.json
|
|
1173
1340
|
var package_default = {
|
|
1174
1341
|
name: "@zypheragent/mcp",
|
|
1175
|
-
version: "0.
|
|
1176
|
-
description: "MCP server of Zypher Agent: Hyperliquid perp analytics, HyperSwap quotes on HyperEVM and
|
|
1342
|
+
version: "0.5.0",
|
|
1343
|
+
description: "MCP server of Zypher Agent: Hyperliquid perp analytics, HyperSwap quotes on HyperEVM and Elysium market and launchpad feed for AI assistants. Read-only by default; optional execution (swaps, Elysium swap and token launch, bridge, perp orders, close, send) only through a user-created Agent Wallet API token. This package holds no keys.",
|
|
1177
1344
|
license: "MIT",
|
|
1178
1345
|
author: "Zypher Agent",
|
|
1179
1346
|
homepage: "https://zypheragent.com",
|
|
@@ -1234,7 +1401,13 @@ globalThis.fetch = (input, init = {}) => {
|
|
|
1234
1401
|
var execCfg = loadExecConfig();
|
|
1235
1402
|
if (!execCfg.enabled && execCfg.reason) console.error(`zypher-mcp: ${execCfg.reason}`);
|
|
1236
1403
|
if (execCfg.enabled && execCfg.warning) console.error(`zypher-mcp: ${execCfg.warning}`);
|
|
1237
|
-
var
|
|
1404
|
+
var uploadTool = {
|
|
1405
|
+
name: "upload_token_image",
|
|
1406
|
+
description: "Upload a token image (PNG, JPEG, GIF or WebP, up to 4 MB, given as base64 or a data: URL) and get back an https URL for the `image` field of agent_elysium_launch. Uploads to Boxa's image host through the Zypher API; no funds are involved and your API token is NOT sent. Rate limited (6 per minute).",
|
|
1407
|
+
shape: { imageBase64: z3.string().min(16).max(56e5) },
|
|
1408
|
+
handler: async (a) => uploadTokenImage(a.imageBase64)
|
|
1409
|
+
};
|
|
1410
|
+
var tools2 = execCfg.enabled ? [...tools, ...execTools(execCfg), uploadTool] : tools;
|
|
1238
1411
|
setExecEnabled(execCfg.enabled);
|
|
1239
1412
|
var server = new McpServer({ name: "zypher-agent", version: package_default.version });
|
|
1240
1413
|
for (const t of tools2) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zypheragent/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server of Zypher Agent: Hyperliquid perp analytics, HyperSwap quotes on HyperEVM and
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "MCP server of Zypher Agent: Hyperliquid perp analytics, HyperSwap quotes on HyperEVM and Elysium market and launchpad feed for AI assistants. Read-only by default; optional execution (swaps, Elysium swap and token launch, bridge, perp orders, close, send) only through a user-created Agent Wallet API token. This package holds no keys.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Zypher Agent",
|
|
7
7
|
"homepage": "https://zypheragent.com",
|