dexe-mcp 0.5.1 → 0.5.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.2
4
+
5
+ Subgraph auth fix. The Graph decentralized gateway now rejects requests
6
+ without `Authorization: Bearer <api-key>` — every subgraph-backed tool
7
+ (`dexe_read_dao_list`, `dexe_proposal_voters`, `dexe_user_inbox`, etc.) was
8
+ silently failing with HTTP 401 / "missing authorization header".
9
+
10
+ ### Fixed
11
+
12
+ - `gqlRequest` (`src/lib/subgraph.ts`) now sends a Bearer token derived from
13
+ (in priority order): explicit `apiKey` arg → `DEXE_GRAPH_API_KEY` env →
14
+ auto-extracted from URL path (`/api/<key>/subgraphs/...`). Backward-compatible
15
+ with the legacy URL shape — no env or call-site changes required for users
16
+ whose key is already embedded in `DEXE_SUBGRAPH_*_URL`.
17
+ - HTTP error path now includes the gateway's response body (truncated to 200
18
+ chars) so 401/403 reasons surface in the thrown message.
19
+
20
+ ### Added
21
+
22
+ - New optional env var `DEXE_GRAPH_API_KEY` for the Bearer-only URL shape
23
+ (`https://gateway.thegraph.com/api/subgraphs/id/<id>`). Documented in
24
+ `.env.example`.
25
+ - Exported helper `extractGraphApiKey(endpoint)` for reuse.
26
+
3
27
  ## 0.5.1
4
28
 
5
29
  OTC tier rate-scaling guardrails. Production incident on 2026-05-04: a sale
package/README.md CHANGED
@@ -105,8 +105,10 @@ All optional. Tools that need a missing variable fail with a clear message point
105
105
  | `DEXE_PINATA_JWT` | IPFS uploads | Pinata JWT for pinning proposal/DAO metadata |
106
106
  | `DEXE_IPFS_GATEWAY` | IPFS fetch | **Dedicated** gateway URL (Pinata provides one alongside your JWT; Filebase / Quicknode / self-hosted also work). Public gateways are unreliable and NOT defaulted |
107
107
  | `DEXE_IPFS_GATEWAYS_FALLBACK` | IPFS fetch (optional) | Comma-separated public gateways tried sequentially after the primary |
108
- | `DEXE_SUBGRAPH_INTERACTIONS_URL` | `dexe_proposal_voters` | The Graph endpoint for the DeXe interactions subgraph |
109
- | `DEXE_SUBGRAPH_POOLS_URL`, `DEXE_SUBGRAPH_VALIDATORS_URL` | reserved | Additional subgraph endpoints for future tools |
108
+ | `DEXE_SUBGRAPH_POOLS_URL` | `dexe_read_dao_list`, `dexe_read_dao_members`, `dexe_read_delegation_map`, `dexe_read_dao_experts`, `dexe_user_inbox`, `dexe_proposal_voters`, `dexe_dao_predict_addresses` | The Graph endpoint for the DeXe pools subgraph |
109
+ | `DEXE_SUBGRAPH_VALIDATORS_URL` | `dexe_read_validator_list` | The Graph endpoint for the DeXe validators subgraph |
110
+ | `DEXE_SUBGRAPH_INTERACTIONS_URL` | `dexe_read_user_activity` | The Graph endpoint for the DeXe interactions subgraph |
111
+ | `DEXE_GRAPH_API_KEY` | subgraph reads (optional) | Bearer token for `gateway.thegraph.com`. Required only when `DEXE_SUBGRAPH_*_URL` does not embed the key in the path (`/api/<key>/subgraphs/...`). Auto-extracted from the URL when present |
110
112
  | `DEXE_BACKEND_API_URL` | off-chain proposals | DeXe backend (e.g. `https://api.dexe.io`) |
111
113
 
112
114
  ## Documentation
@@ -9,7 +9,13 @@ export interface GqlResponse<T> {
9
9
  message: string;
10
10
  }>;
11
11
  }
12
- export declare function gqlRequest<T>(endpoint: string, query: string, variables?: Record<string, unknown>): Promise<T>;
12
+ /**
13
+ * Extracts a Graph API key from URLs of the shape
14
+ * `…/api/<key>/subgraphs/id/<id>`. Returns `undefined` for URLs that don't
15
+ * embed a key (e.g. `…/api/subgraphs/id/<id>` — Bearer-only style).
16
+ */
17
+ export declare function extractGraphApiKey(endpoint: string): string | undefined;
18
+ export declare function gqlRequest<T>(endpoint: string, query: string, variables?: Record<string, unknown>, apiKey?: string): Promise<T>;
13
19
  /** Ported from frontend gov-pools subgraph `proposalInteractions` query. */
14
20
  export declare const PROPOSAL_INTERACTIONS_QUERY = "\n query ProposalInteractions($proposalId: String!, $first: Int!, $skip: Int!) {\n proposalInteractions(\n where: { proposal: $proposalId }\n first: $first\n skip: $skip\n orderBy: timestamp\n orderDirection: desc\n ) {\n id\n hash\n timestamp\n interactionType\n totalVote\n voter {\n id\n voter {\n id\n }\n }\n }\n }\n";
15
21
  //# sourceMappingURL=subgraph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subgraph.d.ts","sourceRoot":"","sources":["../../src/lib/subgraph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CAeZ;AAED,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,2aAsBvC,CAAC"}
1
+ {"version":3,"file":"subgraph.d.ts","sourceRoot":"","sources":["../../src/lib/subgraph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGvE;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAED,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,2aAsBvC,CAAC"}
@@ -1,11 +1,25 @@
1
- export async function gqlRequest(endpoint, query, variables) {
1
+ /**
2
+ * Extracts a Graph API key from URLs of the shape
3
+ * `…/api/<key>/subgraphs/id/<id>`. Returns `undefined` for URLs that don't
4
+ * embed a key (e.g. `…/api/subgraphs/id/<id>` — Bearer-only style).
5
+ */
6
+ export function extractGraphApiKey(endpoint) {
7
+ const m = endpoint.match(/\/api\/([0-9a-f]{32,})\/subgraphs\//i);
8
+ return m ? m[1] : undefined;
9
+ }
10
+ export async function gqlRequest(endpoint, query, variables, apiKey) {
11
+ const headers = { "Content-Type": "application/json" };
12
+ const key = apiKey ?? process.env.DEXE_GRAPH_API_KEY?.trim() ?? extractGraphApiKey(endpoint);
13
+ if (key)
14
+ headers["Authorization"] = `Bearer ${key}`;
2
15
  const res = await fetch(endpoint, {
3
16
  method: "POST",
4
- headers: { "Content-Type": "application/json" },
17
+ headers,
5
18
  body: JSON.stringify({ query, variables }),
6
19
  });
7
20
  if (!res.ok) {
8
- throw new Error(`Subgraph HTTP ${res.status} ${res.statusText}`);
21
+ const detail = await res.text().catch(() => "");
22
+ throw new Error(`Subgraph HTTP ${res.status} ${res.statusText}${detail ? ` — ${detail.slice(0, 200)}` : ""}`);
9
23
  }
10
24
  const body = (await res.json());
11
25
  if (body.errors?.length) {
@@ -1 +1 @@
1
- {"version":3,"file":"subgraph.js","sourceRoot":"","sources":["../../src/lib/subgraph.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,KAAa,EACb,SAAmC;IAEnC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;KAC3C,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;IAClD,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBxD,CAAC"}
1
+ {"version":3,"file":"subgraph.js","sourceRoot":"","sources":["../../src/lib/subgraph.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,KAAa,EACb,SAAmC,EACnC,MAAe;IAEf,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;IAC/E,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7F,IAAI,GAAG;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,GAAG,EAAE,CAAC;IAEpD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;KAC3C,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;IAClD,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBxD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dexe-mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "MCP server for the DeXe Protocol — full DAO operations coverage: deploy DAOs, build every proposal type, IPFS metadata, stake/vote/delegate/execute/claim calldata. Plus dev tooling (build/test/introspect/decode).",
5
5
  "type": "module",
6
6
  "license": "MIT",