@candledottv/mcp 0.7.0 → 0.8.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.
Files changed (2) hide show
  1. package/dist/index.js +19 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -106,7 +106,7 @@ function percentOfBalance(balanceRaw, percent) {
106
106
  import { randomUUID } from "node:crypto";
107
107
 
108
108
  // src/version.ts
109
- var SERVER_VERSION = "0.7.0";
109
+ var SERVER_VERSION = "0.8.0";
110
110
 
111
111
  // src/update-notice.ts
112
112
  var PLAIN_VERSION = /^\d+\.\d+\.\d+$/;
@@ -576,8 +576,15 @@ function buildRequest(name, args, cfg) {
576
576
  };
577
577
  }
578
578
  case "candle_get_feed": {
579
- const { bucket, chain } = args;
580
- const query = new URLSearchParams({ bucket, ...chain ? { chain } : {} });
579
+ const { bucket, chain, where, sort, fields, limit } = args;
580
+ const query = new URLSearchParams({
581
+ bucket,
582
+ ...chain ? { chain } : {},
583
+ ...where ? { where } : {},
584
+ ...sort ? { sort } : {},
585
+ ...fields ? { fields } : {},
586
+ ...limit ? { limit } : {}
587
+ });
581
588
  return {
582
589
  url: `${base2}/api/v1/markets/feed?${query.toString()}`,
583
590
  init: { method: "GET", headers: jsonHeaders() }
@@ -696,7 +703,11 @@ var tokenForensicsShape = {
696
703
  };
697
704
  var getFeedShape = {
698
705
  bucket: z.enum(["new", "graduated", "onfire", "bluechip"]),
699
- chain: z.string().optional().describe("Optional chain filter")
706
+ chain: z.string().optional().describe("Optional chain filter"),
707
+ where: z.string().optional().describe('JSON filter, e.g. {"marketCap":{"lt":150000},"liquidityUsd":{"gte":25000},"mintAuthorityDisabled":{"eq":true}}. ' + "Comparators: eq, ne, lt, lte, gt, gte, present. An ABSENT field satisfies none of them except " + "present:false, so a filter for mintAuthorityDisabled eq true returns only tokens that actually say " + "true, never ones where the flag is simply missing. Use present:false to find the tokens with no data."),
708
+ sort: z.string().optional().describe('Sort as "field" or "field:asc" / "field:desc". A bare field means desc.'),
709
+ fields: z.string().optional().describe("Comma-separated fields to return, e.g. symbol,marketCap,liquidityUsd. chain, address and symbol always " + "ride along. Cuts a 135KB response to a couple of KB."),
710
+ limit: z.string().optional().describe("Max rows to return, 1-200.")
700
711
  };
701
712
  var reportActivityShape = {
702
713
  chain: z.string().describe('"solana" or "hood"'),
@@ -786,14 +797,16 @@ function registerTools(server, env = process.env) {
786
797
  title: "Token forensics",
787
798
  description: `Gate a buy before making it: deployer history, who bought in the deploy window (the creator's own wallets are marked disclosed; strangers in the same slot are the bundle signal), holder concentration, and a risk tier (LOW/MODERATE/HIGH/CRITICAL) with per-factor reasons. Every measurement carries a coverage note -- 'unavailable' is not 'clean'. No key needed.
788
799
 
789
- MARKET_NOT_FOUND means Candle has no market for that token and this could not run. That is also not 'clean': report that you could not check it, rather than reporting the token as safe.`,
800
+ MARKET_NOT_FOUND means Candle has no market for that token and this could not run. That is also not 'clean': report that you could not check it, rather than reporting the token as safe. That refusal now carries error.coverage -- covered:false, a reason ('external_launchpad' when the token launched somewhere else, 'unknown_mint' when nobody has indexed it), the launchpad when known, and every check that consequently did not run. Read it instead of guessing. Most of the feed answers this way.`,
790
801
  inputSchema: tokenForensicsShape
791
802
  }, async (args) => callAndRelay("candle_token_forensics", args, cfg));
792
803
  register("candle_get_feed", {
793
804
  title: "Get a token feed",
794
805
  description: "Read one of the trade page's public feeds: new, graduated, onfire, or bluechip. Reads " + `only; moves nothing. No key needed. Start here when nobody has named a token.
795
806
 
796
- ` + "This indexes the WIDER market, not just Candle's own launches, so rows carry a " + "`launchpad` (pump.fun, pons.family, ...). A row appearing here does NOT mean Candle " + "has a market for it: candle_get_market and candle_token_forensics can legitimately " + "answer MARKET_NOT_FOUND for a mint this returned.",
807
+ ` + "This indexes the WIDER market, not just Candle's own launches, so rows carry a " + "`launchpad` (pump.fun, pons.family, ...). A row appearing here does NOT mean Candle " + "has a market for it: candle_get_market and candle_token_forensics can legitimately " + `answer MARKET_NOT_FOUND for a mint this returned.
808
+
809
+ ` + "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.",
797
810
  inputSchema: getFeedShape
798
811
  }, async (args) => callAndRelay("candle_get_feed", args, cfg));
799
812
  register("candle_report_activity", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@candledottv/mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "MCP server for the Candle agent rail: launch tokens, read markets, report activity",
5
5
  "type": "module",
6
6
  "license": "MIT",