@secondlayer/mcp 3.1.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/bin-http.js +174 -81
- package/dist/bin-http.js.map +10 -10
- package/dist/bin.js +174 -81
- package/dist/bin.js.map +10 -10
- package/dist/index.js +174 -81
- package/dist/index.js.map +10 -10
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -61,6 +61,14 @@ bunx -p @secondlayer/mcp secondlayer-mcp-http
|
|
|
61
61
|
| **Scaffold** (2) | `scaffold_from_contract`, `scaffold_from_abi` |
|
|
62
62
|
| **Account** (3) | `account_whoami`, `account_update`, `account_billing` |
|
|
63
63
|
|
|
64
|
+
### `subscriptions_create` kinds
|
|
65
|
+
|
|
66
|
+
Subscriptions are polymorphic. Pass `subgraphName` + `tableName` for a
|
|
67
|
+
**subgraph** subscription, or a `triggers` array for a **chain** subscription —
|
|
68
|
+
a webhook on raw chain events (contract / event / function / trait) with no
|
|
69
|
+
subgraph (e.g. `[{ "type": "contract_call", "contractId": "SP....amm",
|
|
70
|
+
"functionName": "swap-*" }]`).
|
|
71
|
+
|
|
64
72
|
### `subgraphs_query` enhancements
|
|
65
73
|
|
|
66
74
|
- `fields` — comma-separated column projection (e.g. `"sender,amount_x"`)
|
package/dist/bin-http.js
CHANGED
|
@@ -75,6 +75,34 @@ function jsonResponse(data, isError) {
|
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// src/lib/tool.ts
|
|
79
|
+
var registeredToolNames = new Set;
|
|
80
|
+
function getRegisteredToolNames() {
|
|
81
|
+
return [...registeredToolNames];
|
|
82
|
+
}
|
|
83
|
+
function defineTool(server, name, description, schema, handler) {
|
|
84
|
+
const wrappedHandler = async (args) => {
|
|
85
|
+
try {
|
|
86
|
+
return await handler(args);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
89
|
+
const status = err instanceof Error && "status" in err ? err.status : 0;
|
|
90
|
+
const type = status === 401 ? "unauthorized" : status === 404 ? "not_found" : status === 429 ? "rate_limited" : status >= 500 ? "server_error" : "error";
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: "text",
|
|
95
|
+
text: JSON.stringify({ error: { type, status, message } })
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
isError: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
registeredToolNames.add(name);
|
|
103
|
+
server.tool(name, description, schema, wrappedHandler);
|
|
104
|
+
}
|
|
105
|
+
|
|
78
106
|
// src/resources.ts
|
|
79
107
|
var FILTERS_REFERENCE = [
|
|
80
108
|
{
|
|
@@ -130,39 +158,69 @@ var COLUMN_TYPES = [
|
|
|
130
158
|
description: "Column options: nullable allows NULL, indexed creates a B-tree index, search enables full-text search"
|
|
131
159
|
}
|
|
132
160
|
];
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
],
|
|
143
|
-
discoverFirst: "Call datasets_list / contracts_find to learn what exists before querying."
|
|
161
|
+
var PRODUCT_BLURBS = {
|
|
162
|
+
datasets: "public foundation datasets",
|
|
163
|
+
index: "decoded L2 events, contract calls, blocks, transactions, stacking, mempool",
|
|
164
|
+
streams: "raw canonical chain event firehose",
|
|
165
|
+
contracts: "trait-based contract discovery",
|
|
166
|
+
subgraphs: "author/deploy/query custom indexes",
|
|
167
|
+
subscriptions: "webhook delivery on subgraph rows or raw chain events",
|
|
168
|
+
account: "identity, plan, billing, and API keys",
|
|
169
|
+
scaffold: "generate typed contract clients from a deployment or ABI"
|
|
144
170
|
};
|
|
171
|
+
var PRODUCT_ORDER = [
|
|
172
|
+
"datasets",
|
|
173
|
+
"index",
|
|
174
|
+
"streams",
|
|
175
|
+
"contracts",
|
|
176
|
+
"subgraphs",
|
|
177
|
+
"subscriptions",
|
|
178
|
+
"account",
|
|
179
|
+
"scaffold"
|
|
180
|
+
];
|
|
181
|
+
function buildCapabilities() {
|
|
182
|
+
const byPrefix = new Map;
|
|
183
|
+
for (const name of getRegisteredToolNames()) {
|
|
184
|
+
const prefix = name.slice(0, name.indexOf("_"));
|
|
185
|
+
const tools = byPrefix.get(prefix) ?? [];
|
|
186
|
+
tools.push(name);
|
|
187
|
+
byPrefix.set(prefix, tools);
|
|
188
|
+
}
|
|
189
|
+
const order = [
|
|
190
|
+
...PRODUCT_ORDER.filter((p) => byPrefix.has(p)),
|
|
191
|
+
...[...byPrefix.keys()].filter((p) => !PRODUCT_ORDER.includes(p))
|
|
192
|
+
];
|
|
193
|
+
const products = order.map((p) => {
|
|
194
|
+
const tools = byPrefix.get(p) ?? [];
|
|
195
|
+
const blurb = PRODUCT_BLURBS[p];
|
|
196
|
+
return blurb ? `${p} — ${blurb} (${tools.join(", ")})` : `${p} (${tools.join(", ")})`;
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
products,
|
|
200
|
+
discoverFirst: "Call datasets_list / contracts_find to learn what exists before querying."
|
|
201
|
+
};
|
|
202
|
+
}
|
|
145
203
|
var READ_AUTH_TIERS = {
|
|
146
204
|
datasets: "open — no API key required",
|
|
147
205
|
index: "anonymous reads allowed; free-tier API keys are rejected (Build+ required)",
|
|
148
206
|
streams: "API key required (SL_API_KEY) — keyless calls return 401",
|
|
149
207
|
subgraphs: "reads public during open beta; writes require an API key"
|
|
150
208
|
};
|
|
151
|
-
async function buildContext(deps = {
|
|
152
|
-
clientProvider: getClient,
|
|
153
|
-
accountRequest: () => apiRequest("GET", "/api/accounts/me")
|
|
154
|
-
}) {
|
|
209
|
+
async function buildContext(deps = { clientProvider: getClient }) {
|
|
155
210
|
const unavailable = "unavailable: set SL_API_KEY";
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
count: r.data.length,
|
|
159
|
-
statuses: r.data.map((s) => s.status)
|
|
160
|
-
})).catch(() => unavailable);
|
|
161
|
-
const account = await deps.accountRequest().catch(() => unavailable);
|
|
211
|
+
const orNull = (v) => v == null ? unavailable : v;
|
|
212
|
+
const snap = await deps.clientProvider().context().catch(() => null);
|
|
162
213
|
return {
|
|
163
214
|
authState: { apiKeySet: Boolean(process.env.SL_API_KEY) },
|
|
164
|
-
whatExists: {
|
|
165
|
-
|
|
215
|
+
whatExists: {
|
|
216
|
+
account: orNull(snap?.account),
|
|
217
|
+
streamsTip: orNull(snap?.streamsTip),
|
|
218
|
+
indexTip: orNull(snap?.indexTip),
|
|
219
|
+
subgraphs: snap?.subgraphs ? snap.subgraphs.map(formatSubgraphSummary) : unavailable,
|
|
220
|
+
subscriptions: orNull(snap?.subscriptions),
|
|
221
|
+
activeOperations: orNull(snap?.activeOperations)
|
|
222
|
+
},
|
|
223
|
+
whatYouCanDo: buildCapabilities(),
|
|
166
224
|
readAuthTiers: READ_AUTH_TIERS
|
|
167
225
|
};
|
|
168
226
|
}
|
|
@@ -200,31 +258,6 @@ function registerResources(server) {
|
|
|
200
258
|
|
|
201
259
|
// src/tools/account.ts
|
|
202
260
|
import { z } from "zod/v4";
|
|
203
|
-
|
|
204
|
-
// src/lib/tool.ts
|
|
205
|
-
function defineTool(server, name, description, schema, handler) {
|
|
206
|
-
const wrappedHandler = async (args) => {
|
|
207
|
-
try {
|
|
208
|
-
return await handler(args);
|
|
209
|
-
} catch (err) {
|
|
210
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
211
|
-
const status = err instanceof Error && "status" in err ? err.status : 0;
|
|
212
|
-
const type = status === 401 ? "unauthorized" : status === 404 ? "not_found" : status === 429 ? "rate_limited" : status >= 500 ? "server_error" : "error";
|
|
213
|
-
return {
|
|
214
|
-
content: [
|
|
215
|
-
{
|
|
216
|
-
type: "text",
|
|
217
|
-
text: JSON.stringify({ error: { type, status, message } })
|
|
218
|
-
}
|
|
219
|
-
],
|
|
220
|
-
isError: true
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
server.tool(name, description, schema, wrappedHandler);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// src/tools/account.ts
|
|
228
261
|
function registerAccountTools(server) {
|
|
229
262
|
defineTool(server, "account_whoami", "Show the authenticated account's email and plan.", {}, async () => {
|
|
230
263
|
const result = await apiRequest("GET", "/api/accounts/me");
|
|
@@ -249,6 +282,10 @@ function registerAccountTools(server) {
|
|
|
249
282
|
const result = await apiRequest("GET", "/api/billing/status");
|
|
250
283
|
return jsonResponse(result);
|
|
251
284
|
});
|
|
285
|
+
defineTool(server, "account_create_key", "Mint a scoped streams/index read API key so the agent can self-provision access. Requires an account-level (owner) API key. The returned `key` is shown ONCE — forward it to the user to set as SL_API_KEY.", {
|
|
286
|
+
product: z.enum(["streams", "index"]).optional().describe("Key scope (default streams)"),
|
|
287
|
+
name: z.string().optional().describe("Optional label for the key")
|
|
288
|
+
}, async ({ product, name }) => jsonResponse(await getClient().apiKeys.create({ product, name })));
|
|
252
289
|
}
|
|
253
290
|
|
|
254
291
|
// src/tools/contracts.ts
|
|
@@ -287,20 +324,9 @@ function registerDatasetTools(server, clientProvider = getClient) {
|
|
|
287
324
|
}
|
|
288
325
|
|
|
289
326
|
// src/tools/index.ts
|
|
327
|
+
import { DECODED_EVENT_TYPES } from "@secondlayer/shared";
|
|
290
328
|
import { z as z4 } from "zod/v4";
|
|
291
|
-
var INDEX_EVENT_TYPES =
|
|
292
|
-
"ft_transfer",
|
|
293
|
-
"nft_transfer",
|
|
294
|
-
"stx_transfer",
|
|
295
|
-
"stx_mint",
|
|
296
|
-
"stx_burn",
|
|
297
|
-
"stx_lock",
|
|
298
|
-
"ft_mint",
|
|
299
|
-
"ft_burn",
|
|
300
|
-
"nft_mint",
|
|
301
|
-
"nft_burn",
|
|
302
|
-
"print"
|
|
303
|
-
];
|
|
329
|
+
var INDEX_EVENT_TYPES = DECODED_EVENT_TYPES;
|
|
304
330
|
var rangeFilters = {
|
|
305
331
|
contractId: z4.string().optional().describe("Filter by contract id"),
|
|
306
332
|
fromHeight: z4.number().optional().describe("Start block height (inclusive)"),
|
|
@@ -308,6 +334,13 @@ var rangeFilters = {
|
|
|
308
334
|
cursor: z4.string().optional().describe("Opaque cursor from a prior response's next_cursor"),
|
|
309
335
|
limit: z4.number().optional().describe("Max rows for this page")
|
|
310
336
|
};
|
|
337
|
+
var heightFilters = {
|
|
338
|
+
fromHeight: rangeFilters.fromHeight,
|
|
339
|
+
toHeight: rangeFilters.toHeight,
|
|
340
|
+
cursor: rangeFilters.cursor,
|
|
341
|
+
limit: rangeFilters.limit
|
|
342
|
+
};
|
|
343
|
+
var notFound = (message) => jsonResponse({ error: { type: "not_found", status: 404, message } }, true);
|
|
311
344
|
function registerIndexTools(server, clientProvider = getClient) {
|
|
312
345
|
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).", {
|
|
313
346
|
...rangeFilters,
|
|
@@ -332,6 +365,41 @@ function registerIndexTools(server, clientProvider = getClient) {
|
|
|
332
365
|
functionName: z4.string().optional().describe("Filter by called function name"),
|
|
333
366
|
sender: z4.string().optional().describe("Filter by caller principal")
|
|
334
367
|
}, async (params) => jsonResponse(await clientProvider().index.contractCalls.list(params)));
|
|
368
|
+
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)));
|
|
369
|
+
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)));
|
|
370
|
+
defineTool(server, "index_block", "Get a single block from the Index by height or block hash. Returns not_found if unknown.", {
|
|
371
|
+
ref: z4.string().describe("Block height (digits) or block hash (0x… string)")
|
|
372
|
+
}, async ({ ref }) => {
|
|
373
|
+
const block = await clientProvider().index.blocks.get(/^\d+$/.test(ref) ? Number(ref) : ref);
|
|
374
|
+
return block ? jsonResponse(block) : notFound(`No block for ref ${ref}`);
|
|
375
|
+
});
|
|
376
|
+
defineTool(server, "index_transactions", "List decoded transactions from the Index. Filter by type, sender, or contract. Anonymous reads allowed (free-tier keys rejected).", {
|
|
377
|
+
...rangeFilters,
|
|
378
|
+
type: z4.string().optional().describe("Filter by transaction type"),
|
|
379
|
+
sender: z4.string().optional().describe("Filter by sender principal")
|
|
380
|
+
}, async (params) => jsonResponse(await clientProvider().index.transactions.list(params)));
|
|
381
|
+
defineTool(server, "index_transaction", "Get a single transaction from the Index by tx_id. Returns not_found if unknown.", { txId: z4.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
382
|
+
const tx = await clientProvider().index.transactions.get(txId);
|
|
383
|
+
return tx ? jsonResponse(tx) : notFound(`No transaction for ${txId}`);
|
|
384
|
+
});
|
|
385
|
+
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).", {
|
|
386
|
+
...heightFilters,
|
|
387
|
+
functionName: z4.string().optional().describe("Filter by PoX function name"),
|
|
388
|
+
stacker: z4.string().optional().describe("Filter by stacker principal"),
|
|
389
|
+
caller: z4.string().optional().describe("Filter by caller principal")
|
|
390
|
+
}, async (params) => jsonResponse(await clientProvider().index.stacking.list(params)));
|
|
391
|
+
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).", {
|
|
392
|
+
sender: z4.string().optional().describe("Filter by sender principal"),
|
|
393
|
+
type: z4.string().optional().describe("Filter by transaction type"),
|
|
394
|
+
contractId: z4.string().optional().describe("Filter to pending calls to a single contract"),
|
|
395
|
+
cursor: z4.string().optional().describe("Opaque cursor from a prior response's next_cursor"),
|
|
396
|
+
limit: z4.number().optional().describe("Max rows for this page")
|
|
397
|
+
}, async (params) => jsonResponse(await clientProvider().index.mempool.list(params)));
|
|
398
|
+
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: z4.string().describe("Transaction id (0x… hash)") }, async ({ txId }) => {
|
|
399
|
+
const tx = await clientProvider().index.mempool.get(txId);
|
|
400
|
+
return tx ? jsonResponse(tx) : notFound(`No pending tx for ${txId}`);
|
|
401
|
+
});
|
|
402
|
+
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()));
|
|
335
403
|
}
|
|
336
404
|
|
|
337
405
|
// src/tools/scaffold.ts
|
|
@@ -383,20 +451,9 @@ function registerScaffoldTools(server) {
|
|
|
383
451
|
|
|
384
452
|
// src/tools/streams.ts
|
|
385
453
|
import { AuthError } from "@secondlayer/sdk";
|
|
454
|
+
import { DECODED_EVENT_TYPES as DECODED_EVENT_TYPES2 } from "@secondlayer/shared";
|
|
386
455
|
import { z as z6 } from "zod/v4";
|
|
387
|
-
var STREAMS_EVENT_TYPES =
|
|
388
|
-
"stx_transfer",
|
|
389
|
-
"stx_mint",
|
|
390
|
-
"stx_burn",
|
|
391
|
-
"stx_lock",
|
|
392
|
-
"ft_transfer",
|
|
393
|
-
"ft_mint",
|
|
394
|
-
"ft_burn",
|
|
395
|
-
"nft_transfer",
|
|
396
|
-
"nft_mint",
|
|
397
|
-
"nft_burn",
|
|
398
|
-
"print"
|
|
399
|
-
];
|
|
456
|
+
var STREAMS_EVENT_TYPES = DECODED_EVENT_TYPES2;
|
|
400
457
|
async function withStreamsAuthHint(fn) {
|
|
401
458
|
try {
|
|
402
459
|
return await fn();
|
|
@@ -416,11 +473,21 @@ function registerStreamsTools(server, clientProvider = getClient) {
|
|
|
416
473
|
sender: z6.string().optional().describe("Filter by sender principal"),
|
|
417
474
|
recipient: z6.string().optional().describe("Filter by recipient principal"),
|
|
418
475
|
assetIdentifier: z6.string().optional().describe("Filter by asset identifier"),
|
|
419
|
-
|
|
420
|
-
|
|
476
|
+
fromHeight: z6.number().optional().describe("Start block height (inclusive)"),
|
|
477
|
+
toHeight: z6.number().optional().describe("End block height (inclusive)"),
|
|
421
478
|
cursor: z6.string().optional().describe("Opaque cursor from a prior response"),
|
|
422
479
|
limit: z6.number().optional().describe("Max events for this page")
|
|
423
480
|
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.events.list(params))));
|
|
481
|
+
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))));
|
|
482
|
+
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).", {
|
|
483
|
+
heightOrHash: z6.string().describe("Block height (digits) or block hash (0x… string)")
|
|
484
|
+
}, async ({ heightOrHash }) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.blocks.events(/^\d+$/.test(heightOrHash) ? Number(heightOrHash) : heightOrHash))));
|
|
485
|
+
defineTool(server, "streams_reorgs", "List chain reorgs observed by Streams since a cursor. Streams requires an API key (SL_API_KEY).", {
|
|
486
|
+
since: z6.string().describe("Cursor to list reorgs since (block:index or ISO timestamp)"),
|
|
487
|
+
limit: z6.number().optional().describe("Max reorgs to return")
|
|
488
|
+
}, async (params) => withStreamsAuthHint(async () => jsonResponse(await clientProvider().streams.reorgs.list(params))));
|
|
489
|
+
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))));
|
|
490
|
+
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())));
|
|
424
491
|
}
|
|
425
492
|
|
|
426
493
|
// src/tools/subgraphs.ts
|
|
@@ -501,7 +568,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
501
568
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
502
569
|
};
|
|
503
570
|
});
|
|
504
|
-
defineTool(server, "subgraphs_reindex", "Reindex a subgraph from a specific block range.", {
|
|
571
|
+
defineTool(server, "subgraphs_reindex", "Reindex a subgraph from a specific block range. Returns an operationId — poll subgraphs_operation to track progress to completion.", {
|
|
505
572
|
name: z7.string().describe("Subgraph name"),
|
|
506
573
|
fromBlock: z7.number().optional().describe("Start block (defaults to beginning)"),
|
|
507
574
|
toBlock: z7.number().optional().describe("End block (defaults to latest)")
|
|
@@ -514,6 +581,15 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
514
581
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
515
582
|
};
|
|
516
583
|
});
|
|
584
|
+
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.", {
|
|
585
|
+
name: z7.string().describe("Subgraph name"),
|
|
586
|
+
operationId: z7.string().optional().describe("Operation id from reindex/backfill/stop; omit to list recent operations")
|
|
587
|
+
}, async ({ name, operationId }) => {
|
|
588
|
+
const result = operationId ? await clientProvider().subgraphs.getOperation(name, operationId) : await clientProvider().subgraphs.operations(name);
|
|
589
|
+
return {
|
|
590
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
591
|
+
};
|
|
592
|
+
});
|
|
517
593
|
defineTool(server, "subgraphs_delete", "Delete a subgraph permanently.", { name: z7.string().describe("Subgraph name") }, async ({ name }) => {
|
|
518
594
|
const result = await clientProvider().subgraphs.delete(name);
|
|
519
595
|
return { content: [{ type: "text", text: result.message }] };
|
|
@@ -546,6 +622,7 @@ function registerSubgraphTools(server, clientProvider = getClient) {
|
|
|
546
622
|
}
|
|
547
623
|
|
|
548
624
|
// src/tools/subscriptions.ts
|
|
625
|
+
import { CHAIN_TRIGGER_TYPES } from "@secondlayer/shared";
|
|
549
626
|
import { z as z8 } from "zod/v4";
|
|
550
627
|
function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
551
628
|
defineTool(server, "subscriptions_list", "List all subscriptions for the current account. Returns summary fields (no secrets).", {}, async () => {
|
|
@@ -560,10 +637,26 @@ function registerSubscriptionTools(server, clientProvider = getClient) {
|
|
|
560
637
|
content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
|
|
561
638
|
};
|
|
562
639
|
});
|
|
563
|
-
defineTool(server, "subscriptions_create", "Create a subscription. Returns `signingSecret` ONCE — forward it to the user so they can wire it into their receiver.", {
|
|
640
|
+
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.", {
|
|
564
641
|
name: z8.string().describe("Human-readable name, unique per account"),
|
|
565
|
-
subgraphName: z8.string().describe("Subgraph to subscribe to"),
|
|
566
|
-
tableName: z8.string().describe("Table within the subgraph"),
|
|
642
|
+
subgraphName: z8.string().optional().describe("Subgraph to subscribe to (subgraph subscription)"),
|
|
643
|
+
tableName: z8.string().optional().describe("Table within the subgraph (subgraph subscription)"),
|
|
644
|
+
triggers: z8.array(z8.object({
|
|
645
|
+
type: z8.enum(CHAIN_TRIGGER_TYPES),
|
|
646
|
+
contractId: z8.string().optional(),
|
|
647
|
+
functionName: z8.string().optional(),
|
|
648
|
+
caller: z8.string().optional(),
|
|
649
|
+
sender: z8.string().optional(),
|
|
650
|
+
recipient: z8.string().optional(),
|
|
651
|
+
assetIdentifier: z8.string().optional(),
|
|
652
|
+
deployer: z8.string().optional(),
|
|
653
|
+
contractName: z8.string().optional(),
|
|
654
|
+
topic: z8.string().optional(),
|
|
655
|
+
lockedAddress: z8.string().optional(),
|
|
656
|
+
trait: z8.string().optional(),
|
|
657
|
+
minAmount: z8.union([z8.string(), z8.number()]).optional(),
|
|
658
|
+
maxAmount: z8.union([z8.string(), z8.number()]).optional()
|
|
659
|
+
})).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."),
|
|
567
660
|
url: z8.string().describe("Webhook URL"),
|
|
568
661
|
format: z8.enum([
|
|
569
662
|
"standard-webhooks",
|
|
@@ -769,5 +862,5 @@ httpServer.listen(port, () => {
|
|
|
769
862
|
console.error("Warning: SECONDLAYER_MCP_SECRET not set, authentication disabled");
|
|
770
863
|
});
|
|
771
864
|
|
|
772
|
-
//# debugId=
|
|
865
|
+
//# debugId=587F4DDF9A78B13764756E2164756E21
|
|
773
866
|
//# sourceMappingURL=bin-http.js.map
|