chia-explorer 0.1.6 → 0.2.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 CHANGED
@@ -20,25 +20,48 @@ Backed by the public [coinset.org](https://www.coinset.org) full-node API for ch
20
20
 
21
21
  ## Install
22
22
 
23
+ The server is a single npm package. No global install needed — every config below uses `npx` so it stays up to date.
24
+
23
25
  ```bash
24
- npm install -g chia-explorer
26
+ npx chia-explorer
25
27
  ```
26
28
 
27
- Or run via `npx`:
29
+ If you want it on your PATH:
28
30
 
29
31
  ```bash
30
- npx chia-explorer
32
+ npm install -g chia-explorer
31
33
  ```
32
34
 
33
- ## Use with Claude Code
35
+ Requires Node.js 20+.
36
+
37
+ ## Use it with your AI client
38
+
39
+ ### Claude Code
34
40
 
35
41
  ```bash
36
42
  claude mcp add chia-explorer -- npx chia-explorer
37
43
  ```
38
44
 
39
- ## Use with Claude Desktop
45
+ ### Claude Desktop
46
+
47
+ Edit `claude_desktop_config.json` (Settings → Developer → Edit Config):
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "chia-explorer": {
53
+ "command": "npx",
54
+ "args": ["chia-explorer"]
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ Restart Claude Desktop.
40
61
 
41
- Add to your `claude_desktop_config.json`:
62
+ ### Cursor
63
+
64
+ Create or edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` inside a project:
42
65
 
43
66
  ```json
44
67
  {
@@ -51,6 +74,122 @@ Add to your `claude_desktop_config.json`:
51
74
  }
52
75
  ```
53
76
 
77
+ Restart Cursor and enable the server under Settings → MCP.
78
+
79
+ ### Codex CLI
80
+
81
+ Edit `~/.codex/config.toml`:
82
+
83
+ ```toml
84
+ [mcp_servers.chia-explorer]
85
+ command = "npx"
86
+ args = ["chia-explorer"]
87
+ ```
88
+
89
+ ### VS Code (native MCP)
90
+
91
+ Create `.vscode/mcp.json` in your workspace:
92
+
93
+ ```json
94
+ {
95
+ "servers": {
96
+ "chia-explorer": {
97
+ "command": "npx",
98
+ "args": ["chia-explorer"]
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ### Windsurf
105
+
106
+ Edit `~/.codeium/windsurf/mcp_config.json`:
107
+
108
+ ```json
109
+ {
110
+ "mcpServers": {
111
+ "chia-explorer": {
112
+ "command": "npx",
113
+ "args": ["chia-explorer"]
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Anything else that speaks MCP
120
+
121
+ It's a standard stdio MCP server. The recipe is always the same: `command = npx`, `args = ["chia-explorer"]`. Set `COINGECKO_API_KEY` as an env var if you have one.
122
+
123
+ ## Example prompts
124
+
125
+ Drop these into a chat once the server is wired up.
126
+
127
+ **Offers**
128
+
129
+ > Decode this offer and tell me what's being traded: `offer1qqr83wcuu2rykcmqvpsxgfgqmqys...`
130
+
131
+ > I just got sent this `offer1...` string in Discord. Is it safe to take? What do I give and what do I get?
132
+
133
+ **Smart-coin inspection**
134
+
135
+ > What kind of coin is `0xabc...123`? Pull its puzzle reveal at height 6500000 and tell me if it's a CAT, NFT, DID, or plain XCH.
136
+
137
+ > Walk the children of coin `0xabc...` for two hops. Classify each child.
138
+
139
+ **Mempool and fees**
140
+
141
+ > Is `0xdeadbeef...` (my tx) currently in the mempool?
142
+
143
+ > How many transactions are pending right now? What does the fee market look like for inclusion in the next minute?
144
+
145
+ > What fee should I attach to a take_offer spend to get included in the next 5 minutes?
146
+
147
+ **Balances and pricing**
148
+
149
+ > What's the XCH balance of `xch1yxqsmyuyjdlgxw4sqjg4vqlqv5ms2qzex00586nu643jqemmarwslh08yl`? How much is that in USD and EUR right now?
150
+
151
+ > Convert 1.5 XCH to GBP, EUR, BTC, and SAT.
152
+
153
+ **Chain state**
154
+
155
+ > What block was Chia at one hour ago — height, header hash, transaction count?
156
+
157
+ > Is the network synced? What's the current netspace in EiB?
158
+
159
+ **Strategic reserve**
160
+
161
+ > How much of the 21M XCH strategic reserve has been spent? Where did the most recent five outflows go — partners, market makers, or exchanges?
162
+
163
+ > Show me every spend from the Swiss cold wallet, with the destination labelled.
164
+
165
+ **Identifier glue**
166
+
167
+ > Convert this puzzle hash to a mainnet address: `4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a`.
168
+
169
+ > What's the coin name for parent `0xaaa...`, puzzle hash `0xbbb...`, amount 1000000000000?
170
+
171
+ ## Pre-built workflows: chia-skills
172
+
173
+ [**chia-skills**](https://github.com/Spacetime-Technology/chia-skills) is a companion package of Claude Code skills built on top of this MCP. It turns the read-only tools below into finished workflows you can actually schedule and get notified about: deposit alerts, price triggers, offer safety checks, NFT provenance, invoice watching.
174
+
175
+ ```bash
176
+ npx chia-skills install
177
+ ```
178
+
179
+ What's in the box:
180
+
181
+ - `watch-address` — push notification when XCH, a CAT, or an NFT lands at (or leaves) an address
182
+ - `watch-tx-confirmation` — ping when a specific tx_id moves from mempool to confirmed
183
+ - `watch-xch-price` — alert when XCH crosses a threshold in any CoinGecko currency
184
+ - `watch-fee-market` — catch cheap fee windows to broadcast
185
+ - `watch-prefarm-spend` — flag new strategic-reserve outflows with destinations labelled
186
+ - `address-daily-digest` — daily summary of one or more addresses with USD values
187
+ - `offer-safety-check` — decode an `offer1...` and check both sides against market prices
188
+ - `coin-lineage` / `nft-provenance` — walk coin or NFT history N hops in either direction
189
+ - `invoice-watch` — generate an invoice, watch for the matching deposit, emit a paid receipt
190
+
191
+ Skills are read-only and idempotent, persist state between runs, and accept structured inputs so other skills or agents can chain them. If you want to see what's possible with chia-explorer beyond ad-hoc prompts, start there. If you want to write your own, the skills repo is the reference.
192
+
54
193
  ## Tools
55
194
 
56
195
  | Tool | What it does |
@@ -81,12 +220,17 @@ Add to your `claude_desktop_config.json`:
81
220
  | `get_prefarm_status` | Live per-wallet balances of the 21M XCH strategic reserve, plus total spent |
82
221
  | `get_prefarm_spends` | Outflows from the reserve, with destinations labelled when known (partners / market makers / exchanges). Filter by wallet, height, or count |
83
222
  | `list_prefarm_addresses` | The hardcoded registry: custody wallets and known destination addresses. No network call |
223
+ | `list_chips` | Merged Chia Improvement Proposals on `main`, parsed front matter + abstract. Filter by status or category |
224
+ | `get_chip` | One CHIP by number. Returns the merged version (if any), any open PR drafts proposing the same number, and optionally the full markdown |
225
+ | `list_chip_drafts` | Open PRs against `Chia-Network/chips` that add or modify a CHIP, with parsed front matter and PR context (author, reviewers, draft flag) |
226
+ | `search_chips` | Keyword search across merged CHIPs and open PR drafts (title, description, abstract, authors) |
84
227
 
85
- Blockchain tools take an optional `network: "mainnet" | "testnet11"` (default `mainnet`). The price tools take no network arg. The prefarm tools are mainnet only.
228
+ Blockchain tools take an optional `network: "mainnet" | "testnet11"` (default `mainnet`). The price and CHIPs tools take no network arg. The prefarm tools are mainnet only.
86
229
 
87
230
  ## Optional config
88
231
 
89
232
  - `COINGECKO_API_KEY` — if set, sent as `x-cg-demo-api-key` to lift the free-tier rate limit. The price tools work without it.
233
+ - `GITHUB_TOKEN` — if set, sent as `Authorization: Bearer …` to the GitHub API. Lifts the unauthenticated 60/hr limit to 5000/hr for CHIPs listings. Raw file fetches don't need it. The CHIPs tools work without it.
90
234
 
91
235
  ## Prompts
92
236
 
@@ -0,0 +1,68 @@
1
+ import { type AuthorRef } from './parser.js';
2
+ export interface ChipSummary {
3
+ number: number | null;
4
+ title: string | null;
5
+ status: string | null;
6
+ category: string | null;
7
+ sub_category: string | null;
8
+ type: string | null;
9
+ authors: AuthorRef[];
10
+ editors: AuthorRef[];
11
+ description: string | null;
12
+ abstract: string | null;
13
+ created: string | null;
14
+ updated: string | null;
15
+ comments_uri: string | null;
16
+ requires: string | null;
17
+ replaces: string | null;
18
+ superseded_by: string | null;
19
+ source_url: string;
20
+ filename: string;
21
+ }
22
+ export interface MergedChip extends ChipSummary {
23
+ source: 'merged';
24
+ ref: 'main';
25
+ body?: string;
26
+ }
27
+ export interface DraftChip extends ChipSummary {
28
+ source: 'draft';
29
+ ref: string;
30
+ pr: PrContext;
31
+ modifies_existing: boolean;
32
+ body?: string;
33
+ }
34
+ export interface PrContext {
35
+ number: number;
36
+ url: string;
37
+ title: string;
38
+ state: string;
39
+ draft: boolean;
40
+ author: string | null;
41
+ requested_reviewers: string[];
42
+ created_at: string;
43
+ updated_at: string;
44
+ head_sha: string;
45
+ head_ref: string;
46
+ base_ref: string;
47
+ }
48
+ export declare function listMergedChips(): Promise<ChipSummary[]>;
49
+ export declare function getMergedChip(number: number, options?: {
50
+ includeBody?: boolean;
51
+ }): Promise<MergedChip | null>;
52
+ export declare function listChipDrafts(): Promise<DraftChip[]>;
53
+ export declare function getChipFromPr(prNumber: number, options?: {
54
+ includeBody?: boolean;
55
+ }): Promise<DraftChip | null>;
56
+ export declare function findChipByNumber(number: number, options?: {
57
+ includeBody?: boolean;
58
+ }): Promise<{
59
+ merged: MergedChip | null;
60
+ drafts: DraftChip[];
61
+ }>;
62
+ export interface SearchOptions {
63
+ status?: string;
64
+ source?: 'merged' | 'draft' | 'both';
65
+ limit?: number;
66
+ }
67
+ export declare function searchChips(query: string, options?: SearchOptions): Promise<Array<MergedChip | DraftChip>>;
68
+ export { resetCache } from '../github/cache.js';
@@ -0,0 +1,214 @@
1
+ import { FileNotFoundError, fetchRawFile, githubApi } from '../github/client.js';
2
+ import { getCached } from '../github/cache.js';
3
+ import { buildChipFileName, extractAbstract, extractChipPathInfo, parseChipFrontMatter, } from './parser.js';
4
+ const REPO = 'Chia-Network/chips';
5
+ const DEFAULT_REF = 'main';
6
+ const CHIPS_DIR = 'CHIPs';
7
+ const LISTING_TTL_MS = 5 * 60_000;
8
+ const CONTENT_TTL_MS = 10 * 60_000;
9
+ const PR_LIST_TTL_MS = 2 * 60_000;
10
+ function summarize(fm, body, ref, filename) {
11
+ return {
12
+ number: fm.number,
13
+ title: fm.title,
14
+ status: fm.status,
15
+ category: fm.category,
16
+ sub_category: fm.sub_category,
17
+ type: fm.type,
18
+ authors: fm.authors,
19
+ editors: fm.editors,
20
+ description: fm.description,
21
+ abstract: extractAbstract(body),
22
+ created: fm.created,
23
+ updated: fm.updated,
24
+ comments_uri: fm.comments_uri,
25
+ requires: fm.requires,
26
+ replaces: fm.replaces,
27
+ superseded_by: fm.superseded_by,
28
+ source_url: `https://github.com/${REPO}/blob/${ref}/${filename}`,
29
+ filename,
30
+ };
31
+ }
32
+ async function listChipFilenames() {
33
+ return getCached(`chips:contents:${DEFAULT_REF}`, async () => {
34
+ const entries = await githubApi(`/repos/${REPO}/contents/${CHIPS_DIR}?ref=${DEFAULT_REF}`);
35
+ return entries
36
+ .filter((e) => e.type === 'file' && /^chip-\d{1,5}\.md$/i.test(e.name))
37
+ .map((e) => e.path)
38
+ .sort();
39
+ }, LISTING_TTL_MS);
40
+ }
41
+ async function fetchChipFile(ref, path) {
42
+ return getCached(`chips:raw:${ref}:${path}`, () => fetchRawFile(REPO, ref, path), CONTENT_TTL_MS);
43
+ }
44
+ export async function listMergedChips() {
45
+ const paths = await listChipFilenames();
46
+ const summaries = await Promise.all(paths.map(async (path) => {
47
+ const body = await fetchChipFile(DEFAULT_REF, path);
48
+ const fm = parseChipFrontMatter(body);
49
+ return summarize(fm, body, DEFAULT_REF, path);
50
+ }));
51
+ summaries.sort((a, b) => (a.number ?? 0) - (b.number ?? 0));
52
+ return summaries;
53
+ }
54
+ export async function getMergedChip(number, options = {}) {
55
+ const filename = `${CHIPS_DIR}/${buildChipFileName(number)}`;
56
+ try {
57
+ const body = await fetchChipFile(DEFAULT_REF, filename);
58
+ const fm = parseChipFrontMatter(body);
59
+ const summary = summarize(fm, body, DEFAULT_REF, filename);
60
+ const chip = {
61
+ ...summary,
62
+ source: 'merged',
63
+ ref: 'main',
64
+ };
65
+ if (options.includeBody)
66
+ chip.body = body;
67
+ return chip;
68
+ }
69
+ catch (err) {
70
+ if (err instanceof FileNotFoundError)
71
+ return null;
72
+ throw err;
73
+ }
74
+ }
75
+ async function listOpenChipPrs() {
76
+ return getCached(`chips:prs:open`, () => githubApi(`/repos/${REPO}/pulls?state=open&per_page=100&sort=updated&direction=desc`), PR_LIST_TTL_MS);
77
+ }
78
+ async function listPrChipFiles(prNumber) {
79
+ return getCached(`chips:pr-files:${prNumber}`, () => githubApi(`/repos/${REPO}/pulls/${prNumber}/files?per_page=100`), PR_LIST_TTL_MS);
80
+ }
81
+ function prContext(pr) {
82
+ return {
83
+ number: pr.number,
84
+ url: pr.html_url,
85
+ title: pr.title,
86
+ state: pr.state,
87
+ draft: pr.draft,
88
+ author: pr.user?.login ?? null,
89
+ requested_reviewers: pr.requested_reviewers.map((r) => r.login),
90
+ created_at: pr.created_at,
91
+ updated_at: pr.updated_at,
92
+ head_sha: pr.head.sha,
93
+ head_ref: pr.head.ref,
94
+ base_ref: pr.base.ref,
95
+ };
96
+ }
97
+ async function buildDraftFromPr(pr, file, options = {}) {
98
+ if (file.status === 'removed')
99
+ return null;
100
+ const info = extractChipPathInfo(file.filename);
101
+ if (!info)
102
+ return null;
103
+ let body;
104
+ try {
105
+ body = await fetchChipFile(pr.head.sha, file.filename);
106
+ }
107
+ catch (err) {
108
+ if (err instanceof FileNotFoundError)
109
+ return null;
110
+ throw err;
111
+ }
112
+ const fm = parseChipFrontMatter(body);
113
+ const summary = summarize(fm, body, pr.head.sha, file.filename);
114
+ if (summary.number == null)
115
+ summary.number = info.number;
116
+ const draft = {
117
+ ...summary,
118
+ source: 'draft',
119
+ ref: pr.head.sha,
120
+ pr: prContext(pr),
121
+ modifies_existing: file.status === 'modified' || file.status === 'renamed',
122
+ };
123
+ if (options.includeBody)
124
+ draft.body = body;
125
+ return draft;
126
+ }
127
+ export async function listChipDrafts() {
128
+ const prs = await listOpenChipPrs();
129
+ const results = [];
130
+ for (const pr of prs) {
131
+ const files = await listPrChipFiles(pr.number).catch(() => []);
132
+ const chipFiles = files.filter((f) => extractChipPathInfo(f.filename));
133
+ for (const file of chipFiles) {
134
+ const draft = await buildDraftFromPr(pr, file).catch(() => null);
135
+ if (draft)
136
+ results.push(draft);
137
+ }
138
+ }
139
+ return results;
140
+ }
141
+ export async function getChipFromPr(prNumber, options = {}) {
142
+ const prs = await listOpenChipPrs();
143
+ const pr = prs.find((p) => p.number === prNumber);
144
+ if (!pr)
145
+ return null;
146
+ const files = await listPrChipFiles(prNumber);
147
+ for (const file of files) {
148
+ if (!extractChipPathInfo(file.filename))
149
+ continue;
150
+ const draft = await buildDraftFromPr(pr, file, options);
151
+ if (draft)
152
+ return draft;
153
+ }
154
+ return null;
155
+ }
156
+ export async function findChipByNumber(number, options = {}) {
157
+ const merged = await getMergedChip(number, options);
158
+ const allDrafts = await listChipDrafts();
159
+ const drafts = [];
160
+ for (const d of allDrafts) {
161
+ if (d.number !== number)
162
+ continue;
163
+ if (options.includeBody) {
164
+ const full = await getChipFromPr(d.pr.number, { includeBody: true });
165
+ if (full)
166
+ drafts.push(full);
167
+ else
168
+ drafts.push(d);
169
+ }
170
+ else {
171
+ drafts.push(d);
172
+ }
173
+ }
174
+ return { merged, drafts };
175
+ }
176
+ function matchesQuery(s, q) {
177
+ const needle = q.toLowerCase();
178
+ const haystacks = [];
179
+ if (s.title)
180
+ haystacks.push(s.title);
181
+ if (s.description)
182
+ haystacks.push(s.description);
183
+ if (s.abstract)
184
+ haystacks.push(s.abstract);
185
+ for (const a of s.authors)
186
+ haystacks.push(a.name);
187
+ if (s.number != null)
188
+ haystacks.push(String(s.number));
189
+ return haystacks.some((h) => h.toLowerCase().includes(needle));
190
+ }
191
+ export async function searchChips(query, options = {}) {
192
+ const source = options.source ?? 'both';
193
+ const limit = options.limit ?? 20;
194
+ const statusFilter = options.status?.toLowerCase();
195
+ const pool = [];
196
+ if (source === 'merged' || source === 'both') {
197
+ const merged = await listMergedChips();
198
+ for (const m of merged) {
199
+ pool.push({ ...m, source: 'merged', ref: 'main' });
200
+ }
201
+ }
202
+ if (source === 'draft' || source === 'both') {
203
+ const drafts = await listChipDrafts();
204
+ pool.push(...drafts);
205
+ }
206
+ const filtered = pool.filter((c) => {
207
+ if (statusFilter && (c.status?.toLowerCase() ?? '') !== statusFilter)
208
+ return false;
209
+ return matchesQuery(c, query);
210
+ });
211
+ return filtered.slice(0, limit);
212
+ }
213
+ export { resetCache } from '../github/cache.js';
214
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chips/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export interface AuthorRef {
2
+ name: string;
3
+ url: string | null;
4
+ }
5
+ export interface ChipFrontMatter {
6
+ number: number | null;
7
+ title: string | null;
8
+ description: string | null;
9
+ authors: AuthorRef[];
10
+ editors: AuthorRef[];
11
+ comments_uri: string | null;
12
+ status: string | null;
13
+ category: string | null;
14
+ sub_category: string | null;
15
+ type: string | null;
16
+ created: string | null;
17
+ updated: string | null;
18
+ requires: string | null;
19
+ replaces: string | null;
20
+ superseded_by: string | null;
21
+ extra: Record<string, string>;
22
+ }
23
+ export declare function parseAuthors(raw: string): AuthorRef[];
24
+ export declare function parseChipFrontMatter(markdown: string): ChipFrontMatter;
25
+ export declare function extractAbstract(markdown: string): string | null;
26
+ export declare function buildChipFileName(number: number): string;
27
+ export declare function extractChipPathInfo(path: string): {
28
+ number: number;
29
+ filename: string;
30
+ } | null;
@@ -0,0 +1,208 @@
1
+ const KEY_MAP = {
2
+ 'chip number': 'number',
3
+ 'chip-number': 'number',
4
+ number: 'number',
5
+ title: 'title',
6
+ description: 'description',
7
+ author: 'authors',
8
+ authors: 'authors',
9
+ editor: 'editors',
10
+ editors: 'editors',
11
+ 'comments-uri': 'comments_uri',
12
+ comments_uri: 'comments_uri',
13
+ status: 'status',
14
+ category: 'category',
15
+ 'sub-category': 'sub_category',
16
+ sub_category: 'sub_category',
17
+ type: 'type',
18
+ created: 'created',
19
+ updated: 'updated',
20
+ requires: 'requires',
21
+ replaces: 'replaces',
22
+ 'superseded-by': 'superseded_by',
23
+ superseded_by: 'superseded_by',
24
+ };
25
+ function stripTablePipes(line) {
26
+ let s = line.trim();
27
+ if (s.startsWith('|'))
28
+ s = s.slice(1);
29
+ if (s.endsWith('|'))
30
+ s = s.slice(0, -1);
31
+ return s;
32
+ }
33
+ function isSeparatorRow(cells) {
34
+ if (cells.length === 0)
35
+ return false;
36
+ return cells.every((c) => /^:?-+:?$/.test(c.trim()));
37
+ }
38
+ function isBlankOrNone(value) {
39
+ const v = value.trim().toLowerCase();
40
+ return v === '' || v === 'none' || v === '-' || v === 'n/a';
41
+ }
42
+ export function parseAuthors(raw) {
43
+ const trimmed = raw.trim();
44
+ if (isBlankOrNone(trimmed))
45
+ return [];
46
+ const out = [];
47
+ const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
48
+ const seen = [];
49
+ let match;
50
+ while ((match = linkPattern.exec(trimmed)) !== null) {
51
+ out.push({ name: match[1].trim(), url: match[2].trim() });
52
+ seen.push({ start: match.index, end: match.index + match[0].length });
53
+ }
54
+ if (out.length > 0)
55
+ return out;
56
+ for (const part of trimmed.split(',')) {
57
+ const name = part.trim();
58
+ if (name)
59
+ out.push({ name, url: null });
60
+ }
61
+ return out;
62
+ }
63
+ function parseChipNumber(raw) {
64
+ const m = raw.trim().match(/^\d+/);
65
+ if (!m)
66
+ return null;
67
+ const n = Number(m[0]);
68
+ return Number.isFinite(n) ? n : null;
69
+ }
70
+ function assignField(fm, field, value) {
71
+ switch (field) {
72
+ case 'number':
73
+ fm.number = parseChipNumber(value);
74
+ return;
75
+ case 'authors':
76
+ fm.authors = parseAuthors(value);
77
+ return;
78
+ case 'editors':
79
+ fm.editors = parseAuthors(value);
80
+ return;
81
+ case 'extra':
82
+ return;
83
+ }
84
+ const normalized = isBlankOrNone(value) ? null : value;
85
+ switch (field) {
86
+ case 'title':
87
+ fm.title = normalized;
88
+ return;
89
+ case 'description':
90
+ fm.description = normalized;
91
+ return;
92
+ case 'comments_uri':
93
+ fm.comments_uri = normalized;
94
+ return;
95
+ case 'status':
96
+ fm.status = normalized;
97
+ return;
98
+ case 'category':
99
+ fm.category = normalized;
100
+ return;
101
+ case 'sub_category':
102
+ fm.sub_category = normalized;
103
+ return;
104
+ case 'type':
105
+ fm.type = normalized;
106
+ return;
107
+ case 'created':
108
+ fm.created = normalized;
109
+ return;
110
+ case 'updated':
111
+ fm.updated = normalized;
112
+ return;
113
+ case 'requires':
114
+ fm.requires = normalized;
115
+ return;
116
+ case 'replaces':
117
+ fm.replaces = normalized;
118
+ return;
119
+ case 'superseded_by':
120
+ fm.superseded_by = normalized;
121
+ return;
122
+ }
123
+ }
124
+ function emptyFrontMatter() {
125
+ return {
126
+ number: null,
127
+ title: null,
128
+ description: null,
129
+ authors: [],
130
+ editors: [],
131
+ comments_uri: null,
132
+ status: null,
133
+ category: null,
134
+ sub_category: null,
135
+ type: null,
136
+ created: null,
137
+ updated: null,
138
+ requires: null,
139
+ replaces: null,
140
+ superseded_by: null,
141
+ extra: {},
142
+ };
143
+ }
144
+ export function parseChipFrontMatter(markdown) {
145
+ const fm = emptyFrontMatter();
146
+ const lines = markdown.split(/\r?\n/);
147
+ for (const raw of lines) {
148
+ if (/^##\s/.test(raw))
149
+ break;
150
+ if (/^#\s/.test(raw))
151
+ continue;
152
+ const trimmed = raw.trim();
153
+ if (!trimmed)
154
+ continue;
155
+ if (!trimmed.includes('|'))
156
+ continue;
157
+ const cells = stripTablePipes(trimmed)
158
+ .split('|')
159
+ .map((c) => c.trim());
160
+ if (cells.length < 2)
161
+ continue;
162
+ if (isSeparatorRow(cells))
163
+ continue;
164
+ const key = cells[0].toLowerCase();
165
+ const value = cells.slice(1).join('|').trim();
166
+ const mapped = KEY_MAP[key];
167
+ if (!mapped) {
168
+ if (key)
169
+ fm.extra[key] = value;
170
+ continue;
171
+ }
172
+ assignField(fm, mapped, value);
173
+ }
174
+ return fm;
175
+ }
176
+ export function extractAbstract(markdown) {
177
+ const lines = markdown.split(/\r?\n/);
178
+ let i = 0;
179
+ while (i < lines.length) {
180
+ if (/^##\s+abstract\s*$/i.test(lines[i].trim()))
181
+ break;
182
+ i++;
183
+ }
184
+ if (i >= lines.length)
185
+ return null;
186
+ i++;
187
+ const buf = [];
188
+ while (i < lines.length) {
189
+ const line = lines[i];
190
+ if (/^#{1,6}\s/.test(line.trim()))
191
+ break;
192
+ buf.push(line);
193
+ i++;
194
+ }
195
+ const text = buf.join('\n').trim();
196
+ return text || null;
197
+ }
198
+ export function buildChipFileName(number) {
199
+ return `chip-${String(number).padStart(4, '0')}.md`;
200
+ }
201
+ const CHIP_FILE_PATTERN = /CHIPs\/chip-(\d{1,5})\.md$/i;
202
+ export function extractChipPathInfo(path) {
203
+ const m = CHIP_FILE_PATTERN.exec(path);
204
+ if (!m)
205
+ return null;
206
+ return { number: Number(m[1]), filename: path };
207
+ }
208
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/chips/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function getCached<T>(key: string, loader: () => Promise<T>, ttlMs?: number): Promise<T>;
2
+ export declare function invalidate(key: string): void;
3
+ export declare function resetCache(): void;
@@ -0,0 +1,18 @@
1
+ const DEFAULT_TTL_MS = 5 * 60_000;
2
+ const cache = new Map();
3
+ export async function getCached(key, loader, ttlMs = DEFAULT_TTL_MS) {
4
+ const now = Date.now();
5
+ const entry = cache.get(key);
6
+ if (entry && entry.expiresAt > now)
7
+ return entry.value;
8
+ const value = await loader();
9
+ cache.set(key, { value, expiresAt: now + ttlMs });
10
+ return value;
11
+ }
12
+ export function invalidate(key) {
13
+ cache.delete(key);
14
+ }
15
+ export function resetCache() {
16
+ cache.clear();
17
+ }
18
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/github/cache.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,CAAC,GAAG,MAAM,CAAC;AAOlC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,MAAwB,EACxB,QAAgB,cAAc;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAyB,CAAC;IACrD,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAC;IAC7B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function githubApi<T>(path: string): Promise<T>;
2
+ export declare function fetchRawFile(repo: string, ref: string, path: string): Promise<string>;
3
+ export declare class FileNotFoundError extends Error {
4
+ constructor(message: string);
5
+ }
@@ -0,0 +1,68 @@
1
+ const GITHUB_API_BASE = 'https://api.github.com';
2
+ const RAW_BASE = 'https://raw.githubusercontent.com';
3
+ const REQUEST_TIMEOUT_MS = 10_000;
4
+ const USER_AGENT = 'chia-explorer-mcp';
5
+ function authHeaders() {
6
+ const headers = {
7
+ accept: 'application/vnd.github+json',
8
+ 'x-github-api-version': '2022-11-28',
9
+ 'user-agent': USER_AGENT,
10
+ };
11
+ const token = process.env.GITHUB_TOKEN;
12
+ if (token)
13
+ headers['authorization'] = `Bearer ${token}`;
14
+ return headers;
15
+ }
16
+ function rateLimitMessage(res, body) {
17
+ if (res.status !== 403 && res.status !== 429)
18
+ return null;
19
+ const remaining = res.headers.get('x-ratelimit-remaining');
20
+ const reset = res.headers.get('x-ratelimit-reset');
21
+ if (remaining === '0' || /rate limit/i.test(body)) {
22
+ const resetAt = reset ? new Date(Number(reset) * 1000).toISOString() : 'unknown';
23
+ const tokenHint = process.env.GITHUB_TOKEN
24
+ ? ''
25
+ : ' Set GITHUB_TOKEN to raise the limit from 60/hr to 5000/hr.';
26
+ return `github rate limit exhausted (resets at ${resetAt}).${tokenHint}`;
27
+ }
28
+ return null;
29
+ }
30
+ export async function githubApi(path) {
31
+ const url = path.startsWith('http') ? path : `${GITHUB_API_BASE}${path}`;
32
+ const res = await fetch(url, {
33
+ headers: authHeaders(),
34
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
35
+ });
36
+ if (!res.ok) {
37
+ const body = await res.text().catch(() => '');
38
+ const rateLimit = rateLimitMessage(res, body);
39
+ if (rateLimit)
40
+ throw new Error(rateLimit);
41
+ const detail = body ? `: ${body.slice(0, 200)}` : '';
42
+ throw new Error(`github ${res.status} ${res.statusText}${detail}`);
43
+ }
44
+ return (await res.json());
45
+ }
46
+ export async function fetchRawFile(repo, ref, path) {
47
+ const url = `${RAW_BASE}/${repo}/${ref}/${path}`;
48
+ const res = await fetch(url, {
49
+ headers: { 'user-agent': USER_AGENT },
50
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
51
+ });
52
+ if (res.status === 404) {
53
+ throw new FileNotFoundError(`raw file not found: ${repo}@${ref}/${path}`);
54
+ }
55
+ if (!res.ok) {
56
+ const body = await res.text().catch(() => '');
57
+ const detail = body ? `: ${body.slice(0, 200)}` : '';
58
+ throw new Error(`raw.githubusercontent ${res.status} ${res.statusText}${detail}`);
59
+ }
60
+ return await res.text();
61
+ }
62
+ export class FileNotFoundError extends Error {
63
+ constructor(message) {
64
+ super(message);
65
+ this.name = 'FileNotFoundError';
66
+ }
67
+ }
68
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ export declare const chipNumberSchema: z.ZodPipeline<z.ZodEffects<z.ZodUnion<[z.ZodNumber, z.ZodString]>, number, string | number>, z.ZodNumber>;
3
+ export declare const chipStatusFilterSchema: z.ZodOptional<z.ZodString>;
4
+ export declare const chipCategoryFilterSchema: z.ZodOptional<z.ZodString>;
5
+ export declare const includeBodySchema: z.ZodDefault<z.ZodBoolean>;
6
+ export declare const searchQuerySchema: z.ZodString;
7
+ export declare const searchSourceSchema: z.ZodDefault<z.ZodEnum<["merged", "draft", "both"]>>;
8
+ export declare const searchLimitSchema: z.ZodDefault<z.ZodNumber>;
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ export const chipNumberSchema = z
3
+ .union([z.number().int().nonnegative(), z.string().regex(/^\d+$/)])
4
+ .transform((v) => (typeof v === 'string' ? Number(v) : v))
5
+ .pipe(z.number().int().min(0).max(99999))
6
+ .describe('CHIP number, e.g. 42 or "0042". Accepts the integer or a zero-padded string.');
7
+ export const chipStatusFilterSchema = z
8
+ .string()
9
+ .min(1)
10
+ .max(40)
11
+ .optional()
12
+ .describe("Restrict to a status, e.g. 'Final', 'Review', 'Draft', 'Last Call', 'Living', 'Stagnant', 'Withdrawn', 'Obsolete'. Case-insensitive.");
13
+ export const chipCategoryFilterSchema = z
14
+ .string()
15
+ .min(1)
16
+ .max(40)
17
+ .optional()
18
+ .describe("Restrict to a category, e.g. 'Standards Track', 'Process', 'Informational'. Case-insensitive.");
19
+ export const includeBodySchema = z
20
+ .boolean()
21
+ .default(false)
22
+ .describe('If true, include the full markdown body of the CHIP. Defaults to false.');
23
+ export const searchQuerySchema = z
24
+ .string()
25
+ .min(1)
26
+ .max(200)
27
+ .describe('Case-insensitive keyword matched against title, description, abstract, and authors.');
28
+ export const searchSourceSchema = z
29
+ .enum(['merged', 'draft', 'both'])
30
+ .default('both')
31
+ .describe("Where to search: 'merged' (CHIPs on main), 'draft' (open PRs), or 'both' (default).");
32
+ export const searchLimitSchema = z
33
+ .number()
34
+ .int()
35
+ .positive()
36
+ .max(100)
37
+ .default(20)
38
+ .describe('Maximum results. Default 20, max 100.');
39
+ //# sourceMappingURL=chips.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chips.js","sourceRoot":"","sources":["../../src/schemas/chips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;KAClE,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACzD,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KACxC,QAAQ,CAAC,8EAA8E,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC;KACpC,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,EAAE,CAAC;KACP,QAAQ,EAAE;KACV,QAAQ,CACP,sIAAsI,CACvI,CAAC;AAEJ,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,EAAE,CAAC;KACP,QAAQ,EAAE;KACV,QAAQ,CACP,+FAA+F,CAChG,CAAC;AAEJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,OAAO,EAAE;KACT,OAAO,CAAC,KAAK,CAAC;KACd,QAAQ,CAAC,yEAAyE,CAAC,CAAC;AAEvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,GAAG,CAAC;KACR,QAAQ,CAAC,qFAAqF,CAAC,CAAC;AAEnG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;KACjC,OAAO,CAAC,MAAM,CAAC;KACf,QAAQ,CAAC,qFAAqF,CAAC,CAAC;AAEnG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,EAAE;KACR,GAAG,EAAE;KACL,QAAQ,EAAE;KACV,GAAG,CAAC,GAAG,CAAC;KACR,OAAO,CAAC,EAAE,CAAC;KACX,QAAQ,CAAC,uCAAuC,CAAC,CAAC"}
package/dist/server.js CHANGED
@@ -26,6 +26,10 @@ import { register as registerDecompilePuzzle } from './tools/offers/decompile-pu
26
26
  import { register as registerGetMempool } from './tools/mempool/get-mempool.js';
27
27
  import { register as registerIsInMempool } from './tools/mempool/is-in-mempool.js';
28
28
  import { register as registerEstimateFee } from './tools/mempool/estimate-fee.js';
29
+ import { register as registerListChips } from './tools/chips/list-chips.js';
30
+ import { register as registerGetChip } from './tools/chips/get-chip.js';
31
+ import { register as registerListChipDrafts } from './tools/chips/list-chip-drafts.js';
32
+ import { register as registerSearchChips } from './tools/chips/search-chips.js';
29
33
  import { register as registerNetworkStatusPrompt } from './prompts/network-status.js';
30
34
  import { register as registerAddressSummaryPrompt } from './prompts/address-summary.js';
31
35
  import { register as registerBlockSummaryPrompt } from './prompts/block-summary.js';
@@ -33,11 +37,13 @@ import { register as registerPrefarmSummaryPrompt } from './prompts/prefarm-summ
33
37
  export function createServer() {
34
38
  const server = new McpServer({ name: 'chia-explorer', version: VERSION }, {
35
39
  instructions: 'chia-explorer answers questions about the Chia blockchain via the public coinset.org API, ' +
36
- 'plus XCH spot price and fiat conversion via the public CoinGecko API. ' +
40
+ 'plus XCH spot price and fiat conversion via the public CoinGecko API, ' +
41
+ 'plus Chia Improvement Proposals (CHIPs) read directly from the Chia-Network/chips GitHub repo (merged on main and open PR drafts). ' +
37
42
  'Read-only: no signing, no key material, no push_tx. ' +
38
43
  "Blockchain tools accept an optional `network: 'mainnet' | 'testnet11'` argument; mainnet is the default. " +
39
44
  'When an address is provided, the network is auto-detected from the prefix (xch / txch). ' +
40
- 'Price tools take no network argument.',
45
+ 'Price and CHIPs tools take no network argument. ' +
46
+ 'An optional GITHUB_TOKEN env var lifts the unauthenticated GitHub rate limit on CHIPs listings.',
41
47
  });
42
48
  registerGetBlockchainState(server);
43
49
  registerGetNetspace(server);
@@ -65,6 +71,10 @@ export function createServer() {
65
71
  registerGetMempool(server);
66
72
  registerIsInMempool(server);
67
73
  registerEstimateFee(server);
74
+ registerListChips(server);
75
+ registerGetChip(server);
76
+ registerListChipDrafts(server);
77
+ registerSearchChips(server);
68
78
  registerNetworkStatusPrompt(server);
69
79
  registerAddressSummaryPrompt(server);
70
80
  registerBlockSummaryPrompt(server);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,30 @@
1
+ import { findChipByNumber } from '../../chips/index.js';
2
+ import { chipNumberSchema, includeBodySchema } from '../../schemas/chips.js';
3
+ import { errorText, jsonText } from '../shared/response.js';
4
+ export function register(server) {
5
+ server.tool('get_chip', 'Get a single CHIP by number. Looks first on main (merged) and also surfaces any open PRs proposing changes to the same number. Returns parsed front matter, abstract, source URL, and (with include_body=true) the full markdown body.', {
6
+ number: chipNumberSchema,
7
+ include_body: includeBodySchema,
8
+ }, async ({ number, include_body }) => {
9
+ try {
10
+ const { merged, drafts } = await findChipByNumber(number, { includeBody: include_body });
11
+ if (!merged && drafts.length === 0) {
12
+ return jsonText({
13
+ number,
14
+ found: false,
15
+ message: `no CHIP ${number} on main or in open PRs`,
16
+ });
17
+ }
18
+ return jsonText({
19
+ number,
20
+ found: true,
21
+ merged,
22
+ drafts,
23
+ });
24
+ }
25
+ catch (err) {
26
+ return errorText(err);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=get-chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-chip.js","sourceRoot":"","sources":["../../../src/tools/chips/get-chip.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,UAAU,EACV,wOAAwO,EACxO;QACE,MAAM,EAAE,gBAAgB;QACxB,YAAY,EAAE,iBAAiB;KAChC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;YACzF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,OAAO,QAAQ,CAAC;oBACd,MAAM;oBACN,KAAK,EAAE,KAAK;oBACZ,OAAO,EAAE,WAAW,MAAM,yBAAyB;iBACpD,CAAC,CAAC;YACL,CAAC;YACD,OAAO,QAAQ,CAAC;gBACd,MAAM;gBACN,KAAK,EAAE,IAAI;gBACX,MAAM;gBACN,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,19 @@
1
+ import { listChipDrafts } from '../../chips/index.js';
2
+ import { errorText, jsonText } from '../shared/response.js';
3
+ export function register(server) {
4
+ server.tool('list_chip_drafts', 'List open pull requests against Chia-Network/chips that add or modify a CHIP file. Each entry includes parsed front matter from the proposed file plus PR context (number, url, author, requested reviewers, draft flag, updated_at) and a modifies_existing flag for amendments. PRs that do not touch a CHIPs/chip-*.md file are filtered out.', {}, async () => {
5
+ try {
6
+ const drafts = await listChipDrafts();
7
+ return jsonText({
8
+ source: 'github',
9
+ repo: 'Chia-Network/chips',
10
+ count: drafts.length,
11
+ drafts,
12
+ });
13
+ }
14
+ catch (err) {
15
+ return errorText(err);
16
+ }
17
+ });
18
+ }
19
+ //# sourceMappingURL=list-chip-drafts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-chip-drafts.js","sourceRoot":"","sources":["../../../src/tools/chips/list-chip-drafts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,kVAAkV,EAClV,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;YACtC,OAAO,QAAQ,CAAC;gBACd,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,oBAAoB;gBAC1B,KAAK,EAAE,MAAM,CAAC,MAAM;gBACpB,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,33 @@
1
+ import { listMergedChips } from '../../chips/index.js';
2
+ import { chipCategoryFilterSchema, chipStatusFilterSchema } from '../../schemas/chips.js';
3
+ import { errorText, jsonText } from '../shared/response.js';
4
+ export function register(server) {
5
+ server.tool('list_chips', 'List Chia Improvement Proposals (CHIPs) merged on the main branch of Chia-Network/chips. Returns parsed metadata (number, title, status, category, authors, abstract, dates) for every CHIP. Optional filters: status, category. For in-progress CHIPs in open PRs use list_chip_drafts.', {
6
+ status: chipStatusFilterSchema,
7
+ category: chipCategoryFilterSchema,
8
+ }, async ({ status, category }) => {
9
+ try {
10
+ const all = await listMergedChips();
11
+ const statusLc = status?.toLowerCase();
12
+ const categoryLc = category?.toLowerCase();
13
+ const filtered = all.filter((c) => {
14
+ if (statusLc && (c.status?.toLowerCase() ?? '') !== statusLc)
15
+ return false;
16
+ if (categoryLc && (c.category?.toLowerCase() ?? '') !== categoryLc)
17
+ return false;
18
+ return true;
19
+ });
20
+ return jsonText({
21
+ source: 'github',
22
+ repo: 'Chia-Network/chips',
23
+ ref: 'main',
24
+ count: filtered.length,
25
+ chips: filtered,
26
+ });
27
+ }
28
+ catch (err) {
29
+ return errorText(err);
30
+ }
31
+ });
32
+ }
33
+ //# sourceMappingURL=list-chips.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-chips.js","sourceRoot":"","sources":["../../../src/tools/chips/list-chips.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,0RAA0R,EAC1R;QACE,MAAM,EAAE,sBAAsB;QAC9B,QAAQ,EAAE,wBAAwB;KACnC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,eAAe,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,EAAE,WAAW,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,QAAQ,EAAE,WAAW,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAChC,IAAI,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,QAAQ;oBAAE,OAAO,KAAK,CAAC;gBAC3E,IAAI,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,UAAU;oBAAE,OAAO,KAAK,CAAC;gBACjF,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;gBACd,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,oBAAoB;gBAC1B,GAAG,EAAE,MAAM;gBACX,KAAK,EAAE,QAAQ,CAAC,MAAM;gBACtB,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,31 @@
1
+ import { searchChips } from '../../chips/index.js';
2
+ import { chipStatusFilterSchema, searchLimitSchema, searchQuerySchema, searchSourceSchema, } from '../../schemas/chips.js';
3
+ import { errorText, jsonText } from '../shared/response.js';
4
+ export function register(server) {
5
+ server.tool('search_chips', 'Case-insensitive keyword search across merged CHIPs and open PR drafts. Matches against title, description, abstract, authors, and CHIP number. Optional filters: status, source (merged | draft | both, default both), limit (default 20).', {
6
+ query: searchQuerySchema,
7
+ status: chipStatusFilterSchema,
8
+ source: searchSourceSchema,
9
+ limit: searchLimitSchema,
10
+ }, async ({ query, status, source, limit }) => {
11
+ try {
12
+ const opts = {
13
+ source,
14
+ limit,
15
+ };
16
+ if (status !== undefined)
17
+ opts.status = status;
18
+ const matches = await searchChips(query, opts);
19
+ return jsonText({
20
+ query,
21
+ source,
22
+ count: matches.length,
23
+ matches,
24
+ });
25
+ }
26
+ catch (err) {
27
+ return errorText(err);
28
+ }
29
+ });
30
+ }
31
+ //# sourceMappingURL=search-chips.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-chips.js","sourceRoot":"","sources":["../../../src/tools/chips/search-chips.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,cAAc,EACd,6OAA6O,EAC7O;QACE,KAAK,EAAE,iBAAiB;QACxB,MAAM,EAAE,sBAAsB;QAC9B,MAAM,EAAE,kBAAkB;QAC1B,KAAK,EAAE,iBAAiB;KACzB,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,IAAI,GAA4E;gBACpF,MAAM;gBACN,KAAK;aACN,CAAC;YACF,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC/C,OAAO,QAAQ,CAAC;gBACd,KAAK;gBACL,MAAM;gBACN,KAAK,EAAE,OAAO,CAAC,MAAM;gBACrB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chia-explorer",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server that answers questions about the Chia blockchain via the public coinset.org API",
5
5
  "mcpName": "io.github.Spacetime-Technology/chia-explorer",
6
6
  "type": "module",