https://github.com/tetherto/wdk-mcp-toolkit
https://github.com/tetherto/wdk-mcp-toolkit
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/tetherto/wdk-mcp-toolkit
- Owner: tetherto
- License: apache-2.0
- Created: 2025-11-19T06:20:01.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2026-02-12T17:25:06.000Z (4 months ago)
- Last Synced: 2026-02-13T01:05:46.632Z (4 months ago)
- Language: JavaScript
- Size: 603 KB
- Stars: 0
- Watchers: 0
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @tetherto/wdk-mcp-toolkit
https://github.com/user-attachments/assets/9fc1aa65-b76b-4569-bac0-42f75ccdc1ce
> **Note:** This package is currently in beta. Please test thoroughly in development environments before using in production.
A simple and secure package to expose WDK (Wallet Development Kit) functionality through the Model Context Protocol (MCP). This package provides a clean API for creating MCP servers that enable AI agents to interact with cryptocurrency wallets across multiple blockchains.
## 🔍 About WDK
This module is part of the WDK (Wallet Development Kit) project, which empowers developers to build secure, non-custodial wallets with unified blockchain access, stateless architecture, and complete user control.
For detailed documentation about the complete WDK ecosystem, visit [docs.wallet.tether.io](https://docs.wallet.tether.io).
## 🌟 Features
- **MCP Server Extension**: Extends `McpServer` from [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) with all familiar APIs plus WDK-specific functionality
- **Multi-Chain Support**: Register wallets for any blockchain supported by WDK wallet modules (EVM chains, Bitcoin, Solana, TON, TRON, and more)
- **Built-in Tools**: Pre-built MCP tools for wallet operations, pricing data, and transaction history
- **Extensible & Modular**: Register only the tools you need, create custom tools, and organize functionality into reusable modules
- **Secure by Design**: Automatic memory cleanup and secure key disposal
## ⚙️ Requirements
### MCP Client Compatibility
This toolkit requires an MCP client that supports **tools**. For wallet write operations (sending transactions, signing messages), a client that also supports **elicitations** is required to enable human approval flows before executing sensitive operations.
| Feature | Required For |
|---------|--------------|
| Tools support | All operations (read and write) |
| Elicitations support | Write operations (`sendTransaction`, `transfer`, `sign`, etc.) |
See the [full list of MCP clients and their capabilities](https://modelcontextprotocol.io/clients).
## ⬇️ Installation
To install the `@tetherto/wdk-mcp-toolkit` package, follow these instructions:
You can install it using npm:
```bash
npm install @tetherto/wdk-mcp-toolkit @modelcontextprotocol/sdk
```
You'll also need to install the wallet modules for your target blockchains:
```bash
npm install @tetherto/wdk-wallet-evm @tetherto/wdk-wallet-btc
```
Add `"type": "module"` to your `package.json` for ES module support:
```json
{
"type": "module"
}
```
## 🚀 Quick Start
### Creating a Basic MCP Server
```javascript
import { WdkMcpServer, WALLET_TOOLS, PRICING_TOOLS, INDEXER_TOOLS } from '@tetherto/wdk-mcp-toolkit'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
const server = new WdkMcpServer('my-wallet-server', '1.0.0')
.useWdk({ seed: process.env.WDK_SEED })
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth-mainnet.g.alchemy.com/v2/your-api-key'
})
.registerWallet('bitcoin', WalletManagerBtc, {
network: 'bitcoin'
})
.usePricing()
.useIndexer({ apiKey: process.env.WDK_INDEXER_API_KEY })
.registerTools([...WALLET_TOOLS, ...PRICING_TOOLS, ...INDEXER_TOOLS])
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('WDK MCP Server running on stdio')
```
> **📁 Example:** See [`examples/basic/index.js`](examples/basic/index.js) for a complete working example.
### Example Prompts
Here are example prompts you can use with your AI agent connected to WDK MCP Toolkit:
| Category | Prompt |
|----------|--------|
| **Wallet** | "What's my Ethereum address?" |
| **Wallet** | "Send 0.01 ETH to Vitalik" |
| **Wallet** | "How much USDT do I have on Arbitrum?" |
| **Pricing** | "What's the current price of ETH in USD?" |
| **Indexer** | "Show my recent XAUT transfers on Ethereum" |
| **Swap** | "Swap 100 USDT for XAUT on Ethereum" |
| **Bridge** | "Bridge 50 USDT from Ethereum to Arbitrum" |
| **Lending** | "Supply 100 USDT to Aave on Ethereum" |
| **Fiat On-Ramp** | "Buy $100 worth of ETH with USD" |
### Custom Token Registration
Token registration maps human-readable symbols (like "USDT") to contract addresses. This is necessary because:
1. **AI agents work with symbols** — Users say "send 100 USDT" not "send 100 tokens with contract address 0xXYZ"
2. **Decimal handling** — Each token has different decimals (USDT uses 6, DAI uses 18). The registry stores this so tools can convert between human amounts and raw values.
3. **Chain-specific addresses** — USDT has different contract addresses on each chain. The registry resolves the correct address per chain.
```javascript
// Register additional tokens beyond the defaults
server
.registerToken('ethereum', 'USDC', {
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
decimals: 6
})
.registerToken('ethereum', 'DAI', {
address: '0x6b175474e89094c44da98b954eedeac495271d0f',
decimals: 18
})
// Tools use the registry to resolve symbols
const usdc = server.getTokenInfo('ethereum', 'USDC')
console.log('USDC address:', usdc.address)
```
### Using Read-Only vs Write Tools
```javascript
import { WALLET_READ_TOOLS, WALLET_WRITE_TOOLS } from '@tetherto/wdk-mcp-toolkit'
// For read-only access (balance checks, address lookups, fee estimates)
const readOnlyServer = new WdkMcpServer('read-only-server', '1.0.0')
.useWdk({ seed: process.env.WDK_SEED })
.registerWallet('ethereum', WalletManagerEvm, { provider: '...' })
.registerTools(WALLET_READ_TOOLS)
// For full access (includes sendTransaction, transfer, sign)
const fullAccessServer = new WdkMcpServer('full-access-server', '1.0.0')
.useWdk({ seed: process.env.WDK_SEED })
.registerWallet('ethereum', WalletManagerEvm, { provider: '...' })
.registerTools(WALLET_WRITE_TOOLS)
```
> **💡 Best Practice:** Register only the tools you need. Large tool sets increase context size, which can lead to slower responses, higher costs, and potential hallucinations where the AI invokes incorrect tools. If you only need to check balances, import and register just that tool:
> ```javascript
> import { getBalance } from '@tetherto/wdk-mcp-toolkit'
> server.registerTools([getBalance])
> ```
## 🔌 Enabling Capabilities
`WdkMcpServer` uses a capability pattern. The `use*` methods enable capabilities by initializing underlying clients that tools can access:
| Method | Enables | Tools Can Access |
|--------|---------|------------------|
| `useWdk(config)` | Wallet operations | `server.wdk` |
| `usePricing()` | Price data | `server.pricingClient` |
| `useIndexer(config)` | Transaction history | `server.indexerClient` |
**How it works:**
```javascript
// 1. Enable capabilities
const server = new WdkMcpServer('my-server', '1.0.0')
.useWdk({ seed: process.env.WDK_SEED }) // server.wdk is now available
.usePricing() // server.pricingClient is now available
.useIndexer({ apiKey: process.env.API_KEY }) // server.indexerClient is now available
// 2. Register tools that use those capabilities
server.registerTools(WALLET_TOOLS) // These tools call server.wdk.*
server.registerTools(PRICING_TOOLS) // These tools call server.pricingClient.*
server.registerTools(INDEXER_TOOLS) // These tools call server.indexerClient.*
```
**Writing custom tools:**
You can register tools directly using `registerTool()` from the MCP SDK, or use our `registerTools()` utility for bulk registration.
**Single tool with `registerTool()` (MCP SDK method):**
```javascript
import { z } from 'zod'
const chains = server.getChains()
server.registerTool(
'getAllTokenBalances',
{
title: 'Get All Token Balances',
description: 'Get balances for all registered tokens on a chain.',
inputSchema: z.object({
chain: z.enum(chains).describe('The blockchain to query')
}),
annotations: {
readOnlyHint: true,
destructiveHint: false
}
},
async ({ chain }) => {
try {
const account = await server.wdk.getAccount(chain, 0)
const symbols = server.getRegisteredTokens(chain)
const balances = {}
for (const symbol of symbols) {
const token = server.getTokenInfo(chain, symbol)
const rawBalance = await account.getTokenBalance(token.address)
const balance = Number(rawBalance) / Math.pow(10, token.decimals)
balances[symbol] = balance.toString()
}
return {
content: [{
type: 'text',
text: JSON.stringify(balances, null, 2)
}],
structuredContent: balances
}
} catch (error) {
return {
isError: true,
content: [{
type: 'text',
text: `Error getting token balances: ${error.message}`
}]
}
}
}
)
```
**Multiple tools with `registerTools()` (WdkMcpServer utility):**
The `registerTools()` method is a utility we added on top of the MCP SDK. It accepts an array of tool registration functions, making it easy to organize tools into modules and register them in bulk:
```javascript
// Tool defined as a registration function
function getAllTokenBalances (server) {
const chains = server.getChains()
server.registerTool(
'getAllTokenBalances',
{ /* schema */ },
async ({ chain }) => { /* handler */ }
)
}
function getPortfolioValue (server) {
server.registerTool(
'getPortfolioValue',
{ /* schema */ },
async (params) => { /* handler */ }
)
}
// Register multiple tools at once
server.registerTools([getAllTokenBalances, getPortfolioValue])
```
This pattern allows you to:
- Organize tools into separate files/modules
- Conditionally include tools based on enabled capabilities
- Mix custom tools with built-in tool arrays
- Keep tool counts minimal to reduce context bloat
**Capability dependencies:**
If a tool requires a capability that wasn't enabled, it will fail at runtime. The built-in tools check for this:
- `WALLET_TOOLS` require `useWdk()` and `registerWallet()`
- `PRICING_TOOLS` require `usePricing()`
- `INDEXER_TOOLS` require `useIndexer()`
- `SWAP_TOOLS` require `useWdk()` and `registerProtocol()` with a swap protocol
- `BRIDGE_TOOLS` require `useWdk()` and `registerProtocol()` with a bridge protocol
- `LENDING_TOOLS` require `useWdk()` and `registerProtocol()` with a lending protocol
- `FIAT_TOOLS` require `useWdk()` and `registerProtocol()` with a fiat protocol
## 🖥️ Using with VS Code GitHub Copilot Chat
You can use this MCP server with [VS Code GitHub Copilot Chat](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).
### Quick Setup (Recommended)
The easiest way to get started is using the setup wizard:
```bash
git clone https://github.com/tetherto/wdk-mcp-toolkit.git
cd wdk-mcp-toolkit
npm install
npm run setup
```
The wizard will guide you through:
1. **Seed phrase** (required) — Your BIP-39 wallet seed phrase
2. **WDK Indexer API key** (optional) — For transaction history features ([get one here](https://wdk-api.tether.io/register))
3. **MoonPay credentials** (optional) — For fiat on/off-ramp features ([MoonPay Dashboard](https://dashboard.moonpay.com/))
After setup, the wizard will:
- Install required dependencies automatically
- Generate `.vscode/mcp.json` with your credentials
- Open VS Code ready to start the server
> **🔒 Security:** Your seed phrase is stored locally in `.vscode/mcp.json` which is gitignored. We recommend using a dedicated development wallet.
### Manual Configuration
If you prefer manual setup, create `.vscode/mcp.json` in the project root:
```json
{
"servers": {
"wdk": {
"type": "stdio",
"command": "node",
"args": ["examples/basic/index.js"],
"env": {
"WDK_SEED": "your twelve word seed phrase here",
"WDK_INDEXER_API_KEY": "optional - get at https://wdk-api.tether.io/register",
"MOONPAY_API_KEY": "optional - get at https://dashboard.moonpay.com/",
"MOONPAY_SECRET_KEY": "optional - get at https://dashboard.moonpay.com/"
}
}
}
}
```
Then install the required dependencies:
```bash
npm install @tetherto/wdk-wallet-btc @tetherto/wdk-wallet-evm
npm install @tetherto/wdk-protocol-swap-velora-evm @tetherto/wdk-protocol-bridge-usdt0-evm
npm install @tetherto/wdk-protocol-lending-aave-evm @tetherto/wdk-protocol-fiat-moonpay
```
### Starting the Server
1. Open `.vscode/mcp.json` in VS Code
2. Click the **Start** button that appears above the server configuration
3. Open GitHub Copilot Chat and select **Agent** mode
4. Click **Tools** to verify the MCP server tools are available
### Example Conversations
```
You: What's my ethereum address?
Copilot: Your Ethereum address is 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
You: Check my ETH balance
Copilot: Your ETH balance is 1.5 ETH
You: What's the current price of BTC?
Copilot: The current price of BTC is $98,450.00 USD
You: Send 1 USDT to vitalik.eth
Copilot: I'll transfer 1 USDT to vitalik.eth.
[Requests approval via elicitation]
Transaction sent! Hash: 0xabc123...
```
### Optional Capabilities
The server conditionally enables capabilities based on which environment variables are set:
| Capability | Environment Variables | Tools |
|------------|----------------------|-------|
| Wallet, Pricing, Swap, Bridge, Lending | `WDK_SEED` (required) | Always enabled |
| Transaction History | `WDK_INDEXER_API_KEY` | `INDEXER_TOOLS` |
| Fiat On/Off-Ramp | `MOONPAY_API_KEY` + `MOONPAY_SECRET_KEY` | `FIAT_TOOLS` |
Re-run `npm run setup` to change your configuration or enable additional capabilities.
## 📚 API Reference
### Table of Contents
| Class | Description |
|-------|-------------|
| [WdkMcpServer](#wdkmcpserver) | Main class for creating MCP servers with WDK functionality. Extends `McpServer` from `@modelcontextprotocol/sdk`. |
| [CHAINS](#chains) | Convenience constants for chains with pre-configured token addresses. |
| [DEFAULT_TOKENS](#default_tokens) | Pre-configured token addresses for all supported chains. |
### WdkMcpServer
The main class for creating MCP servers with WDK wallet functionality. Extends `McpServer` from `@modelcontextprotocol/sdk/server/mcp.js`, providing all standard MCP server methods plus WDK-specific functionality.
#### Constructor
```javascript
new WdkMcpServer(name, version)
```
**Parameters:**
- `name` (string): The server name
- `version` (string): The server version
**Example:**
```javascript
const server = new WdkMcpServer('my-wallet-server', '1.0.0')
```
#### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `useWdk(config)` | Initializes the WDK with a seed phrase | `WdkMcpServer` |
| `registerWallet(blockchain, WalletManager, config)` | Registers a wallet for a blockchain | `WdkMcpServer` |
| `useIndexer(config)` | Enables the WDK Indexer client for transaction history | `WdkMcpServer` |
| `usePricing()` | Enables the Bitfinex pricing client | `WdkMcpServer` |
| `registerProtocol(chain, label, Protocol, config)` | Registers a DeFi protocol (swap, bridge, lending, fiat) | `WdkMcpServer` |
| `getSwapChains()` | Returns chains with swap protocols registered | `string[]` |
| `getSwapProtocols(chain)` | Returns swap protocol labels for a chain | `string[]` |
| `getBridgeChains()` | Returns chains with bridge protocols registered | `string[]` |
| `getBridgeProtocols(chain)` | Returns bridge protocol labels for a chain | `string[]` |
| `getLendingChains()` | Returns chains with lending protocols registered | `string[]` |
| `getLendingProtocols(chain)` | Returns lending protocol labels for a chain | `string[]` |
| `getFiatChains()` | Returns chains with fiat protocols registered | `string[]` |
| `getFiatProtocols(chain)` | Returns fiat protocol labels for a chain | `string[]` |
| `registerToken(chain, symbol, token)` | Registers a token address mapping | `WdkMcpServer` |
| `getTokenInfo(chain, symbol)` | Returns token info for a symbol | `TokenInfo \| undefined` |
| `getRegisteredTokens(chain)` | Returns all registered token symbols | `string[]` |
| `getChains()` | Returns all registered blockchain names | `string[]` |
| `registerTools(tools)` | Bulk registers tools from an array of functions | `WdkMcpServer` |
| `close()` | Closes the server and disposes WDK securely | `Promise` |
#### useWdk(config)
Enables wallet capabilities by initializing the Wallet Development Kit. After calling this, `server.wdk` becomes available for tools to use.
**Parameters:**
- `config` (object): Configuration object
- `seed` (string, optional): BIP-39 seed phrase. Falls back to `WDK_SEED` environment variable.
**Returns:** `WdkMcpServer` - The server instance for chaining
**Throws:** `Error` - If no seed is provided
**Example:**
```javascript
server.useWdk({ seed: 'your twelve word seed phrase here' })
// OR use environment variable
server.useWdk({}) // Uses process.env.WDK_SEED
// Now tools can access server.wdk
const account = await server.wdk.getAccount('ethereum', 0)
```
#### registerWallet(blockchain, WalletManager, config)
Registers a wallet module for a specific blockchain. Automatically registers default tokens (USDT) for the chain if available.
**Parameters:**
- `blockchain` (string): The blockchain name (e.g., "ethereum", "bitcoin")
- `WalletManager` (class): The wallet manager class from a WDK wallet package
- `config` (object): Configuration object specific to the wallet manager
**Returns:** `WdkMcpServer` - The server instance for chaining
**Throws:** `Error` - If `useWdk()` has not been called
**Example:**
```javascript
server.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth-mainnet.g.alchemy.com/v2/your-api-key'
})
server.registerWallet('bitcoin', WalletManagerBtc, {
network: 'bitcoin',
host: 'electrum.blockstream.info',
port: 50001
})
```
#### registerProtocol(chain, label, Protocol, config)
Registers a DeFi protocol for a blockchain. Protocols enable swap, bridge, lending, and fiat on/off-ramp functionality. The protocol type is automatically detected from the class inheritance.
**Parameters:**
- `chain` (string): The blockchain name (e.g., "ethereum")
- `label` (string): The protocol label (e.g., "velora", "aave", "moonpay")
- `Protocol` (class): The protocol class (must extend SwapProtocol, BridgeProtocol, LendingProtocol, or FiatProtocol)
- `config` (object, optional): Protocol-specific configuration
**Returns:** `WdkMcpServer` - The server instance for chaining
**Throws:** `Error` - If `useWdk()` has not been called, or if unknown protocol type
**Example:**
```javascript
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'
import MoonPayProtocol from '@tetherto/wdk-protocol-fiat-moonpay'
server
// Swap protocol - enables token swaps
.registerProtocol('ethereum', 'velora', VeloraProtocolEvm)
// Bridge protocol - enables cross-chain transfers
.registerProtocol('ethereum', 'usdt0', Usdt0ProtocolEvm)
// Lending protocol - enables supply, borrow, withdraw, repay
.registerProtocol('ethereum', 'aave', AaveProtocolEvm)
// Fiat protocol - enables buy/sell crypto with fiat
.registerProtocol('ethereum', 'moonpay', MoonPayProtocol, {
secretKey: process.env.MOONPAY_SECRET_KEY,
apiKey: process.env.MOONPAY_API_KEY
})
```
**Learn more about protocols:**
- [Swap Modules](https://docs.wallet.tether.io/sdk/swap-modules)
- [Bridge Modules](https://docs.wallet.tether.io/sdk/bridge-modules)
- [Lending Modules](https://docs.wallet.tether.io/sdk/lending-modules)
- [Fiat Modules](https://docs.wallet.tether.io/sdk/fiat-modules)
#### useIndexer(config)
Enables transaction history capabilities by initializing the WDK Indexer client. After calling this, `server.indexerClient` becomes available for tools to use.
**Parameters:**
- `config` (object): Configuration object
- `apiKey` (string): WDK Indexer API key
**Returns:** `WdkMcpServer` - The server instance for chaining
**Throws:** `Error` - If no apiKey is provided
**Example:**
```javascript
server.useIndexer({ apiKey: process.env.WDK_INDEXER_API_KEY })
// Now tools can access server.indexerClient
const transfers = await server.indexerClient.getTokenTransfers('ethereum', 'usdt', address)
const balance = await server.indexerClient.getTokenBalance('ethereum', 'usdt', address)
```
#### usePricing()
Enables pricing capabilities by initializing the Bitfinex pricing client. After calling this, `server.pricingClient` becomes available for tools to use.
**Returns:** `WdkMcpServer` - The server instance for chaining
**Example:**
```javascript
server.usePricing()
// Now tools can access server.pricingClient
const price = await server.pricingClient.getCurrentPrice('BTC', 'USD')
```
#### registerToken(chain, symbol, token)
Registers a token symbol to contract address mapping for a blockchain.
**Parameters:**
- `chain` (string): The blockchain name
- `symbol` (string): The token symbol (e.g., "USDT", "USDC")
- `token` (object): Token information
- `address` (string): Token contract address
- `decimals` (number): Number of decimal places
**Returns:** `WdkMcpServer` - The server instance for chaining
**Example:**
```javascript
server.registerToken('ethereum', 'USDC', {
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
decimals: 6
})
```
#### getTokenInfo(chain, symbol)
Returns token information for a symbol on a blockchain.
**Parameters:**
- `chain` (string): The blockchain name
- `symbol` (string): The token symbol (case-insensitive)
**Returns:** `TokenInfo | undefined` - The token info or undefined if not found
**Example:**
```javascript
const usdt = server.getTokenInfo('ethereum', 'USDT')
// { address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', decimals: 6 }
```
#### getRegisteredTokens(chain)
Returns all registered token symbols for a blockchain.
**Parameters:**
- `chain` (string): The blockchain name
**Returns:** `string[]` - Array of token symbols
**Example:**
```javascript
const tokens = server.getRegisteredTokens('ethereum')
// ['USDT', 'USDC', 'DAI']
```
#### getChains()
Returns all registered blockchain names.
**Returns:** `string[]` - Array of blockchain names
**Example:**
```javascript
const chains = server.getChains()
// ['ethereum', 'polygon', 'bitcoin']
```
#### registerTools(tools)
Utility method for bulk tool registration. This is a convenience wrapper we added on top of the MCP SDK's `registerTool()` method. Each function in the array receives the server instance and should call `server.registerTool()` internally.
**Parameters:**
- `tools` (array): Array of tool registration functions with signature `(server: WdkMcpServer) => void`
**Returns:** `WdkMcpServer` - The server instance for chaining
**Example:**
```javascript
import { WALLET_TOOLS, PRICING_TOOLS } from '@tetherto/wdk-mcp-toolkit'
// Register built-in tool arrays
server.registerTools([...WALLET_TOOLS, ...PRICING_TOOLS])
// Or mix with custom tools
server.registerTools([
...WALLET_TOOLS,
myCustomTool,
anotherCustomTool
])
```
**Note:** For registering a single tool, you can use `registerTool()` directly (inherited from McpServer).
#### close()
Closes the server and securely disposes the WDK instance, clearing sensitive data from memory.
**Returns:** `Promise`
**Example:**
```javascript
await server.close()
```
### CHAINS
Convenience constants for blockchain names that have pre-configured USDT token addresses. Using these constants triggers automatic token registration via `DEFAULT_TOKENS`.
**Note:** You can register any blockchain name you want. `CHAINS` is purely for convenience. If you use a name not in `CHAINS`, simply register your tokens manually:
```javascript
// Using a custom chain name works fine
server.registerWallet('zksync', WalletManagerEvm, {
provider: 'https://mainnet.era.zksync.io'
})
// Just register tokens yourself since there's no default
server.registerToken('zksync', 'USDT', {
address: '0x493257fD37EDB34451f62EDf8D2a0C418852bA4C',
decimals: 6
})
```
### DEFAULT_TOKENS
Pre-configured USDT token addresses for common chains. These are automatically registered when you call `registerWallet()` with a matching chain name.
| Chain | USDT Address | Decimals |
|-------|--------------|----------|
| Ethereum | `0xdAC17F958D2ee523a2206206994597C13D831ec7` | 6 |
| Polygon | `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` | 6 |
| Arbitrum | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` | 6 |
| Optimism | `0x94b008aA00579c1307B0EF2c499aD98a8ce58e58` | 6 |
| Base | `0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2` | 6 |
| Avalanche | `0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7` | 6 |
| BNB | `0x55d398326f99059fF775485246999027B3197955` | 18 |
| Plasma | `0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb` | 6 |
| TRON | `TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t` | 6 |
| TON | `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs` | 6 |
| Solana | `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` | 6 |
## 🔧 Built-in Tools
### Wallet Tools
| Tool | Category | Description |
|------|----------|-------------|
| `getAddress` | Read | Get wallet address for a blockchain |
| `getBalance` | Read | Get native token balance |
| `getTokenBalance` | Read | Get ERC20/token balance |
| `getFeeRates` | Read | Get current network fee rates |
| `getMaxSpendableBtc` | Read | Get maximum spendable Bitcoin amount |
| `quoteSendTransaction` | Read | Estimate fee for a transaction |
| `quoteTransfer` | Read | Estimate fee for a token transfer |
| `sendTransaction` | Write | Send native tokens |
| `transfer` | Write | Transfer ERC20/tokens |
| `sign` | Write | Sign a message |
| `verify` | Write | Verify a message signature |
### Pricing Tools
| Tool | Description |
|------|-------------|
| `getCurrentPrice` | Get current price for a trading pair |
| `getHistoricalPrice` | Get historical price data |
### Indexer Tools
| Tool | Description |
|------|-------------|
| `getTokenTransfers` | Get token transfer history for an address |
| `getIndexerTokenBalance` | Get token balance via indexer API |
### Swap Tools
Enable token swaps through registered swap protocols (e.g., Velora). See [Swap Modules](https://docs.wallet.tether.io/sdk/swap-modules) for available protocols.
| Tool | Category | Description |
|------|----------|-------------|
| `quoteSwap` | Read | Get a quote for swapping tokens |
| `swap` | Write | Execute a token swap |
### Bridge Tools
Enable cross-chain token transfers through registered bridge protocols (e.g., USDT0). See [Bridge Modules](https://docs.wallet.tether.io/sdk/bridge-modules) for available protocols.
| Tool | Category | Description |
|------|----------|-------------|
| `quoteBridge` | Read | Get a quote for bridging tokens |
| `bridge` | Write | Execute a cross-chain bridge transfer |
### Lending Tools
Enable DeFi lending operations through registered lending protocols (e.g., Aave). See [Lending Modules](https://docs.wallet.tether.io/sdk/lending-modules) for available protocols.
| Tool | Category | Description |
|------|----------|-------------|
| `quoteSupply` | Read | Get a quote for supplying tokens |
| `supply` | Write | Supply tokens to a lending protocol |
| `quoteWithdraw` | Read | Get a quote for withdrawing tokens |
| `withdraw` | Write | Withdraw tokens from a lending protocol |
| `quoteBorrow` | Read | Get a quote for borrowing tokens |
| `borrow` | Write | Borrow tokens from a lending protocol |
| `quoteRepay` | Read | Get a quote for repaying borrowed tokens |
| `repay` | Write | Repay borrowed tokens |
### Fiat Tools
Enable fiat on/off-ramp operations through registered fiat protocols (e.g., MoonPay). See [Fiat Modules](https://docs.wallet.tether.io/sdk/fiat-modules) for available protocols.
| Tool | Category | Description |
|------|----------|-------------|
| `quoteBuy` | Read | Get a quote for buying crypto with fiat |
| `buy` | Write | Execute a fiat-to-crypto purchase |
| `quoteSell` | Read | Get a quote for selling crypto for fiat |
| `sell` | Write | Execute a crypto-to-fiat sale |
| `getTransactionDetail` | Read | Get details of a fiat transaction |
| `getSupportedCryptoAssets` | Read | Get list of supported cryptocurrencies |
| `getSupportedFiatCurrencies` | Read | Get list of supported fiat currencies |
| `getSupportedCountries` | Read | Get list of supported countries |
## 🔒 Security Considerations
- **Seed Phrase Security**: Always store your seed phrase securely and never share it. Use environment variables (`WDK_SEED`) instead of hardcoding.
- **API Key Security**: Store API keys in environment variables, never in source code.
- **Memory Cleanup**: The `close()` method automatically calls `dispose()` on the WDK instance to clear private keys from memory.
- **Read vs Write Tools**: Use `WALLET_READ_TOOLS` for read-only access when write operations are not needed.
- **Elicitations for Write Operations**: For maximum safety, use an MCP client that supports elicitations (like VS Code GitHub Copilot or Cursor) for write operations to ensure human approval before transactions execute.
- **MCP Transport Security**: Use secure transports (stdio, SSE with TLS) in production environments.
- **Tool Annotations**: All tools include proper `readOnlyHint` and `destructiveHint` annotations for MCP clients.
## 🛠️ Development
### Building
```bash
# Install dependencies
npm install
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
```
### Testing
```bash
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
```
### Project Structure
```
src/
├── server.js # WdkMcpServer class, CHAINS, DEFAULT_TOKENS
├── utils/ # Utility functions
│ └── amount.js # Amount parsing and formatting
└── tools/
├── wallet/ # Wallet operation tools
│ ├── index.js # Tool exports
│ ├── getAddress.js
│ ├── getBalance.js
│ ├── getTokenBalance.js
│ ├── getFeeRates.js
│ ├── getMaxSpendableBtc.js
│ ├── quoteSendTransaction.js
│ ├── quoteTransfer.js
│ ├── sendTransaction.js
│ ├── transfer.js
│ ├── sign.js
│ └── verify.js
├── pricing/ # Price data tools
│ ├── index.js
│ ├── getCurrentPrice.js
│ └── getHistoricalPrice.js
├── indexer/ # Transaction history tools
│ ├── index.js
│ ├── getTokenTransfers.js
│ └── getTokenBalance.js
├── swap/ # Token swap tools
│ ├── index.js
│ ├── quoteSwap.js
│ └── swap.js
├── bridge/ # Cross-chain bridge tools
│ ├── index.js
│ ├── quoteBridge.js
│ └── bridge.js
├── lending/ # DeFi lending tools
│ ├── index.js
│ ├── quoteSupply.js
│ ├── supply.js
│ ├── quoteWithdraw.js
│ ├── withdraw.js
│ ├── quoteBorrow.js
│ ├── borrow.js
│ ├── quoteRepay.js
│ └── repay.js
└── fiat/ # Fiat on/off-ramp tools
├── index.js
├── quoteBuy.js
├── buy.js
├── quoteSell.js
├── sell.js
├── getTransactionDetail.js
├── getSupportedCryptoAssets.js
├── getSupportedFiatCurrencies.js
└── getSupportedCountries.js
```
## 📜 License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## 🆘 Support
For support, please open an issue on the GitHub repository.
## 📖 Learn More
- **WDK Documentation**: [docs.wallet.tether.io](https://docs.wallet.tether.io)
- **MCP SDK**: [github.com/modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk)
- **MCP Specification**: [modelcontextprotocol.io/specification/2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25)
- **MCP Clients**: [modelcontextprotocol.io/clients](https://modelcontextprotocol.io/clients)
- **VS Code Copilot MCP**: [Using MCP servers in VS Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)