@secondlayer/mcp 1.0.0 → 1.0.2
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 +2 -4
- package/dist/bin-http.js +19 -420
- package/dist/bin-http.js.map +6 -8
- package/dist/bin.js +19 -420
- package/dist/bin.js.map +6 -8
- package/dist/index.js +19 -420
- package/dist/index.js.map +6 -8
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -45,14 +45,13 @@ npx @secondlayer/mcp-http
|
|
|
45
45
|
|
|
46
46
|
## Tools
|
|
47
47
|
|
|
48
|
-
Tools across
|
|
48
|
+
Tools across 4 domains.
|
|
49
49
|
|
|
50
50
|
| Domain | Tools |
|
|
51
51
|
| --- | --- |
|
|
52
52
|
| **Subgraphs** (6) | `subgraphs_list`, `subgraphs_get`, `subgraphs_query`, `subgraphs_reindex`, `subgraphs_delete`, `subgraphs_deploy` |
|
|
53
53
|
| **Workflows** (6) | `workflows_list`, `workflows_get`, `workflows_trigger`, `workflows_pause`, `workflows_resume`, `workflows_runs` |
|
|
54
54
|
| **Scaffold** (2) | `scaffold_from_contract`, `scaffold_from_abi` |
|
|
55
|
-
| **Templates** (2) | `templates_list`, `templates_get` |
|
|
56
55
|
| **Account** (1) | `account_whoami` |
|
|
57
56
|
|
|
58
57
|
### `subgraphs_query` enhancements
|
|
@@ -64,13 +63,12 @@ Tools across 5 domains.
|
|
|
64
63
|
|
|
65
64
|
## Resources
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
2 MCP resources for agent context:
|
|
68
67
|
|
|
69
68
|
| URI | Description |
|
|
70
69
|
| --- | --- |
|
|
71
70
|
| `secondlayer://filters` | Filter types reference |
|
|
72
71
|
| `secondlayer://column-types` | Column type mappings and options |
|
|
73
|
-
| `secondlayer://templates` | Available subgraph templates |
|
|
74
72
|
|
|
75
73
|
## Error Handling
|
|
76
74
|
|
package/dist/bin-http.js
CHANGED
|
@@ -13,17 +13,30 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
|
|
15
15
|
// src/resources.ts
|
|
16
|
-
import { templates as subgraphTemplates } from "@secondlayer/subgraphs/templates";
|
|
17
|
-
import { templates as workflowTemplates } from "@secondlayer/workflows/templates";
|
|
18
16
|
var FILTERS_REFERENCE = [
|
|
19
|
-
{
|
|
17
|
+
{
|
|
18
|
+
type: "stx_transfer",
|
|
19
|
+
fields: ["sender", "recipient", "minAmount", "maxAmount"]
|
|
20
|
+
},
|
|
20
21
|
{ type: "stx_mint", fields: ["recipient", "minAmount"] },
|
|
21
22
|
{ type: "stx_burn", fields: ["sender", "minAmount"] },
|
|
22
23
|
{ type: "stx_lock", fields: ["lockedAddress", "minAmount"] },
|
|
23
|
-
{
|
|
24
|
+
{
|
|
25
|
+
type: "ft_transfer",
|
|
26
|
+
fields: [
|
|
27
|
+
"sender",
|
|
28
|
+
"recipient",
|
|
29
|
+
"assetIdentifier",
|
|
30
|
+
"minAmount",
|
|
31
|
+
"maxAmount"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
24
34
|
{ type: "ft_mint", fields: ["recipient", "assetIdentifier", "minAmount"] },
|
|
25
35
|
{ type: "ft_burn", fields: ["sender", "assetIdentifier", "minAmount"] },
|
|
26
|
-
{
|
|
36
|
+
{
|
|
37
|
+
type: "nft_transfer",
|
|
38
|
+
fields: ["sender", "recipient", "assetIdentifier", "tokenId"]
|
|
39
|
+
},
|
|
27
40
|
{ type: "nft_mint", fields: ["recipient", "assetIdentifier", "tokenId"] },
|
|
28
41
|
{ type: "nft_burn", fields: ["sender", "assetIdentifier", "tokenId"] },
|
|
29
42
|
{ type: "contract_call", fields: ["contract", "function"] },
|
|
@@ -73,33 +86,6 @@ function registerResources(server) {
|
|
|
73
86
|
}
|
|
74
87
|
]
|
|
75
88
|
}));
|
|
76
|
-
server.resource("templates", "secondlayer://templates", {
|
|
77
|
-
description: "Available subgraph and workflow templates with descriptions and categories"
|
|
78
|
-
}, async () => ({
|
|
79
|
-
contents: [
|
|
80
|
-
{
|
|
81
|
-
uri: "secondlayer://templates",
|
|
82
|
-
mimeType: "application/json",
|
|
83
|
-
text: JSON.stringify([
|
|
84
|
-
...subgraphTemplates.map(({ id, name, description, category }) => ({
|
|
85
|
-
kind: "subgraph",
|
|
86
|
-
id,
|
|
87
|
-
name,
|
|
88
|
-
description,
|
|
89
|
-
category
|
|
90
|
-
})),
|
|
91
|
-
...workflowTemplates.map(({ id, name, description, category, trigger }) => ({
|
|
92
|
-
kind: "workflow",
|
|
93
|
-
id,
|
|
94
|
-
name,
|
|
95
|
-
description,
|
|
96
|
-
category,
|
|
97
|
-
trigger
|
|
98
|
-
}))
|
|
99
|
-
], null, 2)
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}));
|
|
103
89
|
}
|
|
104
90
|
|
|
105
91
|
// src/lib/client.ts
|
|
@@ -351,391 +337,6 @@ function registerSubgraphTools(server) {
|
|
|
351
337
|
});
|
|
352
338
|
}
|
|
353
339
|
|
|
354
|
-
// src/tools/workflows.ts
|
|
355
|
-
import { bundleWorkflowCode } from "@secondlayer/bundler";
|
|
356
|
-
import {
|
|
357
|
-
generateWorkflowCode
|
|
358
|
-
} from "@secondlayer/scaffold";
|
|
359
|
-
import { VersionConflictError } from "@secondlayer/sdk";
|
|
360
|
-
import {
|
|
361
|
-
getTemplateById as getWorkflowTemplateById,
|
|
362
|
-
templates as workflowTemplates2
|
|
363
|
-
} from "@secondlayer/workflows/templates";
|
|
364
|
-
import { createPatch } from "diff";
|
|
365
|
-
import { z as z3 } from "zod/v4";
|
|
366
|
-
function registerWorkflowTools(server) {
|
|
367
|
-
defineTool(server, "workflows_list", "List all workflows. Returns summary fields only.", {}, async () => {
|
|
368
|
-
const { workflows } = await getClient().workflows.list();
|
|
369
|
-
return {
|
|
370
|
-
content: [
|
|
371
|
-
{
|
|
372
|
-
type: "text",
|
|
373
|
-
text: JSON.stringify(workflows, null, 2)
|
|
374
|
-
}
|
|
375
|
-
]
|
|
376
|
-
};
|
|
377
|
-
});
|
|
378
|
-
defineTool(server, "workflows_get", "Get full details of a workflow by name.", { name: z3.string().describe("Workflow name") }, async ({ name }) => {
|
|
379
|
-
const detail = await getClient().workflows.get(name);
|
|
380
|
-
return {
|
|
381
|
-
content: [{ type: "text", text: JSON.stringify(detail, null, 2) }]
|
|
382
|
-
};
|
|
383
|
-
});
|
|
384
|
-
defineTool(server, "workflows_get_definition", "Return the deployed TypeScript source of a workflow plus its stored version. Returns `sourceCode: null` + `readOnly: true` for workflows deployed before source capture.", { name: z3.string().describe("Workflow name") }, async ({ name }) => {
|
|
385
|
-
const source = await getClient().workflows.getSource(name);
|
|
386
|
-
return {
|
|
387
|
-
content: [{ type: "text", text: JSON.stringify(source, null, 2) }]
|
|
388
|
-
};
|
|
389
|
-
});
|
|
390
|
-
defineTool(server, "workflows_propose_edit", "Validate a proposed edit WITHOUT deploying. Fetches the current stored source, bundles the proposed source, computes a unified diff, and returns everything for review. Use this when you want to show the user a diff before committing — pair it with workflows_deploy(expectedVersion=...) to persist.", {
|
|
391
|
-
name: z3.string().describe("Workflow name"),
|
|
392
|
-
proposedCode: z3.string().describe("New TypeScript source — must compile and validate."),
|
|
393
|
-
expectedVersion: z3.string().regex(/^\d+\.\d+\.\d+$/).optional().describe("Version the proposer is editing from (for audit).")
|
|
394
|
-
}, async ({ name, proposedCode, expectedVersion }) => {
|
|
395
|
-
const current = await getClient().workflows.getSource(name);
|
|
396
|
-
if (current.sourceCode === null) {
|
|
397
|
-
return {
|
|
398
|
-
isError: true,
|
|
399
|
-
content: [
|
|
400
|
-
{
|
|
401
|
-
type: "text",
|
|
402
|
-
text: JSON.stringify({
|
|
403
|
-
error: "Workflow has no stored source. Redeploy via CLI first.",
|
|
404
|
-
readOnly: true,
|
|
405
|
-
version: current.version
|
|
406
|
-
}, null, 2)
|
|
407
|
-
}
|
|
408
|
-
]
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
let bundleValid = false;
|
|
412
|
-
let validation;
|
|
413
|
-
let bundleSize = 0;
|
|
414
|
-
try {
|
|
415
|
-
const bundled = await bundleWorkflowCode(proposedCode);
|
|
416
|
-
bundleValid = true;
|
|
417
|
-
bundleSize = Buffer.byteLength(bundled.handlerCode, "utf8");
|
|
418
|
-
validation = {
|
|
419
|
-
name: bundled.name,
|
|
420
|
-
triggerType: bundled.trigger.type
|
|
421
|
-
};
|
|
422
|
-
} catch (err) {
|
|
423
|
-
validation = {
|
|
424
|
-
error: err instanceof Error ? err.message : String(err)
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
const diffText = createPatch(`${name}.ts`, current.sourceCode, proposedCode, `v${current.version}`, "proposed");
|
|
428
|
-
return {
|
|
429
|
-
content: [
|
|
430
|
-
{
|
|
431
|
-
type: "text",
|
|
432
|
-
text: JSON.stringify({
|
|
433
|
-
currentVersion: current.version,
|
|
434
|
-
expectedVersion,
|
|
435
|
-
currentSource: current.sourceCode,
|
|
436
|
-
proposedSource: proposedCode,
|
|
437
|
-
diffText,
|
|
438
|
-
bundleValid,
|
|
439
|
-
validation,
|
|
440
|
-
bundleSize
|
|
441
|
-
}, null, 2)
|
|
442
|
-
}
|
|
443
|
-
]
|
|
444
|
-
};
|
|
445
|
-
});
|
|
446
|
-
defineTool(server, "workflows_tail_run", "Tail a workflow run via SSE and return a compacted log. Resolves as soon as the run completes, `limit` events are collected, or `timeoutMs` elapses (default 60s). MCP is not streaming-first — use this for short-lived follow-ups, not long tails.", {
|
|
447
|
-
name: z3.string().describe("Workflow name"),
|
|
448
|
-
runId: z3.string().describe("Run id"),
|
|
449
|
-
limit: z3.number().int().positive().max(200).optional().describe("Max step events to collect (default 50)"),
|
|
450
|
-
timeoutMs: z3.number().int().positive().max(5 * 60 * 1000).optional().describe("Hard timeout in ms (default 60000, max 300000)")
|
|
451
|
-
}, async ({ name, runId, limit, timeoutMs }) => {
|
|
452
|
-
const cap = limit ?? 50;
|
|
453
|
-
const deadline = timeoutMs ?? 60000;
|
|
454
|
-
const events = [];
|
|
455
|
-
let finalStatus = null;
|
|
456
|
-
let stoppedBy = "timeout";
|
|
457
|
-
const controller = new AbortController;
|
|
458
|
-
const timer = setTimeout(() => {
|
|
459
|
-
stoppedBy = "timeout";
|
|
460
|
-
controller.abort();
|
|
461
|
-
}, deadline);
|
|
462
|
-
try {
|
|
463
|
-
await getClient().workflows.streamRun(name, runId, (event) => {
|
|
464
|
-
if (event.type === "step") {
|
|
465
|
-
events.push(event.step);
|
|
466
|
-
if (events.length >= cap) {
|
|
467
|
-
stoppedBy = "limit";
|
|
468
|
-
controller.abort();
|
|
469
|
-
}
|
|
470
|
-
} else if (event.type === "done") {
|
|
471
|
-
finalStatus = event.done.status;
|
|
472
|
-
stoppedBy = "done";
|
|
473
|
-
}
|
|
474
|
-
}, controller.signal);
|
|
475
|
-
} catch (err) {
|
|
476
|
-
if (!(err instanceof Error) || err.name !== "AbortError") {
|
|
477
|
-
throw err;
|
|
478
|
-
}
|
|
479
|
-
} finally {
|
|
480
|
-
clearTimeout(timer);
|
|
481
|
-
}
|
|
482
|
-
return {
|
|
483
|
-
content: [
|
|
484
|
-
{
|
|
485
|
-
type: "text",
|
|
486
|
-
text: JSON.stringify({
|
|
487
|
-
runId,
|
|
488
|
-
finalStatus,
|
|
489
|
-
stoppedBy,
|
|
490
|
-
eventCount: events.length,
|
|
491
|
-
events
|
|
492
|
-
}, null, 2)
|
|
493
|
-
}
|
|
494
|
-
]
|
|
495
|
-
};
|
|
496
|
-
});
|
|
497
|
-
defineTool(server, "workflows_pause_all", "Pause ALL active workflows for the authenticated account. Irreversible only by calling pause/resume per workflow. Returns the list of affected workflows.", {}, async () => {
|
|
498
|
-
const result = await getClient().workflows.pauseAll();
|
|
499
|
-
return {
|
|
500
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
501
|
-
};
|
|
502
|
-
});
|
|
503
|
-
defineTool(server, "workflows_cancel_run", "Cancel an in-flight workflow run. Marks the run as cancelled and removes any pending queue entry. No-ops if the run is already terminal.", { runId: z3.string().describe("Run id to cancel") }, async ({ runId }) => {
|
|
504
|
-
const result = await getClient().workflows.cancelRun(runId);
|
|
505
|
-
return {
|
|
506
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
507
|
-
};
|
|
508
|
-
});
|
|
509
|
-
defineTool(server, "workflows_rollback", "Roll a workflow back to a prior version. The restored handler is re-published as a NEW version (audit trail), so no history is lost. Pass toVersion to pick a specific bundle; omit to roll back to the immediate previous version on disk. Last 3 versions are retained.", {
|
|
510
|
-
name: z3.string().describe("Workflow name"),
|
|
511
|
-
toVersion: z3.string().regex(/^\d+\.\d+\.\d+$/).optional().describe("Target version to restore. Must be one of the retained bundles on disk.")
|
|
512
|
-
}, async ({ name, toVersion }) => {
|
|
513
|
-
const result = await getClient().workflows.rollback(name, toVersion);
|
|
514
|
-
return {
|
|
515
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
516
|
-
};
|
|
517
|
-
});
|
|
518
|
-
defineTool(server, "workflows_delete", "Delete a workflow permanently.", { name: z3.string().describe("Workflow name") }, async ({ name }) => {
|
|
519
|
-
await getClient().workflows.delete(name);
|
|
520
|
-
return {
|
|
521
|
-
content: [{ type: "text", text: `Deleted workflow "${name}"` }]
|
|
522
|
-
};
|
|
523
|
-
});
|
|
524
|
-
defineTool(server, "workflows_trigger", "Trigger a workflow run. Optionally pass input as a JSON string.", {
|
|
525
|
-
name: z3.string().describe("Workflow name"),
|
|
526
|
-
input: z3.string().optional().describe("Input as JSON string")
|
|
527
|
-
}, async ({ name, input }) => {
|
|
528
|
-
const parsed = input ? JSON.parse(input) : undefined;
|
|
529
|
-
const result = await getClient().workflows.trigger(name, parsed);
|
|
530
|
-
return {
|
|
531
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
532
|
-
};
|
|
533
|
-
});
|
|
534
|
-
defineTool(server, "workflows_pause", "Pause a running workflow.", { name: z3.string().describe("Workflow name") }, async ({ name }) => {
|
|
535
|
-
await getClient().workflows.pause(name);
|
|
536
|
-
return {
|
|
537
|
-
content: [{ type: "text", text: `Paused workflow "${name}"` }]
|
|
538
|
-
};
|
|
539
|
-
});
|
|
540
|
-
defineTool(server, "workflows_resume", "Resume a paused workflow.", { name: z3.string().describe("Workflow name") }, async ({ name }) => {
|
|
541
|
-
await getClient().workflows.resume(name);
|
|
542
|
-
return {
|
|
543
|
-
content: [{ type: "text", text: `Resumed workflow "${name}"` }]
|
|
544
|
-
};
|
|
545
|
-
});
|
|
546
|
-
defineTool(server, "workflows_template_list", "List available workflow templates. Returns metadata only — use workflows_template_get for the full source.", {}, async () => {
|
|
547
|
-
return {
|
|
548
|
-
content: [
|
|
549
|
-
{
|
|
550
|
-
type: "text",
|
|
551
|
-
text: JSON.stringify(workflowTemplates2.map((t) => ({
|
|
552
|
-
id: t.id,
|
|
553
|
-
name: t.name,
|
|
554
|
-
description: t.description,
|
|
555
|
-
category: t.category,
|
|
556
|
-
trigger: t.trigger
|
|
557
|
-
})), null, 2)
|
|
558
|
-
}
|
|
559
|
-
]
|
|
560
|
-
};
|
|
561
|
-
});
|
|
562
|
-
defineTool(server, "workflows_template_get", "Get a workflow template's full TypeScript source and prompt by id.", { id: z3.string().describe("Template id, e.g. 'whale-alert'") }, async ({ id }) => {
|
|
563
|
-
const template = getWorkflowTemplateById(id);
|
|
564
|
-
if (!template) {
|
|
565
|
-
return {
|
|
566
|
-
isError: true,
|
|
567
|
-
content: [
|
|
568
|
-
{
|
|
569
|
-
type: "text",
|
|
570
|
-
text: `Template "${id}" not found. Use workflows_template_list to see available templates.`
|
|
571
|
-
}
|
|
572
|
-
]
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
return {
|
|
576
|
-
content: [
|
|
577
|
-
{
|
|
578
|
-
type: "text",
|
|
579
|
-
text: JSON.stringify(template, null, 2)
|
|
580
|
-
}
|
|
581
|
-
]
|
|
582
|
-
};
|
|
583
|
-
});
|
|
584
|
-
defineTool(server, "workflows_scaffold", "Generate a compilable defineWorkflow() skeleton from a typed intent. Returns the TypeScript source; pass it to workflows_deploy to persist. Placeholders inside the source must be filled in before running a real workflow.", {
|
|
585
|
-
name: z3.string().regex(/^[a-z][a-z0-9-]*$/).describe("Workflow name (lowercase, hyphens)"),
|
|
586
|
-
trigger: z3.discriminatedUnion("type", [
|
|
587
|
-
z3.object({
|
|
588
|
-
type: z3.literal("event"),
|
|
589
|
-
filterType: z3.string().optional()
|
|
590
|
-
}),
|
|
591
|
-
z3.object({
|
|
592
|
-
type: z3.literal("schedule"),
|
|
593
|
-
cron: z3.string().min(1),
|
|
594
|
-
timezone: z3.string().optional()
|
|
595
|
-
}),
|
|
596
|
-
z3.object({ type: z3.literal("manual") })
|
|
597
|
-
]).describe("Trigger shape"),
|
|
598
|
-
steps: z3.array(z3.enum(["run", "query", "ai", "deliver"])).describe("Ordered list of step kinds to include in the handler"),
|
|
599
|
-
deliveryTarget: z3.enum(["webhook", "slack", "email", "discord", "telegram"]).optional().describe("Delivery target used when steps includes `deliver`")
|
|
600
|
-
}, async ({ name, trigger, steps, deliveryTarget }) => {
|
|
601
|
-
const code = generateWorkflowCode({
|
|
602
|
-
name,
|
|
603
|
-
trigger,
|
|
604
|
-
steps,
|
|
605
|
-
deliveryTarget
|
|
606
|
-
});
|
|
607
|
-
return { content: [{ type: "text", text: code }] };
|
|
608
|
-
});
|
|
609
|
-
defineTool(server, "workflows_deploy", "Deploy a workflow from TypeScript source. Pass the full defineWorkflow() source — it will be bundled, validated, and deployed. Use expectedVersion for optimistic concurrency, or dryRun to validate without persisting.", {
|
|
610
|
-
code: z3.string().describe("TypeScript source code containing a defineWorkflow() call"),
|
|
611
|
-
expectedVersion: z3.string().regex(/^\d+\.\d+\.\d+$/).optional().describe("Stored version the client expects (major.minor.patch). Server returns 409 on mismatch."),
|
|
612
|
-
dryRun: z3.boolean().optional().describe("If true, validate and bundle only — do not persist.")
|
|
613
|
-
}, async ({ code, expectedVersion, dryRun }) => {
|
|
614
|
-
let bundled;
|
|
615
|
-
try {
|
|
616
|
-
bundled = await bundleWorkflowCode(code);
|
|
617
|
-
} catch (err) {
|
|
618
|
-
return {
|
|
619
|
-
isError: true,
|
|
620
|
-
content: [
|
|
621
|
-
{
|
|
622
|
-
type: "text",
|
|
623
|
-
text: err instanceof Error ? err.message : String(err)
|
|
624
|
-
}
|
|
625
|
-
]
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
const base = {
|
|
629
|
-
name: bundled.name,
|
|
630
|
-
trigger: bundled.trigger,
|
|
631
|
-
handlerCode: bundled.handlerCode,
|
|
632
|
-
sourceCode: bundled.sourceCode,
|
|
633
|
-
retries: bundled.retries,
|
|
634
|
-
timeout: bundled.timeout,
|
|
635
|
-
expectedVersion
|
|
636
|
-
};
|
|
637
|
-
try {
|
|
638
|
-
const result = dryRun ? await getClient().workflows.deploy({ ...base, dryRun: true }) : await getClient().workflows.deploy(base);
|
|
639
|
-
return {
|
|
640
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
641
|
-
};
|
|
642
|
-
} catch (err) {
|
|
643
|
-
if (err instanceof VersionConflictError) {
|
|
644
|
-
return {
|
|
645
|
-
isError: true,
|
|
646
|
-
content: [
|
|
647
|
-
{
|
|
648
|
-
type: "text",
|
|
649
|
-
text: JSON.stringify({
|
|
650
|
-
error: err.message,
|
|
651
|
-
code: "VERSION_CONFLICT",
|
|
652
|
-
currentVersion: err.currentVersion,
|
|
653
|
-
expectedVersion: err.expectedVersion
|
|
654
|
-
}, null, 2)
|
|
655
|
-
}
|
|
656
|
-
]
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
throw err;
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
defineTool(server, "workflows_runs", "List runs for a workflow. Optionally filter by status and limit results.", {
|
|
663
|
-
name: z3.string().describe("Workflow name"),
|
|
664
|
-
status: z3.enum(["running", "completed", "failed", "cancelled"]).optional().describe("Filter by run status"),
|
|
665
|
-
limit: z3.number().optional().describe("Max runs to return (default 20)")
|
|
666
|
-
}, async ({ name, status, limit }) => {
|
|
667
|
-
const { runs } = await getClient().workflows.listRuns(name, {
|
|
668
|
-
status,
|
|
669
|
-
limit
|
|
670
|
-
});
|
|
671
|
-
return {
|
|
672
|
-
content: [
|
|
673
|
-
{
|
|
674
|
-
type: "text",
|
|
675
|
-
text: JSON.stringify(runs, null, 2)
|
|
676
|
-
}
|
|
677
|
-
]
|
|
678
|
-
};
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// src/tools/templates.ts
|
|
683
|
-
import {
|
|
684
|
-
getTemplateById,
|
|
685
|
-
getTemplatesByCategory,
|
|
686
|
-
templates
|
|
687
|
-
} from "@secondlayer/subgraphs/templates";
|
|
688
|
-
import { z as z4 } from "zod/v4";
|
|
689
|
-
function registerTemplateTools(server) {
|
|
690
|
-
defineTool(server, "templates_list", "List available subgraph templates. Returns metadata only — use templates_get for full code.", {
|
|
691
|
-
category: z4.enum(["defi", "nft", "token", "infrastructure"]).optional().describe("Filter by category")
|
|
692
|
-
}, async ({ category }) => {
|
|
693
|
-
const list = category ? getTemplatesByCategory(category) : templates;
|
|
694
|
-
return {
|
|
695
|
-
content: [
|
|
696
|
-
{
|
|
697
|
-
type: "text",
|
|
698
|
-
text: JSON.stringify(list.map((t) => ({
|
|
699
|
-
id: t.id,
|
|
700
|
-
name: t.name,
|
|
701
|
-
description: t.description,
|
|
702
|
-
category: t.category
|
|
703
|
-
})), null, 2)
|
|
704
|
-
}
|
|
705
|
-
]
|
|
706
|
-
};
|
|
707
|
-
});
|
|
708
|
-
defineTool(server, "templates_get", "Get a template's full code and prompt by ID.", { id: z4.string().describe("Template ID (e.g. 'dex-swaps')") }, async ({ id }) => {
|
|
709
|
-
const template = getTemplateById(id);
|
|
710
|
-
if (!template) {
|
|
711
|
-
return {
|
|
712
|
-
content: [
|
|
713
|
-
{
|
|
714
|
-
type: "text",
|
|
715
|
-
text: `Template "${id}" not found. Use templates_list to see available templates.`
|
|
716
|
-
}
|
|
717
|
-
],
|
|
718
|
-
isError: true
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
return {
|
|
722
|
-
content: [
|
|
723
|
-
{
|
|
724
|
-
type: "text",
|
|
725
|
-
text: JSON.stringify({
|
|
726
|
-
id: template.id,
|
|
727
|
-
name: template.name,
|
|
728
|
-
description: template.description,
|
|
729
|
-
category: template.category,
|
|
730
|
-
code: template.code,
|
|
731
|
-
prompt: template.prompt
|
|
732
|
-
}, null, 2)
|
|
733
|
-
}
|
|
734
|
-
]
|
|
735
|
-
};
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
|
|
739
340
|
// src/server.ts
|
|
740
341
|
var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
741
342
|
var pkg = JSON.parse(readFileSync(join(__dirname2, "../package.json"), "utf-8"));
|
|
@@ -744,11 +345,9 @@ function createServer() {
|
|
|
744
345
|
name: "secondlayer",
|
|
745
346
|
version: pkg.version
|
|
746
347
|
});
|
|
747
|
-
registerTemplateTools(server);
|
|
748
348
|
registerScaffoldTools(server);
|
|
749
349
|
registerSubgraphTools(server);
|
|
750
350
|
registerAccountTools(server);
|
|
751
|
-
registerWorkflowTools(server);
|
|
752
351
|
registerResources(server);
|
|
753
352
|
return server;
|
|
754
353
|
}
|
|
@@ -839,5 +438,5 @@ httpServer.listen(port, () => {
|
|
|
839
438
|
console.error("Warning: SECONDLAYER_MCP_SECRET not set, authentication disabled");
|
|
840
439
|
});
|
|
841
440
|
|
|
842
|
-
//# debugId=
|
|
441
|
+
//# debugId=DFBEBA63DCCFB17E64756E2164756E21
|
|
843
442
|
//# sourceMappingURL=bin-http.js.map
|