Skip to main content
Glama
token.ts18.6 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { DEFAULT_NETWORK } from "../chains.js"; import * as services from "../services/index.js"; import { type Address } from 'viem'; import { getPrivateKeyAsHex } from "../config.js"; /** * Registers tools related to tokens (native, ERC20, ERC721, ERC1155). * @param server The MCP server instance */ export function registerTokenTools(server: McpServer) { // Get Sei balance server.tool( "get_balance", "Get the native token balance (Sei) for an address", { address: z.string().describe("The wallet address to check the balance for"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ address, network = DEFAULT_NETWORK }) => { try { const balance = await services.getBalance(address, network); return { content: [{ type: "text", text: JSON.stringify({ address, network, wei: balance.wei.toString(), ether: balance.sei }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get ERC20 token balance server.tool( "get_erc20_balance", "Get the ERC20 token balance of an EVM address", { address: z.string().describe("The EVM address to check"), tokenAddress: z.string().describe("The ERC20 token contract address"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ address, tokenAddress, network = DEFAULT_NETWORK }) => { try { const balance = await services.getERC20Balance( tokenAddress as Address, address as Address, network ); return { content: [{ type: "text", text: JSON.stringify({ address, tokenAddress, network, balance: { raw: balance.raw.toString(), formatted: balance.formatted, decimals: balance.token.decimals } }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching ERC20 balance for ${address}: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Transfer Sei server.tool( "transfer_sei", "Transfer native tokens (Sei) to an address", { to: z.string().describe("The recipient address"), amount: z.string().describe("Amount to send in SEI"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ to, amount, network = DEFAULT_NETWORK }) => { try { const txHash = await services.transferSei(to, amount, network); return { content: [{ type: "text", text: JSON.stringify({ success: true, txHash, to, amount, network }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error transferring Sei: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Transfer ERC20 server.tool( "transfer_erc20", "Transfer ERC20 tokens to another address", { tokenAddress: z.string().describe("The address of the ERC20 token contract"), toAddress: z.string().describe("The recipient address"), amount: z.string().describe("The amount of tokens to send"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, toAddress, amount, network = DEFAULT_NETWORK }) => { try { const result = await services.transferERC20(tokenAddress, toAddress, amount, network); return { content: [{ type: "text", text: JSON.stringify({ success: true, txHash: result.txHash, network, tokenAddress, recipient: toAddress, amount: result.amount.formatted, symbol: result.token.symbol }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error transferring ERC20 tokens: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Approve ERC20 token spending server.tool( "approve_token_spending", "Approve another address to spend your ERC20 tokens.", { tokenAddress: z.string().describe("The contract address of the ERC20 token"), spenderAddress: z.string().describe("The contract address being approved"), amount: z.string().describe("The amount of tokens to approve"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, spenderAddress, amount, network = DEFAULT_NETWORK }) => { try { const result = await services.approveERC20(tokenAddress, spenderAddress, amount, network); return { content: [{ type: "text", text: JSON.stringify({ success: true, txHash: result.txHash, network, tokenAddress, spender: spenderAddress, amount: result.amount.formatted, symbol: result.token.symbol }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error approving token spending: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Transfer NFT (ERC721) server.tool( "transfer_nft", "Transfer an NFT (ERC721 token) from one address to another.", { tokenAddress: z.string().describe("The contract address of the NFT collection"), tokenId: z.string().describe("The ID of the specific NFT to transfer"), toAddress: z.string().describe("The recipient wallet address"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, toAddress, network = DEFAULT_NETWORK }) => { try { const result = await services.transferERC721(tokenAddress, toAddress, BigInt(tokenId), network); return { content: [{ type: "text", text: JSON.stringify({ success: true, txHash: result.txHash, network, collection: tokenAddress, tokenId: result.tokenId, recipient: toAddress, name: result.token.name, symbol: result.token.symbol }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error transferring NFT: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Transfer ERC1155 token server.tool( "transfer_erc1155", "Transfer ERC1155 tokens to another address.", { tokenAddress: z.string().describe("The contract address of the ERC1155 token collection"), tokenId: z.string().describe("The ID of the specific token to transfer"), amount: z.string().describe("The quantity of tokens to send"), toAddress: z.string().describe("The recipient wallet address"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, amount, toAddress, network = DEFAULT_NETWORK }) => { try { const result = await services.transferERC1155(tokenAddress, toAddress, BigInt(tokenId), amount, network); return { content: [{ type: "text", text: JSON.stringify({ success: true, txHash: result.txHash, network, contract: tokenAddress, tokenId: result.tokenId, amount: result.amount, recipient: toAddress }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error transferring ERC1155 tokens: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get ERC20 token information server.tool( "get_token_info", "Get comprehensive information about an ERC20 token.", { tokenAddress: z.string().describe("The contract address of the ERC20 token"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, network = DEFAULT_NETWORK }) => { try { const tokenInfo = await services.getERC20TokenInfo(tokenAddress as Address, network); const result = { ...tokenInfo, totalSupply: tokenInfo.totalSupply.toString(), }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching token info: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get NFT (ERC721) information server.tool( "get_nft_info", "Get detailed information about a specific NFT (ERC721 token).", { tokenAddress: z.string().describe("The contract address of the NFT collection"), tokenId: z.string().describe("The ID of the specific NFT token"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, network = DEFAULT_NETWORK }) => { try { const nftInfo = await services.getERC721TokenMetadata(tokenAddress as Address, BigInt(tokenId), network); return { content: [{ type: "text", text: JSON.stringify({ contract: tokenAddress, tokenId, network, ...nftInfo }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching NFT info: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Check NFT ownership server.tool( "check_nft_ownership", "Check if an address owns a specific NFT", { tokenAddress: z.string().describe("The contract address of the NFT collection"), tokenId: z.string().describe("The ID of the NFT to check"), ownerAddress: z.string().describe("The wallet address to check ownership against"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, ownerAddress, network = DEFAULT_NETWORK }) => { try { const isOwner = await services.isNFTOwner(tokenAddress, ownerAddress, BigInt(tokenId), network); return { content: [{ type: "text", text: JSON.stringify({ tokenAddress, tokenId, ownerAddress, network, isOwner }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error checking NFT ownership: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get ERC1155 token URI server.tool( "get_erc1155_token_uri", "Get the metadata URI for an ERC1155 token.", { tokenAddress: z.string().describe("The contract address of the ERC1155 token collection"), tokenId: z.string().describe("The ID of the specific token"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, network = DEFAULT_NETWORK }) => { try { const uri = await services.getERC1155TokenURI(tokenAddress as Address, BigInt(tokenId), network); return { content: [{ type: "text", text: JSON.stringify({ contract: tokenAddress, tokenId, network, uri }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching ERC1155 token URI: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get ERC721 NFT balance server.tool( "get_nft_balance", "Get the total number of NFTs owned by an address from a specific collection.", { tokenAddress: z.string().describe("The contract address of the NFT collection"), ownerAddress: z.string().describe("The wallet address to check the NFT balance for"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, ownerAddress, network = DEFAULT_NETWORK }) => { try { const balance = await services.getERC721Balance(tokenAddress as Address, ownerAddress as Address, network); return { content: [{ type: "text", text: JSON.stringify({ collection: tokenAddress, owner: ownerAddress, network, balance: balance.toString() }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching NFT balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get ERC1155 token balance server.tool( "get_erc1155_balance", "Get the balance of a specific ERC1155 token ID owned by an address.", { tokenAddress: z.string().describe("The contract address of the ERC1155 token collection"), tokenId: z.string().describe("The ID of the specific token to check"), ownerAddress: z.string().describe("The wallet address to check the balance for"), network: z.string().optional().describe("Network name or chain ID. Defaults to Sei mainnet.") }, async ({ tokenAddress, tokenId, ownerAddress, network = DEFAULT_NETWORK }) => { try { const balance = await services.getERC1155Balance(tokenAddress as Address, ownerAddress as Address, BigInt(tokenId), network); return { content: [{ type: "text", text: JSON.stringify({ contract: tokenAddress, tokenId, owner: ownerAddress, network, balance: balance.toString() }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching ERC1155 token balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Get address from private key server.tool( "get_address_from_private_key", "Get the EVM address derived from a private key", {}, async () => { try { const privateKeyValue = getPrivateKeyAsHex(); if (!privateKeyValue) { return { content: [{ type: "text", text: "Error: The PRIVATE_KEY environment variable is not set." }], isError: true }; } const address = services.getAddressFromPrivateKey(privateKeyValue); return { content: [{ type: "text", text: JSON.stringify({ address }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error deriving address from private key: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Wrap Sei using WrappedSEI contract directly server.tool( "wrap_sei_directly", "Wrap SEI to WSEI token", { wrappedSeiAddress: z.string().describe("The WSEI contract address"), amount: z.string().describe("Amount of SEI to wrap"), network: z.string().optional().describe("Network to use") }, async ({ wrappedSeiAddress, amount, network = DEFAULT_NETWORK }) => { try { const txHash = await services.wrapSeiDirectly(wrappedSeiAddress, amount, network); return { content: [{ type: "text", text: JSON.stringify({ txHash }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error wrapping SEI: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); // Unwrap WSEI using WrappedSEI contract directly server.tool( "unwrap_sei_directly", "Unwrap WSEI to SEI token", { wrappedSeiAddress: z.string().describe("The WSEI contract address"), amount: z.string().describe("Amount of WSEI to unwrap"), network: z.string().optional().describe("Network to use") }, async ({ wrappedSeiAddress, amount, network = DEFAULT_NETWORK }) => { try { const txHash = await services.unwrapWseiDirectly(wrappedSeiAddress, amount, network); return { content: [{ type: "text", text: JSON.stringify({ txHash }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error unwrapping WSEI: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/testinguser1111111/sei-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server