# 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

```plaintext
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)

```json
{
  "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)

```json
{
  "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:

```bash
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`:

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

***

### Test Call Locally

You can test the signing flow without running an agent:

```bash
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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pil.so/mcp-server-models/metamask-mcp-signing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
