@secondlayer/mcp 3.6.0 → 3.8.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/bin-http.js +156 -35
- package/dist/bin-http.js.map +11 -11
- package/dist/bin.js +156 -35
- package/dist/bin.js.map +11 -11
- package/dist/index.js +156 -35
- package/dist/index.js.map +11 -11
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
6
|
|
|
7
7
|
// src/resources.ts
|
|
8
|
+
import { CHAIN_TRIGGER_FIELDS, DECODED_EVENT_TYPES } from "@secondlayer/shared";
|
|
9
|
+
import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
|
|
8
10
|
import { TYPE_MAP } from "@secondlayer/subgraphs/schema";
|
|
9
11
|
|
|
10
12
|
// src/lib/client.ts
|
|
@@ -17,10 +19,12 @@ function getClient() {
|
|
|
17
19
|
if (!instance) {
|
|
18
20
|
const apiKey = readApiKey();
|
|
19
21
|
const baseUrl = process.env.SECONDLAYER_API_URL;
|
|
22
|
+
const dumpsBaseUrl = process.env.SL_STREAMS_DUMPS_URL;
|
|
20
23
|
instance = new SecondLayer({
|
|
21
24
|
...apiKey ? { apiKey } : {},
|
|
22
25
|
origin: "mcp",
|
|
23
|
-
...baseUrl ? { baseUrl } : {}
|
|
26
|
+
...baseUrl ? { baseUrl } : {},
|
|
27
|
+
...dumpsBaseUrl ? { dumpsBaseUrl } : {}
|
|
24
28
|
});
|
|
25
29
|
}
|
|
26
30
|
return instance;
|
|
@@ -99,6 +103,11 @@ function defineTool(server, name, description, schema, handler) {
|
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
// src/resources.ts
|
|
106
|
+
var TRAIT_BLURBS = {
|
|
107
|
+
"sip-009": "Non-fungible token (NFT) standard",
|
|
108
|
+
"sip-010": "Fungible token standard",
|
|
109
|
+
"sip-013": "Semi-fungible token standard"
|
|
110
|
+
};
|
|
102
111
|
var FILTERS_REFERENCE = [
|
|
103
112
|
{
|
|
104
113
|
type: "stx_transfer",
|
|
@@ -193,7 +202,7 @@ function buildCapabilities() {
|
|
|
193
202
|
});
|
|
194
203
|
return {
|
|
195
204
|
products,
|
|
196
|
-
discoverFirst: "Call datasets_list / contracts_find to learn what exists before querying."
|
|
205
|
+
discoverFirst: "Call datasets_list / index_discover / contracts_find to learn what exists (and which filters each surface accepts) before querying."
|
|
197
206
|
};
|
|
198
207
|
}
|
|
199
208
|
var READ_AUTH_TIERS = {
|
|
@@ -252,6 +261,56 @@ function registerResources(server) {
|
|
|
252
261
|
}
|
|
253
262
|
]
|
|
254
263
|
}));
|
|
264
|
+
server.resource("traits", "secondlayer://traits", {
|
|
265
|
+
description: "SIP trait standards the platform can classify and scaffold against — the valid values for contracts_find `trait` and subgraph scaffold `--trait`."
|
|
266
|
+
}, async () => ({
|
|
267
|
+
contents: [
|
|
268
|
+
{
|
|
269
|
+
uri: "secondlayer://traits",
|
|
270
|
+
mimeType: "application/json",
|
|
271
|
+
text: JSON.stringify({
|
|
272
|
+
traits: TRAIT_STANDARDS.map((id) => ({
|
|
273
|
+
id,
|
|
274
|
+
description: TRAIT_BLURBS[id]
|
|
275
|
+
}))
|
|
276
|
+
}, null, 2)
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
}));
|
|
280
|
+
server.resource("streams-filters", "secondlayer://streams-filters", {
|
|
281
|
+
description: "Streams firehose vocabulary — the decoded event types and the filter fields accepted by streams_events / streams_consume."
|
|
282
|
+
}, async () => ({
|
|
283
|
+
contents: [
|
|
284
|
+
{
|
|
285
|
+
uri: "secondlayer://streams-filters",
|
|
286
|
+
mimeType: "application/json",
|
|
287
|
+
text: JSON.stringify({
|
|
288
|
+
eventTypes: [...DECODED_EVENT_TYPES],
|
|
289
|
+
filters: {
|
|
290
|
+
types: "include only these event types (array)",
|
|
291
|
+
notTypes: "exclude these event types (array)",
|
|
292
|
+
contractId: "match a contract id",
|
|
293
|
+
sender: "match the sender principal",
|
|
294
|
+
recipient: "match the recipient principal",
|
|
295
|
+
assetIdentifier: "match the asset identifier (contract::asset)",
|
|
296
|
+
fromHeight: "start block height (inclusive)",
|
|
297
|
+
toHeight: "end block height (inclusive)"
|
|
298
|
+
}
|
|
299
|
+
}, null, 2)
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
}));
|
|
303
|
+
server.resource("chain-triggers", "secondlayer://chain-triggers", {
|
|
304
|
+
description: "Chain-subscription trigger types and the filter fields each accepts (for subscriptions_create triggers)."
|
|
305
|
+
}, async () => ({
|
|
306
|
+
contents: [
|
|
307
|
+
{
|
|
308
|
+
uri: "secondlayer://chain-triggers",
|
|
309
|
+
mimeType: "application/json",
|
|
310
|
+
text: JSON.stringify(CHAIN_TRIGGER_FIELDS, null, 2)
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
}));
|
|
255
314
|
}
|
|
256
315
|
|
|
257
316
|
// src/tools/account.ts
|
|
@@ -276,7 +335,7 @@ function registerAccountTools(server) {
|
|
|
276
335
|
const result = await apiRequest("PATCH", "/api/accounts/me", body);
|
|
277
336
|
return jsonResponse(result);
|
|
278
337
|
});
|
|
279
|
-
defineTool(server, "account_billing", "Show the account's plan and subscription/billing status. Requires an API key.", {}, async () => {
|
|
338
|
+
defineTool(server, "account_billing", "Show the account's plan and subscription/billing status. Requires an API key. (Plan upgrade / Stripe portal / checkout are deliberately not agent tools — they are session-only human-payment flows; use account_set_caps to bound spend.)", {}, async () => {
|
|
280
339
|
const result = await apiRequest("GET", "/api/billing/status");
|
|
281
340
|
return jsonResponse(result);
|
|
282
341
|
});
|
|
@@ -304,6 +363,7 @@ function registerAccountTools(server) {
|
|
|
304
363
|
}
|
|
305
364
|
|
|
306
365
|
// src/tools/contracts.ts
|
|
366
|
+
import { generateContractInterface } from "@secondlayer/scaffold";
|
|
307
367
|
import { z as z2 } from "zod/v4";
|
|
308
368
|
function registerContractTools(server, clientProvider = getClient) {
|
|
309
369
|
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.', {
|
|
@@ -313,6 +373,47 @@ function registerContractTools(server, clientProvider = getClient) {
|
|
|
313
373
|
limit: z2.number().optional().describe("Page size, 1–500 (default 100)"),
|
|
314
374
|
cursor: z2.string().optional().describe("Opaque cursor from a prior response's next_cursor")
|
|
315
375
|
}, async (params) => jsonResponse(await clientProvider().contracts.list(params)));
|
|
376
|
+
defineTool(server, "get_contract_abi", "Fetch a single deployed contract's ABI from the registry (prod-safe). Returns the contract's metadata + full ABI (functions, maps, variables, fungible/non-fungible tokens). Returns not_found if the contract isn't in the registry. Feed the ABI into scaffold_from_abi or generate a typed client.", {
|
|
377
|
+
contractId: z2.string().describe("Fully qualified contract id (e.g. SP….amm-pool-v2-01)")
|
|
378
|
+
}, async ({ contractId }) => {
|
|
379
|
+
const contract = await clientProvider().contracts.get(contractId, {
|
|
380
|
+
includeAbi: true
|
|
381
|
+
});
|
|
382
|
+
return contract ? jsonResponse(contract) : jsonResponse({
|
|
383
|
+
error: {
|
|
384
|
+
type: "not_found",
|
|
385
|
+
status: 404,
|
|
386
|
+
message: `Contract not in registry: ${contractId}`
|
|
387
|
+
}
|
|
388
|
+
}, true);
|
|
389
|
+
});
|
|
390
|
+
defineTool(server, "generate_contract_interface", "Generate a typed TypeScript contract-client interface (typed methods + map/var/constant readers) from a deployed contract's ABI (fetched from the registry). Returns not_found if the contract isn't in the registry.", {
|
|
391
|
+
contractId: z2.string().describe("Fully qualified contract id (e.g. SP….amm-pool-v2-01)")
|
|
392
|
+
}, async ({ contractId }) => {
|
|
393
|
+
const c = await clientProvider().contracts.get(contractId, {
|
|
394
|
+
includeAbi: true
|
|
395
|
+
});
|
|
396
|
+
if (!c || !c.abi) {
|
|
397
|
+
return jsonResponse({
|
|
398
|
+
error: {
|
|
399
|
+
type: "not_found",
|
|
400
|
+
status: 404,
|
|
401
|
+
message: `Contract not in registry: ${contractId}`
|
|
402
|
+
}
|
|
403
|
+
}, true);
|
|
404
|
+
}
|
|
405
|
+
const [address, contractName] = contractId.split(".");
|
|
406
|
+
const name = (contractName ?? contractId).replace(/[^a-zA-Z0-9]/g, "_");
|
|
407
|
+
const code = generateContractInterface([
|
|
408
|
+
{
|
|
409
|
+
name,
|
|
410
|
+
address,
|
|
411
|
+
contractName: contractName ?? "",
|
|
412
|
+
abi: c.abi
|
|
413
|
+
}
|
|
414
|
+
]);
|
|
415
|
+
return { content: [{ type: "text", text: code }] };
|
|
416
|
+
});
|
|
316
417
|
}
|
|
317
418
|
|
|
318
419
|
// src/tools/datasets.ts
|
|
@@ -339,13 +440,13 @@ function registerDatasetTools(server, clientProvider = getClient) {
|
|
|
339
440
|
}
|
|
340
441
|
|
|
341
442
|
// src/tools/index.ts
|
|
342
|
-
import { DECODED_EVENT_TYPES } from "@secondlayer/shared";
|
|
443
|
+
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES2 } from "@secondlayer/shared";
|
|
343
444
|
import {
|
|
344
|
-
|
|
345
|
-
|
|
445
|
+
INDEX_CODEGEN_TABLES,
|
|
446
|
+
generateIndexSchema
|
|
346
447
|
} from "@secondlayer/subgraphs";
|
|
347
448
|
import { z as z4 } from "zod/v4";
|
|
348
|
-
var INDEX_EVENT_TYPES =
|
|
449
|
+
var INDEX_EVENT_TYPES = DECODED_EVENT_TYPES2;
|
|
349
450
|
var rangeFilters = {
|
|
350
451
|
contractId: z4.string().optional().describe("Filter by contract id"),
|
|
351
452
|
fromHeight: z4.number().optional().describe("Start block height (inclusive)"),
|
|
@@ -372,17 +473,19 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
372
473
|
recipient: z4.string().optional().describe("Filter by recipient principal"),
|
|
373
474
|
assetIdentifier: z4.string().optional().describe("Filter by asset identifier (contract::asset)")
|
|
374
475
|
}, async (params) => jsonResponse(await clientProvider().index.nftTransfers.list(params)));
|
|
375
|
-
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.", {
|
|
476
|
+
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.", {
|
|
376
477
|
eventType: z4.enum(INDEX_EVENT_TYPES).describe("Required. Decoded event type to list."),
|
|
377
478
|
...rangeFilters,
|
|
378
479
|
sender: z4.string().optional().describe("Filter by sender principal"),
|
|
379
480
|
recipient: z4.string().optional().describe("Filter by recipient principal"),
|
|
380
|
-
assetIdentifier: z4.string().optional().describe("Filter by asset identifier where applicable")
|
|
481
|
+
assetIdentifier: z4.string().optional().describe("Filter by asset identifier where applicable"),
|
|
482
|
+
trait: z4.string().optional().describe("Match contracts conforming to a trait/standard (e.g. sip-010). Mutually exclusive with contractId; contract-keyed event types only.")
|
|
381
483
|
}, async (params) => jsonResponse(await clientProvider().index.events.list(params)));
|
|
382
|
-
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.", {
|
|
484
|
+
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.", {
|
|
383
485
|
...rangeFilters,
|
|
384
486
|
functionName: z4.string().optional().describe("Filter by called function name"),
|
|
385
|
-
sender: z4.string().optional().describe("Filter by caller principal")
|
|
487
|
+
sender: z4.string().optional().describe("Filter by caller principal"),
|
|
488
|
+
trait: z4.string().optional().describe("Match contracts conforming to a trait/standard (e.g. sip-010). Mutually exclusive with contractId.")
|
|
386
489
|
}, async (params) => jsonResponse(await clientProvider().index.contractCalls.list(params)));
|
|
387
490
|
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)));
|
|
388
491
|
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)));
|
|
@@ -401,6 +504,10 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
401
504
|
const tx = await clientProvider().index.transactions.get(txId);
|
|
402
505
|
return tx ? jsonResponse(tx) : notFound(`No transaction for ${txId}`);
|
|
403
506
|
});
|
|
507
|
+
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: z4.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
508
|
+
const proof = await clientProvider().index.transactions.getProof(txId);
|
|
509
|
+
return proof ? jsonResponse(proof) : notFound(`No proof available for ${txId}`);
|
|
510
|
+
});
|
|
404
511
|
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).", {
|
|
405
512
|
...heightFilters,
|
|
406
513
|
functionName: z4.string().optional().describe("Filter by PoX function name"),
|
|
@@ -418,6 +525,7 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
418
525
|
const tx = await clientProvider().index.mempool.get(txId);
|
|
419
526
|
return tx ? jsonResponse(tx) : notFound(`No pending tx for ${txId}`);
|
|
420
527
|
});
|
|
528
|
+
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()));
|
|
421
529
|
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()));
|
|
422
530
|
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(", ")}.`, {
|
|
423
531
|
target: z4.enum(["prisma", "kysely", "drizzle", "json-schema"]).optional().describe("Output target (default kysely)"),
|
|
@@ -464,25 +572,32 @@ function registerProjectTools(server, clientProvider = getClient) {
|
|
|
464
572
|
}
|
|
465
573
|
|
|
466
574
|
// src/tools/scaffold.ts
|
|
467
|
-
import {
|
|
575
|
+
import {
|
|
576
|
+
generateSubgraphCode,
|
|
577
|
+
generateTraitSubgraph
|
|
578
|
+
} from "@secondlayer/scaffold";
|
|
579
|
+
import { TRAIT_STANDARDS as TRAIT_STANDARDS2 } from "@secondlayer/stacks/clarity";
|
|
468
580
|
import { z as z6 } from "zod/v4";
|
|
469
|
-
var API_BASE = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
|
|
470
581
|
async function fetchAbi(contractId) {
|
|
471
|
-
const
|
|
472
|
-
|
|
582
|
+
const contract = await getClient().contracts.get(contractId, {
|
|
583
|
+
includeAbi: true
|
|
473
584
|
});
|
|
474
|
-
if (!
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
585
|
+
if (!contract)
|
|
586
|
+
throw new Error(`Contract not found: ${contractId}`);
|
|
587
|
+
const abi = contract.abi;
|
|
588
|
+
if (!abi) {
|
|
589
|
+
throw new Error(`No ABI available for ${contractId} (abi_status: ${contract.abi_status})`);
|
|
478
590
|
}
|
|
479
|
-
|
|
480
|
-
return {
|
|
481
|
-
functions: abi.functions ?? [],
|
|
482
|
-
maps: abi.maps ?? []
|
|
483
|
-
};
|
|
591
|
+
return { functions: abi.functions ?? [], maps: abi.maps ?? [] };
|
|
484
592
|
}
|
|
485
593
|
function registerScaffoldTools(server) {
|
|
594
|
+
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.", {
|
|
595
|
+
trait: z6.enum(TRAIT_STANDARDS2).describe("SIP standard to index (sip-009 | sip-010 | sip-013)"),
|
|
596
|
+
subgraphName: z6.string().optional().describe("Override the subgraph name (defaults to <trait>-transfers)")
|
|
597
|
+
}, async ({ trait, subgraphName }) => {
|
|
598
|
+
const code = generateTraitSubgraph({ trait, name: subgraphName });
|
|
599
|
+
return { content: [{ type: "text", text: code }] };
|
|
600
|
+
});
|
|
486
601
|
defineTool(server, "scaffold_from_contract", "Generate a subgraph scaffold from a deployed Stacks contract. Fetches the ABI automatically.", {
|
|
487
602
|
contractId: z6.string().describe("Fully qualified contract ID (e.g. SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01)"),
|
|
488
603
|
subgraphName: z6.string().optional().describe("Override the subgraph name (defaults to contract name)")
|
|
@@ -512,9 +627,9 @@ function registerScaffoldTools(server) {
|
|
|
512
627
|
|
|
513
628
|
// src/tools/streams.ts
|
|
514
629
|
import { AuthError } from "@secondlayer/sdk";
|
|
515
|
-
import { DECODED_EVENT_TYPES as
|
|
630
|
+
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES3 } from "@secondlayer/shared";
|
|
516
631
|
import { z as z7 } from "zod/v4";
|
|
517
|
-
var STREAMS_EVENT_TYPES =
|
|
632
|
+
var STREAMS_EVENT_TYPES = DECODED_EVENT_TYPES3;
|
|
518
633
|
async function withStreamsAuthHint(fn) {
|
|
519
634
|
try {
|
|
520
635
|
return await fn();
|
|
@@ -591,6 +706,7 @@ function registerStreamsTools(server, clientProvider = getClient) {
|
|
|
591
706
|
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.reorgs.list(params))));
|
|
592
707
|
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: z7.number().describe("Block height") }, async ({ height }) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.canonical(height))));
|
|
593
708
|
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())));
|
|
709
|
+
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()));
|
|
594
710
|
}
|
|
595
711
|
|
|
596
712
|
// src/tools/subgraphs.ts
|
|
@@ -636,7 +752,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
636
752
|
]
|
|
637
753
|
};
|
|
638
754
|
});
|
|
639
|
-
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.', {
|
|
755
|
+
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>"}.', {
|
|
640
756
|
name: z8.string().describe("Subgraph name"),
|
|
641
757
|
table: z8.string().describe("Table name"),
|
|
642
758
|
filters: z8.record(z8.string(), z8.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
|
|
@@ -861,7 +977,7 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
861
977
|
trait: z9.string().optional(),
|
|
862
978
|
minAmount: z9.union([z9.string(), z9.number()]).optional(),
|
|
863
979
|
maxAmount: z9.union([z9.string(), z9.number()]).optional()
|
|
864
|
-
})).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. Forward-looking: starts at chain tip, no backfill."),
|
|
980
|
+
})).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."),
|
|
865
981
|
url: z9.string().describe("Webhook URL"),
|
|
866
982
|
format: z9.enum([
|
|
867
983
|
"standard-webhooks",
|
|
@@ -872,17 +988,20 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
872
988
|
"raw"
|
|
873
989
|
]).optional().describe("Wire format (default standard-webhooks)"),
|
|
874
990
|
runtime: z9.enum(["inngest", "trigger", "cloudflare", "node"]).optional().describe("Receiver runtime label (display only)"),
|
|
875
|
-
filter: z9.record(z9.string(), z9.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}')
|
|
991
|
+
filter: z9.record(z9.string(), z9.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}'),
|
|
992
|
+
authConfig: z9.record(z9.string(), z9.unknown()).optional().describe('Receiver auth sent with each delivery, e.g. {"type": "bearer", "token": "..."}')
|
|
876
993
|
}, async (input) => {
|
|
877
994
|
const res = await clientProvider().subscriptions.create(input);
|
|
878
995
|
return {
|
|
879
996
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
880
997
|
};
|
|
881
998
|
});
|
|
882
|
-
defineTool(server, "subscriptions_update", "Patch a subscription (url, filter, format, runtime, retry, timeout, concurrency).", {
|
|
999
|
+
defineTool(server, "subscriptions_update", "Patch a subscription (name, url, filter, authConfig, format, runtime, retry, timeout, concurrency).", {
|
|
883
1000
|
id: z9.string(),
|
|
1001
|
+
name: z9.string().optional().describe("Rename the subscription"),
|
|
884
1002
|
url: z9.string().optional(),
|
|
885
1003
|
filter: z9.record(z9.string(), z9.unknown()).optional(),
|
|
1004
|
+
authConfig: z9.record(z9.string(), z9.unknown()).optional().describe("Receiver auth sent with each delivery (bearer/etc.)"),
|
|
886
1005
|
format: z9.enum([
|
|
887
1006
|
"standard-webhooks",
|
|
888
1007
|
"inngest",
|
|
@@ -931,14 +1050,16 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
931
1050
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
932
1051
|
};
|
|
933
1052
|
});
|
|
934
|
-
defineTool(server, "subscriptions_replay", "Replay a block range for a subscription. Replays run at 10% of batch capacity — use sparingly.", {
|
|
1053
|
+
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.", {
|
|
935
1054
|
id: z9.string(),
|
|
936
1055
|
fromBlock: z9.number().int().nonnegative(),
|
|
937
|
-
toBlock: z9.number().int().nonnegative()
|
|
938
|
-
|
|
1056
|
+
toBlock: z9.number().int().nonnegative(),
|
|
1057
|
+
force: z9.string().optional().describe("Idempotency suffix to force a duplicate replay of the range")
|
|
1058
|
+
}, async ({ id, fromBlock, toBlock, force }) => {
|
|
939
1059
|
const res = await clientProvider().subscriptions.replay(id, {
|
|
940
1060
|
fromBlock,
|
|
941
|
-
toBlock
|
|
1061
|
+
toBlock,
|
|
1062
|
+
...force !== undefined ? { force } : {}
|
|
942
1063
|
});
|
|
943
1064
|
return {
|
|
944
1065
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
@@ -991,5 +1112,5 @@ export {
|
|
|
991
1112
|
createServer
|
|
992
1113
|
};
|
|
993
1114
|
|
|
994
|
-
//# debugId=
|
|
1115
|
+
//# debugId=EDBF6A8CAB6C22E864756E2164756E21
|
|
995
1116
|
//# sourceMappingURL=index.js.map
|