chaink9-mcp 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ChainK9
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,80 @@
1
- # Temporary Holding Version
1
+ # ChainK9 MCP server
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Token risk checks for AI agents on **BNB Smart Chain, Ethereum and Base**.
4
+
5
+ Most token scanners read flags from someone else's API. ChainK9 does what a buyer would: it
6
+ forks the chain and really buys and sells the token through its market (PancakeSwap or
7
+ Uniswap V2, V3 or V4, hooks included), then runs 60+ checks. A honeypot is caught by what it
8
+ does, not by what its code looks like.
9
+
10
+ Each successful call is paid automatically in **USDC on Base** with the
11
+ [x402](https://x402.org) protocol, from a wallet you choose. There is no account and no API
12
+ key, and failed calls (bad input, not a token, no liquidity, engine busy) are free.
13
+
14
+ ## Tools
15
+
16
+ The tool list is read live from [api.chaink9.com](https://api.chaink9.com), so new products
17
+ appear without updating this package.
18
+
19
+ | Tool | Price | What it does |
20
+ |---|---|---|
21
+ | `scan` | $0.02 | Full check of a token: honeypot, buy/sell taxes and how they change, owner pause, blacklist, mint and confiscation powers, limits, liquidity, upgrade authority. Verdict: danger, caution or ok. |
22
+ | `report` | $0.002 | The latest stored scan of a token, without a new one. |
23
+ | `feed` | $0.002 | Tokens that just got a market, with a verdict where scanned. |
24
+ | `simulate-trade` | $0.02 | Buy or sell for a given wallet on a fork, with its real balances. |
25
+ | `exit-check` | $0.04 | Test up to four sell sizes from a wallet's real balance. |
26
+ | `transaction-preview` | $0.02 | Run any transaction on a fork and see balance changes. |
27
+ | `liquidity-report` | $0.003 | The token's pool: reserves and LP tokens (V2), or liquidity and price (V3/V4). |
28
+ | `launch-feed` | $0.003 | New markets that are actually funded, optionally by verdict. |
29
+ | `risk-changes` | $0.002 | What changed between a token's last two scans. |
30
+ | `deployer-report` | $0.005 | A token's verified creator and their other known tokens. |
31
+ | `portfolio-screen` | $0.005 | A wallet's balances of given tokens, riskiest first. |
32
+
33
+ Every tool takes `chain`: `bsc` (default), `eth` or `base`.
34
+
35
+ ## Setup
36
+
37
+ 1. Make a **new wallet just for this** and put a few dollars of **USDC on Base** in it. It
38
+ needs no ETH: x402 payments are signatures, and the payment service pays the gas.
39
+ 2. Add the server to your MCP client with that wallet's private key.
40
+
41
+ Claude Code:
42
+
43
+ ```bash
44
+ claude mcp add chaink9 -e CHAINK9_PRIVATE_KEY=0x... -- npx -y chaink9-mcp
45
+ ```
46
+
47
+ Cursor, Claude Desktop or any client with a JSON config:
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "chaink9": {
53
+ "command": "npx",
54
+ "args": ["-y", "chaink9-mcp"],
55
+ "env": { "CHAINK9_PRIVATE_KEY": "0x..." }
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ Claude Desktop can also install the `.mcpb` bundle from the
62
+ [releases](https://github.com/ChainK9/chaink9-mcp/releases) with a click.
63
+
64
+ ## Limits
65
+
66
+ | Variable | Default | Meaning |
67
+ |---|---|---|
68
+ | `CHAINK9_PRIVATE_KEY` | (required) | Private key of the dedicated Base wallet that pays. |
69
+ | `CHAINK9_MAX_USD_PER_CALL` | `0.05` | Any single payment above this is refused. |
70
+ | `CHAINK9_MAX_USD_PER_DAY` | `1` | Stops paying once this much was spent today (UTC). |
71
+
72
+ The daily total is kept in `~/.chaink9-mcp/spend.json`. The wallet only ever signs payments
73
+ on Base, and the key never leaves your machine.
74
+
75
+ ## Disclaimer
76
+
77
+ ChainK9 reports what happened when it traded the token on a private copy of its blockchain at
78
+ the block shown. That is evidence, not a guarantee: a token's owner can change its rules after
79
+ the scan, and traps no check tests can be missed. Nothing here is financial advice; you trade
80
+ at your own risk.
package/index.js ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ // chaink9-mcp: ChainK9's token risk checks as MCP tools, paid per call with x402 (USDC on Base).
3
+ // Tools come from the live catalog (https://api.chaink9.com/openapi.json), so new products
4
+ // appear without updating this package.
5
+
6
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { homedir } from "node:os";
8
+ import { join } from "node:path";
9
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
12
+ import { decodePaymentResponseHeader, wrapFetchWithPaymentFromConfig } from "@x402/fetch";
13
+ import { ExactEvmScheme } from "@x402/evm";
14
+ import { privateKeyToAccount } from "viem/accounts";
15
+
16
+ const VERSION = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")).version;
17
+ const API = "https://api.chaink9.com";
18
+ const BASE_MAINNET = "eip155:8453"; // ChainK9 is paid in USDC on Base only
19
+ const MAX_PER_CALL = Number(process.env.CHAINK9_MAX_USD_PER_CALL || 0.05);
20
+ const MAX_PER_DAY = Number(process.env.CHAINK9_MAX_USD_PER_DAY || 1);
21
+ const DIR = join(homedir(), ".chaink9-mcp");
22
+ const LEDGER = join(DIR, "spend.json");
23
+ const log = (...a) => console.error("[chaink9]", ...a); // stdout carries the MCP protocol
24
+
25
+ // ---------------------------------------------------------------- catalog
26
+ let catalog; // name -> { path, price, tool }
27
+ async function loadCatalog() {
28
+ if (catalog) return catalog;
29
+ const res = await fetch(`${API}/openapi.json`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(20_000) });
30
+ if (!res.ok) throw new Error(`could not load the ChainK9 catalog (HTTP ${res.status})`);
31
+ const spec = await res.json();
32
+ catalog = new Map();
33
+ for (const [path, ops] of Object.entries(spec.paths ?? {})) {
34
+ const op = ops.post;
35
+ if (!op) continue;
36
+ const price = Number(op["x-payment-info"]?.price?.amount ?? NaN);
37
+ const name = path.slice(1).replace(/[^a-zA-Z0-9_-]/g, "_");
38
+ catalog.set(name, {
39
+ path,
40
+ price,
41
+ tool: {
42
+ name,
43
+ description: `${op.description || op.summary || name} Costs $${price} per successful call, paid automatically in USDC on Base; failed calls are free.`,
44
+ inputSchema: op.requestBody?.content?.["application/json"]?.schema ?? { type: "object", properties: {} },
45
+ },
46
+ });
47
+ }
48
+ log(`${catalog.size} tools from ${API}`);
49
+ return catalog;
50
+ }
51
+
52
+ // ---------------------------------------------------------------- wallet and limits
53
+ let payFetch;
54
+ function payer() {
55
+ if (payFetch) return payFetch;
56
+ const key = process.env.CHAINK9_PRIVATE_KEY;
57
+ if (!key) return null;
58
+ // The x402 client signs only Base payments and refuses any single one above the cap,
59
+ // whatever a server asks for.
60
+ payFetch = wrapFetchWithPaymentFromConfig(fetch, {
61
+ schemes: [{ network: BASE_MAINNET, client: new ExactEvmScheme(privateKeyToAccount(key)) }],
62
+ spendControls: { maxAmountPerPayment: `$${MAX_PER_CALL}` },
63
+ });
64
+ return payFetch;
65
+ }
66
+
67
+ const today = () => new Date().toISOString().slice(0, 10);
68
+ function spentToday() {
69
+ try {
70
+ const l = JSON.parse(readFileSync(LEDGER, "utf8"));
71
+ return l.day === today() ? l.usd : 0;
72
+ } catch {
73
+ return 0;
74
+ }
75
+ }
76
+ function addSpend(usd) {
77
+ mkdirSync(DIR, { recursive: true });
78
+ writeFileSync(LEDGER, JSON.stringify({ day: today(), usd: Math.round((spentToday() + usd) * 1e6) / 1e6 }));
79
+ }
80
+
81
+ // ---------------------------------------------------------------- MCP
82
+ const fail = (text) => ({ isError: true, content: [{ type: "text", text }] });
83
+ const server = new Server({ name: "chaink9", version: VERSION }, { capabilities: { tools: {} } });
84
+
85
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [...(await loadCatalog()).values()].map((t) => t.tool) }));
86
+
87
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
88
+ const entry = (await loadCatalog()).get(req.params.name);
89
+ if (!entry) return fail(`Unknown tool ${req.params.name}.`);
90
+ const pay = payer();
91
+ if (!pay) return fail("No wallet configured. Set CHAINK9_PRIVATE_KEY to the private key of a dedicated Base wallet holding a little USDC (no ETH needed); see https://api.chaink9.com.");
92
+ if (!(entry.price <= MAX_PER_CALL)) return fail(`${req.params.name} costs $${entry.price}, above CHAINK9_MAX_USD_PER_CALL ($${MAX_PER_CALL}).`);
93
+ if (spentToday() + entry.price > MAX_PER_DAY) return fail(`Daily limit reached: $${spentToday()} of CHAINK9_MAX_USD_PER_DAY ($${MAX_PER_DAY}) spent today.`);
94
+
95
+ let res;
96
+ try {
97
+ res = await pay(`${API}${entry.path}`, {
98
+ method: "POST",
99
+ headers: { "content-type": "application/json", accept: "application/json", "user-agent": `chaink9-mcp/${VERSION}` },
100
+ body: JSON.stringify(req.params.arguments ?? {}),
101
+ signal: AbortSignal.timeout(120_000), // a full scan takes 10-40 s
102
+ });
103
+ } catch (e) {
104
+ return fail(`Payment or request failed: ${e?.message ?? e}`);
105
+ }
106
+ const receipt = res.headers.get("payment-response");
107
+ if (receipt) {
108
+ try {
109
+ if (decodePaymentResponseHeader(receipt).success) addSpend(entry.price);
110
+ } catch {}
111
+ }
112
+ const text = await res.text();
113
+ // ChainK9 charges only for 2xx answers; say so, so the agent can fix its input or retry.
114
+ if (!res.ok) return fail(`${req.params.name} answered ${res.status} (not charged): ${text.slice(0, 2000)}`);
115
+ return { content: [{ type: "text", text }] };
116
+ });
117
+
118
+ await server.connect(new StdioServerTransport());
119
+ log(`chaink9-mcp ${VERSION} ready (limits: $${MAX_PER_CALL}/call, $${MAX_PER_DAY}/day)`);
package/manifest.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "manifest_version": "0.3",
3
+ "name": "chaink9",
4
+ "display_name": "ChainK9 token risk checks",
5
+ "version": "0.1.0",
6
+ "description": "Check a token on BNB Smart Chain, Ethereum or Base for honeypots, hidden taxes and owner traps before buying it. Paid per call in USDC on Base.",
7
+ "long_description": "ChainK9 checks a token by doing what a buyer would: it forks the chain and really buys and sells the token through its market (Uniswap or PancakeSwap V2, V3 or V4, hooks included), then runs 60+ checks: honeypot, buy and sell taxes and how they change, owner pause, blacklist, mint and confiscation powers, transfer and sell limits, liquidity, upgrade authority and more. Tools also simulate a trade for a given wallet, test exits, preview a transaction, read liquidity and follow new launches. There is no account and no API key: each successful call is paid automatically in USDC on Base with the x402 protocol, from a wallet you choose; failed calls are free. Use a dedicated wallet holding a few dollars of USDC; the per-call and per-day limits below are a second safety net. Results are evidence from a private copy of the chain at one block, not a guarantee and not financial advice.",
8
+ "author": { "name": "ChainK9", "email": "hello@chaink9.com", "url": "https://chaink9.com" },
9
+ "repository": { "type": "git", "url": "https://github.com/ChainK9/chaink9-mcp" },
10
+ "homepage": "https://chaink9.com",
11
+ "support": "https://github.com/ChainK9/chaink9-mcp/issues",
12
+ "server": {
13
+ "type": "node",
14
+ "entry_point": "index.js",
15
+ "mcp_config": {
16
+ "command": "node",
17
+ "args": ["${__dirname}/index.js"],
18
+ "env": {
19
+ "CHAINK9_PRIVATE_KEY": "${user_config.private_key}",
20
+ "CHAINK9_MAX_USD_PER_CALL": "${user_config.max_usd_per_call}",
21
+ "CHAINK9_MAX_USD_PER_DAY": "${user_config.max_usd_per_day}"
22
+ }
23
+ }
24
+ },
25
+ "tools_generated": true,
26
+ "keywords": ["token security", "honeypot", "rug pull", "bsc", "ethereum", "base", "x402", "usdc"],
27
+ "license": "MIT",
28
+ "compatibility": { "platforms": ["darwin", "win32", "linux"], "runtimes": { "node": ">=20.0.0" } },
29
+ "user_config": {
30
+ "private_key": {
31
+ "type": "string",
32
+ "title": "Base wallet private key",
33
+ "description": "0x + 64 hex. A NEW, dedicated wallet holding a few dollars of USDC on Base (no ETH needed). Never your main wallet.",
34
+ "sensitive": true,
35
+ "required": true
36
+ },
37
+ "max_usd_per_call": {
38
+ "type": "number",
39
+ "title": "Max USD per call",
40
+ "description": "Any single payment above this is refused. The most expensive tool costs $0.04.",
41
+ "default": 0.05,
42
+ "min": 0.001,
43
+ "max": 1,
44
+ "required": false
45
+ },
46
+ "max_usd_per_day": {
47
+ "type": "number",
48
+ "title": "Max USD per day",
49
+ "description": "Stops paying once this much was spent today (UTC).",
50
+ "default": 1,
51
+ "min": 0.01,
52
+ "max": 100,
53
+ "required": false
54
+ }
55
+ }
56
+ }
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "chaink9-mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "MCP server for ChainK9: token risk checks on BNB Smart Chain, Ethereum and Base. It buys and sells the token on a private fork of the chain to catch honeypots, hidden taxes and owner traps. Paid per call in USDC on Base with x402.",
5
+ "mcpName": "com.chaink9/chaink9",
6
+ "type": "module",
7
+ "bin": {
8
+ "chaink9-mcp": "index.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "README.md",
13
+ "LICENSE",
14
+ "manifest.json"
15
+ ],
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "x402",
23
+ "honeypot",
24
+ "token-security",
25
+ "rug-pull",
26
+ "bsc",
27
+ "ethereum",
28
+ "base",
29
+ "uniswap",
30
+ "pancakeswap",
31
+ "ai-agents"
32
+ ],
33
+ "homepage": "https://chaink9.com",
34
+ "license": "MIT",
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "1.32.0",
37
+ "@x402/evm": "2.28.0",
38
+ "@x402/fetch": "2.28.0",
39
+ "viem": "2.57.7"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/ChainK9/chaink9-mcp.git"
44
+ },
45
+ "scripts": {
46
+ "test": "node test/smoke.mjs"
47
+ }
48
+ }