MCP server for local transaction signing on EVM, UTXO, Tron, XRP, Kaspa, and Solana — no API calls needed
This MCP server provides 6 cryptographic signing tools with generally well-structured schemas and descriptions. Naming is clear and verb-driven (evm_sign, utxo_sign, etc.). Input schemas are comprehensive and use discriminated unions for action variants, which is excellent for parameter clarity. However, several critical gaps reduce the overall score: (1) output schemas are NOT documented, callers cannot predict the structure of signed transactions; (2) error handling is minimal, no guidance on what to do if signing fails; (3) parameter descriptions, while present, lack specificity on valid ranges and formats (e.g., 'hex, with or without 0x prefix' is good, but no validation examples); (4) the server embeds private key parameters as inputs, which is a significant security anti-pattern despite the security warning in descriptions. The tool composition is clean (each does one signing action), and discriminated unions reduce parameter ambiguity. Descriptions are detailed and contextual but verbose (300 - 500+ chars, above the 50 - 200 baseline for LLM-optimized docs). Tool names are excellent (verb_noun format), making intent clear.
Sign an EVM transaction or EIP-712 typed-data message. Three actions: (1) sign-unsigned-hex: sign pre-built unsigned tx hex; (2) sign-from-details: build and sign from fields (blockchain, network, toAddress, value, gas, fee, etc.); (3) sign-typed-data: sign an EIP-712 typed-data message — the x402 GASLESS path, e.g. the EIP-3009 TransferWithAuthorization returned by the x402 buyer /authorize (scheme eip712). For (3) pass domain/types/primaryType/message verbatim; it returns a 65-byte signature (no tx built). Network names (e.g. ethereum+sepolia, polygon+mainnet) are mapped to chainId internally. Private key is always passed as parameter (never from env). SECURITY: Private keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
Sign a Kaspa (native KAS) transaction locally. Kaspa is a UTXO/blockDAG chain (schnorr signatures, mainnet only). Action sign-from-details: sign from a prepared transaction object (data.item from the Kaspa prepare-transaction API) — each input carries its prevout script + sompi. Returns the signed tx as JSON (the form the Kaspa broadcast service expects). Private keys (one per input) are passed as parameters (never from env). SECURITY: Private keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
Partial-sign a Solana (SVM) x402 payment transaction locally (@solana/web3.js). One action: partial-sign — deserialize the base64 UNSIGNED TransferChecked tx from the x402 buyer /authorize (scheme svm-transaction), add ONLY the source-authority (buyer) signature, and re-serialize to base64. The feePayer slot stays UNSIGNED — the facilitator signs it at settle. Returns { transaction } (base64). Secret key is base58, passed as parameter (never from env). SECURITY: keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
Output schemas are NOT documented. Callers have no way to predict the structure of signed transactions (e.g., does evm_sign return { signedTx, hash, r, s, v }? Does utxo_sign return serialized hex or JSON?). LLMs cannot plan downstream operations without knowing what fields to extract.
Private keys are passed as tool PARAMETERS, not injected server-side. This violates the secret-injection pattern: private keys appear in logs, prompt history, and agent traces. The security warning in descriptions is not sufficient, the architecture itself is insecure. This should be fixed in a future version with server-side key management or integration with a secure key provider.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 45 | - | v1 |
Sign a Tron transaction (no TronWeb): Node crypto (sha256) + elliptic (secp256k1) + minimal protobuf encode/decode. Two actions: (1) sign-from-details: sign from transaction object (must include raw_data_hex); (2) sign-unsigned-hex: sign from raw unsigned tx hex. Returns signedTransactionHex. Private key is passed as parameter (never from env). SECURITY: Private keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
Sign a UTXO transaction (bitcoin, bitcoin-cash, litecoin, dogecoin, dash, zcash). Two actions: (1) sign-from-details: sign from prepared transaction object (e.g. HD wallet prepare-transaction); (2) sign-unsigned-hex: sign from raw unsigned tx hex (provide inputs metadata: script, satoshis per input). Private key is passed as parameter (never from env). SECURITY: Private keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
Sign an XRP (Ripple) transaction. Two actions: (1) sign-from-details: sign from transaction object (JSON); (2) sign-unsigned-hex: sign from raw unsigned tx hex (XRPL serialized). Returns signedTransactionHex and signedTransactionHash. Secret is passed as parameter (never from env). SECURITY: Private keys may be logged by MCP clients or stored in conversation history — use only in trusted local environments.
No error handling guidance. If signing fails (invalid key format, unsupported network, malformed transaction), the tool throws a generic error with no recovery instructions. Example: 'Invalid blockchain parameter' should guide the LLM to check supported_chains resource first.
Descriptions are verbose (300 - 500+ chars). Baseline for LLM-optimized descriptions is 50 - 200 chars. While content is good, excess length wastes tokens and buries key details. Example: evm_sign description could be condensed to 'Sign an EVM transaction locally (legacy or EIP-1559) or an EIP-712 typed-data message. Three actions: sign-unsigned-hex, sign-from-details, sign-typed-data. No network calls. Private key passed as parameter, use only in trusted local environments.' (~180 chars).
Parameter descriptions lack validation examples. While 'hex, with or without 0x prefix' is present for private keys, there are no examples of valid formats or constraints on length. E.g., 'privateKey: EVM private key (32 bytes, hex with or without 0x prefix; e.g., 0x1a2b3c... or 1a2b3c...). Invalid format raises InvalidPrivateKeyError.'