mayan-mcp
Provides tools for quoting and building unsigned cross-chain swap transactions on the Ethereum blockchain via Mayan Finance.
Provides tools for quoting and building unsigned cross-chain swap transactions on the Optimism blockchain via Mayan Finance.
Provides tools for quoting and building unsigned cross-chain swap transactions on the Polygon blockchain via Mayan Finance.
Provides tools for quoting and building unsigned cross-chain swap transactions on the Solana blockchain via Mayan Finance.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mayan-mcpWhat would it cost to swap 5 ETH for SOL on Solana?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mayan-mcp
An MCP server for Mayan Finance cross-chain swaps.
Ask an AI assistant what a swap will cost, then get the exact transaction to sign — between Solana and seven EVM chains, through Mayan's Swift and MCTP routes.
This server holds no private keys. It cannot sign and it cannot broadcast. build_swap returns
an unsigned transaction; the caller signs it in their own wallet. There is no tool here that can
move funds.

Before any transaction is handed over, its own encoded arguments are read back and compared against the quote you were shown — the token, the amount, and the contract it forwards to. A payload that spends more than it quoted is refused rather than returned.
Those are real numbers, not a mockup: scripts/capture-demo.ts drives the built server over stdio
against the live API and writes what came back to docs/captured-output.json,
which is what the image above renders. Run it yourself and compare — a tool whose claim is "check
what you are signing" should be checkable itself.
Custody model
Reads quotes, tokens, swap status | yes |
Builds transactions | yes, unsigned |
Holds private keys or seed phrases | no |
Signs transactions | no |
Broadcasts to a chain | no |
The guarantee is structural rather than procedural: there is no key material in the process, so there is no code path from a compromised prompt to a moved balance. The signing step belongs to the wallet, which is also where the user sees the recipient address one last time.
Two consequences worth stating plainly:
Tool annotations are not the guarantee. This server sets
readOnlyHint, but the MCP specification requires clients to treat annotations from an untrusted server as untrusted. The claim that matters is "no keys in the process", which you can check by readingsrc/.A prompt injection cannot move funds through this server, but it can still propose a bad swap. Every response echoes the recipient address, the minimum received and the slippage next to the payload, so the terms are visible before anyone signs.
See SECURITY.md for the threat model, the invariant checks, and a reachability
analysis of the current npm audit output.
Related MCP server: MCP Wallet Signer
Install
Requires Node.js 20 or newer.
npx @sand0vvv/mayan-mcp --helpClaude Desktop / Claude Code
{
"mcpServers": {
"mayan": {
"command": "npx",
"args": ["-y", "@sand0vvv/mayan-mcp"],
"env": {
"SOLANA_RPC_URL": "https://your-solana-rpc-endpoint"
}
}
}
}Cursor / other MCP clients
Same command, over stdio: npx -y @sand0vvv/mayan-mcp.
Streamable HTTP
npx @sand0vvv/mayan-mcp --http --port 8787Stateless — a fresh server per request, no session state. It binds to 127.0.0.1 and validates the
Host and Origin headers, so a page in your browser cannot reach it by pointing its own hostname at
loopback. There is no authentication: exposing it on another interface (--host 0.0.0.0) is a
deliberate act that belongs behind a proxy providing auth and rate limiting.
Configuration
Everything comes from the environment. Nothing is required to get a quote.
Variable | Required | Purpose |
| for Solana builds | Building a Solana-source swap needs a live RPC connection. Without it the server falls back to the public mainnet endpoint, which throttles hard. |
| for allowance reads | Per-chain EVM endpoint, e.g. |
| no | Lifts Mayan's per-IP rate limit. Request one from |
| no | Default |
| no | Default |
| no | Default |
| no | Attaches a fee-split referrer to quotes. Unset by default, and left unset in this project — see SECURITY.md. |
| no |
|
There is no variable for a private key, and there never will be.
Tools
Tool | What it does |
| Every available route for a swap: expected output, guaranteed minimum, slippage, fees, ETA. |
| The unsigned transaction, plus the quote terms and any ERC20 approval needed first. |
| Tokens Mayan can route on a chain, with addresses and decimals. |
| Status of a swap by its source-chain transaction hash. |
| How much the Mayan forwarder is currently allowed to spend, and whether that covers a swap. |
| Supported chains and their EVM chain ids. |
| Gas estimate for a built EVM transaction. |
Supported chains: solana, ethereum, base, arbitrum, optimism, polygon, bsc,
avalanche.
Worked example
"What do I get for 0.5 SOL into USDC on Base?"
get_quote → two routes:
0.5 SOL on solana -> USDC on base
SWIFT V2 · Swift
expected 37.137748 USDC
minimum 36.933584 USDC (slippage 55 bps)
eta 3s
price GOOD (ratio 0.9996)
quote id 0xa4c71a85927b104fe039e05d56efe944
FAST_MCTP · Best Price
expected 37.155133 USDC
minimum 36.954199 USDC (slippage 50 bps)
eta 35s
price GOOD (ratio 0.9996)"Build it."
build_swap → the transaction, unsigned:
Unsigned swap built: 10 USDC on base -> SOL on solana via SWIFT
You receive at least 0.130172143 SOL (expected 0.134198086, slippage 300 bps, ETA 3s)
Recipient: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
Transaction to sign:
to 0x337685fdaB40D39bd02028545a4FfA7D287cC3E2
chainId 8453
value 0x0
data 932 bytes (forwardERC20)
Checked before returning it:
ok target is the Mayan forwarder from the SDK constant
ok chain id matches the quote
ok the call spends USDC, the token quoted
ok the call spends 10000000 base units, the amount quoted
ok forwards to 0x40fFE85A28DC9993541449464d7529a922142960, the SWIFT contract the quote declared
Approval required BEFORE this transaction:
approve 10000000 (base units) of USDC
spender 0x337685fdaB40D39bd02028545a4FfA7D287cC3E2 (Mayan forwarder)
Signers returned: 0. Unsigned. This server holds no private keys and cannot sign or broadcast.Those checks are not decoration. The transaction is assembled from data Mayan's backend served, so the SDK's own encoded arguments are read back and compared against the quote you were shown: the token, the amount, and the protocol contract. A payload that spends more than it quoted, or routes through a substituted contract, is refused rather than returned. See SECURITY.md.
structuredContent carries the same thing machine-readably: evm_transaction, approval, route
and a verification block recording which invariants were checked.
Solana output
Two things are different when the source chain is Solana, both stated here rather than left to be discovered:
The cross-check above does not apply. It reads an EVM call's encoded arguments; a Solana build is a list of instructions with no such envelope. Those fields are therefore absent from the verification block rather than reported as failures. What still holds is the route allow-list and the empty signer set — the custody claim itself. Review the instructions in your wallet.
MCTPfrom Solana cannot be built here. That route needs an ephemeral keypair to carry its CCTP message, and this server does not emit key material of any kind.SWIFTfrom Solana builds without one and is what an unpinnedbuild_swapselects.
A Solana-source swap returns instructions in the SDK's own InstructionInfo shape, so the output
feeds straight back into deserializeInstructionInfo() without a translation step:
{
"programId": "ComputeBudget111111111111111111111111111111",
"accounts": [],
"data": "AsBcFQA="
}Address lookup tables come back as base58 addresses, ready for
connection.getMultipleAccountsInfo().
What the caller still has to do
Send the approval first on EVM sources, or the swap reverts.
build_swaptells you the token, the amount and the spender. WithMAYAN_RPC_URL_<CHAIN>set it reads your current allowance and says nothing when you have already approved enough. (USDT on Ethereum additionally requires zeroing an existing allowance before raising it — the response says so when it applies.)Sign and submit. Not this server's job, by design.
Check the recipient address in your wallet before signing.
Development
npm install
npm run build
npm test # unit tests: invariants, serialisation round-trip, schemas, layering
npm run typecheck
npx tsx scripts/smoke.ts # live: quotes and builds against Mayan's API
npx tsx scripts/e2e.ts # live: spawns the built server and speaks MCP over stdioThe layout keeps one boundary strictly:
src/client/ the only code that talks to @mayanfinance/swap-sdk
src/tools/ MCP tool definitions — Zod in, structuredContent out
src/transport/ stdio and Streamable HTTPtest/layering.test.ts fails the build if anything above src/client imports the SDK or a chain
library directly, and it verifies its own detector fires before trusting the result.
License
MIT. See LICENSE.
Not affiliated with Mayan Finance. This is client software for their public API; it makes no warranty about routing, pricing or settlement, and it is not financial advice.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/sand0vvv/mayan-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server