
Routes blockchain transactions through your actual browser wallet instead of asking for private keys in config files. Exposes MCP tools for EVM chains (MetaMask, Rabby) via EIP-6963 and TRON via TronLink. You get connect_wallet, send_transaction, sign_message, sign_typed_data, plus balance lookups that work without opening a browser. Each signing operation spawns a local HTTP server and opens an approval page where you review the transaction in your wallet extension. Works with Ethereum, Polygon, Arbitrum, Base, and other EVM chains plus TRON mainnet and testnets. Reach for this when you want Claude to interact with smart contracts but need to approve every action yourself.
[!WARNING] Superseded by browser-web3-signer — the same browser-wallet signing flow, reimplemented in Rust with a CLI plus Rust/TypeScript/Go libraries. Everything published from this repo is now a thin compatibility shim over it, so existing installs keep working; new code should use
browser-web3-signerdirectly.
Your private keys never leave your browser. Every transaction requires explicit approval in your own wallet (MetaMask, Rabby, TronLink, …).
Most blockchain tooling wants a private key in a config file — full, unsupervised access to your funds. These packages route each request to the browser wallet you already use, so you review and approve it like any other dapp interaction.
| Package | What it is now |
|---|---|
mcp-wallet-signer | MCP stdio server: four signing tools over browser-web3-signer |
browser-evm-signer | The old WalletSigner EVM library API, re-backed by the Rust bridge |
browser-tron-signer | The same for TRON (TronLink, TRC-20, contract deploys) |
All three spawn browser-web3-signer serve, which owns the localhost bridge, the approval page
and the browser tab. The binary for your platform is installed as a dependency; nothing else to
set up.
claude mcp add wallet-signer -- npx -y mcp-wallet-signer
Or, for Claude Desktop / Cursor / Windsurf and any other stdio MCP client:
{
"mcpServers": {
"wallet-signer": {
"command": "npx",
"args": ["-y", "mcp-wallet-signer"]
}
}
}
| Tool | Description |
|---|---|
connect_wallet | Connect a wallet, return the address |
send_transaction | Send value or call a contract, return the tx hash |
sign_message | personal_sign a message, return the signature |
sign_typed_data | Sign EIP-712 typed data, return the signature |
EVM_MCP_DEFAULT_CHAIN sets the chain id used when a call omits one (default: 1).
import { WalletSigner } from "browser-evm-signer";
const signer = new WalletSigner({ defaultChainId: 8453 });
const { address } = await signer.connectWallet();
const { txHash } = await signer.sendTransaction({ to: "0x…", value: "1000000000000000000" });
PendingStore, pendingStore, createHttpServer, startTestServer,
buildConnectUrl, buildSignUrl, openBrowser — the in-process HTTP bridge they drove no
longer exists.approvalUrl is now the bridge's base URL. The bridge opens the approval page itself and
does not hand the per-request URL back.port (the constructor option) is ignored: the bridge binds its own free port.
getPort() / DEFAULT_PORT still resolve, for source compatibility.get_balance, get_token_balance) and the TRON tools are gone
from the MCP server. Balances never needed a wallet — any RPC-reading MCP server or cast call
does them without an approval prompt — and TRON signing is a CLI away. WalletSigner.getBalance
and .getTokenBalance are untouched in both libraries.browser-evm-signer@0.3.0 never worked at all: its exports
pointed at ./esm/mod.js while the tarball shipped ./esm/browser-evm-signer/src/mod.js,
which took mcp-wallet-signer@0.6.0 down with it
(#2).The pre-shim Deno implementation — the in-process bridge, the Svelte approval UI, the
wallet-signer-core package — is in the history, up to commit
636fd3b.
npm install
npm test # builds, then runs each package's tests against a fake bridge
Releases are per package: tag <package>@<version> and publish a GitHub release.
MIT
EVM_MCP_PORTdefault: 3847HTTP server port for the browser approval UI (default: 3847)
EVM_MCP_DEFAULT_CHAINdefault: 1Default EVM chain ID (default: 1 for Ethereum mainnet)