@defipipe/mcp 0.1.1 → 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 +33 -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,18 +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
|
-
"
|
|
98
|
-
"
|
|
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.",
|
|
99
111
|
inputSchema: {
|
|
100
112
|
series: z.array(z.string()).min(1).max(10).describe("Canonical series IDs (from search_datasets)"),
|
|
101
|
-
freq: z.enum(["1m", "5m", "15m", "1h", "4h", "1d", "7d"]).
|
|
102
|
-
from: z.string().
|
|
103
|
-
to: z.string().
|
|
113
|
+
freq: z.enum(["block", "1m", "5m", "15m", "1h", "4h", "1d", "7d"]).describe("Granularity. block and 1m require an API key."),
|
|
114
|
+
from: z.string().describe("ISO 8601 start of the timeframe, e.g. 2026-07-09"),
|
|
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)"),
|
|
104
118
|
},
|
|
105
|
-
|
|
119
|
+
annotations: { readOnlyHint: true },
|
|
120
|
+
}, async ({ series, freq, from, to, cursor, limit }) => {
|
|
106
121
|
const p = new URLSearchParams({ series: series.join(",") });
|
|
107
122
|
if (freq)
|
|
108
123
|
p.set("freq", freq);
|
|
@@ -110,40 +125,19 @@ export function buildServer() {
|
|
|
110
125
|
p.set("from", from);
|
|
111
126
|
if (to)
|
|
112
127
|
p.set("to", to);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
server.registerTool("get_series_raw", {
|
|
116
|
-
title: "Query raw per-block rows",
|
|
117
|
-
description: "Raw per-block rows for one series (GET /v1/series/:id). Each row is " +
|
|
118
|
-
"[block_number, block_timestamp, value_raw, value_decimal]; value_raw is the exact " +
|
|
119
|
-
"uint256-safe on-chain value as a string. Requires an API key (DEFIPIPE_API_KEY). " +
|
|
120
|
-
"Paginate by passing the response's next_after_block as after_block.",
|
|
121
|
-
inputSchema: {
|
|
122
|
-
id: z.string().describe("Canonical series ID"),
|
|
123
|
-
from: z.string().optional().describe("ISO 8601 start, default: to minus 24 hours"),
|
|
124
|
-
to: z.string().optional().describe("ISO 8601 end, default: now"),
|
|
125
|
-
after_block: z.number().int().optional().describe("Pagination cursor: only rows with a strictly greater block number"),
|
|
126
|
-
limit: z.number().int().min(1).max(10000).optional().describe("Rows per page, default 1,000"),
|
|
127
|
-
},
|
|
128
|
-
}, async ({ id, from, to, after_block, limit }) => {
|
|
129
|
-
const p = new URLSearchParams();
|
|
130
|
-
if (from)
|
|
131
|
-
p.set("from", from);
|
|
132
|
-
if (to)
|
|
133
|
-
p.set("to", to);
|
|
134
|
-
if (after_block !== undefined)
|
|
135
|
-
p.set("after_block", String(after_block));
|
|
128
|
+
if (cursor)
|
|
129
|
+
p.set("cursor", cursor);
|
|
136
130
|
if (limit !== undefined)
|
|
137
131
|
p.set("limit", String(limit));
|
|
138
|
-
|
|
139
|
-
return toolResult(await apiGet(`${API}/v1/series/${encodeURIComponent(id)}${qs}`));
|
|
132
|
+
return toolResult(await apiGet(`${API}/v1/data?${p}`));
|
|
140
133
|
});
|
|
141
134
|
server.registerTool("get_limits", {
|
|
142
135
|
title: "Check tier entitlements",
|
|
143
136
|
description: "Machine-readable entitlements for the current credential (GET /v1/limits): rate " +
|
|
144
|
-
"limits, allowed frequencies,
|
|
137
|
+
"limits, allowed frequencies, history window, and page size. Call this before " +
|
|
145
138
|
"large pulls instead of discovering limits through 429s.",
|
|
146
139
|
inputSchema: {},
|
|
140
|
+
annotations: { readOnlyHint: true },
|
|
147
141
|
}, async () => toolResult(await apiGet(`${API}/v1/limits`)));
|
|
148
142
|
server.registerResource("docs", "defipipe://docs", {
|
|
149
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",
|