@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 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 (aligned queries at 5m
32
- resolution and coarser, trailing 90 days, no raw rows). Keys come from the
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
- | `get_aligned` | Up to 10 series resampled onto one shared UTC time axis. Last value at or before each boundary: no interpolation, no lookahead, safe for backtests. |
42
- | `get_series_raw` | Raw per-block rows for one series: `[block_number, block_timestamp, value_raw, value_decimal]` with the exact uint256 value as a string. Requires an API key. |
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 aligned time series, raw per-block rows,
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 aligned time series, raw per-block rows,
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.1.1";
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 get_aligned and " +
62
- "get_series_raw. Omit the query to list every dataset.",
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("get_aligned", {
95
- title: "Query aligned time series",
96
- description: "Resample up to 10 series onto one shared UTC time axis (GET /v1/aligned). Each value " +
97
- "is the last observation at or before the interval boundary: no interpolation, no " +
98
- "lookahead, safe for backtests. Free tier: 5m resolution and coarser, trailing 90 days.",
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"]).optional().describe("Bar size, default 1h. 1m requires an API key."),
102
- from: z.string().optional().describe("ISO 8601 start, default: to minus 7 days"),
103
- to: z.string().optional().describe("ISO 8601 end, default: now"),
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
- }, async ({ series, freq, from, to }) => {
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
- return toolResult(await apiGet(`${API}/v1/aligned?${p}`));
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
- const qs = p.size ? `?${p}` : "";
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, raw-row access, and history window. Call this before " +
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.1.1",
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",