CometBFT validator ops

io.github.wookja-0由 GitHub 账号 wookja-0 发布v0.4.3更新于 Nov 6, 2026

Read-only health, jail-risk, halt and upgrade checks for CometBFT validators and nodes

概览

AI 生成的概览

只读的 MCP 服务器,让助手检查 CometBFT 验证者与节点的健康状态:签名情况、入狱风险、链停止和升级准备。

可以做什么
  • 汇总整个节点集群:逐节点问题、每个验证者最近 50 个区块的签名、共识轮次与升级状态
  • 检查节点同步:高度、距上一区块时间、是否追赶中、落后集群多少、版本与投票权
  • 查看对等连接:对等节点数量、入站/出站、公网地址对等节点、其他链上的对等节点
  • 评估验证者签名与入狱风险:签名/漏签区块、连续漏签、惩罚计数、距入狱的漏签次数与时间
  • 诊断链停止:当前轮次各验证者投票、是否达到法定票数、谁未投票
  • 检查升级准备:x/upgrade 计划与预计时间、投票中的提案、各节点版本差异
适用场景
适合 CometBFT 或 Cosmos SDK 验证者运维人员,让助手基于自有节点或公共 RPC 回答验证者是否在签名、离停机入狱还有多远、区块为何停止、集群是否已为升级做好准备等问题。
运行要求
以 stdio 本地进程运行;可通过 Go、发布二进制或容器镜像安装。需要 YAML 配置文件(路径由 --config、COMETBFT_MCP_CONFIG 或内联的 COMETBFT_MCP_CONFIG_YAML 提供),其中列出节点名称、角色、CometBFT RPC 地址和可选的共识验证者地址,以及可选的 Cosmos SDK REST 端点。需要能访问这些端点的网络,通常经由 SSH 隧道。
安装前请注意
工具结果(包括节点名称、高度、对等节点数量和验证者地址)会发送到 MCP 客户端并进而传给 LLM 提供商;除非启用 --reveal-network,IP 和节点 ID 会被遮蔽。它只读且会拒绝疑似密钥的配置字段,但无法确认新二进制是否已部署到各主机。v0.4 早期版本,工具接口可能变化;对生产节点使用前请先取得组织批准。

安装

在 SourceWeft 中

  1. 打开 控制台中的 CometBFT validator ops,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

[cometbft-mcp]

[CI] [e2e] [Release] [Go] [MCP Registry] [Glama] [Container] [License]

A read-only MCP server for CometBFT node and validator operators.

Ask your agent "Is my validator signing?", "How close is it to jail?", "Why did the chain stop?" or "Are we ready for the upgrade?" and get an answer grounded in your own nodes and the chain's own slashing state — judged the way an operator would judge them, and unable to change anything.

Works with any CometBFT chain (Cosmos Hub, Osmosis, any Cosmos SDK chain, non-SDK CometBFT apps) and any MCP client (Claude Code, Claude Desktop, Cursor, VS Code, Codex, Gemini CLI, …).

[!WARNING] Early release (v0.4). The tool API may still change.

[Demo: a fleet check comes back ok; val3 goes down and validator_health reports 19 more misses until downtime jail; val2 goes down too and consensus_diagnosis reports no_quorum, naming val3 and val2]
Real tool output against the bundled localnet — nodes are actually stopped; waits are compressed. Reproduce it.

Contents: What you can ask · Quick start · Install · Connect a client · Configuration · Tools · Security model · How it decides · Troubleshooting · FAQ · Development

What you can ask

Real output from the bundled local network.

Is my validator signing — and how far is it from jail?

"Is val3 signing? How long until it gets jailed?"

val3 [critical]: signed 26/30 blocks (88–117), missed 4 (13.33%), 4 missed in a row at the head;21 more misses until downtime jail (~37s at the current rate)

Read from commit signatures (works while the validator itself is down) and the chain's own x/slashing counter, with the jail threshold computed exactly as the SDK does.

Why did blocks stop?

"The chain isn't producing blocks. Why?"

height 115 round 0 (Prevote) for 60s [critical]: prevotes 50.1%, precommits 0.0% of power —no_quorum; not voting: val3, val2

Tells "not enough voting power online — and who is missing" apart from "validators online but not committing" (an upgrade halt, an app hash error). The 50.1% is not a typo: val2 had been slashed 1% for downtime earlier in the run.

Are we ready for the upgrade?

"Is there an upgrade coming? Are all nodes on the same version?"

localnet-1 [ok]: upgrade <untrusted>v2-e2e</untrusted> at height 10000000 in ~164d20h (9999969 blocks)

The x/upgrade plan with an ETA from the measured block time, upgrade proposals still in voting, and version skew across nodes. <untrusted> marks text that came from the chain — here a governance proposal — so the agent treats it as data.

Is everything ok?

"Run a daily check" — or use the daily_check prompt.

[critical] 5 nodes (4 ok, 1 critical), 4 validators (3 ok, 1 critical); localnet-1 [ok]: no upgrade scheduled — needs attention: val3

Also: "Is val0 really behind its sentry?" (peer_health flags validators with public-address peers), "Is any node falling behind?", and incident_triage for an evidence-first diagnosis of one node.

Quick start (1 minute, public RPC)

No access to your nodes needed: point it at a public RPC and watch any validator by its consensus address.

bash
go install github.com/wookja-0/cometbft-mcp/cmd/cometbft-mcp@latest
cat > hub.yaml <<'EOF'cosmos:  rest: https://cosmos-rest.publicnode.comnodes:  - name: public    role: full    rpc: https://cosmos-rpc.publicnode.com:443  - name: my-validator    role: validator    validator_address: cosmosvalcons1...   # yours, or any validator'sEOF
cometbft-mcp check --config hub.yamlclaude mcp add cometbft -- cometbft-mcp --config "$PWD/hub.yaml" --concurrency 8

Then ask: "Is my-validator signing? How far is it from jail?"

validator_address is the consensus address (…valcons1… or 40-char hex), not a wallet (cosmos1…) or operator (cosmosvaloper1…) address. Get it with <appd> comet show-address on the validator, from /status → validator_info.address, or from an explorer.

Install

Method
BinaryLinux and macOS (amd64/arm64) from Releases, with build-provenance attestations: gh attestation verify <file> --repo wookja-0/cometbft-mcp
Gogo install github.com/wookja-0/cometbft-mcp/cmd/cometbft-mcp@latest
Containerghcr.io/wookja-0/cometbft-mcp — distroless, non-root; the only host access it needs is your config, mounted read-only
MCP Registrylisted as io.github.wookja-0/cometbft-mcp
Glamaglama.ai/mcp/servers/wookja-0/cometbft-mcp

[cometbft-mcp MCP server – quality and maintenance score on Glama]

Connect a client

Use absolute paths: most clients do not expand ~.

Claude Code
bash
claude mcp add cometbft -- cometbft-mcp --config /Users/you/.config/cometbft-mcp/config.yaml
Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

json
{  "mcpServers": {    "cometbft": {      "command": "cometbft-mcp",      "args": ["--config", "/Users/you/.config/cometbft-mcp/config.yaml"]    }  }}
Cursor

~/.cursor/mcp.json:

json
{  "mcpServers": {    "cometbft": {      "command": "cometbft-mcp",      "args": ["--config", "/Users/you/.config/cometbft-mcp/config.yaml"]    }  }}
VS Code

.vscode/mcp.json:

json
{  "servers": {    "cometbft": {      "type": "stdio",      "command": "cometbft-mcp",      "args": ["--config", "/Users/you/.config/cometbft-mcp/config.yaml"]    }  }}
Codex CLI

~/.codex/config.toml:

toml
[mcp_servers.cometbft]command = "cometbft-mcp"args = ["--config", "/Users/you/.config/cometbft-mcp/config.yaml"]
Gemini CLI

~/.gemini/settings.json:

json
{  "mcpServers": {    "cometbft": {      "command": "cometbft-mcp",      "args": ["--config", "/Users/you/.config/cometbft-mcp/config.yaml"]    }  }}
Docker (any client)
json
{  "mcpServers": {    "cometbft": {      "command": "docker",      "args": ["run", "-i", "--rm",               "--mount", "type=bind,src=/Users/you/.config/cometbft-mcp/config.yaml,dst=/config/config.yaml,readonly",               "ghcr.io/wookja-0/cometbft-mcp:0.4.3"]    }  }}

Or skip the mount and pass the config inline: "-e", "COMETBFT_MCP_CONFIG_YAML={nodes: [...]}" before the image name.

Inside a container 127.0.0.1 is the container itself: point the config at host.docker.internal (Docker Desktop) or add --network host (Linux) to reach SSH tunnels on the host.

Configuration

Where the config comes from, first match wins:

  1. --config <path>
  2. $COMETBFT_MCP_CONFIG_YAML — the YAML itself, for places that take environment variables but not files (containers, hosted MCP runners). Flow style fits on one line:
    bash
    COMETBFT_MCP_CONFIG_YAML='{cosmos: {rest: "https://cosmos-rest.publicnode.com"}, nodes: [{name: public, role: full, rpc: "https://cosmos-rpc.publicnode.com:443"}]}'
  3. $COMETBFT_MCP_CONFIG — a path
  4. ~/.config/cometbft-mcp/config.yaml

Start from the commented config.example.yaml.

yaml
# Optional: the Cosmos SDK layer (jail status, slashing margin, upgrades, monikers).# Chain state is the same on every node: use a sentry's or full node's REST API.cosmos:  rest: http://127.0.0.1:1317
nodes:  - name: sentry-1    role: sentry                     # validator | sentry | full    rpc: http://127.0.0.1:26657      # CometBFT RPC  - name: val-1    role: validator    rpc: http://127.0.0.1:36657    validator_address: cosmosvalcons1...   # keeps validator_health working while it is down  - name: val-2    role: validator                  # no rpc: watched by address only    validator_address: cosmosvalcons1...
Field
cosmos.restCosmos SDK REST (app.toml [api], port 1317) of any synced node. Omit for non-SDK chains.
nodes[].nameLowercase name the agent uses to refer to the node.
nodes[].rolevalidator, sentry or full. Commits are read from sentries and full nodes first, keeping load off validators.
nodes[].rpcCometBFT RPC (port 26657). Optional for a validator that has validator_address.
nodes[].validator_addressValidators only: consensus address, hex or bech32 …valcons1….

There is deliberately no place for keys, mnemonics or tokens; fields that look like secrets are rejected.

Reaching nodes. Only port 26657 (and optionally 1317 on one node) is used. CometBFT binds RPC to 127.0.0.1 by default, so an SSH tunnel needs no node changes and no open ports: ssh -N -L 36657:127.0.0.1:26657 val-1. Do not open RPC to the internet for this.

FlagDefault
--configsee abovePath to the config
--concurrency4In-flight requests across all nodes. Gentle on your own nodes; 8 suits most public RPCs, less for rate-limited ones (HTTP 429).
--timeout10sPer-request timeout
--reveal-networkoffShow raw peer IPs, node IDs and transport errors to the model

cometbft-mcp check prints a node_status report locally, without an MCP client, to verify a config.

Without a usable config the server still starts: its tools stay listed and each call explains what to create (it never echoes the config's contents, which may hold internal addresses). Fix the file and restart the MCP server.

Tools

All tools are read-only (readOnlyHint). Every result has a summary, a level (ok / warn / critical / unknown) and findings with stable codes.

fleet_overview — everything at once

One line per node with its issues, one summary per validator (last 50 blocks), the consensus round, and the upgrade status. The starting point for "is everything ok?".

No arguments.

node_status — is each node synced?

Height, seconds since the last block, catching_up, blocks behind the highest node in the fleet, CometBFT and app versions; for validators the consensus address and voting power.

Argument
nodeNode name; omit for every node

Findings: unreachable, catching_up, stale_head, behind_fleet, no_voting_power, address_mismatch.

peer_health — is each node well connected?

Peer count, inbound/outbound, peers on public addresses, peers on another chain, and a peer list (longest-lived first, at most 40) with addresses shown only as a class.

Argument
nodeNode name; omit for every node

Findings: no_peers, few_peers, no_outbound_peers, not_listening, validator_public_peers (a validator meant to sit behind sentries has public peers), peers_on_other_chain.

validator_health — is the validator signing? how far from jail?

Signed / nil-vote / missed / not-in-set over the last N canonical blocks, consecutive misses at the head, last signed height, voting power, rank and share of the set, average block time. With cosmos.rest: jailed / tombstoned / bonding status, the chain's missed-block counter, max_missed, misses_until_jail, and time_to_jail when the validator is not signing right now.

Argument
nodeValidator name; optional when only one validator is configured
windowBlocks to scan, 10–500 (default 100)

Findings: not_signing, missed_blocks, left_active_set, not_in_active_set, partial_data, no_data; with Cosmos: jail_risk, jail_imminent, time_to_jail, jailed, tombstoned, not_bonded, jail_after_grace, no_signing_info, cosmos_unavailable.

consensus_diagnosis — why did blocks stop?

The live round as one node sees it: height, round, step, time at this height, each validator's prevote and precommit in the current round (block / nil / missing), and whether more than 2/3 of voting power is voting. Validators are labeled by config name or staking moniker.

Argument
nodeNode to read from; default a synced sentry or full node

Findings: no_quorum (names who is not voting), stuck_with_quorum, many_rounds, vote_set_mismatch.

upgrade_readiness — is an upgrade coming? (needs cosmos.rest)

The x/upgrade plan (name, height, blocks remaining, ETA), software-upgrade proposals in their voting period, and each node's app and CometBFT version. Registered only when cosmos.rest is configured (or when the server has no config yet, so directories list every tool). It cannot see whether the new binary is staged on each host, and says so.

No arguments.

Findings: upgrade_soon, upgrade_height_reached, upgrade_halt, version_skew, plan_unavailable, proposals_unavailable.

Prompts: daily_check (sweep, drill into what is flagged, report as an operator briefing) and incident_triage (arguments node, optional symptom: evidence-first diagnosis ending with what to check on the host).

Security model

Validator operators should not have to trust an LLM with their infrastructure, so this server is built so that it cannot do damage, rather than promising it won't:

  • No keys, ever. No config field can point at priv_validator_key.json, a keyring or a mnemonic; secret-looking fields are rejected by name. Nothing reads the filesystem besides the config.
  • Read-only by construction. One HTTP client issues only GETs to a hard-coded allowlist: CometBFT /status, /net_info, /validators, /commit, /consensus_state, /abci_info, /health, and Cosmos SDK slashing, staking, upgrade and gov queries. broadcast_*, unsafe_*, dial_*, check_tx, /dump_consensus_state (it lists peer addresses) and /cosmos/tx/ are denied outright; path parameters are pattern-checked; redirects are never followed; responses are size-capped.
  • Network details are masked. Peer IPs appear only as a class (private-ipv4, public-ipv4, …), node IDs are truncated, and errors never carry an address, so a sentry-protected validator's IP does not end up in an LLM provider's logs. --reveal-network turns this off, explicitly.
  • Node text is untrusted. Everything a node or REST server controls — monikers, versions, error messages, upgrade plans — is wrapped in <untrusted> tags or must match its expected format, so a hostile peer or public RPC cannot inject instructions into your agent.
  • Gentle on nodes. A global concurrency cap and bounded block scans; commits are read from sentries or full nodes first.
  • Supply chain. Release archives and images carry build-provenance attestations; CI actions and base images are pinned by digest.

Threat model and reporting: SECURITY.md.

How it decides

Liveness. A CometBFT commit lists every validator in the set at that height, in voting-power order, but absent signatures carry no address. So the tool looks for the validator's address in each commit; when it is not there, it reads the validator set at that height and the signature at the validator's index: absent means missed, no index means not in the set. It scans canonical commits only, up to latest − 1: the commit a node returns for the newest height is its seen commit, holding only the precommits that arrived before +2/3, where a validator behind a sentry routinely looks absent. Canonical commits are also what downtime slashing counts.

Jail risk. With the Cosmos SDK layer it reads the chain's own inputs — x/slashing params and signing info, and x/staking matched by consensus key — and computes the threshold exactly as x/slashing does: window − round_half_even(window × min_signed_per_window), including the grace period before start_height + window. A future jailed_until counts as jailed even if the staking lookup fails, because jailing resets the miss counter and would otherwise look like a clean record.

Halts. CometBFT needs more than 2/3 of voting power to prevote and precommit. consensus_diagnosis reads the current round's votes (CometBFT also lists the next round, still empty, which is skipped), checks each vote against the validator at its position, and sums the power that has voted.

Compatibility

Tested on 2026-11-06 against 11 mainnets through public endpoints, read-only (test/mainnet/), and cross-checked against each chain's own state: the x/slashing miss counter and threshold, jailed / tombstoned / bonded status, consensus address and active-set rank.

ChainCometBFTCosmos SDKNotes
Cosmos Hub0.38.250.53.8180 active / 640+ staking validators
Osmosis0.38.220.50.14
Celestia0.38.170.52.12
dYdX0.38.50.50.6~1 s blocks
Injective1.0.10.50.15
Neutron0.38.190.53.4
Akash0.38.190.53.7
Juno0.38.220.53.7
Kava0.37.160.47.15
Noble0.38.190.50.14No x/gov (authority-run): the upgrade plan is checked, proposals are not
Stride0.39.00.54.3ICS consumer, no x/slashing: judged on signing liveness alone
localnet (simd)0.39.40.54.4e2e: downtime, jail + unjail, upgrade, halt

Versions are what the chains' /status and node_info reported. ed25519 consensus keys only. Not supported: Tendermint2 (gno.land).

Speed and rate limits. validator_health (100 blocks) takes ~5 s over a public RPC at --concurrency 8, ~10 s at the default 4. Some public endpoints (cosmos.directory, Polkachu) limit requests by volume: blocks they refuse count as unreadable and the result is unknown, never a guess. Lower --concurrency or use your own node.

Troubleshooting

Error codeMeaningWhat to check
rpc_unreachableConnection refused or DNS failureURL and port, the SSH tunnel, firewall; the node process
rpc_timeoutNo answer within --timeoutNode load, network latency; raise --timeout
rpc_http_statusNon-JSON HTTP errorA proxy or load balancer in front of the RPC; the URL path. HTTP 429 is a public endpoint's rate limit: lower --concurrency
rpc_bad_responseNot a CometBFT JSON-RPC responseThe URL points at something else (REST, gRPC-web, a web page)
height_unavailableThe node has pruned that heightUse a node with more history, or a smaller window
rest_wrong_chaincosmos.rest is on another chain than the nodesThe REST URL
no_slashing_module / no_gov_v1 (ok)The chain does not have that module, e.g. an ICS consumer or an authority-run chainNothing: those checks do not apply there
rest_not_found / no_signing_infoThe chain does not know the addressThat validator_address is the consensus address, not cosmos1… / cosmosvaloper1…
watched by validator_address onlyA node tool was called for a validator without rpcExpected: only validator_health works for it

FAQ

Can it unjail my validator, restart a node or send a transaction? No, by design. There is no code path that signs or writes; see the security model.

Does it need my validator's RPC? No. A validator can be watched by validator_address alone; its signatures are read from your sentries, full nodes or a public RPC.

What leaves my machine? Tool results go to your MCP client and, through it, to the LLM provider: node names, roles, heights, peer counts, validator addresses. IPs and node IDs are masked. For production nodes, get your organization's approval first.

Does it support gno.land? Not yet: Tendermint2's RPC differs from CometBFT's. For gno.land itself see gnoverse/gno-mcp.

Why no disk or memory checks? On purpose: node_exporter and your existing alerting cover host metrics; cometbft-mcp focuses on judgments that need chain rules.

Development

bash
make test           # unit tests, no networkmake lintmake localnet-up    # 4 validators + 1 sentry (simd) in Docker; writes localnet/config.yamlmake e2e            # MCP over stdio: downtime, a real jail + unjail, an upgrade proposal, a chain halt (~5 min)go test -tags mainnet -v ./test/mainnet/   # read-only smoke test on 11 mainnets' public endpoints (~2 min)

The localnet's genesis is tuned so failures show up in seconds (50-block slashing window, 50% min signed, 60 s jail, 30 s voting). Try it interactively:

bash
make buildclaude mcp add cometbft-local -- "$PWD/bin/cometbft-mcp" --config "$PWD/localnet/config.yaml"make localnet-stop VAL=val3           # "is val3 signing? how long until it's jailed?"make localnet-stop VAL="val2 val3"    # halt the chain; wait a minute: "why did blocks stop?"make localnet-down

CI runs lint and unit tests on every push and pull request (skipped when only docs change); the e2e suite runs daily, on demand, and on pull requests labeled e2e. Contributing: CONTRIBUTING.md. The code map and the invariants that must never break: AGENTS.md.

Roadmap

  • ICS consumer chains: read jail status from the provider chain
  • secp256k1 consensus keys
  • Tendermint2 (gno.land) adapter

License

Apache-2.0

来源:README.md,提交 4c92b3f

工具

0
SourceWeft 曾在隔离沙箱中以无凭据方式启动该软件包一次,以列出其工具,但未能完成:该软件包类型无法在沙箱中运行。

版本历史

3
  1. v0.4.3最新Nov 6, 2026
  2. v0.4.2Nov 5, 2026
  3. v0.3.1Nov 5, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分