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.
- package/README.md +189 -107
- package/package.json +10 -5
- 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
|
|
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
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
24
|
+
---
|
|
28
25
|
|
|
29
|
-
|
|
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
|
-
|
|
35
|
-
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img src="docs/charts/domains.svg" alt="Subgraphs by Domain" width="480"/>
|
|
30
|
+
</p>
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
<p align="center">
|
|
33
|
+
<img src="docs/charts/networks.svg" alt="Subgraphs by Network" width="600"/>
|
|
34
|
+
</p>
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
<p align="center">
|
|
37
|
+
<img src="docs/charts/protocol-types.svg" alt="Subgraphs by Protocol Type" width="600"/>
|
|
38
|
+
</p>
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
176
|
+
---
|
|
75
177
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
|
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
|
|
97
|
-
|
|
|
98
|
-
v
|
|
99
|
-
server.py ----- FastAPI REST API with /recommend endpoint
|
|
222
|
+
registry.py --- builds SQLite + indices
|
|
100
223
|
|
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
228
|
+
MCP Server (src/index.js)
|
|
229
|
+
├── stdio ←── Claude Desktop / Claude Code
|
|
230
|
+
└── SSE ←── OpenClaw / remote agents (:3848)
|
|
231
|
+
```
|
|
145
232
|
|
|
146
|
-
|
|
233
|
+
## Quick Start (Local Build)
|
|
147
234
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
-
|
|
151
|
-
|
|
235
|
+
```bash
|
|
236
|
+
cd python
|
|
237
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
238
|
+
pip install -r requirements.txt
|
|
152
239
|
|
|
153
|
-
|
|
240
|
+
echo "GATEWAY_API_KEY=your-key-here" > .env
|
|
154
241
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
```
|
|
242
|
+
# Full crawl + classify (~11 min)
|
|
243
|
+
python registry.py
|
|
158
244
|
|
|
159
|
-
|
|
245
|
+
# Generate charts and category files
|
|
246
|
+
python generate_docs.py
|
|
160
247
|
|
|
161
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
378
|
-
await ensureDb();
|
|
379
|
-
|
|
379
|
+
function createServer() {
|
|
380
380
|
const server = new Server(
|
|
381
|
-
{ name: "subgraph-registry", version: "0.
|
|
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
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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) => {
|