subgraph-registry-mcp 0.9.4 → 0.9.5

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/data/openapi.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "info": {
4
4
  "title": "Subgraph Registry",
5
5
  "description": "Agent-friendly subgraph discovery on The Graph Network. 14,700+ classified subgraphs with semantic search, reliability scoring, schema-evolution tracking, and x402 query URLs ($0.01 USDC on Base, no API key).",
6
- "version": "0.9.4",
6
+ "version": "0.9.5",
7
7
  "license": {
8
8
  "name": "MIT"
9
9
  },
@@ -23,7 +23,7 @@
23
23
  "post": {
24
24
  "operationId": "tool_search_subgraphs",
25
25
  "summary": "Search and filter the classified subgraph registry (15,000+ subgraphs).",
26
- "description": "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Each result includes query_url_x402 (POST GraphQL and pay $0.01 USDC on Base per query — no API key needed) and a legacy query_url (Studio API key required), plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user.",
26
+ "description": "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Discovery only — this tool does not execute GraphQL. Each result carries the subgraph id, a ready-to-run example_query, and both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer) or an x402 URL ($0.01 USDC on Base, no key). Pass the id to your own Graph client if you have one. Plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user.",
27
27
  "tags": [
28
28
  "mcp-tools"
29
29
  ],
@@ -112,7 +112,7 @@
112
112
  "post": {
113
113
  "operationId": "tool_recommend_subgraph",
114
114
  "summary": "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best…",
115
- "description": "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Each result includes query_url_x402 (preferred — POST GraphQL, pay $0.01 USDC on Base per query, no API key) and a legacy query_url for Studio-key flows.",
115
+ "description": "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Discovery only — it returns ids and starter queries, it does not execute GraphQL. Each result carries both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer <STUDIO_API_KEY>) or an x402 URL ($0.01 USDC on Base, no key).",
116
116
  "tags": [
117
117
  "mcp-tools"
118
118
  ],
package/openapi.yaml CHANGED
@@ -5,7 +5,7 @@ openapi: "3.1.0"
5
5
  info:
6
6
  title: "Subgraph Registry"
7
7
  description: "Agent-friendly subgraph discovery on The Graph Network. 14,700+ classified subgraphs with semantic search, reliability scoring, schema-evolution tracking, and x402 query URLs ($0.01 USDC on Base, no API key)."
8
- version: "0.9.4"
8
+ version: "0.9.5"
9
9
  license:
10
10
  name: "MIT"
11
11
  contact:
@@ -19,7 +19,7 @@ paths:
19
19
  post:
20
20
  operationId: "tool_search_subgraphs"
21
21
  summary: "Search and filter the classified subgraph registry (15,000+ subgraphs)."
22
- description: "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Each result includes query_url_x402 (POST GraphQL and pay $0.01 USDC on Base per query — no API key needed) and a legacy query_url (Studio API key required), plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user."
22
+ description: "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Discovery only — this tool does not execute GraphQL. Each result carries the subgraph id, a ready-to-run example_query, and both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer) or an x402 URL ($0.01 USDC on Base, no key). Pass the id to your own Graph client if you have one. Plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user."
23
23
  tags:
24
24
  - "mcp-tools"
25
25
  requestBody:
@@ -81,7 +81,7 @@ paths:
81
81
  post:
82
82
  operationId: "tool_recommend_subgraph"
83
83
  summary: "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best…"
84
- description: "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Each result includes query_url_x402 (preferred — POST GraphQL, pay $0.01 USDC on Base per query, no API key) and a legacy query_url for Studio-key flows."
84
+ description: "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Discovery only — it returns ids and starter queries, it does not execute GraphQL. Each result carries both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer <STUDIO_API_KEY>) or an x402 URL ($0.01 USDC on Base, no key)."
85
85
  tags:
86
86
  - "mcp-tools"
87
87
  requestBody:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subgraph-registry-mcp",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "mcpName": "io.github.PaulieB14/subgraph-registry-mcp",
5
5
  "description": "MCP server for agent-friendly subgraph discovery on The Graph Network. 15,330 classified subgraphs with x402 query URLs ($0.01 USDC on Base, no API key required), reliability scoring, and protocol classification.",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -90,8 +90,42 @@ const X402_PRICING = {
90
90
 
91
91
  function buildQueryEndpoints(subgraphId) {
92
92
  return {
93
- query_url: `https://gateway.thegraph.com/api/[api-key]/subgraphs/id/${subgraphId}`,
93
+ // The keyed gateway URL. This used to carry `[api-key]` as a path segment,
94
+ // a form the gateway no longer uses — an agent that string-replaced the
95
+ // placeholder was building a URL that has not been correct for a while.
96
+ // The current form takes the key in a header:
97
+ // POST https://gateway.thegraph.com/api/subgraphs/id/<ID>
98
+ // Authorization: Bearer <STUDIO_KEY>
99
+ // Verified: without the header this returns HTTP 200 carrying a GraphQL
100
+ // error body, `auth error: missing authorization header` — GraphQL signals
101
+ // auth in the body, so do not treat 200 as success without reading it.
102
+ query_url: `https://gateway.thegraph.com/api/subgraphs/id/${subgraphId}`,
94
103
  query_url_x402: `${X402_GATEWAY_BASE}/subgraphs/id/${subgraphId}`,
104
+
105
+ // Both routes, stated side by side, because which one is right depends
106
+ // entirely on what the caller already has. An agent embedded in a product
107
+ // with a Studio key should use its key; a headless agent with a funded
108
+ // wallet and no way to mint a key should use x402. Neither is "the
109
+ // recommended one" — the previous wording put x402 first and labelled it
110
+ // RECOMMENDED, which sent key-holding agents down a payment path they had
111
+ // no reason to take, and which some hosts forbid outright.
112
+ payment_options: {
113
+ api_key: {
114
+ url: `https://gateway.thegraph.com/api/subgraphs/id/${subgraphId}`,
115
+ method: "POST",
116
+ auth_header: "Authorization: Bearer <STUDIO_API_KEY>",
117
+ get_a_key: "https://thegraph.com/studio/apikeys/",
118
+ cost: "included in your Studio plan (100K free queries/month)",
119
+ use_when: "you already have, or can obtain, a Graph Studio API key",
120
+ },
121
+ x402: {
122
+ url: `${X402_GATEWAY_BASE}/subgraphs/id/${subgraphId}`,
123
+ method: "POST",
124
+ cost: "$0.01 USDC on Base per query",
125
+ flow: "gateway returns HTTP 402 with a payment manifest; an x402 client (@graphprotocol/client-x402, x402-fetch) signs and retries automatically",
126
+ use_when: "you have a funded wallet and no API key, and no human to mint one",
127
+ },
128
+ },
95
129
  pricing: X402_PRICING,
96
130
  };
97
131
  }
@@ -309,7 +343,8 @@ const EMERGING_LIMIT = 3;
309
343
  // the same columns — they feed the same row mapper.
310
344
  const SEARCH_COLS = `id, display_name, description, auto_description, domain, protocol_type, network,
311
345
  reliability_score, ipfs_hash, entity_count, canonical_entities,
312
- powered_by_substreams, active_allocation_count, example_query, denied_at, created_at`;
346
+ powered_by_substreams, active_allocation_count, example_query, denied_at, created_at,
347
+ query_volume_30d`;
313
348
 
314
349
  function ageDays(created_at) {
315
350
  if (!created_at) return null;
@@ -487,6 +522,12 @@ function searchSubgraphs({
487
522
  protocol_type: r.protocol_type,
488
523
  network: r.network,
489
524
  reliability_score: r.reliability_score,
525
+ // The registry has this number and the official Graph MCP's
526
+ // get_deployment_30day_query_counts was observed returning 0 for
527
+ // deployments that plainly serve traffic, so it could not break ties
528
+ // between a real protocol and its forks. Surfacing it here is what lets a
529
+ // caller tell Lido (4.7M queries/30d) from lido-copy.
530
+ query_volume_30d: r.query_volume_30d ?? null,
490
531
  ipfs_hash: r.ipfs_hash,
491
532
  entity_count: r.entity_count,
492
533
  canonical_entities: JSON.parse(r.canonical_entities),
@@ -496,7 +537,6 @@ function searchSubgraphs({
496
537
  // caller passed include_denied — surfaced so that choice stays visible
497
538
  // in the result rather than being silently carried.
498
539
  denied: Boolean(r.denied_at),
499
- testnet: isTestnetNetwork(r.network),
500
540
  testnet: isTestnetNetwork(r.network),
501
541
  // Ready-to-run GraphQL generated from this subgraph's actual schema — so an
502
542
  // agent can POST it to query_url_x402 immediately, no get_subgraph_detail round-trip.
@@ -524,6 +564,12 @@ function searchSubgraphs({
524
564
  protocol_type: r.protocol_type,
525
565
  network: r.network,
526
566
  reliability_score: r.reliability_score,
567
+ // The registry has this number and the official Graph MCP's
568
+ // get_deployment_30day_query_counts was observed returning 0 for
569
+ // deployments that plainly serve traffic, so it could not break ties
570
+ // between a real protocol and its forks. Surfacing it here is what lets a
571
+ // caller tell Lido (4.7M queries/30d) from lido-copy.
572
+ query_volume_30d: r.query_volume_30d ?? null,
527
573
  ipfs_hash: r.ipfs_hash,
528
574
  entity_count: r.entity_count,
529
575
  canonical_entities: JSON.parse(r.canonical_entities),
@@ -543,7 +589,7 @@ function searchSubgraphs({
543
589
  ...(emerging.length
544
590
  ? { emerging, emerging_caveat: EMERGING_CAVEAT }
545
591
  : {}),
546
- query_instructions: "Two ways to query: (a) RECOMMENDED — POST GraphQL to query_url_x402 and pay $0.01 USDC on Base per query via x402 (no API key required; gateway returns HTTP 402 with a payment manifest, use an x402 client like @graphprotocol/client-x402 to sign and retry). (b) LEGACY — replace [api-key] in query_url with a Graph API key from https://thegraph.com/studio/apikeys/. Each result includes a ready-to-run `example_query` generated from that subgraph's real schema — POST it to query_url_x402 as-is, or adapt the entity/fields. Use get_subgraph_detail for the full schema.",
592
+ query_instructions: "This registry does DISCOVERY, not execution — it hands you the subgraph id and a ready-to-run `example_query`, and you run the query with whatever Graph client you already have. Two equally valid routes, pick by what you have: (a) API KEY — POST to `query_url` with header `Authorization: Bearer <STUDIO_API_KEY>` (get one at https://thegraph.com/studio/apikeys/, 100K free queries/month). Note the gateway returns HTTP 200 with a GraphQL error body when the header is missing, so read the body. (b) x402 — POST to `query_url_x402` and pay $0.01 USDC on Base per query, no key and no signup; the gateway answers 402 with a payment manifest and an x402 client signs and retries. Use (a) if you hold a key, (b) if you are headless with a funded wallet. If your client already has an official Graph MCP or gateway connector, just pass it the `id` from this result and ignore both URLs. See `payment_options` for the full shape of each.",
547
593
  };
548
594
  }
549
595
 
@@ -678,6 +724,12 @@ function recommendSubgraph({ goal, chain = "" }) {
678
724
  protocol_type: r.protocol_type,
679
725
  network: r.network,
680
726
  reliability_score: r.reliability_score,
727
+ // The registry has this number and the official Graph MCP's
728
+ // get_deployment_30day_query_counts was observed returning 0 for
729
+ // deployments that plainly serve traffic, so it could not break ties
730
+ // between a real protocol and its forks. Surfacing it here is what lets a
731
+ // caller tell Lido (4.7M queries/30d) from lido-copy.
732
+ query_volume_30d: r.query_volume_30d ?? null,
681
733
  ipfs_hash: r.ipfs_hash,
682
734
  canonical_entities: JSON.parse(r.canonical_entities),
683
735
  active_allocation_count: r.active_allocation_count || 0,
@@ -742,7 +794,11 @@ function getSubgraphDetail({ subgraph_id }) {
742
794
  const exampleQuery = result.example_query || FALLBACK_EXAMPLE;
743
795
 
744
796
  result.query_instructions = {
745
- recommended: "x402",
797
+ // No single recommendation: see payment_options on each result. Callers
798
+ // hold either a Studio key or a wallet, rarely both, and the registry has
799
+ // no way to know which — so it states both and lets the caller choose.
800
+ recommended: null,
801
+ routes: ["api_key", "x402"],
746
802
  x402: {
747
803
  url: endpoints.query_url_x402,
748
804
  payment: endpoints.pricing,
@@ -1039,13 +1095,18 @@ async function semanticSearchSubgraphs({
1039
1095
  protocol_type: r.protocol_type,
1040
1096
  network: r.network,
1041
1097
  reliability_score: r.reliability_score,
1098
+ // The registry has this number and the official Graph MCP's
1099
+ // get_deployment_30day_query_counts was observed returning 0 for
1100
+ // deployments that plainly serve traffic, so it could not break ties
1101
+ // between a real protocol and its forks. Surfacing it here is what lets a
1102
+ // caller tell Lido (4.7M queries/30d) from lido-copy.
1103
+ query_volume_30d: r.query_volume_30d ?? null,
1042
1104
  ipfs_hash: r.ipfs_hash,
1043
1105
  entity_count: r.entity_count,
1044
1106
  canonical_entities: JSON.parse(r.canonical_entities),
1045
1107
  powered_by_substreams: Boolean(r.powered_by_substreams),
1046
1108
  active_allocation_count: r.active_allocation_count || 0,
1047
1109
  denied: Boolean(r.denied_at),
1048
- testnet: isTestnetNetwork(r.network),
1049
1110
  testnet: isTestnetNetwork(r.network),
1050
1111
  example_query: r.example_query || null,
1051
1112
  // No `emerging` companion list here: this tool ranks by cosine score,
@@ -1067,7 +1128,7 @@ async function semanticSearchSubgraphs({
1067
1128
  model: "sentence-transformers/all-MiniLM-L6-v2",
1068
1129
  subgraphs: results,
1069
1130
  query_instructions:
1070
- "Each result includes query_url_x402 (pay $0.01 USDC on Base, no API key) and a legacy query_url. semantic_score is cosine similarity in [0,1]; values >0.5 are typically strong matches.",
1131
+ "Each result includes both query routes in `payment_options` — a keyed gateway URL (Authorization: Bearer <STUDIO_API_KEY>) and an x402 URL ($0.01 USDC on Base, no key). Use whichever your client already has. semantic_score is cosine similarity in [0,1]; values >0.5 are typically strong matches.",
1071
1132
  };
1072
1133
  }
1073
1134
 
@@ -1237,7 +1298,7 @@ const TOOLS = [
1237
1298
  {
1238
1299
  name: "search_subgraphs",
1239
1300
  description:
1240
- "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Each result includes query_url_x402 (POST GraphQL and pay $0.01 USDC on Base per query — no API key needed) and a legacy query_url (Studio API key required), plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user.",
1301
+ "Search and filter the classified subgraph registry (15,000+ subgraphs). Filter by domain (defi, nfts, dao, gaming, identity, infrastructure, social, analytics), network (mainnet, arbitrum-one, base, matic, bsc, optimism, avalanche), protocol_type (dex, lending, bridge, staking, options, perpetuals, nft-marketplace, yield-aggregator, governance, name-service), canonical entity type (liquidity_pool, trade, token, position, vault, loan, collateral, liquidation, nft_collection, nft_item, nft_sale, proposal, delegate, domain_name, account, transaction, daily_snapshot, hourly_snapshot), or free-text keyword. Returns subgraphs ranked by reliability score. Discovery only — this tool does not execute GraphQL. Each result carries the subgraph id, a ready-to-run example_query, and both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer) or an x402 URL ($0.01 USDC on Base, no key). Pass the id to your own Graph client if you have one. Plus age_days and maturity (new | emerging | established). Because reliability_score is cumulative it structurally favours older deployments, so a separate `emerging` list carries recent matches that ranked below the main cut for age rather than quality — read `emerging_caveat` before offering one to a user.",
1241
1302
  inputSchema: {
1242
1303
  type: "object",
1243
1304
  additionalProperties: false,
@@ -1270,7 +1331,7 @@ const TOOLS = [
1270
1331
  {
1271
1332
  name: "recommend_subgraph",
1272
1333
  description:
1273
- "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Each result includes query_url_x402 (preferred — POST GraphQL, pay $0.01 USDC on Base per query, no API key) and a legacy query_url for Studio-key flows.",
1334
+ "Given a natural-language goal like 'find DEX trades on Arbitrum' or 'get lending liquidation data', returns the best matching subgraphs with reliability scores. Automatically infers domain and protocol type from the goal. Discovery only — it returns ids and starter queries, it does not execute GraphQL. Each result carries both query routes in `payment_options`: a keyed gateway URL (Authorization: Bearer <STUDIO_API_KEY>) or an x402 URL ($0.01 USDC on Base, no key).",
1274
1335
  inputSchema: {
1275
1336
  type: "object",
1276
1337
  additionalProperties: false,