@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/bin-http.js
CHANGED
|
@@ -13,6 +13,8 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
|
|
15
15
|
// src/resources.ts
|
|
16
|
+
import { CHAIN_TRIGGER_FIELDS, DECODED_EVENT_TYPES } from "@secondlayer/shared";
|
|
17
|
+
import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
|
|
16
18
|
import { TYPE_MAP } from "@secondlayer/subgraphs/schema";
|
|
17
19
|
|
|
18
20
|
// src/lib/client.ts
|
|
@@ -25,10 +27,12 @@ function getClient() {
|
|
|
25
27
|
if (!instance) {
|
|
26
28
|
const apiKey = readApiKey();
|
|
27
29
|
const baseUrl = process.env.SECONDLAYER_API_URL;
|
|
30
|
+
const dumpsBaseUrl = process.env.SL_STREAMS_DUMPS_URL;
|
|
28
31
|
instance = new SecondLayer({
|
|
29
32
|
...apiKey ? { apiKey } : {},
|
|
30
33
|
origin: "mcp",
|
|
31
|
-
...baseUrl ? { baseUrl } : {}
|
|
34
|
+
...baseUrl ? { baseUrl } : {},
|
|
35
|
+
...dumpsBaseUrl ? { dumpsBaseUrl } : {}
|
|
32
36
|
});
|
|
33
37
|
}
|
|
34
38
|
return instance;
|
|
@@ -107,6 +111,11 @@ function defineTool(server, name, description, schema, handler) {
|
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
// src/resources.ts
|
|
114
|
+
var TRAIT_BLURBS = {
|
|
115
|
+
"sip-009": "Non-fungible token (NFT) standard",
|
|
116
|
+
"sip-010": "Fungible token standard",
|
|
117
|
+
"sip-013": "Semi-fungible token standard"
|
|
118
|
+
};
|
|
110
119
|
var FILTERS_REFERENCE = [
|
|
111
120
|
{
|
|
112
121
|
type: "stx_transfer",
|
|
@@ -201,7 +210,7 @@ function buildCapabilities() {
|
|
|
201
210
|
});
|
|
202
211
|
return {
|
|
203
212
|
products,
|
|
204
|
-
discoverFirst: "Call datasets_list / contracts_find to learn what exists before querying."
|
|
213
|
+
discoverFirst: "Call datasets_list / index_discover / contracts_find to learn what exists (and which filters each surface accepts) before querying."
|
|
205
214
|
};
|
|
206
215
|
}
|
|
207
216
|
var READ_AUTH_TIERS = {
|
|
@@ -260,6 +269,56 @@ function registerResources(server) {
|
|
|
260
269
|
}
|
|
261
270
|
]
|
|
262
271
|
}));
|
|
272
|
+
server.resource("traits", "secondlayer://traits", {
|
|
273
|
+
description: "SIP trait standards the platform can classify and scaffold against — the valid values for contracts_find `trait` and subgraph scaffold `--trait`."
|
|
274
|
+
}, async () => ({
|
|
275
|
+
contents: [
|
|
276
|
+
{
|
|
277
|
+
uri: "secondlayer://traits",
|
|
278
|
+
mimeType: "application/json",
|
|
279
|
+
text: JSON.stringify({
|
|
280
|
+
traits: TRAIT_STANDARDS.map((id) => ({
|
|
281
|
+
id,
|
|
282
|
+
description: TRAIT_BLURBS[id]
|
|
283
|
+
}))
|
|
284
|
+
}, null, 2)
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}));
|
|
288
|
+
server.resource("streams-filters", "secondlayer://streams-filters", {
|
|
289
|
+
description: "Streams firehose vocabulary — the decoded event types and the filter fields accepted by streams_events / streams_consume."
|
|
290
|
+
}, async () => ({
|
|
291
|
+
contents: [
|
|
292
|
+
{
|
|
293
|
+
uri: "secondlayer://streams-filters",
|
|
294
|
+
mimeType: "application/json",
|
|
295
|
+
text: JSON.stringify({
|
|
296
|
+
eventTypes: [...DECODED_EVENT_TYPES],
|
|
297
|
+
filters: {
|
|
298
|
+
types: "include only these event types (array)",
|
|
299
|
+
notTypes: "exclude these event types (array)",
|
|
300
|
+
contractId: "match a contract id",
|
|
301
|
+
sender: "match the sender principal",
|
|
302
|
+
recipient: "match the recipient principal",
|
|
303
|
+
assetIdentifier: "match the asset identifier (contract::asset)",
|
|
304
|
+
fromHeight: "start block height (inclusive)",
|
|
305
|
+
toHeight: "end block height (inclusive)"
|
|
306
|
+
}
|
|
307
|
+
}, null, 2)
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
}));
|
|
311
|
+
server.resource("chain-triggers", "secondlayer://chain-triggers", {
|
|
312
|
+
description: "Chain-subscription trigger types and the filter fields each accepts (for subscriptions_create triggers)."
|
|
313
|
+
}, async () => ({
|
|
314
|
+
contents: [
|
|
315
|
+
{
|
|
316
|
+
uri: "secondlayer://chain-triggers",
|
|
317
|
+
mimeType: "application/json",
|
|
318
|
+
text: JSON.stringify(CHAIN_TRIGGER_FIELDS, null, 2)
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
}));
|
|
263
322
|
}
|
|
264
323
|
|
|
265
324
|
// src/tools/account.ts
|
|
@@ -284,7 +343,7 @@ function registerAccountTools(server) {
|
|
|
284
343
|
const result = await apiRequest("PATCH", "/api/accounts/me", body);
|
|
285
344
|
return jsonResponse(result);
|
|
286
345
|
});
|
|
287
|
-
defineTool(server, "account_billing", "Show the account's plan and subscription/billing status. Requires an API key.", {}, async () => {
|
|
346
|
+
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 () => {
|
|
288
347
|
const result = await apiRequest("GET", "/api/billing/status");
|
|
289
348
|
return jsonResponse(result);
|
|
290
349
|
});
|
|
@@ -312,6 +371,7 @@ function registerAccountTools(server) {
|
|
|
312
371
|
}
|
|
313
372
|
|
|
314
373
|
// src/tools/contracts.ts
|
|
374
|
+
import { generateContractInterface } from "@secondlayer/scaffold";
|
|
315
375
|
import { z as z2 } from "zod/v4";
|
|
316
376
|
function registerContractTools(server, clientProvider = getClient) {
|
|
317
377
|
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.', {
|
|
@@ -321,6 +381,47 @@ function registerContractTools(server, clientProvider = getClient) {
|
|
|
321
381
|
limit: z2.number().optional().describe("Page size, 1–500 (default 100)"),
|
|
322
382
|
cursor: z2.string().optional().describe("Opaque cursor from a prior response's next_cursor")
|
|
323
383
|
}, async (params) => jsonResponse(await clientProvider().contracts.list(params)));
|
|
384
|
+
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.", {
|
|
385
|
+
contractId: z2.string().describe("Fully qualified contract id (e.g. SP….amm-pool-v2-01)")
|
|
386
|
+
}, async ({ contractId }) => {
|
|
387
|
+
const contract = await clientProvider().contracts.get(contractId, {
|
|
388
|
+
includeAbi: true
|
|
389
|
+
});
|
|
390
|
+
return contract ? jsonResponse(contract) : jsonResponse({
|
|
391
|
+
error: {
|
|
392
|
+
type: "not_found",
|
|
393
|
+
status: 404,
|
|
394
|
+
message: `Contract not in registry: ${contractId}`
|
|
395
|
+
}
|
|
396
|
+
}, true);
|
|
397
|
+
});
|
|
398
|
+
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.", {
|
|
399
|
+
contractId: z2.string().describe("Fully qualified contract id (e.g. SP….amm-pool-v2-01)")
|
|
400
|
+
}, async ({ contractId }) => {
|
|
401
|
+
const c = await clientProvider().contracts.get(contractId, {
|
|
402
|
+
includeAbi: true
|
|
403
|
+
});
|
|
404
|
+
if (!c || !c.abi) {
|
|
405
|
+
return jsonResponse({
|
|
406
|
+
error: {
|
|
407
|
+
type: "not_found",
|
|
408
|
+
status: 404,
|
|
409
|
+
message: `Contract not in registry: ${contractId}`
|
|
410
|
+
}
|
|
411
|
+
}, true);
|
|
412
|
+
}
|
|
413
|
+
const [address, contractName] = contractId.split(".");
|
|
414
|
+
const name = (contractName ?? contractId).replace(/[^a-zA-Z0-9]/g, "_");
|
|
415
|
+
const code = generateContractInterface([
|
|
416
|
+
{
|
|
417
|
+
name,
|
|
418
|
+
address,
|
|
419
|
+
contractName: contractName ?? "",
|
|
420
|
+
abi: c.abi
|
|
421
|
+
}
|
|
422
|
+
]);
|
|
423
|
+
return { content: [{ type: "text", text: code }] };
|
|
424
|
+
});
|
|
324
425
|
}
|
|
325
426
|
|
|
326
427
|
// src/tools/datasets.ts
|
|
@@ -347,13 +448,13 @@ function registerDatasetTools(server, clientProvider = getClient) {
|
|
|
347
448
|
}
|
|
348
449
|
|
|
349
450
|
// src/tools/index.ts
|
|
350
|
-
import { DECODED_EVENT_TYPES } from "@secondlayer/shared";
|
|
451
|
+
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES2 } from "@secondlayer/shared";
|
|
351
452
|
import {
|
|
352
|
-
|
|
353
|
-
|
|
453
|
+
INDEX_CODEGEN_TABLES,
|
|
454
|
+
generateIndexSchema
|
|
354
455
|
} from "@secondlayer/subgraphs";
|
|
355
456
|
import { z as z4 } from "zod/v4";
|
|
356
|
-
var INDEX_EVENT_TYPES =
|
|
457
|
+
var INDEX_EVENT_TYPES = DECODED_EVENT_TYPES2;
|
|
357
458
|
var rangeFilters = {
|
|
358
459
|
contractId: z4.string().optional().describe("Filter by contract id"),
|
|
359
460
|
fromHeight: z4.number().optional().describe("Start block height (inclusive)"),
|
|
@@ -380,17 +481,19 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
380
481
|
recipient: z4.string().optional().describe("Filter by recipient principal"),
|
|
381
482
|
assetIdentifier: z4.string().optional().describe("Filter by asset identifier (contract::asset)")
|
|
382
483
|
}, async (params) => jsonResponse(await clientProvider().index.nftTransfers.list(params)));
|
|
383
|
-
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.", {
|
|
484
|
+
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.", {
|
|
384
485
|
eventType: z4.enum(INDEX_EVENT_TYPES).describe("Required. Decoded event type to list."),
|
|
385
486
|
...rangeFilters,
|
|
386
487
|
sender: z4.string().optional().describe("Filter by sender principal"),
|
|
387
488
|
recipient: z4.string().optional().describe("Filter by recipient principal"),
|
|
388
|
-
assetIdentifier: z4.string().optional().describe("Filter by asset identifier where applicable")
|
|
489
|
+
assetIdentifier: z4.string().optional().describe("Filter by asset identifier where applicable"),
|
|
490
|
+
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.")
|
|
389
491
|
}, async (params) => jsonResponse(await clientProvider().index.events.list(params)));
|
|
390
|
-
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.", {
|
|
492
|
+
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.", {
|
|
391
493
|
...rangeFilters,
|
|
392
494
|
functionName: z4.string().optional().describe("Filter by called function name"),
|
|
393
|
-
sender: z4.string().optional().describe("Filter by caller principal")
|
|
495
|
+
sender: z4.string().optional().describe("Filter by caller principal"),
|
|
496
|
+
trait: z4.string().optional().describe("Match contracts conforming to a trait/standard (e.g. sip-010). Mutually exclusive with contractId.")
|
|
394
497
|
}, async (params) => jsonResponse(await clientProvider().index.contractCalls.list(params)));
|
|
395
498
|
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)));
|
|
396
499
|
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)));
|
|
@@ -409,6 +512,10 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
409
512
|
const tx = await clientProvider().index.transactions.get(txId);
|
|
410
513
|
return tx ? jsonResponse(tx) : notFound(`No transaction for ${txId}`);
|
|
411
514
|
});
|
|
515
|
+
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 }) => {
|
|
516
|
+
const proof = await clientProvider().index.transactions.getProof(txId);
|
|
517
|
+
return proof ? jsonResponse(proof) : notFound(`No proof available for ${txId}`);
|
|
518
|
+
});
|
|
412
519
|
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).", {
|
|
413
520
|
...heightFilters,
|
|
414
521
|
functionName: z4.string().optional().describe("Filter by PoX function name"),
|
|
@@ -426,6 +533,7 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
426
533
|
const tx = await clientProvider().index.mempool.get(txId);
|
|
427
534
|
return tx ? jsonResponse(tx) : notFound(`No pending tx for ${txId}`);
|
|
428
535
|
});
|
|
536
|
+
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()));
|
|
429
537
|
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()));
|
|
430
538
|
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(", ")}.`, {
|
|
431
539
|
target: z4.enum(["prisma", "kysely", "drizzle", "json-schema"]).optional().describe("Output target (default kysely)"),
|
|
@@ -472,25 +580,32 @@ function registerProjectTools(server, clientProvider = getClient) {
|
|
|
472
580
|
}
|
|
473
581
|
|
|
474
582
|
// src/tools/scaffold.ts
|
|
475
|
-
import {
|
|
583
|
+
import {
|
|
584
|
+
generateSubgraphCode,
|
|
585
|
+
generateTraitSubgraph
|
|
586
|
+
} from "@secondlayer/scaffold";
|
|
587
|
+
import { TRAIT_STANDARDS as TRAIT_STANDARDS2 } from "@secondlayer/stacks/clarity";
|
|
476
588
|
import { z as z6 } from "zod/v4";
|
|
477
|
-
var API_BASE = process.env.SECONDLAYER_API_URL || "https://api.secondlayer.tools";
|
|
478
589
|
async function fetchAbi(contractId) {
|
|
479
|
-
const
|
|
480
|
-
|
|
590
|
+
const contract = await getClient().contracts.get(contractId, {
|
|
591
|
+
includeAbi: true
|
|
481
592
|
});
|
|
482
|
-
if (!
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
593
|
+
if (!contract)
|
|
594
|
+
throw new Error(`Contract not found: ${contractId}`);
|
|
595
|
+
const abi = contract.abi;
|
|
596
|
+
if (!abi) {
|
|
597
|
+
throw new Error(`No ABI available for ${contractId} (abi_status: ${contract.abi_status})`);
|
|
486
598
|
}
|
|
487
|
-
|
|
488
|
-
return {
|
|
489
|
-
functions: abi.functions ?? [],
|
|
490
|
-
maps: abi.maps ?? []
|
|
491
|
-
};
|
|
599
|
+
return { functions: abi.functions ?? [], maps: abi.maps ?? [] };
|
|
492
600
|
}
|
|
493
601
|
function registerScaffoldTools(server) {
|
|
602
|
+
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.", {
|
|
603
|
+
trait: z6.enum(TRAIT_STANDARDS2).describe("SIP standard to index (sip-009 | sip-010 | sip-013)"),
|
|
604
|
+
subgraphName: z6.string().optional().describe("Override the subgraph name (defaults to <trait>-transfers)")
|
|
605
|
+
}, async ({ trait, subgraphName }) => {
|
|
606
|
+
const code = generateTraitSubgraph({ trait, name: subgraphName });
|
|
607
|
+
return { content: [{ type: "text", text: code }] };
|
|
608
|
+
});
|
|
494
609
|
defineTool(server, "scaffold_from_contract", "Generate a subgraph scaffold from a deployed Stacks contract. Fetches the ABI automatically.", {
|
|
495
610
|
contractId: z6.string().describe("Fully qualified contract ID (e.g. SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01)"),
|
|
496
611
|
subgraphName: z6.string().optional().describe("Override the subgraph name (defaults to contract name)")
|
|
@@ -520,9 +635,9 @@ function registerScaffoldTools(server) {
|
|
|
520
635
|
|
|
521
636
|
// src/tools/streams.ts
|
|
522
637
|
import { AuthError } from "@secondlayer/sdk";
|
|
523
|
-
import { DECODED_EVENT_TYPES as
|
|
638
|
+
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES3 } from "@secondlayer/shared";
|
|
524
639
|
import { z as z7 } from "zod/v4";
|
|
525
|
-
var STREAMS_EVENT_TYPES =
|
|
640
|
+
var STREAMS_EVENT_TYPES = DECODED_EVENT_TYPES3;
|
|
526
641
|
async function withStreamsAuthHint(fn) {
|
|
527
642
|
try {
|
|
528
643
|
return await fn();
|
|
@@ -599,6 +714,7 @@ function registerStreamsTools(server, clientProvider = getClient) {
|
|
|
599
714
|
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.reorgs.list(params))));
|
|
600
715
|
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))));
|
|
601
716
|
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())));
|
|
717
|
+
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()));
|
|
602
718
|
}
|
|
603
719
|
|
|
604
720
|
// src/tools/subgraphs.ts
|
|
@@ -644,7 +760,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
644
760
|
]
|
|
645
761
|
};
|
|
646
762
|
});
|
|
647
|
-
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.', {
|
|
763
|
+
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>"}.', {
|
|
648
764
|
name: z8.string().describe("Subgraph name"),
|
|
649
765
|
table: z8.string().describe("Table name"),
|
|
650
766
|
filters: z8.record(z8.string(), z8.string()).optional().describe('Column filters — plain values or with operators (e.g. {"amount.gte": "1000", "sender": "SP..."})'),
|
|
@@ -869,7 +985,7 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
869
985
|
trait: z9.string().optional(),
|
|
870
986
|
minAmount: z9.union([z9.string(), z9.number()]).optional(),
|
|
871
987
|
maxAmount: z9.union([z9.string(), z9.number()]).optional()
|
|
872
|
-
})).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."),
|
|
988
|
+
})).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."),
|
|
873
989
|
url: z9.string().describe("Webhook URL"),
|
|
874
990
|
format: z9.enum([
|
|
875
991
|
"standard-webhooks",
|
|
@@ -880,17 +996,20 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
880
996
|
"raw"
|
|
881
997
|
]).optional().describe("Wire format (default standard-webhooks)"),
|
|
882
998
|
runtime: z9.enum(["inngest", "trigger", "cloudflare", "node"]).optional().describe("Receiver runtime label (display only)"),
|
|
883
|
-
filter: z9.record(z9.string(), z9.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}')
|
|
999
|
+
filter: z9.record(z9.string(), z9.unknown()).optional().describe('Scalar filter DSL, e.g. {"amount": {"gte": 100}, "sender": "SP..."}'),
|
|
1000
|
+
authConfig: z9.record(z9.string(), z9.unknown()).optional().describe('Receiver auth sent with each delivery, e.g. {"type": "bearer", "token": "..."}')
|
|
884
1001
|
}, async (input) => {
|
|
885
1002
|
const res = await clientProvider().subscriptions.create(input);
|
|
886
1003
|
return {
|
|
887
1004
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
888
1005
|
};
|
|
889
1006
|
});
|
|
890
|
-
defineTool(server, "subscriptions_update", "Patch a subscription (url, filter, format, runtime, retry, timeout, concurrency).", {
|
|
1007
|
+
defineTool(server, "subscriptions_update", "Patch a subscription (name, url, filter, authConfig, format, runtime, retry, timeout, concurrency).", {
|
|
891
1008
|
id: z9.string(),
|
|
1009
|
+
name: z9.string().optional().describe("Rename the subscription"),
|
|
892
1010
|
url: z9.string().optional(),
|
|
893
1011
|
filter: z9.record(z9.string(), z9.unknown()).optional(),
|
|
1012
|
+
authConfig: z9.record(z9.string(), z9.unknown()).optional().describe("Receiver auth sent with each delivery (bearer/etc.)"),
|
|
894
1013
|
format: z9.enum([
|
|
895
1014
|
"standard-webhooks",
|
|
896
1015
|
"inngest",
|
|
@@ -939,14 +1058,16 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
939
1058
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
940
1059
|
};
|
|
941
1060
|
});
|
|
942
|
-
defineTool(server, "subscriptions_replay", "Replay a block range for a subscription. Replays run at 10% of batch capacity — use sparingly.", {
|
|
1061
|
+
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.", {
|
|
943
1062
|
id: z9.string(),
|
|
944
1063
|
fromBlock: z9.number().int().nonnegative(),
|
|
945
|
-
toBlock: z9.number().int().nonnegative()
|
|
946
|
-
|
|
1064
|
+
toBlock: z9.number().int().nonnegative(),
|
|
1065
|
+
force: z9.string().optional().describe("Idempotency suffix to force a duplicate replay of the range")
|
|
1066
|
+
}, async ({ id, fromBlock, toBlock, force }) => {
|
|
947
1067
|
const res = await clientProvider().subscriptions.replay(id, {
|
|
948
1068
|
fromBlock,
|
|
949
|
-
toBlock
|
|
1069
|
+
toBlock,
|
|
1070
|
+
...force !== undefined ? { force } : {}
|
|
950
1071
|
});
|
|
951
1072
|
return {
|
|
952
1073
|
content: [{ type: "text", text: JSON.stringify(res, null, 2) }]
|
|
@@ -1082,5 +1203,5 @@ httpServer.listen(port, () => {
|
|
|
1082
1203
|
console.error("Warning: SECONDLAYER_MCP_SECRET not set, authentication disabled");
|
|
1083
1204
|
});
|
|
1084
1205
|
|
|
1085
|
-
//# debugId=
|
|
1206
|
+
//# debugId=4D2E7E6934E70FD064756E2164756E21
|
|
1086
1207
|
//# sourceMappingURL=bin-http.js.map
|