@secondlayer/mcp 3.0.0 → 3.1.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/dist/index.js CHANGED
@@ -4,6 +4,69 @@ import { dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
6
 
7
+ // src/lib/client.ts
8
+ import { SecondLayer } from "@secondlayer/sdk";
9
+ var instance = null;
10
+ function readApiKey() {
11
+ return process.env.SL_API_KEY;
12
+ }
13
+ function getClient() {
14
+ if (!instance) {
15
+ const apiKey = readApiKey();
16
+ const baseUrl = process.env.SECONDLAYER_API_URL;
17
+ instance = new SecondLayer({
18
+ ...apiKey ? { apiKey } : {},
19
+ origin: "mcp",
20
+ ...baseUrl ? { baseUrl } : {}
21
+ });
22
+ }
23
+ return instance;
24
+ }
25
+ var keyHint = " — set SL_API_KEY to an sk-sl_ API key from " + "https://secondlayer.tools/platform/api-keys for write and account operations";
26
+ async function apiRequest(method, path, body) {
27
+ const apiKey = readApiKey();
28
+ const baseUrl = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
29
+ const res = await fetch(`${baseUrl}${path}`, {
30
+ method,
31
+ headers: {
32
+ "Content-Type": "application/json",
33
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
34
+ },
35
+ body: body ? JSON.stringify(body) : undefined
36
+ });
37
+ if (!res.ok) {
38
+ const text = await res.text().catch(() => "");
39
+ const needsKey = !apiKey && (res.status === 401 || res.status === 403);
40
+ throw Object.assign(new Error((text || `HTTP ${res.status}`) + (needsKey ? keyHint : "")), { status: res.status });
41
+ }
42
+ if (res.status === 204)
43
+ return;
44
+ return res.json();
45
+ }
46
+
47
+ // src/lib/format.ts
48
+ function formatSubgraphSummary(s) {
49
+ return {
50
+ name: s.name,
51
+ status: s.status,
52
+ tables: Array.isArray(s.tables) ? s.tables : Object.keys(s.tables),
53
+ lastProcessedBlock: s.lastProcessedBlock
54
+ };
55
+ }
56
+ function withCap(items, cap) {
57
+ return {
58
+ items: items.slice(0, cap),
59
+ truncated: items.length > cap,
60
+ total: items.length
61
+ };
62
+ }
63
+ function jsonResponse(data, isError) {
64
+ return {
65
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
66
+ ...isError && { isError: true }
67
+ };
68
+ }
69
+
7
70
  // src/resources.ts
8
71
  var FILTERS_REFERENCE = [
9
72
  {
@@ -59,7 +122,54 @@ var COLUMN_TYPES = [
59
122
  description: "Column options: nullable allows NULL, indexed creates a B-tree index, search enables full-text search"
60
123
  }
61
124
  ];
125
+ var CAPABILITIES = {
126
+ products: [
127
+ "datasets — public foundation datasets (datasets_list, datasets_query)",
128
+ "index — decoded L2 events + contract calls (index_ft_transfers, index_nft_transfers, index_events, index_contract_calls)",
129
+ "streams — raw chain event firehose (streams_tip, streams_events)",
130
+ "contracts — trait-based contract discovery (contracts_find)",
131
+ "subgraphs — author/deploy/query custom indexes (subgraphs_deploy, subgraphs_query, subgraphs_list, subgraphs_get, subgraphs_reindex, subgraphs_delete)",
132
+ "subscriptions — webhook delivery of subgraph rows (subscriptions_create, subscriptions_list, subscriptions_update, …)",
133
+ "account — identity + plan (account_whoami)"
134
+ ],
135
+ discoverFirst: "Call datasets_list / contracts_find to learn what exists before querying."
136
+ };
137
+ var READ_AUTH_TIERS = {
138
+ datasets: "open — no API key required",
139
+ index: "anonymous reads allowed; free-tier API keys are rejected (Build+ required)",
140
+ streams: "API key required (SL_API_KEY) — keyless calls return 401",
141
+ subgraphs: "reads public during open beta; writes require an API key"
142
+ };
143
+ async function buildContext(deps = {
144
+ clientProvider: getClient,
145
+ accountRequest: () => apiRequest("GET", "/api/accounts/me")
146
+ }) {
147
+ const unavailable = "unavailable: set SL_API_KEY";
148
+ const subgraphs = await deps.clientProvider().subgraphs.list().then((r) => r.data.map(formatSubgraphSummary)).catch(() => unavailable);
149
+ const subscriptions = await deps.clientProvider().subscriptions.list().then((r) => ({
150
+ count: r.data.length,
151
+ statuses: r.data.map((s) => s.status)
152
+ })).catch(() => unavailable);
153
+ const account = await deps.accountRequest().catch(() => unavailable);
154
+ return {
155
+ authState: { apiKeySet: Boolean(process.env.SL_API_KEY) },
156
+ whatExists: { subgraphs, subscriptions, account },
157
+ whatYouCanDo: CAPABILITIES,
158
+ readAuthTiers: READ_AUTH_TIERS
159
+ };
160
+ }
62
161
  function registerResources(server) {
162
+ server.resource("context", "secondlayer://context", {
163
+ description: "Live agent context — what exists (your subgraphs, subscriptions, account), what you can do, and read-auth tiers. Read this first."
164
+ }, async () => ({
165
+ contents: [
166
+ {
167
+ uri: "secondlayer://context",
168
+ mimeType: "application/json",
169
+ text: JSON.stringify(await buildContext(), null, 2)
170
+ }
171
+ ]
172
+ }));
63
173
  server.resource("filters", "secondlayer://filters", { description: "Event filter types and their available fields" }, async () => ({
64
174
  contents: [
65
175
  {
@@ -80,68 +190,8 @@ function registerResources(server) {
80
190
  }));
81
191
  }
82
192
 
83
- // src/lib/client.ts
84
- import { SecondLayer } from "@secondlayer/sdk";
85
- var instance = null;
86
- function readApiKey() {
87
- return process.env.SL_API_KEY;
88
- }
89
- function getClient() {
90
- if (!instance) {
91
- const apiKey = readApiKey();
92
- const baseUrl = process.env.SECONDLAYER_API_URL;
93
- instance = new SecondLayer({
94
- ...apiKey ? { apiKey } : {},
95
- origin: "mcp",
96
- ...baseUrl ? { baseUrl } : {}
97
- });
98
- }
99
- return instance;
100
- }
101
- var keyHint = " — set SL_API_KEY to an sk-sl_ API key from " + "https://secondlayer.tools/platform/api-keys for write and account operations";
102
- async function apiRequest(method, path, body) {
103
- const apiKey = readApiKey();
104
- const baseUrl = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
105
- const res = await fetch(`${baseUrl}${path}`, {
106
- method,
107
- headers: {
108
- "Content-Type": "application/json",
109
- ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
110
- },
111
- body: body ? JSON.stringify(body) : undefined
112
- });
113
- if (!res.ok) {
114
- const text = await res.text().catch(() => "");
115
- const needsKey = !apiKey && (res.status === 401 || res.status === 403);
116
- throw Object.assign(new Error((text || `HTTP ${res.status}`) + (needsKey ? keyHint : "")), { status: res.status });
117
- }
118
- if (res.status === 204)
119
- return;
120
- return res.json();
121
- }
122
-
123
- // src/lib/format.ts
124
- function formatSubgraphSummary(s) {
125
- return {
126
- name: s.name,
127
- status: s.status,
128
- tables: Array.isArray(s.tables) ? s.tables : Object.keys(s.tables),
129
- lastProcessedBlock: s.lastProcessedBlock
130
- };
131
- }
132
- function withCap(items, cap) {
133
- return {
134
- items: items.slice(0, cap),
135
- truncated: items.length > cap,
136
- total: items.length
137
- };
138
- }
139
- function jsonResponse(data, isError) {
140
- return {
141
- content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
142
- ...isError && { isError: true }
143
- };
144
- }
193
+ // src/tools/account.ts
194
+ import { z } from "zod/v4";
145
195
 
146
196
  // src/lib/tool.ts
147
197
  function defineTool(server, name, description, schema, handler) {
@@ -172,11 +222,113 @@ function registerAccountTools(server) {
172
222
  const result = await apiRequest("GET", "/api/accounts/me");
173
223
  return jsonResponse(result);
174
224
  });
225
+ defineTool(server, "account_update", "Update the authenticated account's profile. Requires an API key.", {
226
+ displayName: z.string().optional().describe("Display name"),
227
+ bio: z.string().optional().describe("Profile bio"),
228
+ slug: z.string().optional().describe("Account URL slug")
229
+ }, async ({ displayName, bio, slug }) => {
230
+ const body = {};
231
+ if (displayName !== undefined)
232
+ body.display_name = displayName;
233
+ if (bio !== undefined)
234
+ body.bio = bio;
235
+ if (slug !== undefined)
236
+ body.slug = slug;
237
+ const result = await apiRequest("PATCH", "/api/accounts/me", body);
238
+ return jsonResponse(result);
239
+ });
240
+ defineTool(server, "account_billing", "Show the account's plan and subscription/billing status. Requires an API key.", {}, async () => {
241
+ const result = await apiRequest("GET", "/api/billing/status");
242
+ return jsonResponse(result);
243
+ });
244
+ }
245
+
246
+ // src/tools/contracts.ts
247
+ import { z as z2 } from "zod/v4";
248
+ function registerContractTools(server, clientProvider = getClient) {
249
+ defineTool(server, "contracts_find", 'Discover deployed Stacks contracts conforming to a trait (e.g. "sip-010", "sip-009", "sip-013"). The discovery endpoint for "which contracts implement X". Reads are public.', {
250
+ trait: z2.string().describe('Required. Trait to match (e.g. "sip-010").'),
251
+ conformance: z2.enum(["declared", "inferred", "any"]).optional().describe("declared = parsed from source, inferred = ABI shape-match, any = either (default)"),
252
+ include: z2.literal("abi").optional().describe(`Set to "abi" to include each contract's full ABI`),
253
+ limit: z2.number().optional().describe("Page size, 1–500 (default 100)"),
254
+ cursor: z2.string().optional().describe("Opaque cursor from a prior response's next_cursor")
255
+ }, async (params) => jsonResponse(await clientProvider().contracts.list(params)));
256
+ }
257
+
258
+ // src/tools/datasets.ts
259
+ import { z as z3 } from "zod/v4";
260
+ function registerDatasetTools(server, clientProvider = getClient) {
261
+ defineTool(server, "datasets_list", "List the Foundation Datasets catalog with freshness — the discovery endpoint for what dataset slugs exist and how current each is. Reads are public.", {}, async () => {
262
+ const catalog = await clientProvider().datasets.listDatasets();
263
+ return jsonResponse(catalog);
264
+ });
265
+ defineTool(server, "datasets_query", 'Query a cursor-paginated Foundation Dataset by slug (e.g. "stx-transfers", "sbtc/events", "pox-4/calls", "bns/events"). Filters are passed through as documented query params (e.g. {"sender": "SP...", "from_block": "150000"}). Returns { rows, next_cursor, tip }. Call datasets_list first to discover slugs.', {
266
+ slug: z3.string().describe("Dataset slug from datasets_list (e.g. stx-transfers)"),
267
+ filters: z3.record(z3.string(), z3.string()).optional().describe("Documented per-dataset query params (snake_case values)"),
268
+ limit: z3.number().optional().describe("Max rows for this page"),
269
+ cursor: z3.string().optional().describe("Opaque cursor from a prior response's next_cursor")
270
+ }, async ({ slug, filters, limit, cursor }) => {
271
+ const params = { ...filters ?? {} };
272
+ if (limit !== undefined)
273
+ params.limit = limit;
274
+ if (cursor !== undefined)
275
+ params.cursor = cursor;
276
+ const result = await clientProvider().datasets.query(slug, params);
277
+ return jsonResponse(result);
278
+ });
279
+ }
280
+
281
+ // src/tools/index.ts
282
+ import { z as z4 } from "zod/v4";
283
+ var INDEX_EVENT_TYPES = [
284
+ "ft_transfer",
285
+ "nft_transfer",
286
+ "stx_transfer",
287
+ "stx_mint",
288
+ "stx_burn",
289
+ "stx_lock",
290
+ "ft_mint",
291
+ "ft_burn",
292
+ "nft_mint",
293
+ "nft_burn",
294
+ "print"
295
+ ];
296
+ var rangeFilters = {
297
+ contractId: z4.string().optional().describe("Filter by contract id"),
298
+ fromHeight: z4.number().optional().describe("Start block height (inclusive)"),
299
+ toHeight: z4.number().optional().describe("End block height (inclusive)"),
300
+ cursor: z4.string().optional().describe("Opaque cursor from a prior response's next_cursor"),
301
+ limit: z4.number().optional().describe("Max rows for this page")
302
+ };
303
+ function registerIndexTools(server, clientProvider = getClient) {
304
+ defineTool(server, "index_ft_transfers", "List decoded SIP-010 fungible-token transfers from the Index (L2 decoded layer). Anonymous reads allowed (free-tier API keys are rejected — Build+ required).", {
305
+ ...rangeFilters,
306
+ sender: z4.string().optional().describe("Filter by sender principal"),
307
+ recipient: z4.string().optional().describe("Filter by recipient principal")
308
+ }, async (params) => jsonResponse(await clientProvider().index.ftTransfers.list(params)));
309
+ defineTool(server, "index_nft_transfers", "List decoded SIP-009 non-fungible-token transfers from the Index. Anonymous reads allowed (free-tier keys rejected).", {
310
+ ...rangeFilters,
311
+ sender: z4.string().optional().describe("Filter by sender principal"),
312
+ recipient: z4.string().optional().describe("Filter by recipient principal"),
313
+ assetIdentifier: z4.string().optional().describe("Filter by asset identifier (contract::asset)")
314
+ }, async (params) => jsonResponse(await clientProvider().index.nftTransfers.list(params)));
315
+ defineTool(server, "index_events", "List decoded chain events from the Index by event type. Use this for event types without a dedicated tool (stx_*, ft_mint/burn, nft_mint/burn, print). For ft/nft transfers prefer index_ft_transfers / index_nft_transfers.", {
316
+ eventType: z4.enum(INDEX_EVENT_TYPES).describe("Required. Decoded event type to list."),
317
+ ...rangeFilters,
318
+ sender: z4.string().optional().describe("Filter by sender principal"),
319
+ recipient: z4.string().optional().describe("Filter by recipient principal"),
320
+ assetIdentifier: z4.string().optional().describe("Filter by asset identifier where applicable")
321
+ }, async (params) => jsonResponse(await clientProvider().index.events.list(params)));
322
+ defineTool(server, "index_contract_calls", "List decoded contract calls from the Index (function name, args, result). Note: contract-call cursors are a SEPARATE keyspace from event cursors — they are not interchangeable.", {
323
+ ...rangeFilters,
324
+ functionName: z4.string().optional().describe("Filter by called function name"),
325
+ sender: z4.string().optional().describe("Filter by caller principal")
326
+ }, async (params) => jsonResponse(await clientProvider().index.contractCalls.list(params)));
175
327
  }
176
328
 
177
329
  // src/tools/scaffold.ts
178
330
  import { generateSubgraphCode } from "@secondlayer/scaffold";
179
- import { z } from "zod/v4";
331
+ import { z as z5 } from "zod/v4";
180
332
  var API_BASE = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
181
333
  async function fetchAbi(contractId) {
182
334
  const res = await fetch(`${API_BASE}/api/node/contracts/${contractId}/abi`, {
@@ -195,17 +347,17 @@ async function fetchAbi(contractId) {
195
347
  }
196
348
  function registerScaffoldTools(server) {
197
349
  defineTool(server, "scaffold_from_contract", "Generate a subgraph scaffold from a deployed Stacks contract. Fetches the ABI automatically.", {
198
- contractId: z.string().describe("Fully qualified contract ID (e.g. SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01)"),
199
- subgraphName: z.string().optional().describe("Override the subgraph name (defaults to contract name)")
350
+ contractId: z5.string().describe("Fully qualified contract ID (e.g. SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01)"),
351
+ subgraphName: z5.string().optional().describe("Override the subgraph name (defaults to contract name)")
200
352
  }, async ({ contractId, subgraphName }) => {
201
353
  const { functions, maps } = await fetchAbi(contractId);
202
354
  const code = generateSubgraphCode(contractId, functions, subgraphName, maps);
203
355
  return { content: [{ type: "text", text: code }] };
204
356
  });
205
357
  defineTool(server, "scaffold_from_abi", "Generate a subgraph scaffold from a provided ABI JSON. Use when you already have the ABI.", {
206
- abi: z.string().describe("ABI JSON string (the full contract ABI object)"),
207
- contractId: z.string().describe("Fully qualified contract ID"),
208
- subgraphName: z.string().optional().describe("Override the subgraph name")
358
+ abi: z5.string().describe("ABI JSON string (the full contract ABI object)"),
359
+ contractId: z5.string().describe("Fully qualified contract ID"),
360
+ subgraphName: z5.string().optional().describe("Override the subgraph name")
209
361
  }, async ({ abi, contractId, subgraphName }) => {
210
362
  let parsed;
211
363
  try {
@@ -221,9 +373,51 @@ function registerScaffoldTools(server) {
221
373
  });
222
374
  }
223
375
 
376
+ // src/tools/streams.ts
377
+ import { AuthError } from "@secondlayer/sdk";
378
+ import { z as z6 } from "zod/v4";
379
+ var STREAMS_EVENT_TYPES = [
380
+ "stx_transfer",
381
+ "stx_mint",
382
+ "stx_burn",
383
+ "stx_lock",
384
+ "ft_transfer",
385
+ "ft_mint",
386
+ "ft_burn",
387
+ "nft_transfer",
388
+ "nft_mint",
389
+ "nft_burn",
390
+ "print"
391
+ ];
392
+ async function withStreamsAuthHint(fn) {
393
+ try {
394
+ return await fn();
395
+ } catch (err) {
396
+ if (err instanceof AuthError) {
397
+ throw Object.assign(new Error(err.message + keyHint), { status: 401 });
398
+ }
399
+ throw err;
400
+ }
401
+ }
402
+ function registerStreamsTools(server, clientProvider = getClient) {
403
+ defineTool(server, "streams_tip", "Get the current Streams chain tip (latest processed block + lag). Streams requires an API key (SL_API_KEY).", {}, async () => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.tip())));
404
+ defineTool(server, "streams_events", "List raw chain events from the Streams firehose. Streams requires an API key (SL_API_KEY). Filter by event types, principals, contract, asset, or block range; page with cursor.", {
405
+ types: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to include"),
406
+ notTypes: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to exclude (applied after types)"),
407
+ contractId: z6.string().optional().describe("Filter by contract id"),
408
+ sender: z6.string().optional().describe("Filter by sender principal"),
409
+ recipient: z6.string().optional().describe("Filter by recipient principal"),
410
+ assetIdentifier: z6.string().optional().describe("Filter by asset identifier"),
411
+ fromBlock: z6.number().optional().describe("Start block (inclusive)"),
412
+ toBlock: z6.number().optional().describe("End block (inclusive)"),
413
+ cursor: z6.string().optional().describe("Opaque cursor from a prior response"),
414
+ limit: z6.number().optional().describe("Max events for this page")
415
+ }, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.events.list(params))));
416
+ }
417
+
224
418
  // src/tools/subgraphs.ts
225
419
  import { bundleSubgraphCode } from "@secondlayer/bundler";
226
- import { z as z2 } from "zod/v4";
420
+ import { z as z7 } from "zod/v4";
227
421
  function registerSubgraphTools(server, clientProvider = getClient) {
228
422
  defineTool(server, "subgraphs_list", "List all deployed subgraphs. Returns summary fields only.", {}, async () => {
229
423
  const { data } = await clientProvider().subgraphs.list();
@@ -236,16 +430,16 @@ function registerSubgraphTools(server, clientProvider = getClient) {
236
430
  ]
237
431
  };
238
432
  });
239
- defineTool(server, "subgraphs_get", "Get full details of a subgraph including schema, health, and table columns.", { name: z2.string().describe("Subgraph name") }, async ({ name }) => {
433
+ defineTool(server, "subgraphs_get", "Get full details of a subgraph including schema, health, and table columns.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
240
434
  const detail = await clientProvider().subgraphs.get(name);
241
435
  return {
242
436
  content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
243
437
  };
244
438
  });
245
439
  defineTool(server, "subgraphs_spec", "Get generated API documentation for a subgraph. Defaults to compact agent schema; supports OpenAPI JSON and Markdown.", {
246
- name: z2.string().describe("Subgraph name"),
247
- format: z2.enum(["agent", "openapi", "markdown"]).optional().describe("Spec format to return. Defaults to agent."),
248
- serverUrl: z2.string().optional().describe("Override the server URL embedded in generated docs.")
440
+ name: z7.string().describe("Subgraph name"),
441
+ format: z7.enum(["agent", "openapi", "markdown"]).optional().describe("Spec format to return. Defaults to agent."),
442
+ serverUrl: z7.string().optional().describe("Override the server URL embedded in generated docs.")
249
443
  }, async ({ name, format = "agent", serverUrl }) => {
250
444
  const options = serverUrl ? { serverUrl } : undefined;
251
445
  const spec = format === "openapi" ? await clientProvider().subgraphs.openapi(name, options) : format === "markdown" ? await clientProvider().subgraphs.markdown(name, options) : await clientProvider().subgraphs.schema(name, options);
@@ -259,15 +453,15 @@ function registerSubgraphTools(server, clientProvider = getClient) {
259
453
  };
260
454
  });
261
455
  defineTool(server, "subgraphs_query", 'Query rows from a subgraph table (max 200 rows). Filters support operators: "amount.gte": "1000", "sender.neq": "SP...", "name.like": "%token%". Available operators: eq, neq, gt, gte, lt, lte, like.', {
262
- name: z2.string().describe("Subgraph name"),
263
- table: z2.string().describe("Table name"),
264
- filters: z2.record(z2.string(), z2.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
265
- sort: z2.string().optional().describe("Column to sort by"),
266
- order: z2.enum(["asc", "desc"]).optional().describe("Sort order"),
267
- limit: z2.number().max(200).optional().describe("Max rows (default 50, max 200)"),
268
- offset: z2.number().optional().describe("Offset for pagination"),
269
- fields: z2.string().optional().describe('Comma-separated column list to return (e.g. "sender,amount")'),
270
- count: z2.boolean().optional().describe("If true, return row count instead of rows")
456
+ name: z7.string().describe("Subgraph name"),
457
+ table: z7.string().describe("Table name"),
458
+ filters: z7.record(z7.string(), z7.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
459
+ sort: z7.string().optional().describe("Column to sort by"),
460
+ order: z7.enum(["asc", "desc"]).optional().describe("Sort order"),
461
+ limit: z7.number().max(200).optional().describe("Max rows (default 50, max 200)"),
462
+ offset: z7.number().optional().describe("Offset for pagination"),
463
+ fields: z7.string().optional().describe('Comma-separated column list to return (e.g. "sender,amount")'),
464
+ count: z7.boolean().optional().describe("If true, return row count instead of rows")
271
465
  }, async ({
272
466
  name,
273
467
  table,
@@ -300,9 +494,9 @@ function registerSubgraphTools(server, clientProvider = getClient) {
300
494
  };
301
495
  });
302
496
  defineTool(server, "subgraphs_reindex", "Reindex a subgraph from a specific block range.", {
303
- name: z2.string().describe("Subgraph name"),
304
- fromBlock: z2.number().optional().describe("Start block (defaults to beginning)"),
305
- toBlock: z2.number().optional().describe("End block (defaults to latest)")
497
+ name: z7.string().describe("Subgraph name"),
498
+ fromBlock: z7.number().optional().describe("Start block (defaults to beginning)"),
499
+ toBlock: z7.number().optional().describe("End block (defaults to latest)")
306
500
  }, async ({ name, fromBlock, toBlock }) => {
307
501
  const result = await clientProvider().subgraphs.reindex(name, {
308
502
  fromBlock,
@@ -312,13 +506,13 @@ function registerSubgraphTools(server, clientProvider = getClient) {
312
506
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
313
507
  };
314
508
  });
315
- defineTool(server, "subgraphs_delete", "Delete a subgraph permanently.", { name: z2.string().describe("Subgraph name") }, async ({ name }) => {
509
+ defineTool(server, "subgraphs_delete", "Delete a subgraph permanently.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
316
510
  const result = await clientProvider().subgraphs.delete(name);
317
511
  return { content: [{ type: "text", text: result.message }] };
318
512
  });
319
513
  defineTool(server, "subgraphs_deploy", "Deploy a subgraph from TypeScript code. Pass the full defineSubgraph() source — it will be bundled, validated, and deployed. Optional startBlock overrides the source definition for this deploy. Call `subgraphs_reindex` separately if you need a forced reindex.", {
320
- code: z2.string().describe("TypeScript source code containing a defineSubgraph() call"),
321
- startBlock: z2.number().int().nonnegative().optional().describe("Override the definition startBlock for this deploy")
514
+ code: z7.string().describe("TypeScript source code containing a defineSubgraph() call"),
515
+ startBlock: z7.number().int().nonnegative().optional().describe("Override the definition startBlock for this deploy")
322
516
  }, async ({ code, startBlock }) => {
323
517
  const bundled = await bundleSubgraphCode(code);
324
518
  const result = await clientProvider().subgraphs.deploy({
@@ -335,7 +529,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
335
529
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
336
530
  };
337
531
  });
338
- defineTool(server, "subgraphs_read_source", "Fetch the deployed TypeScript source of a subgraph (plus its stored version). Returns a readOnly payload for subgraphs deployed before source capture — in that case the caller should redeploy via CLI before editing.", { name: z2.string().describe("Subgraph name") }, async ({ name }) => {
532
+ defineTool(server, "subgraphs_read_source", "Fetch the deployed TypeScript source of a subgraph (plus its stored version). Returns a readOnly payload for subgraphs deployed before source capture — in that case the caller should redeploy via CLI before editing.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
339
533
  const source = await clientProvider().subgraphs.getSource(name);
340
534
  return {
341
535
  content: [{ type: "text", text: JSON.stringify(source, null, 2) }]
@@ -344,7 +538,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
344
538
  }
345
539
 
346
540
  // src/tools/subscriptions.ts
347
- import { z as z3 } from "zod/v4";
541
+ import { z as z8 } from "zod/v4";
348
542
  function registerSubscriptionTools(server, clientProvider = getClient) {
349
543
  defineTool(server, "subscriptions_list", "List all subscriptions for the current account. Returns summary fields (no secrets).", {}, async () => {
350
544
  const { data } = await clientProvider().subscriptions.list();
@@ -352,18 +546,18 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
352
546
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
353
547
  };
354
548
  });
355
- defineTool(server, "subscriptions_get", "Get full detail for a subscription (filter, auth, retry config, circuit state).", { id: z3.string().describe("Subscription id") }, async ({ id }) => {
549
+ defineTool(server, "subscriptions_get", "Get full detail for a subscription (filter, auth, retry config, circuit state).", { id: z8.string().describe("Subscription id") }, async ({ id }) => {
356
550
  const detail = await clientProvider().subscriptions.get(id);
357
551
  return {
358
552
  content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
359
553
  };
360
554
  });
361
555
  defineTool(server, "subscriptions_create", "Create a subscription. Returns `signingSecret` ONCE — forward it to the user so they can wire it into their receiver.", {
362
- name: z3.string().describe("Human-readable name, unique per account"),
363
- subgraphName: z3.string().describe("Subgraph to subscribe to"),
364
- tableName: z3.string().describe("Table within the subgraph"),
365
- url: z3.string().describe("Webhook URL"),
366
- format: z3.enum([
556
+ name: z8.string().describe("Human-readable name, unique per account"),
557
+ subgraphName: z8.string().describe("Subgraph to subscribe to"),
558
+ tableName: z8.string().describe("Table within the subgraph"),
559
+ url: z8.string().describe("Webhook URL"),
560
+ format: z8.enum([
367
561
  "standard-webhooks",
368
562
  "inngest",
369
563
  "trigger",
@@ -371,8 +565,8 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
371
565
  "cloudevents",
372
566
  "raw"
373
567
  ]).optional().describe("Wire format (default standard-webhooks)"),
374
- runtime: z3.enum(["inngest", "trigger", "cloudflare", "node"]).optional().describe("Receiver runtime label (display only)"),
375
- filter: z3.record(z3.string(), z3.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}')
568
+ runtime: z8.enum(["inngest", "trigger", "cloudflare", "node"]).optional().describe("Receiver runtime label (display only)"),
569
+ filter: z8.record(z8.string(), z8.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}')
376
570
  }, async (input) => {
377
571
  const res = await clientProvider().subscriptions.create(input);
378
572
  return {
@@ -380,10 +574,10 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
380
574
  };
381
575
  });
382
576
  defineTool(server, "subscriptions_update", "Patch a subscription (url, filter, format, runtime, retry, timeout, concurrency).", {
383
- id: z3.string(),
384
- url: z3.string().optional(),
385
- filter: z3.record(z3.string(), z3.unknown()).optional(),
386
- format: z3.enum([
577
+ id: z8.string(),
578
+ url: z8.string().optional(),
579
+ filter: z8.record(z8.string(), z8.unknown()).optional(),
580
+ format: z8.enum([
387
581
  "standard-webhooks",
388
582
  "inngest",
389
583
  "trigger",
@@ -391,44 +585,44 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
391
585
  "cloudevents",
392
586
  "raw"
393
587
  ]).optional(),
394
- runtime: z3.enum(["inngest", "trigger", "cloudflare", "node"]).nullable().optional(),
395
- maxRetries: z3.number().int().min(0).optional(),
396
- timeoutMs: z3.number().int().min(100).optional(),
397
- concurrency: z3.number().int().min(1).optional()
588
+ runtime: z8.enum(["inngest", "trigger", "cloudflare", "node"]).nullable().optional(),
589
+ maxRetries: z8.number().int().min(0).optional(),
590
+ timeoutMs: z8.number().int().min(100).optional(),
591
+ concurrency: z8.number().int().min(1).optional()
398
592
  }, async ({ id, ...patch }) => {
399
593
  const res = await clientProvider().subscriptions.update(id, patch);
400
594
  return {
401
595
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
402
596
  };
403
597
  });
404
- defineTool(server, "subscriptions_pause", "Pause a subscription. Pending rows remain queued until resumed.", { id: z3.string() }, async ({ id }) => {
598
+ defineTool(server, "subscriptions_pause", "Pause a subscription. Pending rows remain queued until resumed.", { id: z8.string() }, async ({ id }) => {
405
599
  const res = await clientProvider().subscriptions.pause(id);
406
600
  return {
407
601
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
408
602
  };
409
603
  });
410
- defineTool(server, "subscriptions_resume", "Resume a paused or circuit-open subscription and reset circuit failures.", { id: z3.string() }, async ({ id }) => {
604
+ defineTool(server, "subscriptions_resume", "Resume a paused or circuit-open subscription and reset circuit failures.", { id: z8.string() }, async ({ id }) => {
411
605
  const res = await clientProvider().subscriptions.resume(id);
412
606
  return {
413
607
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
414
608
  };
415
609
  });
416
- defineTool(server, "subscriptions_delete", "Delete a subscription. Pending outbox rows are cascade-deleted.", { id: z3.string() }, async ({ id }) => {
610
+ defineTool(server, "subscriptions_delete", "Delete a subscription. Pending outbox rows are cascade-deleted.", { id: z8.string() }, async ({ id }) => {
417
611
  const res = await clientProvider().subscriptions.delete(id);
418
612
  return {
419
613
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
420
614
  };
421
615
  });
422
- defineTool(server, "subscriptions_rotate_secret", "Rotate a subscription signing secret. Returns the new plaintext secret once.", { id: z3.string() }, async ({ id }) => {
616
+ defineTool(server, "subscriptions_rotate_secret", "Rotate a subscription signing secret. Returns the new plaintext secret once.", { id: z8.string() }, async ({ id }) => {
423
617
  const res = await clientProvider().subscriptions.rotateSecret(id);
424
618
  return {
425
619
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
426
620
  };
427
621
  });
428
622
  defineTool(server, "subscriptions_replay", "Replay a block range for a subscription. Replays run at 10% of batch capacity — use sparingly.", {
429
- id: z3.string(),
430
- fromBlock: z3.number().int().nonnegative(),
431
- toBlock: z3.number().int().nonnegative()
623
+ id: z8.string(),
624
+ fromBlock: z8.number().int().nonnegative(),
625
+ toBlock: z8.number().int().nonnegative()
432
626
  }, async ({ id, fromBlock, toBlock }) => {
433
627
  const res = await clientProvider().subscriptions.replay(id, {
434
628
  fromBlock,
@@ -438,22 +632,22 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
438
632
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
439
633
  };
440
634
  });
441
- defineTool(server, "subscriptions_dead", "Return the last 100 dead-letter outbox rows for a subscription.", { id: z3.string() }, async ({ id }) => {
635
+ defineTool(server, "subscriptions_dead", "Return the last 100 dead-letter outbox rows for a subscription.", { id: z8.string() }, async ({ id }) => {
442
636
  const { data } = await clientProvider().subscriptions.dead(id);
443
637
  return {
444
638
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
445
639
  };
446
640
  });
447
641
  defineTool(server, "subscriptions_requeue_dead", "Requeue one dead-letter outbox row for delivery retry.", {
448
- id: z3.string(),
449
- outboxId: z3.string()
642
+ id: z8.string(),
643
+ outboxId: z8.string()
450
644
  }, async ({ id, outboxId }) => {
451
645
  const res = await clientProvider().subscriptions.requeueDead(id, outboxId);
452
646
  return {
453
647
  content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
454
648
  };
455
649
  });
456
- defineTool(server, "subscriptions_recent_deliveries", "Return the last 100 delivery attempts (attempt #, status code, duration, truncated response).", { id: z3.string() }, async ({ id }) => {
650
+ defineTool(server, "subscriptions_recent_deliveries", "Return the last 100 delivery attempts (attempt #, status code, duration, truncated response).", { id: z8.string() }, async ({ id }) => {
457
651
  const { data } = await clientProvider().subscriptions.recentDeliveries(id);
458
652
  return {
459
653
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
@@ -473,6 +667,10 @@ function createServer() {
473
667
  registerSubgraphTools(server);
474
668
  registerSubscriptionTools(server);
475
669
  registerAccountTools(server);
670
+ registerDatasetTools(server);
671
+ registerIndexTools(server);
672
+ registerStreamsTools(server);
673
+ registerContractTools(server);
476
674
  registerResources(server);
477
675
  return server;
478
676
  }
@@ -480,5 +678,5 @@ export {
480
678
  createServer
481
679
  };
482
680
 
483
- //# debugId=0FFA87D2B4CA59E664756E2164756E21
681
+ //# debugId=BA0BE1DE0E196D9164756E2164756E21
484
682
  //# sourceMappingURL=index.js.map