subgraph-registry-mcp 0.2.3 → 0.3.1

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 (3) hide show
  1. package/README.md +189 -107
  2. package/package.json +10 -5
  3. package/src/index.js +69 -8
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Agent-friendly semantic classification of all subgraphs on [The Graph Network](https://thegraph.com).
8
8
 
9
- Pre-computed index of 15,500+ subgraphs with domain classification, protocol type detection, schema fingerprinting, canonical entity mapping, and composite reliability scoring.
9
+ Pre-computed index of **14,700+ subgraphs** with domain classification, protocol type detection, schema fingerprinting, canonical entity mapping, and composite reliability scoring.
10
10
 
11
11
  ## The Problem
12
12
 
@@ -14,37 +14,142 @@ Agents querying The Graph need to discover and select the right subgraph before
14
14
 
15
15
  ## What It Does
16
16
 
17
- 1. **Crawls** all active subgraphs from the Graph Network meta-subgraph (subgraphs indexing subgraphs)
17
+ 1. **Crawls** all active subgraphs from the Graph Network meta-subgraph
18
18
  2. **Fetches** the GraphQL schema for every deployment
19
- 3. **Classifies** each subgraph by:
20
- - **Domain**: DeFi, NFTs, DAOs, Gaming, Identity, Infrastructure, Social, Analytics
21
- - **Protocol Type**: DEX, Lending, Bridge, Staking, Options, Perpetuals, Marketplace, etc.
22
- - **Canonical Entities**: Maps schema types to a standard vocabulary (Pool -> `liquidity_pool`, Swap -> `trade`, etc.)
23
- - **Schema Family**: Groups forks/clones by schema fingerprint
24
- 4. **Scores** reliability (see [Reliability Score](#reliability-score) below)
25
- 5. **Publishes** as JSON registry + SQLite database + REST API
19
+ 3. **Classifies** each subgraph by domain, protocol type, canonical entities, and schema family
20
+ 4. **Scores** reliability using on-chain signals (query fees, volume, curation, stake)
21
+ 5. **Publishes** as SQLite database + REST API + MCP server
22
+ 6. **Generates** visual dashboards and bot-readable category files (auto-updated with each sync)
26
23
 
27
- ## Quick Start
24
+ ---
28
25
 
29
- ```bash
30
- cd python
31
- python3 -m venv .venv && source .venv/bin/activate
32
- pip install -r requirements.txt
26
+ ## Registry at a Glance
33
27
 
34
- # Create .env with your Graph API key
35
- echo "GATEWAY_API_KEY=your-key-here" > .env
28
+ <p align="center">
29
+ <img src="docs/charts/domains.svg" alt="Subgraphs by Domain" width="480"/>
30
+ </p>
36
31
 
37
- # Full crawl + classify (all 15K+ subgraphs, ~11 min)
38
- python registry.py
32
+ <p align="center">
33
+ <img src="docs/charts/networks.svg" alt="Subgraphs by Network" width="600"/>
34
+ </p>
39
35
 
40
- # Or limit to top N by signal
41
- python registry.py --max 500
36
+ <p align="center">
37
+ <img src="docs/charts/protocol-types.svg" alt="Subgraphs by Protocol Type" width="600"/>
38
+ </p>
42
39
 
43
- # Start API server
44
- python server.py
40
+ <p align="center">
41
+ <img src="docs/charts/reliability-dist.svg" alt="Reliability Distribution" width="480"/>
42
+ </p>
43
+
44
+ > Charts auto-generated from `registry.db` on each sync. See [`python/generate_docs.py`](python/generate_docs.py).
45
+
46
+ ---
47
+
48
+ ## Browse by Category
49
+
50
+ ### Domains
51
+
52
+ Explore subgraphs by use case — each file lists the top 25 subgraphs ranked by reliability score.
53
+
54
+ | Domain | Count | File |
55
+ |--------|-------|------|
56
+ | [DeFi](docs/domains/defi.md) | 11,218 | Swaps, pools, lending, vaults, yield |
57
+ | [NFTs](docs/domains/nfts.md) | 857 | Collections, marketplaces, sales |
58
+ | [Infrastructure](docs/domains/infrastructure.md) | 581 | Indexers, oracles, registries |
59
+ | [DAO](docs/domains/dao.md) | 429 | Governance, proposals, voting |
60
+ | [Identity](docs/domains/identity.md) | 401 | ENS, name services, resolvers |
61
+ | [Analytics](docs/domains/analytics.md) | 327 | Snapshots, metrics, historical data |
62
+ | [Gaming](docs/domains/gaming.md) | 247 | Players, quests, items, worlds |
63
+ | [Social](docs/domains/social.md) | 74 | Profiles, posts, follows |
64
+
65
+ Full index: [`docs/DOMAINS.md`](docs/DOMAINS.md)
66
+
67
+ ### Networks
68
+
69
+ Explore subgraphs by blockchain — each file lists the top 25 subgraphs on that chain.
70
+
71
+ | Network | Count | File |
72
+ |---------|-------|------|
73
+ | [Ethereum](docs/networks/mainnet.md) | 2,377 | Largest ecosystem |
74
+ | [Base](docs/networks/base.md) | 1,728 | Fast-growing L2 |
75
+ | [BSC](docs/networks/bsc.md) | 1,582 | BNB Chain |
76
+ | [Arbitrum](docs/networks/arbitrum-one.md) | 1,376 | Leading L2 |
77
+ | [Polygon](docs/networks/matic.md) | 1,266 | Polygon PoS |
78
+ | [Optimism](docs/networks/optimism.md) | 568 | OP Stack L2 |
79
+ | [Avalanche](docs/networks/avalanche.md) | 440 | C-Chain |
80
+
81
+ Full index: [`docs/NETWORKS.md`](docs/NETWORKS.md)
82
+
83
+ ### Protocol Types
84
+
85
+ | Type | Count | Description |
86
+ |------|-------|-------------|
87
+ | DEX | 4,176 | Uniswap, Sushi, Curve, Balancer, PancakeSwap |
88
+ | Lending | 1,424 | Aave, Compound, Morpho, Spark, Silo |
89
+ | Staking | 867 | Lido, Rocket Pool, EigenLayer, Graph Network |
90
+ | Bridge | 771 | Hop, Stargate, Across, Wormhole, LayerZero |
91
+ | NFT Marketplace | 436 | OpenSea, Blur, Rarible, Foundation |
92
+ | Governance | 416 | Snapshot, Tally, Compound Governor |
93
+ | Yield Aggregator | 387 | Yearn, Beefy, Harvest, Convex |
94
+ | Perpetuals | 266 | GMX, Gains, dYdX, Hyperliquid |
95
+ | Name Service | 223 | ENS, Space ID, Unstoppable Domains |
96
+ | Options | 179 | Premia, Dopex, Lyra, Hegic |
97
+
98
+ ---
99
+
100
+ ## Reliability Score
101
+
102
+ Each subgraph gets a composite reliability score (0-1) based on four on-chain signals:
103
+
104
+ | Signal | Weight | What it measures |
105
+ |--------|--------|------------------|
106
+ | **Query Fees** | 30% | GRT fees earned from actual usage |
107
+ | **Query Volume** | 30% | 30-day query count |
108
+ | **Curation Signal** | 20% | GRT tokens curated by the community |
109
+ | **Indexer Allocation** | 20% | GRT allocated to this subgraph by indexers |
110
+
111
+ All values are log-scaled and capped at 1.0. A 0.5 penalty is applied if the subgraph has been denied/deprecated.
112
+
113
+ **Score tiers:** High (0.7+) = strong signal, real usage | Medium (0.3-0.7) = functional, some activity | Low (<0.3) = minimal signal or test deployment
114
+
115
+ ---
116
+
117
+ ## MCP Server
118
+
119
+ The registry is available as an MCP server with **dual transport** — stdio for local clients and SSE/HTTP for remote agents.
120
+
121
+ **4 tools:**
122
+ - **search_subgraphs** — filter by domain, network, protocol type, entity, or keyword
123
+ - **recommend_subgraph** — natural language goal to best subgraphs
124
+ - **get_subgraph_detail** — full classification for a specific subgraph
125
+ - **list_registry_stats** — registry overview (domains, networks, counts)
126
+
127
+ ### Install
128
+
129
+ ```bash
130
+ # Claude Code
131
+ claude mcp add subgraph-registry -- npx subgraph-registry-mcp
132
+
133
+ # Claude Desktop
134
+ {
135
+ "mcpServers": {
136
+ "subgraph-registry": {
137
+ "command": "npx",
138
+ "args": ["subgraph-registry-mcp"]
139
+ }
140
+ }
141
+ }
142
+
143
+ # Remote agents (SSE)
144
+ npx subgraph-registry-mcp --http-only
145
+ # Then connect to http://localhost:3848/sse
45
146
  ```
46
147
 
47
- ## API Endpoints
148
+ The server auto-downloads the pre-built registry (8MB SQLite) from GitHub on first run.
149
+
150
+ ---
151
+
152
+ ## REST API
48
153
 
49
154
  ```
50
155
  GET /summary Registry overview and stats
@@ -57,123 +162,100 @@ GET /search?q=uniswap Free-text search
57
162
  GET /recommend?goal=...&chain= Agent-optimized recommendation
58
163
  ```
59
164
 
60
- ### Example: Agent Recommendation
61
-
62
165
  ```bash
63
- curl "http://localhost:3847/recommend?goal=query+DEX+trades+on+Arbitrum&chain=arbitrum-one"
64
- ```
65
-
66
- Returns the top subgraphs matching the intent, with reliability scores and query instructions.
166
+ # Start API server
167
+ cd python && python server.py
67
168
 
68
- ### Example: Filter by Entity Type
169
+ # Example: find DEX subgraphs on Arbitrum
170
+ curl "http://localhost:3847/recommend?goal=query+DEX+trades+on+Arbitrum&chain=arbitrum-one"
69
171
 
70
- ```bash
172
+ # Example: filter by entity type
71
173
  curl "http://localhost:3847/subgraphs?entity=liquidity_pool&network=base&min_reliability=0.5"
72
174
  ```
73
175
 
74
- ## Weekly Sync
176
+ ---
75
177
 
76
- ```bash
77
- # Run weekly incremental updates (only fetches new/changed subgraphs)
78
- python scheduler.py
178
+ ## Bot-Readable Category Files
179
+
180
+ The `docs/` directory contains structured `.md` files with YAML frontmatter designed for AI agents and bots to consume:
79
181
 
80
- # One-shot incremental
81
- python scheduler.py --once
182
+ ```
183
+ docs/
184
+ ├── DOMAINS.md # Index of all domains with counts
185
+ ├── NETWORKS.md # Index of all networks with counts
186
+ ├── charts/ # Auto-generated SVG visualizations
187
+ │ ├── domains.svg
188
+ │ ├── networks.svg
189
+ │ ├── protocol-types.svg
190
+ │ └── reliability.svg
191
+ ├── domains/ # One file per domain
192
+ │ ├── defi.md # Top 25 DeFi subgraphs by reliability
193
+ │ ├── nfts.md
194
+ │ ├── dao.md
195
+ │ └── ...
196
+ └── networks/ # One file per network
197
+ ├── mainnet.md # Top 25 Ethereum subgraphs by reliability
198
+ ├── base.md
199
+ ├── arbitrum-one.md
200
+ └── ...
82
201
  ```
83
202
 
203
+ Each category file includes:
204
+ - YAML frontmatter (domain/network, count, percentage, last updated)
205
+ - Top 25 subgraphs ranked by reliability score
206
+ - MCP tool and REST API query examples
207
+
208
+ ---
209
+
84
210
  ## Architecture
85
211
 
86
212
  ```
87
213
  Graph Network Subgraph (meta-subgraph, 140M queries/month)
88
214
  |
89
215
  v
90
- crawler.py ---- async httpx, ID-based cursor pagination (bypasses 5K skip limit)
216
+ crawler.py ---- async httpx, ID-based cursor pagination
91
217
  |
92
218
  v
93
219
  classifier.py - rule-based domain/protocol classification + schema fingerprinting
94
220
  |
95
221
  v
96
- registry.py --- builds JSON registry + SQLite + indices
97
- |
98
- v
99
- server.py ----- FastAPI REST API with /recommend endpoint
222
+ registry.py --- builds SQLite + indices
100
223
  |
101
- v
102
- scheduler.py -- weekly incremental sync via updatedAt filtering
103
- ```
104
-
105
- ## Output
106
-
107
- | File | Size | Description |
108
- |---|---|---|
109
- | `registry.json` | ~130 MB | Full registry with all entity details |
110
- | `registry.db` | ~8 MB | SQLite with indexed lookups |
111
- | `sync-state.json` | <1 KB | Last sync timestamp for incremental updates |
112
-
113
- ## Classification Results (as of March 2026)
114
-
115
- | Domain | Count | | Network | Count |
116
- |---|---|---|---|---|
117
- | DeFi | 11,841 | | Ethereum | 2,471 |
118
- | NFTs | 893 | | Base | 1,845 |
119
- | Infrastructure | 602 | | BSC | 1,664 |
120
- | DAO | 450 | | Arbitrum | 1,442 |
121
- | Identity | 424 | | Polygon | 1,364 |
122
- | Analytics | 348 | | Optimism | 593 |
123
- | Gaming | 255 | | Avalanche | 454 |
124
- | Social | 78 | | | |
125
-
126
- ## Reliability Score
127
-
128
- Each subgraph gets a composite reliability score (0–1) based on four on-chain signals:
129
-
130
- | Signal | Weight | What it measures | Source |
131
- |---|---|---|---|
132
- | **Query Fees** | 30% | GRT fees earned from actual usage — proves real demand | Network subgraph |
133
- | **Query Volume** | 30% | 30-day query count — recent activity level | QoS subgraph |
134
- | **Curation Signal** | 20% | GRT tokens curated — community vote of confidence | Network subgraph |
135
- | **Indexer Stake** | 20% | GRT staked by indexers — skin in the game | Network subgraph |
136
-
137
- All values are log-scaled and capped at 1.0. Usage signals (fees + volume) are weighted higher at 60% because they prove real demand. A 0.5 penalty is applied if the subgraph has been denied/deprecated.
138
-
139
- **What the scores mean:**
140
- - **0.7–1.0**: High reliability — strong signal, active indexers, real usage (e.g. Uniswap, Aave)
141
- - **0.3–0.7**: Moderate — some signal and usage, likely functional
142
- - **0.0–0.3**: Low — minimal signal, may be inactive or a test deployment
224
+ ├── server.py ------ FastAPI REST API (:3847)
225
+ ├── generate_docs.py SVG charts + category .md files
226
+ └── scheduler.py --- weekly incremental sync
143
227
 
144
- ## MCP Server
228
+ MCP Server (src/index.js)
229
+ ├── stdio ←── Claude Desktop / Claude Code
230
+ └── SSE ←── OpenClaw / remote agents (:3848)
231
+ ```
145
232
 
146
- The registry is available as an MCP server for agent integration. It exposes 4 tools:
233
+ ## Quick Start (Local Build)
147
234
 
148
- - **search_subgraphs** — filter by domain, network, protocol type, entity, or keyword
149
- - **recommend_subgraph** — natural language goal to best subgraphs
150
- - **get_subgraph_detail** full classification for a specific subgraph
151
- - **list_registry_stats** registry overview (domains, networks, counts)
235
+ ```bash
236
+ cd python
237
+ python3 -m venv .venv && source .venv/bin/activate
238
+ pip install -r requirements.txt
152
239
 
153
- ### Install via NPM
240
+ echo "GATEWAY_API_KEY=your-key-here" > .env
154
241
 
155
- ```bash
156
- npx subgraph-registry-mcp
157
- ```
242
+ # Full crawl + classify (~11 min)
243
+ python registry.py
158
244
 
159
- ### Add to Claude Desktop
245
+ # Generate charts and category files
246
+ python generate_docs.py
160
247
 
161
- ```json
162
- {
163
- "mcpServers": {
164
- "subgraph-registry": {
165
- "command": "npx",
166
- "args": ["subgraph-registry-mcp"]
167
- }
168
- }
169
- }
248
+ # Start API server
249
+ python server.py
170
250
  ```
171
251
 
172
- The server auto-downloads the pre-built registry (8MB SQLite) from GitHub on first run — no local build needed.
173
-
174
252
  ## How It Stays Current
175
253
 
176
- The Graph Network subgraph indexes all subgraph deployments on-chain. The crawler queries `updatedAt_gte: lastSyncTimestamp` to fetch only what changed since the last run. Weekly syncs keep the registry fresh without full rebuilds.
254
+ A GitHub Actions workflow runs every 3 days:
255
+ 1. Incremental crawl (`updatedAt_gte: lastSyncTimestamp`)
256
+ 2. Reclassify new/changed subgraphs
257
+ 3. Regenerate SVG charts and category .md files
258
+ 4. Commit and push updates
177
259
 
178
260
  ## License
179
261
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "subgraph-registry-mcp",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "mcpName": "io.github.PaulieB14/subgraph-registry-mcp",
5
- "description": "MCP server for agent-friendly subgraph discovery on The Graph Network. 15,500+ classified subgraphs with reliability scoring.",
5
+ "description": "MCP server for agent-friendly subgraph discovery on The Graph Network. 14,700+ classified subgraphs with domain, protocol type, and reliability scoring.",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "subgraph-registry-mcp": "src/index.js"
@@ -12,7 +12,9 @@
12
12
  "data/registry.db"
13
13
  ],
14
14
  "scripts": {
15
- "start": "node src/index.js"
15
+ "start": "node src/index.js",
16
+ "start:http": "node src/index.js --http",
17
+ "start:http-only": "node src/index.js --http-only"
16
18
  },
17
19
  "keywords": [
18
20
  "mcp",
@@ -21,7 +23,9 @@
21
23
  "web3",
22
24
  "defi",
23
25
  "agent",
24
- "ai"
26
+ "ai",
27
+ "openclaw",
28
+ "sse"
25
29
  ],
26
30
  "repository": {
27
31
  "type": "git",
@@ -31,6 +35,7 @@
31
35
  "license": "MIT",
32
36
  "dependencies": {
33
37
  "@modelcontextprotocol/sdk": "^1.12.1",
34
- "better-sqlite3": "^11.8.2"
38
+ "better-sqlite3": "^11.8.2",
39
+ "express": "^4.21.0"
35
40
  }
36
41
  }
package/src/index.js CHANGED
@@ -15,11 +15,13 @@
15
15
 
16
16
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
17
17
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
18
19
  import {
19
20
  CallToolRequestSchema,
20
21
  ListToolsRequestSchema,
21
22
  } from "@modelcontextprotocol/sdk/types.js";
22
23
  import Database from "better-sqlite3";
24
+ import express from "express";
23
25
  import { fileURLToPath } from "url";
24
26
  import { dirname, join } from "path";
25
27
  import { existsSync, mkdirSync, writeFileSync } from "fs";
@@ -326,7 +328,7 @@ const TOOLS = [
326
328
  network: { type: "string", description: "Filter by chain: mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche, etc." },
327
329
  protocol_type: { type: "string", description: "Filter by protocol type: dex, lending, bridge, staking, options, perpetuals, etc." },
328
330
  entity: { type: "string", description: "Filter by canonical entity: liquidity_pool, trade, token, position, vault, loan, etc." },
329
- min_reliability: { type: "number", description: "Minimum reliability score (0-1). Higher = more signal/stake/fees." },
331
+ min_reliability: { type: "number", description: "Minimum reliability score (0-1). Higher = more query fees, volume, curation signal, and indexer allocation." },
330
332
  limit: { type: "integer", description: "Max results to return (default: 20)", default: 20 },
331
333
  },
332
334
  },
@@ -374,11 +376,9 @@ const HANDLERS = {
374
376
  list_registry_stats: listRegistryStats,
375
377
  };
376
378
 
377
- async function main() {
378
- await ensureDb();
379
-
379
+ function createServer() {
380
380
  const server = new Server(
381
- { name: "subgraph-registry", version: "0.2.3" },
381
+ { name: "subgraph-registry", version: "0.3.0" },
382
382
  { capabilities: { tools: {} } }
383
383
  );
384
384
 
@@ -408,9 +408,70 @@ async function main() {
408
408
  }
409
409
  });
410
410
 
411
- const transport = new StdioServerTransport();
412
- await server.connect(transport);
413
- console.error(`Subgraph Registry MCP server running (${getDb().prepare("SELECT COUNT(*) as c FROM subgraphs").get().c} subgraphs)`);
411
+ return server;
412
+ }
413
+
414
+ // ── SSE/HTTP Transport (OpenClaw + remote agents) ──────────
415
+
416
+ function startHttpTransport(port) {
417
+ const app = express();
418
+ const sessions = new Map();
419
+
420
+ app.get("/sse", async (req, res) => {
421
+ const transport = new SSEServerTransport("/messages", res);
422
+ sessions.set(transport.sessionId, transport);
423
+
424
+ const server = createServer();
425
+
426
+ res.on("close", () => {
427
+ sessions.delete(transport.sessionId);
428
+ });
429
+
430
+ await server.connect(transport);
431
+ });
432
+
433
+ app.post("/messages", async (req, res) => {
434
+ const sessionId = req.query.sessionId;
435
+ const transport = sessions.get(sessionId);
436
+ if (!transport) {
437
+ res.status(400).json({ error: "Invalid or expired session" });
438
+ return;
439
+ }
440
+ await transport.handlePostMessage(req, res);
441
+ });
442
+
443
+ app.get("/health", (_req, res) => {
444
+ res.json({ status: "ok", subgraphs: getDb().prepare("SELECT COUNT(*) as c FROM subgraphs").get().c });
445
+ });
446
+
447
+ app.listen(port, () => {
448
+ console.error(`SSE transport listening on http://localhost:${port}/sse`);
449
+ });
450
+ }
451
+
452
+ // ── Entry Point ────────────────────────────────────────────
453
+
454
+ async function main() {
455
+ await ensureDb();
456
+
457
+ const subgraphCount = getDb().prepare("SELECT COUNT(*) as c FROM subgraphs").get().c;
458
+ const httpPort = process.env.MCP_HTTP_PORT || (process.argv.includes("--http") ? "3848" : null);
459
+ const httpOnly = process.argv.includes("--http-only");
460
+
461
+ // Start SSE/HTTP transport if requested
462
+ if (httpPort || httpOnly) {
463
+ const port = parseInt(httpPort || "3848", 10);
464
+ startHttpTransport(port);
465
+ }
466
+
467
+ // Start stdio transport (default, skip if --http-only)
468
+ if (!httpOnly) {
469
+ const server = createServer();
470
+ const transport = new StdioServerTransport();
471
+ await server.connect(transport);
472
+ }
473
+
474
+ console.error(`Subgraph Registry MCP server running (${subgraphCount} subgraphs)`);
414
475
  }
415
476
 
416
477
  main().catch((err) => {