Emercoin swap
OfficialThis server is a cashier service for exchanging USDT (TRC20/TRON) for Emercoin (EMC) at a fixed rate, designed for agent-based interactions via MCP — no account or API key required.
Get swap configuration (
get_swap_config): Retrieve the fixed exchange rate (1 USDT = 10 EMC), minimum/maximum order amounts, and operator support email.Open a buy order (
buy_emc): Create an order by specifying a USDT amount (fixed denominations: 5 or 10 USDT) and your destination EMC address. Returns a unique TRON deposit address, the exact USDT amount to send (used as a matching tag), and an order token for tracking. Supports an optional idempotency key to prevent duplicate orders on retries.Poll order status (
get_order_status): Track an order using its token through the full lifecycle:awaiting_payment → confirmed → emc_delivered → notified. Returns the EMC transaction ID once delivered.Cancel an unpaid order (
cancel_order): Abort an order before payment is made, freeing its slot ahead of TTL expiry. Cannot be used once payment is in flight or confirmed.
Key constraints:
Only 5 or 10 USDT orders accepted
Payment must be the exact returned amount — wrong amounts are not refunded
One-way exchange: no refunds
USDT must be sent via TRC20 (TRON network)
AML screening (OFAC SDN + Tether blacklist) is applied to all deposits, which may result in an
aml_holdstatus
Allows buying EMC with USDT (Tether) on the TRON network via TRC20 deposits.
swap — EMC cashier (USDT → EMC)
A minimal cashier exposing one primitive. All business logic stays in the calling services; swap knows nothing about NVS/DNS/subscriptions.
buy_emc(amount_usdt, destination_emc_address, callback_url, ref)
→ collect USDT on a unique deposit address
→ on confirmation, deliver EMC (fixed rate ×10) to destination
→ notify the caller with a SIGNED callbackdestination is opaque to swap: it can be a service's address (the service
then renders its own product on that EMC — the user only ever pays USDT and
never touches a wallet) or the user's own address (raw on-ramp).
Use via MCP
An AI agent with USDT can buy EMC directly — no account, no API key, no callback. swap exposes a keyless MCP exchanger over Streamable HTTP at:
https://swap.emercoin.com/mcpAdd it to a client:
# Claude Code
claude mcp add --transport http swap https://swap.emercoin.com/mcpClaude Desktop — Settings → Connectors → Add custom connector → the URL above.
MCP Inspector —
npx @modelcontextprotocol/inspector→ Streamable HTTP → the URL.
Tools:
Tool | What it does |
| min/max USDT per order + the fixed EMC-per-USDT rate |
| open an order → returns a deposit address + the exact USDT amount to send (+ optional |
| poll an order by its token until delivered |
| drop an unpaid order early |
Flow: get_swap_config → buy_emc(amount, your_emc_address) → send the exact
returned amount (TRC20) to the deposit address → poll get_order_status by token
until notified. One-way, exact-amount, no refunds. The same primitive is also
available as keyed REST (for services, with a signed callback) and a keyless
web page at swap.emercoin.com.
This server is not self-contained — use the hosted endpoint above. Running an order needs deployed infrastructure: an Emercoin node + adapter (the EMC payout rail,
/wallet/send), a TronGrid USDT watcher, a funded EMC reserve, and a configured TRON deposit address. An image built from this repo in isolation — e.g. by a registry/sandbox like Glama — is therefore an introspection target only:tools/list(for tool-definition quality scoring) works with zero config, but execution tools likebuy_emccannot complete without that backing infra (no deposit address → "deposit address not configured"; no adapter → reserve pre-flight fails). That's correct isolation, not a defect. To actually buy EMC, call the hostedhttps://swap.emercoin.com/mcp. The repo never ships the adapter key or any wallet secret — those live only on the deployed host.
Related MCP server: Armor Crypto MCP
Locked decisions
Topic | Decision |
Rate | static 1 USDT = 10 EMC |
Amounts | fixed denominations: 5 or 10 USDT (not a free range; floor 5: below it TRON gas dominates). REST/MCP/web validate the input against this exact set |
USDT rail | TRC20 (TRON) |
Payment match | one shared deposit address + unique per-order amount tag |
EMC delivery | via emercoin adapter |
Callback signature | HMAC-SHA256 over canonical body, per-service secret |
KYC | none (amounts far below threshold) |
AML | minimal but mandatory — OFAC SDN + Tether freeze blacklist |
Terms | exact amount, single transfer, one-way (no refunds) — state in the offer |
Layout
swap/
config.py env-driven settings (pydantic-settings)
models.py OrderStatus enum + request/response schemas
states.py order state machine (allowed transitions)
schema.sql DDL: services/orders/deposits/aml_checks/sweeps/callbacks
db.py SQLite connection + init
repository.py DB access layer
auth.py caller auth by API key
orders.py buy_emc business logic (shared by REST + MCP)
main.py FastAPI app (REST: POST /buy_emc, GET /order/{id})
mcp_app.py keyless MCP exchanger at /mcp (agent tools, mirrors /web)
web.py public keyless /web/* channel (raw on-ramp for humans)
site/ static exchanger page + offer (index.html, oferta.html)
clients/
adapter.py EMC delivery + balance via emercoin adapter
trongrid.py TRC20 deposit watcher source (TronGrid)
tron/
hd.py HD derivation of deposit addresses (BIP44, coin 195)
services/
aml.py OFAC + Tether blacklist screening
delivery.py deliver EMC from reserve (idempotent)
callback.py signed callback notifier + retries
watcher.py background loop: deposits → confirm → AML → deliver → notify
sweep.py USDT consolidation from deposit addressesState machine
created → awaiting_payment → confirmed → emc_delivered → notified (done)
↘ underpaid (top-up or partial refund)
↘ overpaid (refund excess)
↘ aml_hold (sender blacklisted → manual)
↘ deliver_failed (retry; else refund USDT)
expired — no payment before TTLDev
uv sync --extra dev
cp .env.example .env # fill secrets
uv run uvicorn swap.main:app --reload --port 8002EMC delivery and the TRON watcher need the emercoin adapter and TronGrid creds;
for local end-to-end you can bring up the node+adapter from emercoin_docker
(docker compose --profile dev up). TRON parts are verified in a test
environment before they are wired into the watcher.
Schema changes have no migrations.
db.pyappliesschema.sqlwithCREATE TABLE IF NOT EXISTS, which does not alter an existing table. After editingschema.sqlin dev, reset the database:rm swap.db(then restart — it recreates the schema — and re-runscripts/register_servicesince theservicestable is wiped too).swap.dbholds only local/test data.
Status: full happy path verified live end-to-end (+ 41 unit tests). On 2026-06-14 a real run took a TRC20 USDT deposit on TRON Nile testnet →
confirmed→ delivered real EMC on Emercoin mainnet (via the adapter/wallet/send) → signed callback verified by the receiver against the service's HMAC secret:awaiting_payment → confirmed → emc_delivered → notified. Seedocs/TESTNET.mdfor the runbook (scripts/testnet/).AML is live: OFAC SDN addresses (TRON) loaded into memory + refreshed, and a per-deposit live Tether
isBlackListedcheck; a hit →aml_hold(no delivery).Payment matching: pivoted from a unique HD address per order to one shared deposit address + a unique per-order amount tag (matched by exact amount). This removes per-order sweeping and the fresh-address gas penalty; the trade-off is exact-amount, single-transfer payments (no auto under/overpaid). Collected USDT is moved to treasury / off-ramp manually at low volume. MCP exchanger: the keyless web on-ramp is also exposed as MCP tools (
buy_emc,get_order_status,cancel_order,get_swap_config) over Streamable HTTP at/mcp, so an AI agent buys EMC with USDT directly — no key, no callback, same anti-spam as the web channel. No auth by design: it's a public "pay for a service" on-ramp, not an account. Tool definitions pass a pre-publication TDQS review (all tier A); seedocs/TDQS.md.Deferred: USDT sweep / TRON tx signing (
services/sweep.py, kept off the hot path).
License
MIT — see LICENSE.
Maintenance
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/emercoin/swap'
If you have feedback or need assistance with the MCP directory API, please join our Discord server