A self-contained MCP server that lets AI assistants read blockchain data and prepare transactions, while users keep full custody of their keys and sign in their own wallet.
This blockchain MCP server has 5 well-defined tools with explicit schemas and descriptions visible in src/mcp/server.ts. Tool naming follows verb-noun conventions (get-chains, get-balance, read-contract, prepare-transaction, get-transaction-status). Descriptions are present and substantive (89-200 chars), explaining not just what the tool does but also prerequisites (e.g., read-contract mentions ETHERSCAN_API_KEY for auto-fetching ABIs). Input schemas are fully typed with parameter descriptions. However, output schemas are not explicitly documented in the code samples provided, we can infer structure from the implementation (e.g., get-chains returns chain objects with id/name/nativeCurrency), but LLMs would benefit from explicit response documentation. Error handling is present but could be more granular: the code shows basic try-catch blocks in http handlers (e.g., markSubmitted catches and returns errors) but lacks structured error categories or recovery guidance. Tool composition is sound: prepare-transaction generates unsigned transaction URLs (keeping private keys client-side), and get-transaction-status tracks prepared transactions, these chain well. One critical security pattern is well-executed: private key custody is preserved via external signing URLs rather than exposing credentials as parameters.
Get an address's native-token balance (e.g. ETH) on a given chain.
List the blockchain networks this server supports, with their chain ids and native currencies.
Check the current status of a prepared transaction by its id.
Create an unsigned transaction and return a URL the user opens to review and sign it in their own wallet. Private keys never reach this server. Share the returned URL with the user.
Call a read-only (view/pure) contract method. Provide `abi` as human-readable signatures (e.g. ["function balanceOf(address) view returns (uint256)"]) for zero-config use, or set ETHERSCAN_API_KEY to auto-fetch verified ABIs.
Output schemas not documented. While input schemas are explicit and typed, response structures are inferred from implementation rather than formally declared. LLMs cannot plan downstream tool calls or extract fields without seeing the shape of returned data.
Error handling lacks structured error categories and recovery guidance. Code catches errors and returns messages, but does not classify them as retryable, user-fixable, or fatal, or provide actionable next steps for LLMs (e.g., 'Try with a different chain ID' or 'Check that the ABI is valid').
read-contract parameter 'abi' accepts a union type (string | array | JSON) but the description could better clarify the exact format and valid signatures. Example: 'Provide as either a single function signature string (e.g., "function balanceOf(address) view returns (uint256)"), an array of signature strings, or a full JSON ABI array.'
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 73 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 44 | - | v1 |
prepare-transaction parameters 'value', 'data', and 'gasLimit' have reasonable defaults documented in descriptions, but the schema does not enforce numeric constraints (e.g., gasLimit must be a positive integer). LLMs could pass invalid values like negative numbers or extremely large values.