@candledottv/mcp 0.10.27 → 0.10.29
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 +4 -3
- package/dist/index.js +110 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @candledottv/mcp
|
|
2
2
|
|
|
3
3
|
An MCP (Model Context Protocol) server for the Candle agent rail. The current source exposes Candle's REST API as
|
|
4
|
-
eighty-
|
|
4
|
+
eighty-three tools over stdio, plus four Hyperliquid market reads (eighty-seven in all), so an MCP-capable agent can launch tokens (optionally seeded with a dev
|
|
5
5
|
buy in the same call), trade, convert between base assets (including across chains), read market
|
|
6
6
|
and feed data, read one token's signals and tracked-wallet trades and its card data, report on-chain activity,
|
|
7
7
|
check an agent profile, and backtest a strategy in hacc's strategy lab without hand-rolling HTTP calls. The five
|
|
@@ -35,7 +35,7 @@ Environment below -- or skip env editing entirely: install the Candle CLI
|
|
|
35
35
|
environment.
|
|
36
36
|
|
|
37
37
|
`CANDLE_MCP_TOOLS` (optional) is a comma-separated allowlist of tool names; only those register.
|
|
38
|
-
Unset means all eighty-
|
|
38
|
+
Unset means all eighty-three. An unknown name fails startup with the valid names in the message, rather
|
|
39
39
|
than silently registering the wrong surface. `candle mcp --read-only` / `--tools` set this for
|
|
40
40
|
you.
|
|
41
41
|
|
|
@@ -163,6 +163,7 @@ tools, getting a key, funding the embedded wallet, and idempotent retries, see
|
|
|
163
163
|
| `candle_execution_status` | One call before trading: wallets to spend from, tier, and whether trading is possible | Composes the wallet and tier reads | `CANDLE_AGENT_API_KEY` |
|
|
164
164
|
| `candle_get_operation` | Look up a trade or launch by the id its write used, and whether it landed | `GET /api/v1/trade/agent/jobs/:clientId` or `/api/v1/launch/headless/jobs/:clientId` | `CANDLE_AGENT_API_KEY` |
|
|
165
165
|
| `candle_get_fees` | The creator fees the account's launched tokens can pay: raw amounts from chain reads, and the reason a token cannot be claimed | `GET /api/v1/agent/fees` | `CANDLE_AGENT_API_KEY` (`account:read`) |
|
|
166
|
+
| `candle_atomic_launch_dry_run` | Check a Solana launch with first buys and price each buy on the curve it would deploy; builds, reserves and writes nothing | `POST /api/v1/launch/atomic/dry-run` | `CANDLE_AGENT_API_KEY` (`launch:write`, `swap:write`, Pro or Max) |
|
|
166
167
|
| `candle_claim_fees` | Collect one token's creator fees to the wallet fixed at launch (no destination argument); `dryRun` sends nothing | `POST /api/v1/agent/fees/:mint/claim` | `CANDLE_AGENT_API_KEY` (`launch:write`) |
|
|
167
168
|
| `candle_get_staking` | Read CNDL/sCNDL, withdrawals, rewards, pool wait and wallet eligibility notes | `GET /api/v1/agent/staking` |
|
|
168
169
|
| `candle_stake` | Stake raw CNDL; stable clientStakeId, dryRun first | `POST /api/v1/agent/staking/stake/build` |
|
|
@@ -239,7 +240,7 @@ explicitly. Assets with nothing spendable report `empty`; a failed asset never s
|
|
|
239
240
|
## Errors
|
|
240
241
|
|
|
241
242
|
This package never reinterprets an error body, and that body is not one uniform shape across all
|
|
242
|
-
eighty-
|
|
243
|
+
eighty-three tools:
|
|
243
244
|
|
|
244
245
|
- `candle_token_events`, called with `kind`, is the one narrowing of a SUCCESS body, never an
|
|
245
246
|
error one: the relayed `events` are filtered to that kind and the body gains `filteredByKind`.
|
package/dist/index.js
CHANGED
|
@@ -189,7 +189,7 @@ function readClusterResult(value, mint) {
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
// src/version.ts
|
|
192
|
-
var SERVER_VERSION = "0.10.
|
|
192
|
+
var SERVER_VERSION = "0.10.29";
|
|
193
193
|
|
|
194
194
|
// src/update-notice.ts
|
|
195
195
|
var PLAIN_VERSION = /^\d+\.\d+\.\d+$/;
|
|
@@ -1442,6 +1442,77 @@ var LAUNCH_DEFINITION = {
|
|
|
1442
1442
|
}
|
|
1443
1443
|
}
|
|
1444
1444
|
},
|
|
1445
|
+
{
|
|
1446
|
+
key: "feeWallet",
|
|
1447
|
+
type: "string",
|
|
1448
|
+
help: "Solana only: the wallet this launch's curve and pool fees earn to, an on-curve wallet or a Squads v4 vault; defaults to the wallet that launches the token (the account wallet on a server without LAUNCH_FEE_WALLET_FROM_LAUNCHER, except an embedded launch).",
|
|
1449
|
+
chains: [
|
|
1450
|
+
"solana"
|
|
1451
|
+
],
|
|
1452
|
+
surfaces: {
|
|
1453
|
+
cli: {
|
|
1454
|
+
flag: "--fee-wallet",
|
|
1455
|
+
value: "<address>"
|
|
1456
|
+
},
|
|
1457
|
+
mcp: {
|
|
1458
|
+
key: "feeWallet"
|
|
1459
|
+
},
|
|
1460
|
+
sdk: {
|
|
1461
|
+
key: "feeWallet"
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
},
|
|
1465
|
+
{
|
|
1466
|
+
key: "feeWalletMultisig.address",
|
|
1467
|
+
type: "string",
|
|
1468
|
+
help: "The Squads v4 multisig behind an off-curve --fee-wallet vault; takes --fee-wallet-multisig-vault-index.",
|
|
1469
|
+
chains: [
|
|
1470
|
+
"solana"
|
|
1471
|
+
],
|
|
1472
|
+
requires: [
|
|
1473
|
+
"feeWallet"
|
|
1474
|
+
],
|
|
1475
|
+
surfaces: {
|
|
1476
|
+
cli: {
|
|
1477
|
+
flag: "--fee-wallet-multisig",
|
|
1478
|
+
value: "<address>"
|
|
1479
|
+
},
|
|
1480
|
+
mcp: {
|
|
1481
|
+
key: "feeWalletMultisig.address"
|
|
1482
|
+
},
|
|
1483
|
+
sdk: {
|
|
1484
|
+
key: "feeWalletMultisig.address"
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
key: "feeWalletMultisig.vaultIndex",
|
|
1490
|
+
type: "integer",
|
|
1491
|
+
help: "The Squads vault index, 0 to 255, that with the multisig derives an off-curve --fee-wallet.",
|
|
1492
|
+
chains: [
|
|
1493
|
+
"solana"
|
|
1494
|
+
],
|
|
1495
|
+
range: {
|
|
1496
|
+
min: "0",
|
|
1497
|
+
max: "255",
|
|
1498
|
+
unit: "vault index"
|
|
1499
|
+
},
|
|
1500
|
+
requires: [
|
|
1501
|
+
"feeWalletMultisig.address"
|
|
1502
|
+
],
|
|
1503
|
+
surfaces: {
|
|
1504
|
+
cli: {
|
|
1505
|
+
flag: "--fee-wallet-multisig-vault-index",
|
|
1506
|
+
value: "<n>"
|
|
1507
|
+
},
|
|
1508
|
+
mcp: {
|
|
1509
|
+
key: "feeWalletMultisig.vaultIndex"
|
|
1510
|
+
},
|
|
1511
|
+
sdk: {
|
|
1512
|
+
key: "feeWalletMultisig.vaultIndex"
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1445
1516
|
{
|
|
1446
1517
|
key: "buy",
|
|
1447
1518
|
type: "decimal",
|
|
@@ -1486,7 +1557,7 @@ var LAUNCH_DEFINITION = {
|
|
|
1486
1557
|
};
|
|
1487
1558
|
|
|
1488
1559
|
// src/launch-schema.ts
|
|
1489
|
-
var M2_TOP_KEYS = new Set(["wallet", "buy"]);
|
|
1560
|
+
var M2_TOP_KEYS = new Set(["wallet", "buy", "feeWallet", "feeWalletMultisig"]);
|
|
1490
1561
|
var GROUPED_TOP_KEYS = new Set(["socials", "curve", "poolFee"]);
|
|
1491
1562
|
function mcpKey(field) {
|
|
1492
1563
|
const surface = field.surfaces.mcp;
|
|
@@ -6267,6 +6338,7 @@ var TOOL_NAMES = [
|
|
|
6267
6338
|
"candle_get_plans",
|
|
6268
6339
|
"candle_trade",
|
|
6269
6340
|
"candle_launch_and_seed",
|
|
6341
|
+
"candle_atomic_launch_dry_run",
|
|
6270
6342
|
"candle_swap",
|
|
6271
6343
|
"candle_transfer",
|
|
6272
6344
|
"candle_sweep",
|
|
@@ -6401,6 +6473,18 @@ function buildRequest(name, args, cfg) {
|
|
|
6401
6473
|
init: { method: "POST", headers: jsonHeaders(apiKey), body: JSON.stringify(body) }
|
|
6402
6474
|
};
|
|
6403
6475
|
}
|
|
6476
|
+
case "candle_atomic_launch_dry_run": {
|
|
6477
|
+
const apiKey = requireApiKey2(cfg);
|
|
6478
|
+
const { payer, chain: _chain, buyAmount: _buyAmount, ...rest } = args;
|
|
6479
|
+
return {
|
|
6480
|
+
url: `${base2}/api/v1/launch/atomic/dry-run`,
|
|
6481
|
+
init: {
|
|
6482
|
+
method: "POST",
|
|
6483
|
+
headers: jsonHeaders(apiKey),
|
|
6484
|
+
body: JSON.stringify({ ...rest, chain: "solana", payer: payer ?? { type: "main" } })
|
|
6485
|
+
}
|
|
6486
|
+
};
|
|
6487
|
+
}
|
|
6404
6488
|
case "candle_get_market": {
|
|
6405
6489
|
const { chain, mint } = args;
|
|
6406
6490
|
return {
|
|
@@ -6840,6 +6924,22 @@ var getFeesShape = {
|
|
|
6840
6924
|
cursor: z9.string().optional().describe("The previous page's continueCursor, verbatim"),
|
|
6841
6925
|
limit: z9.number().optional().describe("Tokens per page, 1 to 50 (default 20). Each one costs chain reads")
|
|
6842
6926
|
};
|
|
6927
|
+
var atomicPayerShape = z9.union([
|
|
6928
|
+
z9.object({ type: z9.literal("main") }),
|
|
6929
|
+
z9.object({ type: z9.literal("linked"), linkedWalletId: z9.string().min(1) })
|
|
6930
|
+
]);
|
|
6931
|
+
var atomicLaunchDryRunShape = (() => {
|
|
6932
|
+
const { buyAmount: _buyAmount, chain: _chain, ...launch } = launchTokenShape;
|
|
6933
|
+
return {
|
|
6934
|
+
...launch,
|
|
6935
|
+
clientLaunchId: z9.string().optional().describe("Not used by a dry run; send the id you will launch with"),
|
|
6936
|
+
payer: atomicPayerShape.optional().describe("Who pays for the launch: {type:'main'} (default) or {type:'linked', linkedWalletId}"),
|
|
6937
|
+
firstBuys: z9.array(z9.object({
|
|
6938
|
+
payer: atomicPayerShape,
|
|
6939
|
+
amountRaw: z9.string().regex(/^[1-9][0-9]*$/).describe("Quote-asset raw units")
|
|
6940
|
+
})).min(1).max(4).describe("One to four first buys, each priced on the curve this launch would deploy")
|
|
6941
|
+
};
|
|
6942
|
+
})();
|
|
6843
6943
|
var claimFeesShape = {
|
|
6844
6944
|
mint: z9.string().describe("The launched token: a Solana mint or a Hood token address, as candle_get_fees lists it"),
|
|
6845
6945
|
dryRun: z9.boolean().optional().describe("Check and read only. Sends nothing and writes nothing. Use it first to see what would be claimed")
|
|
@@ -7232,12 +7332,12 @@ MARKET_NOT_FOUND means Candle has no market for that token and this could not ru
|
|
|
7232
7332
|
}, async (args) => callAndRelay("candle_claim_staking_reward", args, getConfig(), doFetch));
|
|
7233
7333
|
register("candle_get_fees", {
|
|
7234
7334
|
title: "Read the creator fees this account's tokens can pay",
|
|
7235
|
-
description: "The tokens launched by the account's own wallets, with what each could pay now in creator fees " + "(raw units from direct chain reads) and `
|
|
7335
|
+
description: "The tokens launched by the account's own wallets, with what each could pay now in creator fees " + "(raw units from direct chain reads) and a `reason` saying who can claim: `claimable_by_key` on a " + "claimable Solana row, and otherwise why this key cannot (including `claimable_via_web_session` " + "and `fee_wallet_designated`, which name whose authority collects). Reads only; " + "moves nothing. It returns no earned or paid-out totals. An unreadable token is marked, never " + "shown as zero. Paged: pass `continueCursor` back as `cursor`.",
|
|
7236
7336
|
inputSchema: getFeesShape
|
|
7237
7337
|
}, async (args) => callAndRelay("candle_get_fees", args, getConfig(), doFetch));
|
|
7238
7338
|
register("candle_claim_fees", {
|
|
7239
7339
|
title: "Claim a token's creator fees",
|
|
7240
|
-
description: "Collect one token's creator fees and pay them to the wallet fixed at launch. There is no destination " + "argument and the tool cannot send funds anywhere else. Candle signs with the embedded wallet, which " + "pays the network fee. Needs launch:write. " + "Call it with dryRun: true first; a real claim moves real funds into the recipient wallet, which may be " + "the wallet this agent trades from. Not idempotent by id: if the result is lost, read candle_get_fees " + "before claiming again.",
|
|
7340
|
+
description: "Collect one token's creator fees and pay them to the wallet fixed at launch. There is no destination " + "argument and the tool cannot send funds anywhere else. Candle signs with the embedded wallet, which " + "pays the network fee. A fee recipient that is a TEE wallet is refused here: claim it with the candle CLI " + "(`candle fees claim`). The dry run reports the same refusal (`claimable: false`, `reason: " + "wallet_not_signable`) and counts only what this tool could claim. Needs launch:write. " + "Call it with dryRun: true first; a real claim moves real funds into the recipient wallet, which may be " + "the wallet this agent trades from. Not idempotent by id: if the result is lost, read candle_get_fees " + "before claiming again.",
|
|
7241
7341
|
inputSchema: claimFeesShape
|
|
7242
7342
|
}, async (args) => callAndRelay("candle_claim_fees", args, getConfig(), doFetch));
|
|
7243
7343
|
register("candle_get_wallets", {
|
|
@@ -7345,6 +7445,12 @@ MARKET_NOT_FOUND means Candle has no market for that token and this could not ru
|
|
|
7345
7445
|
const result = await executeTrade(args, getConfig(), doFetch);
|
|
7346
7446
|
return { content: [{ type: "text", text: result.text }], ...result.isError ? { isError: true } : {} };
|
|
7347
7447
|
});
|
|
7448
|
+
register("candle_atomic_launch_dry_run", {
|
|
7449
|
+
title: "Dry-run an atomic Solana launch",
|
|
7450
|
+
description: "Check a Solana launch bundled with first buys and price each buy, without building anything. Runs the " + "same checks as the atomic build, in the same order (payers, Believer check, fee and spend limits, the " + "key's transaction cap), then returns the launch preview (curveTerms) and one fill per first buy: the " + "tokens it would receive and the floor the build would sign it at. Reads only; moves nothing, reserves " + "nothing, and the clientLaunchId stays unused. It does not check balances, the daily cap, or the " + "transaction's size, so the real launch can still refuse. Needs launch:write, swap:write and Pro or Max.",
|
|
7451
|
+
inputSchema: atomicLaunchDryRunShape,
|
|
7452
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
7453
|
+
}, async (args) => callAndRelay("candle_atomic_launch_dry_run", args, getConfig(), doFetch));
|
|
7348
7454
|
register("candle_launch_and_seed", {
|
|
7349
7455
|
title: "Launch a token and seed it",
|
|
7350
7456
|
description: "Launch a new token from the account's embedded wallet, with an optional dev-buy seed, then " + "return the fresh market state and token links in one result. On solana a seed makes this " + (options.headlessSeed === true ? "the seed is a separate first-buy transaction in the same Jito bundle as the launch, so " + "both land or neither does. That works on every plan, Free included, and needs no " + "swap:write. On hood the seed is " : "the atomic launch: the launch and the seed are two transactions Candle signs and sends as " + "one Jito bundle, so both land or neither does. That needs Pro or Max (TIER_REQUIRED " + "otherwise) and swap:write on the key, and the result carries bundleId. On hood the seed is ") + "a best-effort follow-up. A launch with no seed works on every plan, Free included. MOVES " + "REAL FUNDS unless dryRun; dry-run first, which spends nothing. Seeds above the platform " + "dev-buy ceiling are rejected (DEV_BUY_TOO_HIGH): at most 0.5 SOL / 500 USDC / 2,000,000 " + "CNDL, or on an exp- curve 10% of the threshold when that is lower; the server holds the " + "creator's own seed to the effective ceiling, so launch with the largest devBuy it allows " + "and top up with candle_trade. " + LAUNCH_SHARED_SENTENCES + (imageDir ? IMAGE_PATH_DISCLOSURE : ""),
|