metamask-mcp: Signing

The metamask-mcp server is the default wallet signer module in PILSO OS.

It acts as a secure bridge between an agent’s intent and the user’s wallet, preparing unsigned transaction payloads and routing them to MetaMask for final signature and onchain execution.

No private key is ever exposed — and no transaction is sent without explicit user approval.


What It Does

  • Prepares and formats raw Ethereum transactions (or EIP-712 messages)

  • Ensures the transaction structure is valid and RPC-ready

  • Sends the payload to MetaMask for signing

  • Waits for confirmation and returns signed tx or status

  • Supports eth_sendTransaction and eth_signTypedData_v4


Architecture Overview

LLM Agent → metamask-mcp → MetaMask UI → User signs → tx is sent
  • LLM builds intent: "Transfer 0.1 ETH to Bob"

  • metamask-mcp constructs a safe, valid transaction object

  • The object is passed to MetaMask via browser context or injected signer

  • User sees and approves/rejects

  • The signed transaction is broadcast to the chain


Tool Name: metamask.sign

Request (from agent)

{
  "tool": "metamask.sign",
  "args": {
    "to": "0x1234567890abcdef...",
    "data": "0x...",
    "value": "0",
    "gas": "21000",
    "chainId": 1
  }
}
  • to: Target contract or address

  • data: Hex-encoded function call or message

  • value: Optional ETH value to send

  • gas: Estimated gas limit

  • chainId: Target network ID

Response (to agent)

{
  "status": "signed",
  "txHash": "0xabc...",
  "explorer": "https://etherscan.io/tx/0xabc..."
}

Server Setup

This server is included in the official MCP server repo.

To run it locally:

git clone https://github.com/pilso-os/mcp-servers
cd mcp-servers/metamask-mcp
npm install
npm start

It will default to http://localhost:3020.

Add this endpoint in your pilso.config.json:

"tools": [
  "http://localhost:3020"
]

Test Call Locally

You can test the signing flow without running an agent:

npx pilso call \
  --tool metamask.sign \
  --args '{"to": "0x123...", "data": "0x...", "chainId": 1}'

MetaMask will prompt for signature. Nothing is signed without user approval.


Security Principles

  • Non-custodial: The server cannot access or sign transactions directly

  • User-controlled: All signing is done through MetaMask UI

  • Modular: Can be swapped out with other signer MCPs (e.g. safe-mcp)

  • Auditable: All unsigned payloads are visible in logs before submission


Signing Best Practices

  • Always preview transaction payloads in your session logs

  • Set alwaysAllow to false for signing tools — manual approval is safer

  • Only expose metamask.sign to scoped roles like signer, not developer

  • Use guardrails like “Never send tokens” in roles to prevent misuse


Future Additions

  • Support for WalletConnect via walletconnect-mcp

  • Support for Gnosis Safe via safe-mcp

  • EIP-712 typed data signing (WIP)


✅ Summary

Property
Value

Tool name

metamask.sign

Port

3020 (default)

Signs?

No — prepares and sends to MetaMask

Custody risk

None

Execution flow

Agent → MCP → Wallet UI → Signature

metamask-mcp ensures that every transaction is intentional, visible, and user-approved. It’s the foundation of PILSO’s non-custodial execution model.

Last updated