@secondlayer/mcp 3.8.0 → 3.10.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 +6 -2
- package/dist/bin-http.js +252 -217
- package/dist/bin-http.js.map +10 -11
- package/dist/bin.js +252 -217
- package/dist/bin.js.map +10 -11
- package/dist/index.js +252 -217
- package/dist/index.js.map +10 -11
- package/package.json +5 -5
package/dist/bin.js
CHANGED
|
@@ -15,21 +15,49 @@ import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
|
|
|
15
15
|
import { TYPE_MAP } from "@secondlayer/subgraphs/schema";
|
|
16
16
|
|
|
17
17
|
// src/lib/client.ts
|
|
18
|
-
import { SecondLayer } from "@secondlayer/sdk";
|
|
18
|
+
import { SecondLayer, readX402Receipt, withX402 } from "@secondlayer/sdk";
|
|
19
|
+
import { privateKeyToAccount } from "@secondlayer/stacks/accounts";
|
|
19
20
|
var instance = null;
|
|
20
21
|
function readApiKey() {
|
|
21
22
|
return process.env.SL_API_KEY;
|
|
22
23
|
}
|
|
24
|
+
function buildFetchImpl() {
|
|
25
|
+
const key = process.env.X402_PRIVATE_KEY;
|
|
26
|
+
if (!key)
|
|
27
|
+
return;
|
|
28
|
+
const account = privateKeyToAccount(key);
|
|
29
|
+
const topUpUsd = Number(process.env.X402_TOPUP_USD ?? "");
|
|
30
|
+
const paid = withX402(fetch, {
|
|
31
|
+
account,
|
|
32
|
+
...Number.isFinite(topUpUsd) && topUpUsd > 0 ? {
|
|
33
|
+
topUp: {
|
|
34
|
+
usd: topUpUsd,
|
|
35
|
+
whenBelow: Number(process.env.X402_TOPUP_WHEN_BELOW ?? "0.5")
|
|
36
|
+
}
|
|
37
|
+
} : {}
|
|
38
|
+
});
|
|
39
|
+
const wrapped = async (input, init) => {
|
|
40
|
+
const res = await paid(input, init);
|
|
41
|
+
const receipt = readX402Receipt(res);
|
|
42
|
+
if (receipt) {
|
|
43
|
+
console.error(`[x402] paid call settled tier=${receipt.state ?? "confirmed"} txid=${receipt.txid}`);
|
|
44
|
+
}
|
|
45
|
+
return res;
|
|
46
|
+
};
|
|
47
|
+
return wrapped;
|
|
48
|
+
}
|
|
23
49
|
function getClient() {
|
|
24
50
|
if (!instance) {
|
|
25
51
|
const apiKey = readApiKey();
|
|
26
52
|
const baseUrl = process.env.SECONDLAYER_API_URL;
|
|
27
53
|
const dumpsBaseUrl = process.env.SL_STREAMS_DUMPS_URL;
|
|
54
|
+
const fetchImpl = buildFetchImpl();
|
|
28
55
|
instance = new SecondLayer({
|
|
29
56
|
...apiKey ? { apiKey } : {},
|
|
30
57
|
origin: "mcp",
|
|
31
58
|
...baseUrl ? { baseUrl } : {},
|
|
32
|
-
...dumpsBaseUrl ? { dumpsBaseUrl } : {}
|
|
59
|
+
...dumpsBaseUrl ? { dumpsBaseUrl } : {},
|
|
60
|
+
...fetchImpl ? { fetchImpl } : {}
|
|
33
61
|
});
|
|
34
62
|
}
|
|
35
63
|
return instance;
|
|
@@ -58,11 +86,14 @@ async function apiRequest(method, path, body) {
|
|
|
58
86
|
|
|
59
87
|
// src/lib/format.ts
|
|
60
88
|
function formatSubgraphSummary(s) {
|
|
89
|
+
const apiUrl = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
|
|
61
90
|
return {
|
|
62
91
|
name: s.name,
|
|
63
92
|
status: s.status,
|
|
64
93
|
tables: Array.isArray(s.tables) ? s.tables : Object.keys(s.tables),
|
|
65
|
-
lastProcessedBlock: s.lastProcessedBlock
|
|
94
|
+
lastProcessedBlock: s.lastProcessedBlock,
|
|
95
|
+
...s.visibility ? { visibility: s.visibility } : {},
|
|
96
|
+
...s.visibility === "public" ? { publicUrl: `${apiUrl}/v1/subgraphs/${s.name}` } : {}
|
|
66
97
|
};
|
|
67
98
|
}
|
|
68
99
|
function withCap(items, cap) {
|
|
@@ -167,7 +198,6 @@ var COLUMN_TYPES = [
|
|
|
167
198
|
}
|
|
168
199
|
];
|
|
169
200
|
var PRODUCT_BLURBS = {
|
|
170
|
-
datasets: "public foundation datasets",
|
|
171
201
|
index: "decoded L2 events, contract calls, blocks, transactions, stacking, mempool",
|
|
172
202
|
streams: "raw canonical chain event firehose",
|
|
173
203
|
contracts: "trait-based contract discovery",
|
|
@@ -178,7 +208,6 @@ var PRODUCT_BLURBS = {
|
|
|
178
208
|
scaffold: "generate typed contract clients from a deployment or ABI"
|
|
179
209
|
};
|
|
180
210
|
var PRODUCT_ORDER = [
|
|
181
|
-
"datasets",
|
|
182
211
|
"index",
|
|
183
212
|
"streams",
|
|
184
213
|
"contracts",
|
|
@@ -207,21 +236,30 @@ function buildCapabilities() {
|
|
|
207
236
|
});
|
|
208
237
|
return {
|
|
209
238
|
products,
|
|
210
|
-
discoverFirst: "Call
|
|
239
|
+
discoverFirst: "Call index_discover / contracts_find to learn what exists (and which filters each surface accepts) before querying."
|
|
211
240
|
};
|
|
212
241
|
}
|
|
242
|
+
var X402_CAPABILITY = {
|
|
243
|
+
what: "Index and Streams reads (/v1/index/*, /v1/streams/*) accept x402 v2 pay-per-call (network stacks:1, sponsored transfers — the payer holds sBTC/STX/USDCx, never gas). Index grants 1,000 free reads/day/IP before any 402; a paid Streams call opens a 500-call/1h PAYMENT-SESSION.",
|
|
244
|
+
paidWrites: "POST /v1/subgraphs (x402 $2) deploys a subgraph owned by the paying wallet — live from deploy, 7-day TTL, renewable via POST /v1/subgraphs/{name}/renew ($0.50/wk); claiming the account clears the expiry.",
|
|
245
|
+
prepaid: "POST /v1/x402/deposit?usd=N loads a prepaid tab (PAYMENT-BALANCE token, $0.25 min) — calls debit it instantly, no per-call on-chain settle. GET /v1/x402/balance reads it.",
|
|
246
|
+
discovery: "GET /v1/x402/supported on the API host for scheme, assets, prices, quotas, sessions, and prepaid metadata.",
|
|
247
|
+
autopay: "Set X402_PRIVATE_KEY (a Stacks private key holding an accepted token) and this MCP server pays 402 challenges automatically (sessions replayed). Add X402_TOPUP_USD (and optionally X402_TOPUP_WHEN_BELOW) for an autonomous prepaid tab that refills itself. Receipts are logged per paid call."
|
|
248
|
+
};
|
|
213
249
|
var READ_AUTH_TIERS = {
|
|
214
|
-
datasets: "open — no API key required",
|
|
215
250
|
index: "anonymous reads allowed; free-tier API keys are rejected (Build+ required)",
|
|
216
251
|
streams: "API key required (SL_API_KEY) — keyless calls return 401",
|
|
217
|
-
subgraphs: "
|
|
252
|
+
subgraphs: "public subgraphs anon-readable at /v1/subgraphs/<name>/<table> ({ rows, next_cursor, tip } cursor envelope); private subgraphs need the owning account's API key (anon → 404); writes require an API key"
|
|
218
253
|
};
|
|
219
254
|
async function buildContext(deps = { clientProvider: getClient }) {
|
|
220
255
|
const unavailable = "unavailable: set SL_API_KEY";
|
|
221
256
|
const orNull = (v) => v == null ? unavailable : v;
|
|
222
257
|
const snap = await deps.clientProvider().context().catch(() => null);
|
|
223
258
|
return {
|
|
224
|
-
authState: {
|
|
259
|
+
authState: {
|
|
260
|
+
apiKeySet: Boolean(process.env.SL_API_KEY),
|
|
261
|
+
x402WalletSet: Boolean(process.env.X402_PRIVATE_KEY)
|
|
262
|
+
},
|
|
225
263
|
whatExists: {
|
|
226
264
|
account: orNull(snap?.account),
|
|
227
265
|
streamsTip: orNull(snap?.streamsTip),
|
|
@@ -233,7 +271,8 @@ async function buildContext(deps = { clientProvider: getClient }) {
|
|
|
233
271
|
activeOperations: orNull(snap?.activeOperations)
|
|
234
272
|
},
|
|
235
273
|
whatYouCanDo: buildCapabilities(),
|
|
236
|
-
readAuthTiers: READ_AUTH_TIERS
|
|
274
|
+
readAuthTiers: READ_AUTH_TIERS,
|
|
275
|
+
payPerCall: X402_CAPABILITY
|
|
237
276
|
};
|
|
238
277
|
}
|
|
239
278
|
function registerResources(server) {
|
|
@@ -421,43 +460,20 @@ function registerContractTools(server, clientProvider = getClient) {
|
|
|
421
460
|
});
|
|
422
461
|
}
|
|
423
462
|
|
|
424
|
-
// src/tools/datasets.ts
|
|
425
|
-
import { z as z3 } from "zod/v4";
|
|
426
|
-
function registerDatasetTools(server, clientProvider = getClient) {
|
|
427
|
-
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 () => {
|
|
428
|
-
const catalog = await clientProvider().datasets.listDatasets();
|
|
429
|
-
return jsonResponse(catalog);
|
|
430
|
-
});
|
|
431
|
-
defineTool(server, "datasets_query", 'Query ANY Foundation Dataset by slug — every family returned by datasets_list is queryable, including bespoke ones (bns/resolve with {"fqn":"alice.btc"}, bns/names, bns/namespaces, network-health/summary) and any dataset added later. Accepts family ("sbtc-events") or path ("sbtc/events") slug forms. Filters are passed through as documented query params (e.g. {"sender": "SP...", "from_block": "150000"}). Returns { rows, next_cursor, tip }; single-record datasets like bns/resolve return 0-or-1 rows (empty = not found). Call datasets_list first to discover slugs and their filters.', {
|
|
432
|
-
slug: z3.string().describe("Dataset slug from datasets_list (e.g. stx-transfers)"),
|
|
433
|
-
filters: z3.record(z3.string(), z3.string()).optional().describe("Documented per-dataset query params (snake_case values)"),
|
|
434
|
-
limit: z3.number().optional().describe("Max rows for this page"),
|
|
435
|
-
cursor: z3.string().optional().describe("Opaque cursor from a prior response's next_cursor")
|
|
436
|
-
}, async ({ slug, filters, limit, cursor }) => {
|
|
437
|
-
const params = { ...filters ?? {} };
|
|
438
|
-
if (limit !== undefined)
|
|
439
|
-
params.limit = limit;
|
|
440
|
-
if (cursor !== undefined)
|
|
441
|
-
params.cursor = cursor;
|
|
442
|
-
const result = await clientProvider().datasets.get(slug, params);
|
|
443
|
-
return jsonResponse(result);
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
|
|
447
463
|
// src/tools/index.ts
|
|
448
464
|
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES2 } from "@secondlayer/shared";
|
|
449
465
|
import {
|
|
450
466
|
INDEX_CODEGEN_TABLES,
|
|
451
467
|
generateIndexSchema
|
|
452
468
|
} from "@secondlayer/subgraphs";
|
|
453
|
-
import { z as
|
|
469
|
+
import { z as z3 } from "zod/v4";
|
|
454
470
|
var INDEX_EVENT_TYPES = DECODED_EVENT_TYPES2;
|
|
455
471
|
var rangeFilters = {
|
|
456
|
-
contractId:
|
|
457
|
-
fromHeight:
|
|
458
|
-
toHeight:
|
|
459
|
-
cursor:
|
|
460
|
-
limit:
|
|
472
|
+
contractId: z3.string().optional().describe("Filter by contract id"),
|
|
473
|
+
fromHeight: z3.number().optional().describe("Start block height (inclusive)"),
|
|
474
|
+
toHeight: z3.number().optional().describe("End block height (inclusive)"),
|
|
475
|
+
cursor: z3.string().optional().describe("Opaque cursor from a prior response's next_cursor"),
|
|
476
|
+
limit: z3.number().optional().describe("Max rows for this page")
|
|
461
477
|
};
|
|
462
478
|
var heightFilters = {
|
|
463
479
|
fromHeight: rangeFilters.fromHeight,
|
|
@@ -469,89 +485,95 @@ var notFound = (message) => jsonResponse({ error: { type: "not_found", status: 4
|
|
|
469
485
|
function registerIndexTools(server, clientProvider = getClient) {
|
|
470
486
|
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).", {
|
|
471
487
|
...rangeFilters,
|
|
472
|
-
sender:
|
|
473
|
-
recipient:
|
|
488
|
+
sender: z3.string().optional().describe("Filter by sender principal"),
|
|
489
|
+
recipient: z3.string().optional().describe("Filter by recipient principal")
|
|
474
490
|
}, async (params) => jsonResponse(await clientProvider().index.ftTransfers.list(params)));
|
|
475
491
|
defineTool(server, "index_nft_transfers", "List decoded SIP-009 non-fungible-token transfers from the Index. Anonymous reads allowed (free-tier keys rejected).", {
|
|
476
492
|
...rangeFilters,
|
|
477
|
-
sender:
|
|
478
|
-
recipient:
|
|
479
|
-
assetIdentifier:
|
|
493
|
+
sender: z3.string().optional().describe("Filter by sender principal"),
|
|
494
|
+
recipient: z3.string().optional().describe("Filter by recipient principal"),
|
|
495
|
+
assetIdentifier: z3.string().optional().describe("Filter by asset identifier (contract::asset)")
|
|
480
496
|
}, async (params) => jsonResponse(await clientProvider().index.nftTransfers.list(params)));
|
|
481
497
|
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), and for trait-scoped queries: set `trait` (e.g. sip-010) to match all contracts conforming to a standard — pair with contracts_find to discover traits. For ft/nft transfers without a trait prefer index_ft_transfers / index_nft_transfers.", {
|
|
482
|
-
eventType:
|
|
498
|
+
eventType: z3.enum(INDEX_EVENT_TYPES).describe("Required. Decoded event type to list."),
|
|
483
499
|
...rangeFilters,
|
|
484
|
-
sender:
|
|
485
|
-
recipient:
|
|
486
|
-
assetIdentifier:
|
|
487
|
-
trait:
|
|
500
|
+
sender: z3.string().optional().describe("Filter by sender principal"),
|
|
501
|
+
recipient: z3.string().optional().describe("Filter by recipient principal"),
|
|
502
|
+
assetIdentifier: z3.string().optional().describe("Filter by asset identifier where applicable"),
|
|
503
|
+
trait: z3.string().optional().describe("Match contracts conforming to a trait/standard (e.g. sip-010). Mutually exclusive with contractId; contract-keyed event types only.")
|
|
488
504
|
}, async (params) => jsonResponse(await clientProvider().index.events.list(params)));
|
|
489
505
|
defineTool(server, "index_contract_calls", "List decoded contract calls from the Index (function name, args, result). Set `trait` (e.g. sip-010) to match calls to all contracts conforming to a standard. Note: contract-call cursors are a SEPARATE keyspace from event cursors — they are not interchangeable.", {
|
|
490
506
|
...rangeFilters,
|
|
491
|
-
functionName:
|
|
492
|
-
sender:
|
|
493
|
-
trait:
|
|
507
|
+
functionName: z3.string().optional().describe("Filter by called function name"),
|
|
508
|
+
sender: z3.string().optional().describe("Filter by caller principal"),
|
|
509
|
+
trait: z3.string().optional().describe("Match contracts conforming to a trait/standard (e.g. sip-010). Mutually exclusive with contractId.")
|
|
494
510
|
}, async (params) => jsonResponse(await clientProvider().index.contractCalls.list(params)));
|
|
495
511
|
defineTool(server, "index_canonical", "List the canonical Stacks block sequence from the Index (height + hash). Anonymous reads allowed (free-tier keys rejected).", { ...heightFilters }, async (params) => jsonResponse(await clientProvider().index.canonical.list(params)));
|
|
496
512
|
defineTool(server, "index_blocks", "List decoded blocks from the Index. Anonymous reads allowed (free-tier keys rejected).", { ...heightFilters }, async (params) => jsonResponse(await clientProvider().index.blocks.list(params)));
|
|
497
513
|
defineTool(server, "index_block", "Get a single block from the Index by height or block hash. Returns not_found if unknown.", {
|
|
498
|
-
ref:
|
|
514
|
+
ref: z3.string().describe("Block height (digits) or block hash (0x… string)")
|
|
499
515
|
}, async ({ ref }) => {
|
|
500
516
|
const block = await clientProvider().index.blocks.get(/^\d+$/.test(ref) ? Number(ref) : ref);
|
|
501
517
|
return block ? jsonResponse(block) : notFound(`No block for ref ${ref}`);
|
|
502
518
|
});
|
|
503
519
|
defineTool(server, "index_transactions", "List decoded transactions from the Index. Filter by type, sender, or contract. Anonymous reads allowed (free-tier keys rejected).", {
|
|
504
520
|
...rangeFilters,
|
|
505
|
-
type:
|
|
506
|
-
sender:
|
|
521
|
+
type: z3.string().optional().describe("Filter by transaction type"),
|
|
522
|
+
sender: z3.string().optional().describe("Filter by sender principal")
|
|
507
523
|
}, async (params) => jsonResponse(await clientProvider().index.transactions.list(params)));
|
|
508
|
-
defineTool(server, "index_transaction", "Get a single transaction from the Index by tx_id. Returns not_found if unknown.", { txId:
|
|
524
|
+
defineTool(server, "index_transaction", "Get a single transaction from the Index by tx_id. Returns not_found if unknown.", { txId: z3.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
509
525
|
const tx = await clientProvider().index.transactions.get(txId);
|
|
510
526
|
return tx ? jsonResponse(tx) : notFound(`No transaction for ${txId}`);
|
|
511
527
|
});
|
|
512
|
-
defineTool(server, "index_transaction_proof", "Fetch a transaction's inclusion proof (raw tx + signed Nakamoto block header + merkle path) so it can be verified trustlessly client-side with the SDK's verifyTransactionProof. Returns not_found if the tx/block is unknown; a 503 means the proof can't be assembled on this deployment right now (PROOF_TX_SET_INCOMPLETE, or PROOF_NODE_UNAVAILABLE when the stacks-node header source isn't configured).", { txId:
|
|
528
|
+
defineTool(server, "index_transaction_proof", "Fetch a transaction's inclusion proof (raw tx + signed Nakamoto block header + merkle path) so it can be verified trustlessly client-side with the SDK's verifyTransactionProof. Returns not_found if the tx/block is unknown; a 503 means the proof can't be assembled on this deployment right now (PROOF_TX_SET_INCOMPLETE, or PROOF_NODE_UNAVAILABLE when the stacks-node header source isn't configured).", { txId: z3.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
513
529
|
const proof = await clientProvider().index.transactions.getProof(txId);
|
|
514
530
|
return proof ? jsonResponse(proof) : notFound(`No proof available for ${txId}`);
|
|
515
531
|
});
|
|
516
532
|
defineTool(server, "index_stacking", "List decoded PoX-4 stacking actions from the Index (stack-stx, delegate-stx, etc.). Anonymous reads allowed (free-tier keys rejected).", {
|
|
517
533
|
...heightFilters,
|
|
518
|
-
functionName:
|
|
519
|
-
stacker:
|
|
520
|
-
caller:
|
|
534
|
+
functionName: z3.string().optional().describe("Filter by PoX function name"),
|
|
535
|
+
stacker: z3.string().optional().describe("Filter by stacker principal"),
|
|
536
|
+
caller: z3.string().optional().describe("Filter by caller principal")
|
|
521
537
|
}, async (params) => jsonResponse(await clientProvider().index.stacking.list(params)));
|
|
522
538
|
defineTool(server, "index_mempool", "List pending (unconfirmed) transactions from the Index mempool. Sequence-cursor paginated (no height range). Anonymous reads allowed (free-tier keys rejected).", {
|
|
523
|
-
sender:
|
|
524
|
-
type:
|
|
525
|
-
contractId:
|
|
526
|
-
cursor:
|
|
527
|
-
limit:
|
|
539
|
+
sender: z3.string().optional().describe("Filter by sender principal"),
|
|
540
|
+
type: z3.string().optional().describe("Filter by transaction type"),
|
|
541
|
+
contractId: z3.string().optional().describe("Filter to pending calls to a single contract"),
|
|
542
|
+
cursor: z3.string().optional().describe("Opaque cursor from a prior response's next_cursor"),
|
|
543
|
+
limit: z3.number().optional().describe("Max rows for this page")
|
|
528
544
|
}, async (params) => jsonResponse(await clientProvider().index.mempool.list(params)));
|
|
529
|
-
defineTool(server, "index_mempool_tx", "Get a single pending transaction from the Index mempool by tx_id. Returns not_found once it is mined or dropped.", { txId:
|
|
545
|
+
defineTool(server, "index_mempool_tx", "Get a single pending transaction from the Index mempool by tx_id. Returns not_found once it is mined or dropped.", { txId: z3.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
530
546
|
const tx = await clientProvider().index.mempool.get(txId);
|
|
531
547
|
return tx ? jsonResponse(tx) : notFound(`No pending tx for ${txId}`);
|
|
532
548
|
});
|
|
533
549
|
defineTool(server, "index_discover", "Discover the Index vocabulary: every event type and its columns, allowed/equality filters, and required-non-null fields (and which types accept `trait`). Read this before building Index queries instead of guessing filters. Anonymous read.", {}, async () => jsonResponse(await clientProvider().index.discover()));
|
|
534
550
|
defineTool(server, "index_usage", "Your own Index consumption (decoded events today + this month) and tier limits. Requires a Build+ API key (anonymous reads can't report usage).", {}, async () => jsonResponse(await clientProvider().index.usage()));
|
|
535
551
|
defineTool(server, "index_codegen", `Generate a typed schema (Prisma, Kysely, Drizzle, or JSON-Schema) for the public Index domain tables so they can be mirrored into a BYO database with full types. Returns the schema as text. Tables: ${INDEX_CODEGEN_TABLES.join(", ")}.`, {
|
|
536
|
-
target:
|
|
537
|
-
tables:
|
|
538
|
-
schemaName:
|
|
552
|
+
target: z3.enum(["prisma", "kysely", "drizzle", "json-schema"]).optional().describe("Output target (default kysely)"),
|
|
553
|
+
tables: z3.array(z3.string()).optional().describe("Subset of Index tables (default: all)"),
|
|
554
|
+
schemaName: z3.string().optional().describe("Postgres schema to qualify table names with")
|
|
539
555
|
}, async ({ target = "kysely", tables, schemaName }) => {
|
|
540
556
|
const out = generateIndexSchema(target, { tables, schemaName });
|
|
541
557
|
return { content: [{ type: "text", text: out }] };
|
|
542
558
|
});
|
|
559
|
+
defineTool(server, "batch_query", "Run up to 10 public /v1 reads in one round trip (POST /v1/batch). Each item keeps its own auth/quota/pay-per-call semantics; results return in order with per-item status. Paths must start with /v1/index, /v1/subgraphs, /v1/streams, or /v1/contracts.", {
|
|
560
|
+
requests: z3.array(z3.object({
|
|
561
|
+
path: z3.string().describe("Public /v1 read path"),
|
|
562
|
+
params: z3.record(z3.string(), z3.string()).optional()
|
|
563
|
+
})).min(1).max(10).describe("Read descriptors, executed concurrently")
|
|
564
|
+
}, async (params) => jsonResponse(await clientProvider().batch(params.requests)));
|
|
543
565
|
}
|
|
544
566
|
|
|
545
567
|
// src/tools/projects.ts
|
|
546
|
-
import { z as
|
|
568
|
+
import { z as z4 } from "zod/v4";
|
|
547
569
|
function registerProjectTools(server, clientProvider = getClient) {
|
|
548
570
|
defineTool(server, "project_list", "List the account's projects. Requires an account-level (owner) API key.", {}, async () => jsonResponse(await clientProvider().projects.list()));
|
|
549
|
-
defineTool(server, "project_get", "Get a single project by slug.", { slug:
|
|
571
|
+
defineTool(server, "project_get", "Get a single project by slug.", { slug: z4.string().describe("Project slug") }, async ({ slug }) => jsonResponse(await clientProvider().projects.get(slug)));
|
|
550
572
|
defineTool(server, "project_create", "Create a project. The slug is derived from the name when omitted. Requires an account-level (owner) API key.", {
|
|
551
|
-
name:
|
|
552
|
-
slug:
|
|
553
|
-
network:
|
|
554
|
-
nodeRpc:
|
|
573
|
+
name: z4.string().describe("Project name"),
|
|
574
|
+
slug: z4.string().optional().describe("URL slug (auto-derived from name if omitted)"),
|
|
575
|
+
network: z4.string().optional().describe("Network (e.g. mainnet, testnet)"),
|
|
576
|
+
nodeRpc: z4.string().optional().describe("Custom node RPC URL")
|
|
555
577
|
}, async ({ name, slug, network, nodeRpc }) => jsonResponse(await clientProvider().projects.create({
|
|
556
578
|
name,
|
|
557
579
|
slug,
|
|
@@ -559,12 +581,12 @@ function registerProjectTools(server, clientProvider = getClient) {
|
|
|
559
581
|
nodeRpc
|
|
560
582
|
})));
|
|
561
583
|
defineTool(server, "project_update", "Update a project. `slug` selects the project; `newSlug` renames it. Requires an account-level (owner) API key.", {
|
|
562
|
-
slug:
|
|
563
|
-
newSlug:
|
|
564
|
-
name:
|
|
565
|
-
network:
|
|
566
|
-
nodeRpc:
|
|
567
|
-
settings:
|
|
584
|
+
slug: z4.string().describe("Slug of the project to update"),
|
|
585
|
+
newSlug: z4.string().optional().describe("New slug (renames the project)"),
|
|
586
|
+
name: z4.string().optional().describe("New display name"),
|
|
587
|
+
network: z4.string().optional().describe("Network (e.g. mainnet, testnet)"),
|
|
588
|
+
nodeRpc: z4.string().optional().describe("Custom node RPC URL"),
|
|
589
|
+
settings: z4.record(z4.string(), z4.unknown()).optional().describe("Arbitrary project settings to merge")
|
|
568
590
|
}, async ({ slug, newSlug, name, network, nodeRpc, settings }) => jsonResponse(await clientProvider().projects.update(slug, {
|
|
569
591
|
...newSlug !== undefined ? { slug: newSlug } : {},
|
|
570
592
|
...name !== undefined ? { name } : {},
|
|
@@ -572,8 +594,8 @@ function registerProjectTools(server, clientProvider = getClient) {
|
|
|
572
594
|
...nodeRpc !== undefined ? { nodeRpc } : {},
|
|
573
595
|
...settings !== undefined ? { settings } : {}
|
|
574
596
|
})));
|
|
575
|
-
defineTool(server, "project_delete", "Delete a project permanently. The account's last remaining project cannot be deleted.", { slug:
|
|
576
|
-
defineTool(server, "project_team_list", "List a project's team members and pending invitations.", { slug:
|
|
597
|
+
defineTool(server, "project_delete", "Delete a project permanently. The account's last remaining project cannot be deleted.", { slug: z4.string().describe("Project slug") }, async ({ slug }) => jsonResponse(await clientProvider().projects.delete(slug)));
|
|
598
|
+
defineTool(server, "project_team_list", "List a project's team members and pending invitations.", { slug: z4.string().describe("Project slug") }, async ({ slug }) => jsonResponse(await clientProvider().projects.team(slug)));
|
|
577
599
|
}
|
|
578
600
|
|
|
579
601
|
// src/tools/scaffold.ts
|
|
@@ -582,7 +604,7 @@ import {
|
|
|
582
604
|
generateTraitSubgraph
|
|
583
605
|
} from "@secondlayer/scaffold";
|
|
584
606
|
import { TRAIT_STANDARDS as TRAIT_STANDARDS2 } from "@secondlayer/stacks/clarity";
|
|
585
|
-
import { z as
|
|
607
|
+
import { z as z5 } from "zod/v4";
|
|
586
608
|
async function fetchAbi(contractId) {
|
|
587
609
|
const contract = await getClient().contracts.get(contractId, {
|
|
588
610
|
includeAbi: true
|
|
@@ -597,24 +619,24 @@ async function fetchAbi(contractId) {
|
|
|
597
619
|
}
|
|
598
620
|
function registerScaffoldTools(server) {
|
|
599
621
|
defineTool(server, "scaffold_from_trait", "Generate a deploy-ready subgraph scaffold that indexes EVERY contract conforming to a SIP trait (no specific contract needed) — sip-009 → an nft_transfer source, sip-010/sip-013 → ft_transfer. Use scaffold_from_contract/abi instead when targeting one contract. See the secondlayer://traits resource for valid trait ids.", {
|
|
600
|
-
trait:
|
|
601
|
-
subgraphName:
|
|
622
|
+
trait: z5.enum(TRAIT_STANDARDS2).describe("SIP standard to index (sip-009 | sip-010 | sip-013)"),
|
|
623
|
+
subgraphName: z5.string().optional().describe("Override the subgraph name (defaults to <trait>-transfers)")
|
|
602
624
|
}, async ({ trait, subgraphName }) => {
|
|
603
625
|
const code = generateTraitSubgraph({ trait, name: subgraphName });
|
|
604
626
|
return { content: [{ type: "text", text: code }] };
|
|
605
627
|
});
|
|
606
628
|
defineTool(server, "scaffold_from_contract", "Generate a subgraph scaffold from a deployed Stacks contract. Fetches the ABI automatically.", {
|
|
607
|
-
contractId:
|
|
608
|
-
subgraphName:
|
|
629
|
+
contractId: z5.string().describe("Fully qualified contract ID (e.g. SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01)"),
|
|
630
|
+
subgraphName: z5.string().optional().describe("Override the subgraph name (defaults to contract name)")
|
|
609
631
|
}, async ({ contractId, subgraphName }) => {
|
|
610
632
|
const { functions, maps } = await fetchAbi(contractId);
|
|
611
633
|
const code = generateSubgraphCode(contractId, functions, subgraphName, maps);
|
|
612
634
|
return { content: [{ type: "text", text: code }] };
|
|
613
635
|
});
|
|
614
636
|
defineTool(server, "scaffold_from_abi", "Generate a subgraph scaffold from a provided ABI JSON. Use when you already have the ABI.", {
|
|
615
|
-
abi:
|
|
616
|
-
contractId:
|
|
617
|
-
subgraphName:
|
|
637
|
+
abi: z5.string().describe("ABI JSON string (the full contract ABI object)"),
|
|
638
|
+
contractId: z5.string().describe("Fully qualified contract ID"),
|
|
639
|
+
subgraphName: z5.string().optional().describe("Override the subgraph name")
|
|
618
640
|
}, async ({ abi, contractId, subgraphName }) => {
|
|
619
641
|
let parsed;
|
|
620
642
|
try {
|
|
@@ -633,7 +655,7 @@ function registerScaffoldTools(server) {
|
|
|
633
655
|
// src/tools/streams.ts
|
|
634
656
|
import { AuthError } from "@secondlayer/sdk";
|
|
635
657
|
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES3 } from "@secondlayer/shared";
|
|
636
|
-
import { z as
|
|
658
|
+
import { z as z6 } from "zod/v4";
|
|
637
659
|
var STREAMS_EVENT_TYPES = DECODED_EVENT_TYPES3;
|
|
638
660
|
async function withStreamsAuthHint(fn) {
|
|
639
661
|
try {
|
|
@@ -648,28 +670,28 @@ async function withStreamsAuthHint(fn) {
|
|
|
648
670
|
function registerStreamsTools(server, clientProvider = getClient) {
|
|
649
671
|
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())));
|
|
650
672
|
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.", {
|
|
651
|
-
types:
|
|
652
|
-
notTypes:
|
|
653
|
-
contractId:
|
|
654
|
-
sender:
|
|
655
|
-
recipient:
|
|
656
|
-
assetIdentifier:
|
|
657
|
-
fromHeight:
|
|
658
|
-
toHeight:
|
|
659
|
-
cursor:
|
|
660
|
-
limit:
|
|
673
|
+
types: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to include"),
|
|
674
|
+
notTypes: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to exclude (applied after types)"),
|
|
675
|
+
contractId: z6.string().optional().describe("Filter by contract id"),
|
|
676
|
+
sender: z6.string().optional().describe("Filter by sender principal"),
|
|
677
|
+
recipient: z6.string().optional().describe("Filter by recipient principal"),
|
|
678
|
+
assetIdentifier: z6.string().optional().describe("Filter by asset identifier"),
|
|
679
|
+
fromHeight: z6.number().optional().describe("Start block height (inclusive)"),
|
|
680
|
+
toHeight: z6.number().optional().describe("End block height (inclusive)"),
|
|
681
|
+
cursor: z6.string().optional().describe("Opaque cursor from a prior response"),
|
|
682
|
+
limit: z6.number().optional().describe("Max events for this page")
|
|
661
683
|
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.events.list(params))));
|
|
662
684
|
defineTool(server, "streams_consume", "Consume a bounded, reorg-aware run of Streams events from a cursor. Walks up to maxPages pages and returns the events, any reorgs observed, and a resume `cursor` to pass back as fromCursor next call — the agent-native consume/resume primitive. Streams requires an API key (SL_API_KEY).", {
|
|
663
|
-
fromCursor:
|
|
664
|
-
types:
|
|
665
|
-
notTypes:
|
|
666
|
-
contractId:
|
|
667
|
-
sender:
|
|
668
|
-
recipient:
|
|
669
|
-
assetIdentifier:
|
|
670
|
-
batchSize:
|
|
671
|
-
maxPages:
|
|
672
|
-
finalizedOnly:
|
|
685
|
+
fromCursor: z6.string().optional().describe("Resume cursor from a prior consume (omit to start at genesis)"),
|
|
686
|
+
types: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to include"),
|
|
687
|
+
notTypes: z6.array(z6.enum(STREAMS_EVENT_TYPES)).optional().describe("Event types to exclude"),
|
|
688
|
+
contractId: z6.string().optional().describe("Filter by contract id"),
|
|
689
|
+
sender: z6.string().optional().describe("Filter by sender principal"),
|
|
690
|
+
recipient: z6.string().optional().describe("Filter by recipient principal"),
|
|
691
|
+
assetIdentifier: z6.string().optional().describe("Filter by asset identifier"),
|
|
692
|
+
batchSize: z6.number().optional().describe("Events per page (1–1000, default 100)"),
|
|
693
|
+
maxPages: z6.number().optional().describe("Max pages to walk this call (1–20, default 5)"),
|
|
694
|
+
finalizedOnly: z6.boolean().optional().describe("Only emit finalized events; skip reorg handling")
|
|
673
695
|
}, async (params) => withStreamsAuthHint(async () => {
|
|
674
696
|
const maxPages = Math.min(Math.max(params.maxPages ?? 5, 1), 20);
|
|
675
697
|
const batchSize = Math.min(Math.max(params.batchSize ?? 100, 1), 1000);
|
|
@@ -701,15 +723,15 @@ function registerStreamsTools(server, clientProvider = getClient) {
|
|
|
701
723
|
pages: result.pages
|
|
702
724
|
});
|
|
703
725
|
}));
|
|
704
|
-
defineTool(server, "streams_event_by_txid", "List all Streams events emitted by a single transaction. Streams requires an API key (SL_API_KEY).", { txId:
|
|
726
|
+
defineTool(server, "streams_event_by_txid", "List all Streams events emitted by a single transaction. Streams requires an API key (SL_API_KEY).", { txId: z6.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.events.byTxId(txId))));
|
|
705
727
|
defineTool(server, "streams_block_events", "List all Streams events in a single block, by height or block hash. Streams requires an API key (SL_API_KEY).", {
|
|
706
|
-
heightOrHash:
|
|
728
|
+
heightOrHash: z6.string().describe("Block height (digits) or block hash (0x… string)")
|
|
707
729
|
}, async ({ heightOrHash }) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.blocks.events(/^\d+$/.test(heightOrHash) ? Number(heightOrHash) : heightOrHash))));
|
|
708
730
|
defineTool(server, "streams_reorgs", "List chain reorgs observed by Streams since a cursor. Streams requires an API key (SL_API_KEY).", {
|
|
709
|
-
since:
|
|
710
|
-
limit:
|
|
731
|
+
since: z6.string().describe("Cursor to list reorgs since (block:index or ISO timestamp)"),
|
|
732
|
+
limit: z6.number().optional().describe("Max reorgs to return")
|
|
711
733
|
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.reorgs.list(params))));
|
|
712
|
-
defineTool(server, "streams_canonical", "Get the canonical block at a given height from Streams (height + hashes + is_canonical). Streams requires an API key (SL_API_KEY).", { height:
|
|
734
|
+
defineTool(server, "streams_canonical", "Get the canonical block at a given height from Streams (height + hashes + is_canonical). Streams requires an API key (SL_API_KEY).", { height: z6.number().describe("Block height") }, async ({ height }) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.canonical(height))));
|
|
713
735
|
defineTool(server, "streams_usage", "Your own Streams consumption (events today + this month) and tier limits (rate limit, retention). Streams requires an API key (SL_API_KEY).", {}, async () => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.usage())));
|
|
714
736
|
defineTool(server, "streams_dumps", "List the Streams bulk parquet dumps manifest — coverage range, latest_finalized_cursor, and per-file metadata (block range, row count, size, sha256, signed URL). This is the cold backfill path for downloading all raw data; fetch the file URLs directly (e.g. with DuckDB). Requires the dumps base URL to be configured (SL_STREAMS_DUMPS_URL).", {}, async () => jsonResponse(await clientProvider().streams.dumps.list()));
|
|
715
737
|
}
|
|
@@ -722,9 +744,9 @@ import {
|
|
|
722
744
|
generateKyselySchema,
|
|
723
745
|
generatePrismaSchema
|
|
724
746
|
} from "@secondlayer/subgraphs";
|
|
725
|
-
import { z as
|
|
747
|
+
import { z as z7 } from "zod/v4";
|
|
726
748
|
function registerSubgraphTools(server, clientProvider = getClient) {
|
|
727
|
-
defineTool(server, "subgraphs_list", "List all deployed subgraphs. Returns summary fields only
|
|
749
|
+
defineTool(server, "subgraphs_list", "List all deployed subgraphs. Returns summary fields only, including visibility — public subgraphs are anon-readable at /v1/subgraphs/<name>.", {}, async () => {
|
|
728
750
|
const { data } = await clientProvider().subgraphs.list();
|
|
729
751
|
return {
|
|
730
752
|
content: [
|
|
@@ -735,16 +757,16 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
735
757
|
]
|
|
736
758
|
};
|
|
737
759
|
});
|
|
738
|
-
defineTool(server, "subgraphs_get", "Get full details of a subgraph including schema, health, and table columns.", { name:
|
|
760
|
+
defineTool(server, "subgraphs_get", "Get full details of a subgraph including schema, health, and table columns.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
739
761
|
const detail = await clientProvider().subgraphs.get(name);
|
|
740
762
|
return {
|
|
741
763
|
content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
|
|
742
764
|
};
|
|
743
765
|
});
|
|
744
766
|
defineTool(server, "subgraphs_spec", "Get generated API documentation for a subgraph. Defaults to compact agent schema; supports OpenAPI JSON and Markdown.", {
|
|
745
|
-
name:
|
|
746
|
-
format:
|
|
747
|
-
serverUrl:
|
|
767
|
+
name: z7.string().describe("Subgraph name"),
|
|
768
|
+
format: z7.enum(["agent", "openapi", "markdown"]).optional().describe("Spec format to return. Defaults to agent."),
|
|
769
|
+
serverUrl: z7.string().optional().describe("Override the server URL embedded in generated docs.")
|
|
748
770
|
}, async ({ name, format = "agent", serverUrl }) => {
|
|
749
771
|
const options = serverUrl ? { serverUrl } : undefined;
|
|
750
772
|
const spec = format === "openapi" ? await clientProvider().subgraphs.openapi(name, options) : format === "markdown" ? await clientProvider().subgraphs.markdown(name, options) : await clientProvider().subgraphs.schema(name, options);
|
|
@@ -757,16 +779,16 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
757
779
|
]
|
|
758
780
|
};
|
|
759
781
|
});
|
|
760
|
-
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. To TAIL new rows (no streaming over MCP): sort=_id, order=desc for the latest, then poll forward with the filter {"_id.gt": "<last _id seen>"}, order=asc. Fetch one row by id with {"_id": "<id>"}.', {
|
|
761
|
-
name:
|
|
762
|
-
table:
|
|
763
|
-
filters:
|
|
764
|
-
sort:
|
|
765
|
-
order:
|
|
766
|
-
limit:
|
|
767
|
-
offset:
|
|
768
|
-
fields:
|
|
769
|
-
count:
|
|
782
|
+
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. To TAIL new rows (no streaming over MCP): sort=_id, order=desc for the latest, then poll forward with the filter {"_id.gt": "<last _id seen>"}, order=asc. Fetch one row by id with {"_id": "<id>"}. Public subgraphs are also keyless over HTTP at GET /v1/subgraphs/<name>/<table> — { rows, next_cursor, tip } envelope, resume with ?cursor=<next_cursor> + _order=asc|desc (no _offset/_sort on /v1); hand that URL to third parties.', {
|
|
783
|
+
name: z7.string().describe("Subgraph name"),
|
|
784
|
+
table: z7.string().describe("Table name"),
|
|
785
|
+
filters: z7.record(z7.string(), z7.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
|
|
786
|
+
sort: z7.string().optional().describe("Column to sort by"),
|
|
787
|
+
order: z7.enum(["asc", "desc"]).optional().describe("Sort order"),
|
|
788
|
+
limit: z7.number().max(200).optional().describe("Max rows (default 50, max 200)"),
|
|
789
|
+
offset: z7.number().optional().describe("Offset for pagination"),
|
|
790
|
+
fields: z7.string().optional().describe('Comma-separated column list to return (e.g. "sender,amount")'),
|
|
791
|
+
count: z7.boolean().optional().describe("If true, return row count instead of rows")
|
|
770
792
|
}, async ({
|
|
771
793
|
name,
|
|
772
794
|
table,
|
|
@@ -799,14 +821,14 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
799
821
|
};
|
|
800
822
|
});
|
|
801
823
|
defineTool(server, "subgraphs_aggregate", `Compute scalar aggregates over a subgraph table's filtered rows. Supports count, countDistinct, and sum/min/max (numeric columns only — uint/int plus the system _block_height). Filters use the same grammar as subgraphs_query (e.g. {"amount.gte": "1000"}). sum/min/max come back as lossless strings; counts as numbers. With no aggregate requested, returns the row count.`, {
|
|
802
|
-
name:
|
|
803
|
-
table:
|
|
804
|
-
filters:
|
|
805
|
-
count:
|
|
806
|
-
countDistinct:
|
|
807
|
-
sum:
|
|
808
|
-
min:
|
|
809
|
-
max:
|
|
824
|
+
name: z7.string().describe("Subgraph name"),
|
|
825
|
+
table: z7.string().describe("Table name"),
|
|
826
|
+
filters: z7.record(z7.string(), z7.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
|
|
827
|
+
count: z7.boolean().optional().describe("Include COUNT(*) of matching rows"),
|
|
828
|
+
countDistinct: z7.array(z7.string()).optional().describe("Columns to count distinct values of"),
|
|
829
|
+
sum: z7.array(z7.string()).optional().describe("Numeric columns to sum (lossless string result)"),
|
|
830
|
+
min: z7.array(z7.string()).optional().describe("Numeric columns to take the minimum of"),
|
|
831
|
+
max: z7.array(z7.string()).optional().describe("Numeric columns to take the maximum of")
|
|
810
832
|
}, async ({ name, table, filters, count, countDistinct, sum, min, max }) => {
|
|
811
833
|
const result = await clientProvider().subgraphs.queryTableAggregate(name, table, { filters, count, countDistinct, sum, min, max });
|
|
812
834
|
return {
|
|
@@ -814,9 +836,9 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
814
836
|
};
|
|
815
837
|
});
|
|
816
838
|
defineTool(server, "subgraphs_reindex", "Reindex a subgraph from a specific block range. Returns an operationId — poll subgraphs_operation to track progress to completion.", {
|
|
817
|
-
name:
|
|
818
|
-
fromBlock:
|
|
819
|
-
toBlock:
|
|
839
|
+
name: z7.string().describe("Subgraph name"),
|
|
840
|
+
fromBlock: z7.number().optional().describe("Start block (defaults to beginning)"),
|
|
841
|
+
toBlock: z7.number().optional().describe("End block (defaults to latest)")
|
|
820
842
|
}, async ({ name, fromBlock, toBlock }) => {
|
|
821
843
|
const result = await clientProvider().subgraphs.reindex(name, {
|
|
822
844
|
fromBlock,
|
|
@@ -827,8 +849,8 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
827
849
|
};
|
|
828
850
|
});
|
|
829
851
|
defineTool(server, "subgraphs_operation", "Check reindex/backfill progress. With operationId, returns that operation's status (poll until status is completed/failed/cancelled); without it, lists recent operations for the subgraph.", {
|
|
830
|
-
name:
|
|
831
|
-
operationId:
|
|
852
|
+
name: z7.string().describe("Subgraph name"),
|
|
853
|
+
operationId: z7.string().optional().describe("Operation id from reindex/backfill/stop; omit to list recent operations")
|
|
832
854
|
}, async ({ name, operationId }) => {
|
|
833
855
|
const result = operationId ? await clientProvider().subgraphs.getOperation(name, operationId) : await clientProvider().subgraphs.operations(name);
|
|
834
856
|
return {
|
|
@@ -836,9 +858,9 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
836
858
|
};
|
|
837
859
|
});
|
|
838
860
|
defineTool(server, "subgraphs_backfill", "Backfill a subgraph over a block range. Non-destructive forward fill (does not drop existing data) — unlike subgraphs_reindex, and the only data-fill path for BYO subgraphs (reindex is blocked there). Both blocks required. Returns an operationId — poll subgraphs_operation to track progress.", {
|
|
839
|
-
name:
|
|
840
|
-
fromBlock:
|
|
841
|
-
toBlock:
|
|
861
|
+
name: z7.string().describe("Subgraph name"),
|
|
862
|
+
fromBlock: z7.number().int().nonnegative().describe("Start block (inclusive)"),
|
|
863
|
+
toBlock: z7.number().int().nonnegative().describe("End block (inclusive)")
|
|
842
864
|
}, async ({ name, fromBlock, toBlock }) => {
|
|
843
865
|
const result = await clientProvider().subgraphs.backfill(name, {
|
|
844
866
|
fromBlock,
|
|
@@ -848,17 +870,17 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
848
870
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
849
871
|
};
|
|
850
872
|
});
|
|
851
|
-
defineTool(server, "subgraphs_stop", "Cancel an in-flight reindex or backfill operation for a subgraph. Returns the stop request status; poll subgraphs_operation to confirm it reaches a terminal state.", { name:
|
|
873
|
+
defineTool(server, "subgraphs_stop", "Cancel an in-flight reindex or backfill operation for a subgraph. Returns the stop request status; poll subgraphs_operation to confirm it reaches a terminal state.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
852
874
|
const result = await clientProvider().subgraphs.stop(name);
|
|
853
875
|
return {
|
|
854
876
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
855
877
|
};
|
|
856
878
|
});
|
|
857
879
|
defineTool(server, "subgraphs_gaps", "List indexing gaps (missing block ranges) for a subgraph. Each gap reports start/end/size, reason, and detected/resolved timestamps. Feed an unresolved gap's range into subgraphs_backfill to fill it. Defaults to unresolved gaps.", {
|
|
858
|
-
name:
|
|
859
|
-
limit:
|
|
860
|
-
offset:
|
|
861
|
-
resolved:
|
|
880
|
+
name: z7.string().describe("Subgraph name"),
|
|
881
|
+
limit: z7.number().int().positive().optional().describe("Max gaps to return"),
|
|
882
|
+
offset: z7.number().int().nonnegative().optional().describe("Pagination offset"),
|
|
883
|
+
resolved: z7.boolean().optional().describe("Filter by resolved state (omit for unresolved only)")
|
|
862
884
|
}, async ({ name, limit, offset, resolved }) => {
|
|
863
885
|
const result = await clientProvider().subgraphs.gaps(name, {
|
|
864
886
|
limit,
|
|
@@ -869,16 +891,17 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
869
891
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
870
892
|
};
|
|
871
893
|
});
|
|
872
|
-
defineTool(server, "subgraphs_delete", "Delete a subgraph permanently.", { name:
|
|
894
|
+
defineTool(server, "subgraphs_delete", "Delete a subgraph permanently.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
873
895
|
const result = await clientProvider().subgraphs.delete(name);
|
|
874
896
|
return { content: [{ type: "text", text: result.message }] };
|
|
875
897
|
});
|
|
876
|
-
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. Set dryRun to validate and preview the schema/DDL without writing anything. Set databaseUrl to deploy to your own Postgres (BYO data plane) — the server verifies the connection first; with dryRun it returns the DDL + grant script. A breaking BYO schema change is refused and returns a migration plan (drop + rebuild DDL) instead of deploying. Call `subgraphs_reindex` separately if you need a forced reindex.", {
|
|
877
|
-
code:
|
|
878
|
-
startBlock:
|
|
879
|
-
databaseUrl:
|
|
880
|
-
dryRun:
|
|
881
|
-
|
|
898
|
+
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. Set dryRun to validate and preview the schema/DDL without writing anything. Set databaseUrl to deploy to your own Postgres (BYO data plane) — the server verifies the connection first; with dryRun it returns the DDL + grant script. A breaking BYO schema change is refused and returns a migration plan (drop + rebuild DDL) instead of deploying. Visibility defaults: managed deploys are public (anon-readable at /v1/subgraphs/<name>, name claimed in the global public namespace), BYO deploys are private. Call `subgraphs_reindex` separately if you need a forced reindex.", {
|
|
899
|
+
code: z7.string().describe("TypeScript source code containing a defineSubgraph() call"),
|
|
900
|
+
startBlock: z7.number().int().nonnegative().optional().describe("Override the definition startBlock for this deploy"),
|
|
901
|
+
databaseUrl: z7.string().optional().describe("BYO data plane: Postgres connection string to host the subgraph's schema and rows in your own database"),
|
|
902
|
+
dryRun: z7.boolean().optional().describe("Validate and preview the deploy (schema/DDL, BYO connection) without writing changes"),
|
|
903
|
+
visibility: z7.enum(["public", "private"]).optional().describe("Read visibility: public = anon /v1 reads + global name claim; private = owning account's key only. Defaults: managed → public, BYO → private.")
|
|
904
|
+
}, async ({ code, startBlock, databaseUrl, dryRun, visibility }) => {
|
|
882
905
|
const bundled = await bundleSubgraphCode(code);
|
|
883
906
|
try {
|
|
884
907
|
const result = await clientProvider().subgraphs.deploy({
|
|
@@ -891,7 +914,8 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
891
914
|
sourceCode: code,
|
|
892
915
|
...startBlock !== undefined ? { startBlock } : {},
|
|
893
916
|
...databaseUrl !== undefined ? { databaseUrl } : {},
|
|
894
|
-
...dryRun !== undefined ? { dryRun } : {}
|
|
917
|
+
...dryRun !== undefined ? { dryRun } : {},
|
|
918
|
+
...visibility !== undefined ? { visibility } : {}
|
|
895
919
|
});
|
|
896
920
|
return {
|
|
897
921
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
@@ -910,17 +934,29 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
910
934
|
throw err;
|
|
911
935
|
}
|
|
912
936
|
});
|
|
913
|
-
defineTool(server, "
|
|
937
|
+
defineTool(server, "subgraphs_publish", "Make a subgraph publicly readable at /v1/subgraphs/<name> — anyone (or any agent) can read it without a key. Claims the name in the global public namespace; fails with PUBLIC_NAME_TAKEN if another account holds it.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
938
|
+
const result = await clientProvider().subgraphs.publish(name);
|
|
939
|
+
return {
|
|
940
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
941
|
+
};
|
|
942
|
+
});
|
|
943
|
+
defineTool(server, "subgraphs_unpublish", "Make a subgraph private again — /v1 reads then require the owning account's bearer key, and the global public name claim is released.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
944
|
+
const result = await clientProvider().subgraphs.unpublish(name);
|
|
945
|
+
return {
|
|
946
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
947
|
+
};
|
|
948
|
+
});
|
|
949
|
+
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 }) => {
|
|
914
950
|
const source = await clientProvider().subgraphs.getSource(name);
|
|
915
951
|
return {
|
|
916
952
|
content: [{ type: "text", text: JSON.stringify(source, null, 2) }]
|
|
917
953
|
};
|
|
918
954
|
});
|
|
919
955
|
defineTool(server, "subgraphs_codegen", "Generate a typed ORM schema (Prisma, Drizzle, or Kysely) for a subgraph's tables so they can be queried from a BYO database. Pass either `code` (defineSubgraph source) or `name` (a deployed subgraph — its captured source is used). Returns the schema as text.", {
|
|
920
|
-
code:
|
|
921
|
-
name:
|
|
922
|
-
target:
|
|
923
|
-
schemaName:
|
|
956
|
+
code: z7.string().optional().describe("defineSubgraph() source (mutually exclusive with name)"),
|
|
957
|
+
name: z7.string().optional().describe("Deployed subgraph name (mutually exclusive with code)"),
|
|
958
|
+
target: z7.enum(["prisma", "drizzle", "kysely"]).optional().describe("ORM target (default prisma)"),
|
|
959
|
+
schemaName: z7.string().optional().describe("Postgres schema name (defaults to subgraph_<name>)")
|
|
924
960
|
}, async ({ code, name, target = "prisma", schemaName }) => {
|
|
925
961
|
if (code && name || !code && !name) {
|
|
926
962
|
throw new Error("Provide exactly one of `code` or `name`.");
|
|
@@ -949,7 +985,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
949
985
|
|
|
950
986
|
// src/tools/subscriptions.ts
|
|
951
987
|
import { CHAIN_TRIGGER_TYPES } from "@secondlayer/shared";
|
|
952
|
-
import { z as
|
|
988
|
+
import { z as z8 } from "zod/v4";
|
|
953
989
|
function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
954
990
|
defineTool(server, "subscriptions_list", "List all subscriptions for the current account. Returns summary fields (no secrets).", {}, async () => {
|
|
955
991
|
const { data } = await clientProvider().subscriptions.list();
|
|
@@ -957,34 +993,34 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
957
993
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
958
994
|
};
|
|
959
995
|
});
|
|
960
|
-
defineTool(server, "subscriptions_get", "Get full detail for a subscription (filter, auth, retry config, circuit state).", { id:
|
|
996
|
+
defineTool(server, "subscriptions_get", "Get full detail for a subscription (filter, auth, retry config, circuit state).", { id: z8.string().describe("Subscription id") }, async ({ id }) => {
|
|
961
997
|
const detail = await clientProvider().subscriptions.get(id);
|
|
962
998
|
return {
|
|
963
999
|
content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
|
|
964
1000
|
};
|
|
965
1001
|
});
|
|
966
1002
|
defineTool(server, "subscriptions_create", "Create a subscription. Two kinds (mutually exclusive): a SUBGRAPH subscription fires on a subgraph table's rows (set subgraphName + tableName + optional filter); a CHAIN subscription fires on raw chain events with no subgraph (set triggers). Returns `signingSecret` ONCE — forward it to the user so they can wire it into their receiver.", {
|
|
967
|
-
name:
|
|
968
|
-
subgraphName:
|
|
969
|
-
tableName:
|
|
970
|
-
triggers:
|
|
971
|
-
type:
|
|
972
|
-
contractId:
|
|
973
|
-
functionName:
|
|
974
|
-
caller:
|
|
975
|
-
sender:
|
|
976
|
-
recipient:
|
|
977
|
-
assetIdentifier:
|
|
978
|
-
deployer:
|
|
979
|
-
contractName:
|
|
980
|
-
topic:
|
|
981
|
-
lockedAddress:
|
|
982
|
-
trait:
|
|
983
|
-
minAmount:
|
|
984
|
-
maxAmount:
|
|
1003
|
+
name: z8.string().describe("Human-readable name, unique per account"),
|
|
1004
|
+
subgraphName: z8.string().optional().describe("Subgraph to subscribe to (subgraph subscription)"),
|
|
1005
|
+
tableName: z8.string().optional().describe("Table within the subgraph (subgraph subscription)"),
|
|
1006
|
+
triggers: z8.array(z8.object({
|
|
1007
|
+
type: z8.enum(CHAIN_TRIGGER_TYPES),
|
|
1008
|
+
contractId: z8.string().optional(),
|
|
1009
|
+
functionName: z8.string().optional(),
|
|
1010
|
+
caller: z8.string().optional(),
|
|
1011
|
+
sender: z8.string().optional(),
|
|
1012
|
+
recipient: z8.string().optional(),
|
|
1013
|
+
assetIdentifier: z8.string().optional(),
|
|
1014
|
+
deployer: z8.string().optional(),
|
|
1015
|
+
contractName: z8.string().optional(),
|
|
1016
|
+
topic: z8.string().optional(),
|
|
1017
|
+
lockedAddress: z8.string().optional(),
|
|
1018
|
+
trait: z8.string().optional(),
|
|
1019
|
+
minAmount: z8.union([z8.string(), z8.number()]).optional(),
|
|
1020
|
+
maxAmount: z8.union([z8.string(), z8.number()]).optional()
|
|
985
1021
|
})).optional().describe("Chain triggers (chain subscription) — provide INSTEAD of subgraphName/tableName. Each targets a raw chain event/tx; string fields accept `*` wildcards, `trait` scopes to a SIP/trait. Per-type accepted fields: see the secondlayer://chain-triggers resource. Forward-looking: starts at chain tip, no backfill."),
|
|
986
|
-
url:
|
|
987
|
-
format:
|
|
1022
|
+
url: z8.string().describe("Webhook URL"),
|
|
1023
|
+
format: z8.enum([
|
|
988
1024
|
"standard-webhooks",
|
|
989
1025
|
"inngest",
|
|
990
1026
|
"trigger",
|
|
@@ -992,9 +1028,9 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
992
1028
|
"cloudevents",
|
|
993
1029
|
"raw"
|
|
994
1030
|
]).optional().describe("Wire format (default standard-webhooks)"),
|
|
995
|
-
runtime:
|
|
996
|
-
filter:
|
|
997
|
-
authConfig:
|
|
1031
|
+
runtime: z8.enum(["inngest", "trigger", "cloudflare", "node"]).optional().describe("Receiver runtime label (display only)"),
|
|
1032
|
+
filter: z8.record(z8.string(), z8.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}'),
|
|
1033
|
+
authConfig: z8.record(z8.string(), z8.unknown()).optional().describe('Receiver auth sent with each delivery, e.g. {"type": "bearer", "token": "..."}')
|
|
998
1034
|
}, async (input) => {
|
|
999
1035
|
const res = await clientProvider().subscriptions.create(input);
|
|
1000
1036
|
return {
|
|
@@ -1002,12 +1038,12 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
1002
1038
|
};
|
|
1003
1039
|
});
|
|
1004
1040
|
defineTool(server, "subscriptions_update", "Patch a subscription (name, url, filter, authConfig, format, runtime, retry, timeout, concurrency).", {
|
|
1005
|
-
id:
|
|
1006
|
-
name:
|
|
1007
|
-
url:
|
|
1008
|
-
filter:
|
|
1009
|
-
authConfig:
|
|
1010
|
-
format:
|
|
1041
|
+
id: z8.string(),
|
|
1042
|
+
name: z8.string().optional().describe("Rename the subscription"),
|
|
1043
|
+
url: z8.string().optional(),
|
|
1044
|
+
filter: z8.record(z8.string(), z8.unknown()).optional(),
|
|
1045
|
+
authConfig: z8.record(z8.string(), z8.unknown()).optional().describe("Receiver auth sent with each delivery (bearer/etc.)"),
|
|
1046
|
+
format: z8.enum([
|
|
1011
1047
|
"standard-webhooks",
|
|
1012
1048
|
"inngest",
|
|
1013
1049
|
"trigger",
|
|
@@ -1015,51 +1051,51 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
1015
1051
|
"cloudevents",
|
|
1016
1052
|
"raw"
|
|
1017
1053
|
]).optional(),
|
|
1018
|
-
runtime:
|
|
1019
|
-
maxRetries:
|
|
1020
|
-
timeoutMs:
|
|
1021
|
-
concurrency:
|
|
1054
|
+
runtime: z8.enum(["inngest", "trigger", "cloudflare", "node"]).nullable().optional(),
|
|
1055
|
+
maxRetries: z8.number().int().min(0).optional(),
|
|
1056
|
+
timeoutMs: z8.number().int().min(100).optional(),
|
|
1057
|
+
concurrency: z8.number().int().min(1).optional()
|
|
1022
1058
|
}, async ({ id, ...patch }) => {
|
|
1023
1059
|
const res = await clientProvider().subscriptions.update(id, patch);
|
|
1024
1060
|
return {
|
|
1025
1061
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1026
1062
|
};
|
|
1027
1063
|
});
|
|
1028
|
-
defineTool(server, "subscriptions_pause", "Pause a subscription. Pending rows remain queued until resumed.", { id:
|
|
1064
|
+
defineTool(server, "subscriptions_pause", "Pause a subscription. Pending rows remain queued until resumed.", { id: z8.string() }, async ({ id }) => {
|
|
1029
1065
|
const res = await clientProvider().subscriptions.pause(id);
|
|
1030
1066
|
return {
|
|
1031
1067
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1032
1068
|
};
|
|
1033
1069
|
});
|
|
1034
|
-
defineTool(server, "subscriptions_resume", "Resume a paused or circuit-open subscription and reset circuit failures.", { id:
|
|
1070
|
+
defineTool(server, "subscriptions_resume", "Resume a paused or circuit-open subscription and reset circuit failures.", { id: z8.string() }, async ({ id }) => {
|
|
1035
1071
|
const res = await clientProvider().subscriptions.resume(id);
|
|
1036
1072
|
return {
|
|
1037
1073
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1038
1074
|
};
|
|
1039
1075
|
});
|
|
1040
|
-
defineTool(server, "subscriptions_delete", "Delete a subscription. Pending outbox rows are cascade-deleted.", { id:
|
|
1076
|
+
defineTool(server, "subscriptions_delete", "Delete a subscription. Pending outbox rows are cascade-deleted.", { id: z8.string() }, async ({ id }) => {
|
|
1041
1077
|
const res = await clientProvider().subscriptions.delete(id);
|
|
1042
1078
|
return {
|
|
1043
1079
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1044
1080
|
};
|
|
1045
1081
|
});
|
|
1046
|
-
defineTool(server, "subscriptions_rotate_secret", "Rotate a subscription signing secret. Returns the new plaintext secret once.", { id:
|
|
1082
|
+
defineTool(server, "subscriptions_rotate_secret", "Rotate a subscription signing secret. Returns the new plaintext secret once.", { id: z8.string() }, async ({ id }) => {
|
|
1047
1083
|
const res = await clientProvider().subscriptions.rotateSecret(id);
|
|
1048
1084
|
return {
|
|
1049
1085
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1050
1086
|
};
|
|
1051
1087
|
});
|
|
1052
|
-
defineTool(server, "subscriptions_test", "Send a one-off test webhook to a subscription's URL (built for its format, SSRF-guarded). Logged as a delivery row — check subscriptions_recent_deliveries. Returns {ok, statusCode, error, durationMs, deliveryId}.", { id:
|
|
1088
|
+
defineTool(server, "subscriptions_test", "Send a one-off test webhook to a subscription's URL (built for its format, SSRF-guarded). Logged as a delivery row — check subscriptions_recent_deliveries. Returns {ok, statusCode, error, durationMs, deliveryId}.", { id: z8.string().describe("Subscription id") }, async ({ id }) => {
|
|
1053
1089
|
const res = await clientProvider().subscriptions.test(id);
|
|
1054
1090
|
return {
|
|
1055
1091
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1056
1092
|
};
|
|
1057
1093
|
});
|
|
1058
1094
|
defineTool(server, "subscriptions_replay", "Replay a block range for a subscription. Replays run at 10% of batch capacity — use sparingly. Pass `force` (a short idempotency suffix) to re-run a range that was already replayed.", {
|
|
1059
|
-
id:
|
|
1060
|
-
fromBlock:
|
|
1061
|
-
toBlock:
|
|
1062
|
-
force:
|
|
1095
|
+
id: z8.string(),
|
|
1096
|
+
fromBlock: z8.number().int().nonnegative(),
|
|
1097
|
+
toBlock: z8.number().int().nonnegative(),
|
|
1098
|
+
force: z8.string().optional().describe("Idempotency suffix to force a duplicate replay of the range")
|
|
1063
1099
|
}, async ({ id, fromBlock, toBlock, force }) => {
|
|
1064
1100
|
const res = await clientProvider().subscriptions.replay(id, {
|
|
1065
1101
|
fromBlock,
|
|
@@ -1070,22 +1106,22 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
1070
1106
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1071
1107
|
};
|
|
1072
1108
|
});
|
|
1073
|
-
defineTool(server, "subscriptions_dead", "Return the last 100 dead-letter outbox rows for a subscription.", { id:
|
|
1109
|
+
defineTool(server, "subscriptions_dead", "Return the last 100 dead-letter outbox rows for a subscription.", { id: z8.string() }, async ({ id }) => {
|
|
1074
1110
|
const { data } = await clientProvider().subscriptions.dead(id);
|
|
1075
1111
|
return {
|
|
1076
1112
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1077
1113
|
};
|
|
1078
1114
|
});
|
|
1079
1115
|
defineTool(server, "subscriptions_requeue_dead", "Requeue one dead-letter outbox row for delivery retry.", {
|
|
1080
|
-
id:
|
|
1081
|
-
outboxId:
|
|
1116
|
+
id: z8.string(),
|
|
1117
|
+
outboxId: z8.string()
|
|
1082
1118
|
}, async ({ id, outboxId }) => {
|
|
1083
1119
|
const res = await clientProvider().subscriptions.requeueDead(id, outboxId);
|
|
1084
1120
|
return {
|
|
1085
1121
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
1086
1122
|
};
|
|
1087
1123
|
});
|
|
1088
|
-
defineTool(server, "subscriptions_recent_deliveries", "Return the last 100 delivery attempts (attempt #, status code, duration, truncated response).", { id:
|
|
1124
|
+
defineTool(server, "subscriptions_recent_deliveries", "Return the last 100 delivery attempts (attempt #, status code, duration, truncated response).", { id: z8.string() }, async ({ id }) => {
|
|
1089
1125
|
const { data } = await clientProvider().subscriptions.recentDeliveries(id);
|
|
1090
1126
|
return {
|
|
1091
1127
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
@@ -1106,7 +1142,6 @@ function createServer() {
|
|
|
1106
1142
|
registerSubscriptionTools(server);
|
|
1107
1143
|
registerAccountTools(server);
|
|
1108
1144
|
registerProjectTools(server);
|
|
1109
|
-
registerDatasetTools(server);
|
|
1110
1145
|
registerIndexTools(server);
|
|
1111
1146
|
registerStreamsTools(server);
|
|
1112
1147
|
registerContractTools(server);
|
|
@@ -1119,5 +1154,5 @@ var server = createServer();
|
|
|
1119
1154
|
var transport = new StdioServerTransport;
|
|
1120
1155
|
await server.connect(transport);
|
|
1121
1156
|
|
|
1122
|
-
//# debugId=
|
|
1157
|
+
//# debugId=DF363B254E9A96CE64756E2164756E21
|
|
1123
1158
|
//# sourceMappingURL=bin.js.map
|