A read-only Model Context Protocol server for Cosmos SDK chains. It exposes only the tools backed by the RPC, gRPC, and LCD endpoints configured at startup, and is designed to run as a local stdio server in Hermes Agent.
- Official Go MCP SDK with stdio transport
- Any combination of CometBFT RPC, Cosmos gRPC, and LCD/REST endpoints
- Capability-based tool discovery: unconfigured protocols do not expose tools
- Read-only RPC allowlist, LCD GET-only access, and gRPC Query-service enforcement
- Dynamic gRPC calls through server reflection
- Version-independent high-level queries with lazy capability discovery and LCD fallback
- Timeouts, response-size limits, TLS by default, and redacted endpoint status
- Single binaries for Linux, macOS, and Windows plus a container image
go install github.com/jhlee-young/cosmos-mcp/cmd/cosmos-mcp@latestYou can also download an archive and checksum from GitHub Releases, or run ghcr.io/jhlee-young/cosmos-mcp:<version>.
At least one endpoint is required. Endpoint reachability is checked at call time, so a temporarily unavailable node does not prevent the MCP server from starting.
# RPC only
cosmos-mcp serve --rpc-url https://rpc.example.com
# LCD only
cosmos-mcp serve --lcd-url https://lcd.example.com
# Plaintext gRPC only (common for local nodes)
cosmos-mcp serve --grpc-target localhost:9090 --grpc-insecure
# Any combination
cosmos-mcp serve \
--rpc-url https://rpc.example.com \
--grpc-target grpc.example.com:443 \
--lcd-url https://lcd.example.comValidate the configured endpoints without starting MCP:
cosmos-mcp validate --rpc-url https://rpc.example.comConfiguration can also be supplied through environment variables:
| Flag | Environment variable | Default |
|---|---|---|
--rpc-url |
COSMOS_MCP_RPC_URL |
unset |
--grpc-target |
COSMOS_MCP_GRPC_TARGET |
unset |
--grpc-insecure |
COSMOS_MCP_GRPC_INSECURE |
false |
--lcd-url |
COSMOS_MCP_LCD_URL |
unset |
--timeout |
COSMOS_MCP_TIMEOUT |
15s |
--max-response-bytes |
COSMOS_MCP_MAX_RESPONSE_BYTES |
4MiB |
Flags take precedence over environment variables. gRPC uses TLS certificate verification unless --grpc-insecure is explicitly set.
Add a server under mcp_servers in ~/.hermes/config.yaml.
RPC-only example:
mcp_servers:
cosmos:
command: "cosmos-mcp"
args: ["serve", "--rpc-url", "https://rpc.example.com"]
supports_parallel_tool_calls: trueLCD-only example:
mcp_servers:
cosmos:
command: "cosmos-mcp"
args: ["serve", "--lcd-url", "https://lcd.example.com"]
supports_parallel_tool_calls: truegRPC-only example:
mcp_servers:
cosmos:
command: "cosmos-mcp"
args: ["serve", "--grpc-target", "localhost:9090", "--grpc-insecure"]
supports_parallel_tool_calls: trueCombined example using environment variables:
mcp_servers:
cosmos:
command: "cosmos-mcp"
args: ["serve"]
env:
COSMOS_MCP_RPC_URL: "https://rpc.example.com"
COSMOS_MCP_GRPC_TARGET: "grpc.example.com:443"
COSMOS_MCP_LCD_URL: "https://lcd.example.com"
supports_parallel_tool_calls: trueContainer example:
mcp_servers:
cosmos:
command: "docker"
args:
- "run"
- "--rm"
- "-i"
- "ghcr.io/jhlee-young/cosmos-mcp:latest"
- "serve"
- "--rpc-url"
- "https://rpc.example.com"Hermes prefixes discovered tools with the MCP server name, such as mcp_cosmos_chain_status.
endpoint_status is always exposed and reports available, unavailable, or not_configured for each protocol.
| Required endpoint | Tools |
|---|---|
| Any RPC, LCD, or gRPC | chain_status, get_block, get_transaction, search_transactions |
| LCD or gRPC | get_account, get_balances, get_token_info, get_total_supply, get_denom_trace, get_validators, get_validator, get_validator_delegations, get_delegations, get_unbonding_delegations, get_redelegations, get_rewards, get_staking_pool, get_signing_infos, get_community_pool, get_inflation, get_proposals, get_proposal, get_proposal_tally, get_proposal_votes, get_proposal_deposits, get_staking_params, get_gov_params, get_distribution_params, get_mint_params, get_slashing_params, get_bank_params |
| RPC | rpc_query |
| LCD | lcd_query |
| gRPC | grpc_query, simulate_transaction |
Every tool in the LCD-or-gRPC row accepts an optional height to read historical state. It is sent as the
x-cosmos-block-height header, which gRPC carries as request metadata and the LCD forwards through
grpc-gateway. A node that has pruned the height rejects the query instead of answering from current
state, and that rejection is returned as-is rather than retried against an older API version.
High-level tools resolve the best API lazily at call time instead of relying on a reported Cosmos SDK version. They prefer current gRPC services, fall back to legacy service versions and LCD routes when an API is absent, and cache successful bindings. Temporary endpoint failures, authentication failures, rate limits, and server errors do not trigger a version fallback. gRPC high-level queries require server reflection unless an LCD fallback is configured.
Governance tools try cosmos.gov.v1 before cosmos.gov.v1beta1, and get_denom_trace tries the ibc-go v8 DenomTrace route before the v9 Denom rename. get_inflation and get_token_info combine independent queries and report a warnings array when only part of the result is available; chains that replaced the standard x/mint return unsupported_capability for get_inflation. get_token_info additionally resolves the transfer path when given an ibc/ denomination.
List tools use a default page size of 50 and enforce a maximum of 200. Module queries return a continuation key instead of automatically fetching every page; search_transactions uses page-aligned offsets and rejects key or reverse pagination. Normalized high-level results include the original upstream response under raw; meta.binding reports the selected gRPC method, LCD route, or RPC method.
rpc_query accepts only known read-only CometBFT methods and rejects broadcast_tx_*, unsafe_*, and unknown methods. lcd_query accepts a path on the configured origin and only performs GET requests; query parameters already fixed on the configured LCD URL cannot be overridden by a tool call. grpc_query accepts unary services named Query plus a small allowlist of Cosmos read services; the node must expose gRPC reflection. simulate_transaction accepts base64 protobuf transaction bytes and never broadcasts them.
All results include both MCP text content and structured content:
{
"source": "rpc",
"request": {"method": "status"},
"data": {},
"meta": {
"duration_ms": 12,
"binding": "/cosmos.bank.v1beta1.Query/AllBalances"
}
}source is rpc, lcd, or grpc for the endpoint that answered the call, system when the response did not require an endpoint (such as a validation error), or mixed when a tool combines sub-queries answered by different endpoints (for example get_token_info when supply and metadata resolve through different sources).
Tool failures use isError and one of: invalid_input, not_configured, endpoint_unavailable, upstream_timeout, upstream_error, response_too_large, grpc_reflection_unavailable, or unsupported_capability.
go test -race ./...
go vet ./...
go build ./cmd/cosmos-mcpTests use local in-memory and loopback servers and do not depend on a public Cosmos node.
- Tools cannot choose a different host from the endpoint fixed at startup.
- This server does not create, sign, store, or broadcast transactions.
- Transaction simulation is read-only and accepts only already encoded transaction bytes.
- Embedded URL credentials and query strings are removed from status output.
- TLS verification is enabled by default.
- Configure endpoints you trust: query responses are external, untrusted tool data.
grpc_querytreats any gRPC service named...Queryas read-only by Cosmos SDK convention; this is not enforced by the gRPC protocol itself, so a chain that violates the convention could expose a mutating method through it.