@defipipe/mcp 0.2.0 → 0.3.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 +4 -5
- package/dist/server.d.ts +2 -1
- package/dist/server.js +31 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,8 +28,8 @@ Or in any MCP client config:
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
`DEFIPIPE_API_KEY` is optional: without it you run on the free tier (
|
|
32
|
-
|
|
31
|
+
`DEFIPIPE_API_KEY` is optional: without it you run on the free tier (5m resolution and
|
|
32
|
+
coarser, trailing 90 days). Keys come from the
|
|
33
33
|
[dashboard](https://defipipe.io/dashboard); tiers are on the
|
|
34
34
|
[pricing page](https://defipipe.io/pricing).
|
|
35
35
|
|
|
@@ -38,9 +38,8 @@ resolution and coarser, trailing 90 days, no raw rows). Keys come from the
|
|
|
38
38
|
| Tool | What it does |
|
|
39
39
|
|---|---|
|
|
40
40
|
| `search_datasets` | Search the catalog (protocol, metric, category). Returns datasets with their canonical series IDs. |
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `get_limits` | Machine-readable entitlements for the current credential: rate limits, allowed frequencies, history window. |
|
|
41
|
+
| `get_data` | Up to 10 series on one shared UTC time grid at any granularity (block to 1d). Every point is a real on-chain observation and returns both the exact raw integer (uint256-safe string) and the unit-scaled float, plus the scaling metadata (unit, decimals) so the arithmetic is auditable. Pages via a `next` cursor. |
|
|
42
|
+
| `get_limits` | Machine-readable entitlements for the current credential: rate limits, allowed frequencies, history window, page size. |
|
|
44
43
|
|
|
45
44
|
Plus a `defipipe://docs` resource with the full API reference as markdown.
|
|
46
45
|
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** MCP server for defipipe (stdio). Thin wrapper over the public HTTPS API:
|
|
2
|
-
* search the dataset catalog, query
|
|
2
|
+
* search the dataset catalog, query observations for one or more series on a
|
|
3
|
+
* shared time grid (raw integers + curated floats, self-describing units),
|
|
3
4
|
* and tier entitlements. Set DEFIPIPE_API_KEY for keyed tiers; the free tier
|
|
4
5
|
* works without one. */
|
|
5
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** MCP server for defipipe (stdio). Thin wrapper over the public HTTPS API:
|
|
2
|
-
* search the dataset catalog, query
|
|
2
|
+
* search the dataset catalog, query observations for one or more series on a
|
|
3
|
+
* shared time grid (raw integers + curated floats, self-describing units),
|
|
3
4
|
* and tier entitlements. Set DEFIPIPE_API_KEY for keyed tiers; the free tier
|
|
4
5
|
* works without one. */
|
|
5
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -7,7 +8,7 @@ import { z } from "zod";
|
|
|
7
8
|
const API = process.env.DEFIPIPE_API_URL ?? "https://api.defipipe.io";
|
|
8
9
|
const SITE = process.env.DEFIPIPE_SITE_URL ?? "https://defipipe.io";
|
|
9
10
|
const KEY = process.env.DEFIPIPE_API_KEY;
|
|
10
|
-
const VERSION = "0.
|
|
11
|
+
const VERSION = "0.3.0";
|
|
11
12
|
function headers() {
|
|
12
13
|
return KEY ? { authorization: `Bearer ${KEY}` } : {};
|
|
13
14
|
}
|
|
@@ -58,14 +59,15 @@ export function buildServer() {
|
|
|
58
59
|
server.registerTool("search_datasets", {
|
|
59
60
|
title: "Search defipipe datasets",
|
|
60
61
|
description: "Search the defipipe catalog of historical per-block DeFi datasets. Returns matching " +
|
|
61
|
-
"datasets with their canonical series IDs, which are the inputs to
|
|
62
|
-
"
|
|
62
|
+
"datasets with their canonical series IDs, which are the inputs to get_data. " +
|
|
63
|
+
"Omit the query to list every dataset.",
|
|
63
64
|
inputSchema: {
|
|
64
65
|
query: z
|
|
65
66
|
.string()
|
|
66
67
|
.optional()
|
|
67
68
|
.describe("Case-insensitive match against protocol, label, category, and metrics (e.g. 'aave', 'borrow rate', 'lending')"),
|
|
68
69
|
},
|
|
70
|
+
annotations: { readOnlyHint: true },
|
|
69
71
|
}, async ({ query }) => {
|
|
70
72
|
let datasets;
|
|
71
73
|
try {
|
|
@@ -91,20 +93,31 @@ export function buildServer() {
|
|
|
91
93
|
content: [{ type: "text", text: JSON.stringify({ count: out.length, datasets: out }, null, 2) }],
|
|
92
94
|
};
|
|
93
95
|
});
|
|
94
|
-
server.registerTool("
|
|
95
|
-
title: "Query
|
|
96
|
-
description: "
|
|
97
|
-
"and granularity are explicit: pick from/to and a freq from the ladder;
|
|
98
|
-
"returns one row per sampled block
|
|
99
|
-
"
|
|
100
|
-
"lookahead, safe for backtests.
|
|
96
|
+
server.registerTool("get_data", {
|
|
97
|
+
title: "Query historical DeFi data",
|
|
98
|
+
description: "Observations for up to 10 series on one shared UTC time grid (GET /v1/data). " +
|
|
99
|
+
"Timeframe and granularity are explicit: pick from/to and a freq from the ladder; " +
|
|
100
|
+
"freq=block returns one row per sampled block. Every point at every freq is a real " +
|
|
101
|
+
"on-chain observation (last observation at or before each boundary; never an " +
|
|
102
|
+
"average): no interpolation, no lookahead, safe for backtests. Each series returns " +
|
|
103
|
+
"values (unit-scaled floats), raw (the exact on-chain integers as strings — " +
|
|
104
|
+
"uint256-safe), blocks (per-point source block), and its scaling metadata " +
|
|
105
|
+
"(unit, decimals, note), so the arithmetic behind every float is auditable. " +
|
|
106
|
+
"Derived series (kind=derived) are computed at query time and expose their formula " +
|
|
107
|
+
"instead of raw. Windows larger than one page return a `next` cursor: pass it back " +
|
|
108
|
+
"as `cursor` and keep the other params identical until next is null. " +
|
|
109
|
+
"Free tier: 5m and coarser, trailing 90 days; block/1m need an API key; full " +
|
|
110
|
+
"history needs quant.",
|
|
101
111
|
inputSchema: {
|
|
102
112
|
series: z.array(z.string()).min(1).max(10).describe("Canonical series IDs (from search_datasets)"),
|
|
103
113
|
freq: z.enum(["block", "1m", "5m", "15m", "1h", "4h", "1d", "7d"]).describe("Granularity. block and 1m require an API key."),
|
|
104
|
-
from: z.string().describe("ISO 8601 start of the timeframe, e.g. 2026-07-
|
|
114
|
+
from: z.string().describe("ISO 8601 start of the timeframe, e.g. 2026-07-09"),
|
|
105
115
|
to: z.string().describe("ISO 8601 end of the timeframe, e.g. 2026-07-12"),
|
|
116
|
+
cursor: z.string().optional().describe("The `next` value from the previous page, verbatim"),
|
|
117
|
+
limit: z.number().int().min(1).optional().describe("Points per page (capped by tier page size)"),
|
|
106
118
|
},
|
|
107
|
-
|
|
119
|
+
annotations: { readOnlyHint: true },
|
|
120
|
+
}, async ({ series, freq, from, to, cursor, limit }) => {
|
|
108
121
|
const p = new URLSearchParams({ series: series.join(",") });
|
|
109
122
|
if (freq)
|
|
110
123
|
p.set("freq", freq);
|
|
@@ -112,40 +125,19 @@ export function buildServer() {
|
|
|
112
125
|
p.set("from", from);
|
|
113
126
|
if (to)
|
|
114
127
|
p.set("to", to);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
server.registerTool("get_series_raw", {
|
|
118
|
-
title: "Query raw per-block rows",
|
|
119
|
-
description: "Raw per-block rows for one series (GET /v1/series/:id). Each row is " +
|
|
120
|
-
"[block_number, block_timestamp, value_raw, value_decimal]; value_raw is the exact " +
|
|
121
|
-
"uint256-safe on-chain value as a string. Requires an API key (DEFIPIPE_API_KEY). " +
|
|
122
|
-
"Paginate by passing the response's next_after_block as after_block.",
|
|
123
|
-
inputSchema: {
|
|
124
|
-
id: z.string().describe("Canonical series ID"),
|
|
125
|
-
from: z.string().describe("ISO 8601 start of the timeframe, e.g. 2026-07-11"),
|
|
126
|
-
to: z.string().describe("ISO 8601 end of the timeframe, e.g. 2026-07-12"),
|
|
127
|
-
after_block: z.number().int().optional().describe("Pagination cursor: only rows with a strictly greater block number"),
|
|
128
|
-
limit: z.number().int().min(1).max(10000).optional().describe("Rows per page, default 1,000"),
|
|
129
|
-
},
|
|
130
|
-
}, async ({ id, from, to, after_block, limit }) => {
|
|
131
|
-
const p = new URLSearchParams();
|
|
132
|
-
if (from)
|
|
133
|
-
p.set("from", from);
|
|
134
|
-
if (to)
|
|
135
|
-
p.set("to", to);
|
|
136
|
-
if (after_block !== undefined)
|
|
137
|
-
p.set("after_block", String(after_block));
|
|
128
|
+
if (cursor)
|
|
129
|
+
p.set("cursor", cursor);
|
|
138
130
|
if (limit !== undefined)
|
|
139
131
|
p.set("limit", String(limit));
|
|
140
|
-
|
|
141
|
-
return toolResult(await apiGet(`${API}/v1/series/${encodeURIComponent(id)}${qs}`));
|
|
132
|
+
return toolResult(await apiGet(`${API}/v1/data?${p}`));
|
|
142
133
|
});
|
|
143
134
|
server.registerTool("get_limits", {
|
|
144
135
|
title: "Check tier entitlements",
|
|
145
136
|
description: "Machine-readable entitlements for the current credential (GET /v1/limits): rate " +
|
|
146
|
-
"limits, allowed frequencies,
|
|
137
|
+
"limits, allowed frequencies, history window, and page size. Call this before " +
|
|
147
138
|
"large pulls instead of discovering limits through 429s.",
|
|
148
139
|
inputSchema: {},
|
|
140
|
+
annotations: { readOnlyHint: true },
|
|
149
141
|
}, async () => toolResult(await apiGet(`${API}/v1/limits`)));
|
|
150
142
|
server.registerResource("docs", "defipipe://docs", {
|
|
151
143
|
title: "defipipe API reference",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defipipe/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server for defipipe: historical, point-in-time DeFi contract state per block. Search datasets, query aligned time series and raw per-block rows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|