secondlayer

tools.secondlayerPublished by secondlayer.toolsOfficial publisherv11.2.4Updated Oct 30, 2026

Stacks chain data: contracts, events, transfers, subgraph scaffolds. Hosted with browser sign-in.

VerifiedStreamable HTTPWeb executableDatabasesDeveloper ToolsData & Analytics

Overview

AI-generated overview

Gives an assistant access to Stacks chain data — decoded Index rows, contract discovery, subgraph lifecycle, webhooks and Streams — via hosted or self-hosted…

What you can do
  • Read decoded Stacks data: blocks, transactions, contract calls, events, fungible and non-fungible token transfers, print schemas, plus batched reads
  • Discover contracts by SIP trait and fetch a deployed contract's ABI
  • Build and run subgraphs: scaffold from observed events, test a mapping, deploy, query rows, backfill, reindex, stop, inspect gaps and operation history
  • Manage chain-event webhooks: create, update, pause, resume, test, replay, rotate signing secrets, inspect deliveries and dead-letter queue
  • Check Streams chain tip and list bulk parquet dumps; generate an ORM schema for Index tables
When to use it
Useful when building or debugging on Stacks: exploring on-chain activity, writing and deploying subgraph mappings, or wiring webhooks that react to chain events. Read-only Index and contract tools work without a key, so it is also a quick way to answer chain-data questions.
Requirements
Remote endpoint at api.secondlayer.tools over Streamable HTTP with browser OAuth sign-in, or the local npm package @secondlayer/mcp run with bun. Hosted writes and credits use SECONDLAYER_API_KEY (sk-sl_*); self-hosted writes use INSTANCE_TOKEN from secondlayer init. SECONDLAYER_API_URL selects the instance. Some tools are local only.
Before you install
Write tools create, deploy, reindex, backfill and permanently delete subgraphs, and create or delete webhooks; verify results with the operations and deliveries tools. Webhook signing secrets are returned once and old secrets stop verifying after rotation. Hosted use consumes credits tied to SECONDLAYER_API_KEY. Subgraph sources on the hosted API are restricted to event filters and contract call/deploy.

Installation

In SourceWeft

  1. Open secondlayer in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/tools.secondlayer%2Fsecondlayer/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "secondlayer": {
      "type": "http",
      "url": "https://api.secondlayer.tools/mcp"
    }
  }
}

README

@secondlayer/mcp

Gives your coding agent direct access to Stacks data, on the hosted API (api.secondlayer.tools) or on your own instance: Index (decoded rows), Subgraphs (tables you define, served from your account or instance), and Streams (raw inputs). Exposes the golden-path tools only: Index reads, the subgraph lifecycle, webhooks, contract discovery/scaffolding, instance status, archive verify/bootstrap, and hosted credits/quote. Everything else (single-record lookups, mempool, stacking, proofs, live Streams reads) is available over REST /v1 + OpenAPI. There is no consume tool.

Hosted

No install: the hosted API serves the read tools over Streamable HTTP, with a browser sign-in.

bash
claude mcp add --transport http secondlayer https://api.secondlayer.tools/mcp

Clients without OAuth send Authorization: Bearer <sk-sl_ key>. Subgraph deploys, webhooks, archive, codegen and instance tools are local only. See /docs/mcp.

Install

bash
bun add @secondlayer/mcp

Auth

Most reads are public: index_* and contracts_find work with no key. Subgraph tools need an INSTANCE_TOKEN past loopback, and so does GET /v1/subgraphs/<name>/<table> over HTTP ({ rows, next_cursor, tip } cursor envelope); on loopback it is open. There is no per-subgraph public or private flag. streams_dumps needs no key: the dumps manifest is public; the tool only needs SL_STREAMS_DUMPS_URL configured. streams_tip is key-mandatory (keyless → 401). Live Streams list reads are REST-only (GET /v1/streams/*). Writes (deploy, reindex, delete, webhooks) need a key, and the key follows the host: on https://api.secondlayer.tools the server uses SECONDLAYER_API_KEY (sk-sl_*) automatically; anywhere else it uses INSTANCE_TOKEN from secondlayer init. Hosted credits/quote use SECONDLAYER_API_KEY too. On the hosted API, subgraph sources are limited to event filters and contract_call/contract_deploy (422 SOURCE_NOT_HOSTABLE otherwise); set startBlock. Read secondlayer://context first: it reports auth state and read-auth tiers.

Quick Start — Stdio (IDE)

Add to your Claude Desktop or Cursor config:

json
{  "mcpServers": {    "secondlayer": {      "command": "bunx",      "args": ["-p", "@secondlayer/mcp", "secondlayer-mcp"],      "env": {        "SECONDLAYER_API_URL": "http://127.0.0.1:3800",        "INSTANCE_TOKEN": "..."      }    }  }}

Quick Start — HTTP (Remote)

bash
export SECONDLAYER_API_URL=http://127.0.0.1:3800export INSTANCE_TOKEN=<from secondlayer init>export SECONDLAYER_MCP_SECRET=your-secretbunx -p @secondlayer/mcp secondlayer-mcp-http# Listening on port 3100

Environment Variables

VariableRequiredDefaultDescription
INSTANCE_TOKENWrites on your instance—From secondlayer init. Required for write tools elsewhere than api.secondlayer.tools; reads are public. Not sent to the hosted API.
SECONDLAYER_API_KEYHosted API, credits/quote/latest—sk-sl_*, used automatically when SECONDLAYER_API_URL is https://api.secondlayer.tools.
SECONDLAYER_API_URLNohttp://127.0.0.1:3800Instance API, or https://api.secondlayer.tools for hosted.
SECONDLAYER_BINCLI toolssecondlayer on PATHPath to the CLI binary (bootstrap, repair).
SECONDLAYER_CWDCLI toolsprocess cwdCompose project directory.
SECONDLAYER_MCP_PORTNo3100HTTP transport port.
SECONDLAYER_MCP_SECRETNo—Bearer token for HTTP auth. Disabled if unset.

Tools

DomainTools
Index (9)index_events, index_ft_transfers, index_nft_transfers, index_contract_calls, index_blocks, index_transactions, index_print_schema, index_discover, batch_query
Subgraphs (12)subgraphs_list, subgraphs_status, subgraphs_spec, subgraphs_scaffold, subgraphs_deploy, subgraphs_delete, subgraphs_query, subgraphs_backfill, subgraphs_reindex, subgraphs_stop, subgraphs_operations, subgraphs_gaps
Webhooks (13)webhooks_create, webhooks_list, webhooks_get, webhooks_update, webhooks_delete, webhooks_test, webhooks_pause, webhooks_resume, webhooks_rotate_secret, webhooks_deliveries, webhooks_dead, webhooks_requeue, webhooks_replay
Streams (2)streams_tip, streams_dumps
Contracts (2)contracts_find, contracts_get_abi
Instance (1)instance_status
Archive (5)archive_verify, archive_bootstrap, archive_repair, archive_latest, archive_quote
Credits (1)credits_balance (needs SECONDLAYER_API_KEY)
Account (4)account_whoami, account_create_key, account_list_keys, account_rotate_key (only when pointed at https://api.secondlayer.tools)

Verify after mutating: subgraphs_operations for deploy/reindex/backfill/stop, webhooks_deliveries for create/test/replay. Empty index: archive_bootstrap, poll instance_status until decoders are ok, then archive_verify, then codegen_index_schema.

Periphery surfaces (single block/tx lookups, mempool, stacking, proofs, credits/caps, live Streams reads/SSE) are REST-only: see the OpenAPI spec at the API host. Live Streams list reads use GET /v1/streams/events.

Point the server at your instance with SECONDLAYER_API_URL (default http://127.0.0.1:3800). Writes use INSTANCE_TOKEN from secondlayer init. account_* tools appear only when the server is pointed at https://api.secondlayer.tools.

webhooks_create triggers

Webhooks fire on raw chain events. Pass a triggers array (contract / event / function / trait), e.g. [{ "type": "contract_call", "contractId": "SP....amm", "functionName": "swap-*" }]. To react to subgraph rows, read the table from your own Postgres or poll the subgraph API.

subgraphs_query enhancements

  • fields — comma-separated column projection (e.g. "sender,amount_x")
  • count — boolean, returns row count instead of rows
  • Filter operators: eq, neq, gt, gte, lt, lte, like
  • Max limit: 200

Resources

URIDescription
secondlayer://contextLive state — what exists (your subgraphs, webhooks, account), what you can do, and read-auth tiers. Read first.
secondlayer://filtersSubgraph source filter types and their fields
secondlayer://column-typesColumn type mappings and options
secondlayer://traitsSIP trait standards (valid trait values)
secondlayer://chain-triggersChain-webhook trigger types and fields

Error Handling

All tools return structured errors with isError: true:

json
{ "error": { "type": "not_found", "status": 404, "message": "Subgraph not found" } }
Error typeStatusWhen
unauthorized401Invalid or missing API key
not_found404Resource doesn't exist
rate_limited429Too many requests
server_error5xxServer-side failure
errorotherValidation, bundling, etc.

Bundle/deploy errors use descriptive prefixes: "Bundle failed:", "Module evaluation failed:", "Validation failed:". HTTP transport enforces a 1MB body limit (413) and JSON parse safety (400). Scaffold ABI fetch has a 10s timeout.

Programmatic Usage

typescript
import { createServer } from "@secondlayer/mcp";
const server = createServer();// Connect to your own transport

License

MIT

Source: packages/mcp/README.md at commit 7869d72

Tools

47

subgraphs_scaffold

Generate a subgraph from observed print events when available; ABI token transfers or public functions only when the contract has never printed. Review the TypeScript, run subgraphs_test until ok: true with written >= 1, read skipped, then subgraphs_deploy. dryRun is DDL only.

ParameterscontractIdrequiredsubgraphName

subgraphs_list

List all deployed subgraphs. Returns summary fields only; read rows with subgraphs_query.

Takes no parameters.

subgraphs_status

Get full details of a subgraph including schema, health (incl. health.emptyMapping when processed events wrote 0 rows), and table columns.

Parametersnamerequired

subgraphs_spec

Fetch a subgraph's self-describing spec — the tables, columns, filters, and read URLs a consumer needs, without guessing. `agent` (default) returns the compact JSON schema built for tool use, `openapi` the OpenAPI document for the subgraph's read routes, `markdown` human-readable docs. Read it before writing queries against an unfamiliar subgraph.

Parametersnamerequiredformat

subgraphs_query

Query rows from a subgraph table (max 200 rows), reading the open /v1 surface — { rows, next_cursor, tip } envelope, cursor-paginated (no offset). Filters support operators: "amount.gte": "1000", "sender.neq": "SP...", "name.like": "%token%". Available operators: eq, neq, gt, gte, lt, lte, like. Every page with rows returns next_cursor (null only when empty): pass it back as `cursor` to read the next page. To TAIL new rows (no streaming over MCP), poll with cursor = next_cursor ?? the cursor you sent. Fetch one row by id with {"_id": "<id>"}. The same rows are readable over HTTP at GET /v1/subgraphs/<name>/<table>; hand that URL to third parties.

Parametersnamerequiredsortcountlimitordertablerequiredcursorfieldsfilters

subgraphs_reindex

Reindex a subgraph: drops and rebuilds the whole subgraph from its start block to chain tip. Takes no block range — use subgraphs_backfill to process a specific range. Returns an operationId — check subgraphs_status (health) or the REST operations endpoint to track progress to completion.

Parametersnamerequired

subgraphs_backfill

Backfill a subgraph over a block range. Non-destructive forward fill (does not drop existing data) — unlike subgraphs_reindex, and the only data-fill path for BYO subgraphs (reindex is blocked there). Both blocks required. Returns an operationId — check subgraphs_status (health) or the REST operations endpoint to track progress.

ParametersnamerequiredtoBlockrequiredfromBlockrequired

subgraphs_stop

Cancel an in-flight reindex or backfill operation for a subgraph. Returns the stop request status; check subgraphs_status (health) or the REST operations endpoint to confirm it reaches a terminal state.

Parametersnamerequired

subgraphs_gaps

List indexing gaps (missing block ranges) for a subgraph. Each gap reports start/end/size, reason, and detected/resolved timestamps. Feed an unresolved gap's range into subgraphs_backfill to fill it. Defaults to unresolved gaps.

Parametersnamerequiredlimitoffsetresolved

subgraphs_operations

Operation history for a subgraph (deploy/reindex/backfill/stop), newest first — status, block range, progress, and error. THIS IS THE VERIFY CALL: after subgraphs_deploy, subgraphs_reindex, subgraphs_backfill, or subgraphs_stop, poll it with the returned operationId until `status` is terminal (completed/failed/cancelled) before reporting success. Omit operationId for the recent history.

ParametersnamerequiredoperationId

subgraphs_delete

Delete a subgraph permanently.

Parametersnamerequired

subgraphs_deploy

Deploy a subgraph from TypeScript code. Pass the full defineSubgraph() source — it will be bundled, validated, and deployed. Optional startBlock overrides the source definition for this deploy. dryRun validates schema/DDL only and does not run handlers — call subgraphs_test first and deploy only when it returns ok: true with written >= 1. Call subgraphs_reindex separately if you need a forced reindex.

ParameterscoderequireddryRunstartBlock

subgraphs_test

Prove a subgraph mapping writes rows against Index data before deploy. Pass full defineSubgraph() source plus a height range. Returns ok/written/tables; EMPTY_MAPPING means events matched but 0 rows were written — read hint for observed event.data keys and do not invent fields. subgraphs_deploy dryRun is DDL only; do not deploy until ok: true with written >= 1.

ParameterscoderequiredlimittoHeightfromHeightrequired

webhooks_list

List all webhooks for the current account. Returns summary fields (no secrets).

Takes no parameters.

webhooks_get

Get full detail for a webhook (triggers, auth, retry config, circuit state).

Parametersidrequired

webhooks_create

Create a webhook that fires on raw chain events (set triggers). Returns `signingSecret` ONCE — forward it to the user so they can wire it into their receiver.

ParametersurlrequirednamerequiredformattriggersrequiredauthConfig

webhooks_update

Patch a webhook (name, url, authConfig, format, retry, timeout, concurrency).

ParametersidrequiredurlnameformattimeoutMsauthConfigmaxRetriesconcurrency

webhooks_delete

Delete a webhook. Pending outbox rows are cascade-deleted.

Parametersidrequired

webhooks_test

Send a one-off test webhook to a webhook's URL (built for its format, SSRF-guarded). Logged as a delivery row. Returns {ok, statusCode, error, durationMs, deliveryId}.

Parametersidrequired

webhooks_pause

Pause a webhook: stops delivery attempts and stops queueing new ones. Nothing is deleted — resume picks the webhook back up from the tip. Verify with webhooks_get (status).

Parametersidrequired

webhooks_resume

Resume a paused webhook (also clears a tripped circuit breaker). Deliveries restart from the current tip — use webhooks_replay for the blocks missed while paused. Verify with webhooks_get (status).

Parametersidrequired

webhooks_rotate_secret

Rotate a webhook's signing secret. Returns the NEW `signingSecret` ONCE — forward it to the user; deliveries signed with the old secret stop verifying as soon as this returns, so the receiver must be updated.

Parametersidrequired

webhooks_deliveries

List recent delivery attempts for a webhook — status code, attempt count, error, duration, timestamps. THIS IS THE VERIFY CALL: after webhooks_create, webhooks_test, or webhooks_replay, read it to confirm the webhook actually landed (and to see the receiver's response when it didn't) instead of trusting the enqueue result.

Parametersidrequired

webhooks_dead

List a webhook's dead-letter queue — deliveries that exhausted their retries, with the outbox id, payload, and last error. Diagnose the receiver first (webhooks_get for the URL/auth, webhooks_test for a live probe), then requeue rows with webhooks_requeue.

Parametersidrequired

webhooks_requeue

Requeue ONE dead-lettered delivery for another attempt, by its outbox id from webhooks_dead. Fix the receiver first — a requeue against a still-broken endpoint just dies again. Verify with webhooks_deliveries.

ParametersidrequiredoutboxIdrequired

webhooks_replay

Replay a block range for a webhook. Replays run at 10% of batch capacity — use sparingly. Pass `force` (a short idempotency suffix) to re-run a range that was already replayed.

ParametersidrequiredforcetoBlockrequiredfromBlockrequired

index_ft_transfers

List decoded SIP-010 fungible-token transfers from Index. Reads are keyless.

ParameterslimitordercursorsendertoHeightrecipientcontractIdfromHeightassetIdentifier

index_nft_transfers

List decoded SIP-009 non-fungible-token transfers from Index. Reads are keyless.

ParameterslimitordercursorsendertoHeightrecipientcontractIdfromHeightassetIdentifier

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.

ParameterslimitordertraitcursorsendertoHeighteventTyperequiredrecipienttxContextcontractIdfromHeightassetIdentifier

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.

ParameterslimittraitcursorsendertoHeightcontractIdfromHeightfunctionName

index_blocks

List decoded blocks from Index. Reads are keyless.

ParameterslimitcursortoHeightfromHeight

index_transactions

List decoded transactions from Index. Filter by type, sender, or contract. Reads are keyless.

ParameterstypelimitcursorsendertoHeightcontractIdfromHeight

index_print_schema

Empirical per-topic print payload schemas for a contract, inferred from sampled on-chain events: each topic's fields with observed Clarity types, decoded TS types, subgraph column types, and presence rates. Use before writing print_event subgraph handlers to learn what's on e.data. Anonymous read.

ParameterscontractIdrequired

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.

Takes no parameters.

batch_query

Run up to 10 public /v1 reads in one round trip (POST /v1/batch). Each item keeps its own auth/quota/pay-per-call semantics; results return in order with per-item status. Paths must start with /v1/index, /v1/subgraphs, /v1/streams, or /v1/contracts.

Parametersrequestsrequired

streams_tip

Current canonical chain tip as Streams sees it: block height/hash, burn height, finalized_height, lag_seconds, and the oldest seekable height/cursor for this key's retention window. Call it before a cursor walk to know where the stream ends, and after an ingest to check lag.

Takes no parameters.

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). For live reads use REST GET /v1/streams/events; for tip/lag use streams_tip.

Takes no parameters.

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.

Parameterslimittraitrequiredcursorincludeconformance

contracts_get_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. Use it to inspect a contract before subgraphs_scaffold.

ParameterscontractIdrequired

codegen_index_schema

Generate an ORM schema for the Index tables (blocks, transactions, decoded_events, …) — the same output as `sl codegen index`. Returns the file contents as text; write it wherever your project keeps its schema. Use `tables` to emit only what you read.

ParameterstablestargetschemaNamedatasourceEnv

instance_status

Decoder health and empty-index diagnosis from GET /public/status. If state is empty-index, next tool is archive_bootstrap. Poll until index.decoders are ok before treating Index as ready — do not start decoders. Then archive_verify, then codegen_index_schema. Do not download parquet.

Takes no parameters.

archive_verify

Read-only, free compare of this instance against a signed archive (POST /v1/archive/verify). unanchored means pin a key or check the URL — not that the instance is fine. After bootstrap, poll instance_status until decoders ok, then this, then codegen_index_schema. Do not download parquet.

ParameterstargetagainstrequiredtoBlockfromBlock

archive_latest

Signed pointer to the official archive tree (hosted). Needs SECONDLAYER_API_KEY (sk-sl_*), not INSTANCE_TOKEN. Use the returned origin as --against for archive_bootstrap. Do not download parquet.

Parametersagainst

archive_quote

Price a hosted archive fetch (metered). Needs SECONDLAYER_API_KEY (sk-sl_*), not INSTANCE_TOKEN. Quote happens here; bootstrap/repair also quote inside the CLI. Do not download parquet.

Parametersflowrequiredpathsrequired

credits_balance

Archive credits balance at api.secondlayer.tools. Needs SECONDLAYER_API_KEY (sk-sl_*); INSTANCE_TOKEN is the instance.

Takes no parameters.

archive_bootstrap

Restore verified history into this instance (secondlayer bootstrap --against … --yes --json). Metered against the official archive; quote happens inside the CLI. After bootstrap, poll instance_status until decoders ok, then archive_verify, then codegen_index_schema. Do not download parquet.

ParametersagainstrequiredtoBlockfromBlock

archive_repair

Plan (default) or apply a repair of local chain data against a signed archive. Metered when apply fetches from the official archive. After apply, poll instance_status until decoders ok, then archive_verify. Do not download parquet.

ParametersapplyagainstrequiredtoBlockfromBlock

Version history

1
  1. v11.2.4LatestOct 30, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts