@candledottv/mcp 0.10.14 → 0.10.15

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 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
- forty-one tools over stdio, so an MCP-capable agent can launch tokens (optionally seeded with a dev
4
+ forty-two tools over stdio, 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, report on-chain activity, and check an agent profile without hand-rolling HTTP
7
7
  calls.
@@ -31,7 +31,7 @@ Environment below -- or skip env editing entirely: install the Candle CLI
31
31
  environment.
32
32
 
33
33
  `CANDLE_MCP_TOOLS` (optional) is a comma-separated allowlist of tool names; only those register.
34
- Unset means all forty-one. An unknown name fails startup with the valid names in the message, rather
34
+ Unset means all forty-two. An unknown name fails startup with the valid names in the message, rather
35
35
  than silently registering the wrong surface. `candle mcp --read-only` / `--tools` set this for
36
36
  you.
37
37
 
@@ -95,6 +95,7 @@ tools, getting a key, funding the embedded wallet, and idempotent retries, see
95
95
  | `candle_launch_token` | Launch a token on Candle | `POST /api/v1/launch/headless` (or `/dry-run` when `dryRun: true`); with `imagePath`, `POST /api/v1/uploads/agent-image` first | `CANDLE_AGENT_API_KEY` |
96
96
  | `candle_get_market` | Get market state | `GET /api/v1/markets/:chain/:mint` | none |
97
97
  | `candle_get_feed` | Get a token feed | `GET /api/v1/markets/feed?bucket=...` | none |
98
+ | `candle_vamp_candidates` | Tickers being copied near graduation: Solana tokens near graduation or graduated in the last 6 hours, most-copied in the last 24 hours first, each with a launch draft (name, ticker, image URL) and `draftNotes` for the fields you must supply. Counts exclude the candidate itself. Answers 404 where the deployment has not switched it on | `GET /api/v1/markets/vamp-candidates?limit=...&minCopies24h=...&stage=...` | `CANDLE_AGENT_API_KEY` (`account:read`) |
98
99
  | `candle_token_forensics` | Deployer history, deploy-window buyers, sourced token safety flags | `GET /api/v1/markets/:chain/:mint/forensics` | none |
99
100
  | `candle_report_activity` | Report on-chain activity | `POST /api/v1/activity/report` | `CANDLE_AGENT_API_KEY` |
100
101
  | `candle_get_agent_profile` | Get an agent profile | `GET /api/v1/users/:idOrWallet/agent` | none |
@@ -178,7 +179,7 @@ explicitly. Assets with nothing spendable report `empty`; a failed asset never s
178
179
  ## Errors
179
180
 
180
181
  This package never reinterprets an error body, and that body is not one uniform shape across all
181
- forty-one tools:
182
+ forty-two tools:
182
183
 
183
184
  - `candle_launch_token`, `candle_get_market`, and `candle_get_feed` hit endpoints that use the
184
185
  structured envelope `{ success: false, error: { code, message, ... } }`. Branch on `error.code`.
package/dist/index.js CHANGED
@@ -112,7 +112,7 @@ import { lstat, open, realpath } from "node:fs/promises";
112
112
  import { dirname, isAbsolute, relative, sep } from "node:path";
113
113
 
114
114
  // src/version.ts
115
- var SERVER_VERSION = "0.10.14";
115
+ var SERVER_VERSION = "0.10.15";
116
116
 
117
117
  // src/update-notice.ts
118
118
  var PLAIN_VERSION = /^\d+\.\d+\.\d+$/;
@@ -1652,6 +1652,7 @@ function planTableMarkdown(table) {
1652
1652
  }
1653
1653
 
1654
1654
  // src/tools.ts
1655
+ var VAMP_CANDIDATES_DESCRIPTION = "Lists Solana tokens that are close to graduating or graduated in the last 6 hours whose ticker other tokens " + "are copying, most-copied in the last 24 hours first. Each entry carries a launch draft (name, ticker, image URL) " + "for `candle_launch_token` or `candle_launch_and_seed`; draft notes identify fields you must supply or adjust. " + "Upload your own image through the agent image upload when the image is unavailable. Use `dryRun: true` first. " + "Counts exclude the candidate itself and cover both Solana and Hood launches at the venues returned in " + "`coverage`, not Candle's own. `coverage.since` is the returned Solana coverage date; Hood history may differ.";
1655
1656
  var localProfileTools = new WeakMap;
1656
1657
  var STAKING_DISCLOSURE = "No instant unstake. Read pool.withdrawalTimelockSeconds for the wait. Solana rewards accrue to the holding wallet. Outside the account's main wallet, sCNDL earns no Hood staking rewards; Pro eligibility follows the deployment's tier mode (main-wallet mode excludes it). CNDL in a pending withdrawal counts toward nothing for Pro.";
1657
1658
  var stakingWriteShape = {
@@ -1664,6 +1665,7 @@ var TOOL_NAMES = [
1664
1665
  "candle_launch_token",
1665
1666
  "candle_get_market",
1666
1667
  "candle_get_feed",
1668
+ "candle_vamp_candidates",
1667
1669
  "candle_token_forensics",
1668
1670
  "candle_report_activity",
1669
1671
  "candle_get_agent_profile",
@@ -1792,6 +1794,21 @@ function buildRequest(name, args, cfg) {
1792
1794
  init: { method: "GET", headers: jsonHeaders() }
1793
1795
  };
1794
1796
  }
1797
+ case "candle_vamp_candidates": {
1798
+ const apiKey = requireApiKey2(cfg);
1799
+ const { limit, minCopies24h, stage } = args;
1800
+ const params = new URLSearchParams;
1801
+ if (limit !== undefined)
1802
+ params.set("limit", String(limit));
1803
+ if (minCopies24h !== undefined)
1804
+ params.set("minCopies24h", String(minCopies24h));
1805
+ if (stage !== undefined)
1806
+ params.set("stage", stage);
1807
+ return {
1808
+ url: `${base2}/api/v1/markets/vamp-candidates${params.size ? `?${params}` : ""}`,
1809
+ init: { method: "GET", headers: jsonHeaders(apiKey) }
1810
+ };
1811
+ }
1795
1812
  case "candle_report_activity": {
1796
1813
  const apiKey = requireApiKey2(cfg);
1797
1814
  return {
@@ -2122,6 +2139,11 @@ var getOperationShape = {
2122
2139
  clientId: z2.string().describe("The clientTradeId or clientLaunchId the write used, or that the tool echoed back to you"),
2123
2140
  kind: z2.enum(["trade", "launch"]).describe("Which rail the id belongs to. Required: ids are caller-chosen strings with no shape to dispatch on")
2124
2141
  };
2142
+ var vampCandidatesShape = {
2143
+ limit: z2.number().optional().describe("Entries to return, 1 to 50 (default 20)"),
2144
+ minCopies24h: z2.number().optional().describe("Only tokens whose ticker was copied at least this many times in the last 24 hours (default 1)"),
2145
+ stage: z2.enum(["final_stretch", "graduated", "all"]).optional().describe("final_stretch: still on the bonding curve; graduated: graduated in the last 6 hours; all (default)")
2146
+ };
2125
2147
  var getFeesShape = {
2126
2148
  cursor: z2.string().optional().describe("The previous page's continueCursor, verbatim"),
2127
2149
  limit: z2.number().optional().describe("Tokens per page, 1 to 50 (default 20). Each one costs chain reads")
@@ -2257,6 +2279,11 @@ MARKET_NOT_FOUND means Candle has no market for that token and this could not ru
2257
2279
  ` + "Filter, sort and pick fields SERVER-SIDE rather than reading the whole feed: an " + "unfiltered response is around 135KB and will not fit in a tool result. See `where`, " + "`sort` and `fields`.\n\n" + "One rule to know before screening on safety: a missing field is NOT a false one. " + "mintAuthorityDisabled and freezeAuthorityDisabled are absent on a real share of rows, " + "and absent means nobody checked, not that the authority is disabled. `where` never lets " + 'an absent field satisfy a comparison, so {"mintAuthorityDisabled":{"eq":true}} returns ' + "only tokens that actually say so.",
2258
2280
  inputSchema: getFeedShape
2259
2281
  }, async (args) => callAndRelay("candle_get_feed", args, getConfig(), doFetch));
2282
+ register("candle_vamp_candidates", {
2283
+ title: "Tickers being copied near graduation",
2284
+ description: VAMP_CANDIDATES_DESCRIPTION,
2285
+ inputSchema: vampCandidatesShape
2286
+ }, async (args) => callAndRelay("candle_vamp_candidates", args, getConfig(), doFetch));
2260
2287
  register("candle_report_activity", {
2261
2288
  title: "Report on-chain activity",
2262
2289
  description: "Report a client-executed transaction (transfer, swap, stake) so Candle records and verifies it.",
@@ -2592,6 +2619,8 @@ Never let a MARKET_NOT_FOUND stand in for a clean bill of health. The same rule
2592
2619
  coverage note on every forensics measurement: "unavailable" is NOT "clean" — say so rather than
2593
2620
  reporting a token as safe.
2594
2621
 
2622
+ LAUNCHING A COPY: candle_vamp_candidates (a key with account:read) lists Solana tickers being copied near graduation, each with a launch draft for candle_launch_token or candle_launch_and_seed. Supply any draft field that is null (draftNotes says why), and launch with dryRun: true first. Where the deployment has not switched it on it answers 404.
2623
+
2595
2624
  WRITING (trade, launch, transfer, sweep, swap) needs a key. If a call returns an auth error, the fix is on the human's side: they run \`candle auth login\`, which authorizes a device in the browser and stores the credentials. Do not ask them to paste a key into a config file, and do not retry the call until they confirm.
2596
2625
 
2597
2626
  Two chains: solana and hood. Most tools take an explicit chain — resolve it with candle_resolve_token rather than guessing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@candledottv/mcp",
3
- "version": "0.10.14",
3
+ "version": "0.10.15",
4
4
  "description": "MCP server for the Candle agent rail: launch tokens, read markets, report activity",
5
5
  "type": "module",
6
6
  "license": "MIT",