Skip to main content
Glama
emercoin

Emercoin swap

Official

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 callback

destination 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/mcp

Add it to a client:

# Claude Code
claude mcp add --transport http swap https://swap.emercoin.com/mcp
  • Claude Desktop — Settings → Connectors → Add custom connector → the URL above.

  • MCP Inspectornpx @modelcontextprotocol/inspector → Streamable HTTP → the URL.

Tools:

Tool

What it does

get_swap_config

min/max USDT per order + the fixed EMC-per-USDT rate

buy_emc

open an order → returns a deposit address + the exact USDT amount to send (+ optional idempotency_key)

get_order_status

poll an order by its token until delivered

cancel_order

drop an unpaid order early

Flow: get_swap_configbuy_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 like buy_emc cannot 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 hosted https://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: TRON Energy/Bandwidth MCP Server

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 POST /wallet/send (X-Internal-Key)

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 addresses

State 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 TTL

Dev

uv sync --extra dev
cp .env.example .env          # fill secrets
uv run uvicorn swap.main:app --reload --port 8002

EMC 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.py applies schema.sql with CREATE TABLE IF NOT EXISTS, which does not alter an existing table. After editing schema.sql in dev, reset the database: rm swap.db (then restart — it recreates the schema — and re-run scripts/register_service since the services table is wiped too). swap.db holds 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 testnetconfirmed → 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. See docs/TESTNET.md for the runbook (scripts/testnet/).

AML is live: OFAC SDN addresses (TRON) loaded into memory + refreshed, and a per-deposit live Tether isBlackListed check; 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); see docs/TDQS.md.

Deferred: USDT sweep / TRON tx signing (services/sweep.py, kept off the hot path).

License

MIT — see LICENSE.

Available Tools

4 tools
buy_emcBuy EMC with USDT (open an order)A

Open an order to buy EMC with USDT (TRC20) and get back a shared TRON deposit_address plus the EXACT amount_usdt to send. This does NOT move funds: you then transfer that exact figure (it is your order's matching tag) to the deposit address; on confirmed payment, EMC (amount_usdt × rate) is delivered to your address automatically. Keep the returned token and poll get_order_status until 'notified'; to abandon before paying, call cancel_order. One-way — a wrong amount cannot be matched and is NOT refunded. By default each call opens a NEW order; pass a stable idempotency_key to make retries return the same order. Use get_swap_config first to pick a valid amount.

ParametersJSON Schema
NameRequiredDescriptionDefault
amount_usdtYesUSDT to pay; must be one of the allowed denominations from get_swap_config (currently 5 or 10)
destination_emc_addressYesyour EMC address to receive EMC (legacy 'E…' or bech32 'em1…')
idempotency_keyNooptional: a stable string you choose; retrying buy_emc with the same key + address + amount returns the SAME order instead of opening a new one (use it so a retry after a timeout doesn't create a duplicate)

Output Schema

ParametersJSON Schema
NameRequiredDescription
tokenYesopaque handle to poll this order
order_idYes
deposit_addressYes
amount_usdtYesEXACT amount to send — pay this figure
emc_amountYes
statusYes
expires_atYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description clarifies that the tool does NOT move funds, describes the payment flow, and idempotency behavior. It does not contradict annotations (readOnlyHint=false, etc.) and adds beyond them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and process. It is somewhat lengthy but each sentence adds value. Could be slightly more concise, but well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (financial transaction, multiple steps), the description covers the flow, safety warnings, idempotency, and ties to siblings. Output schema exists but is not shown; still fairly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds meaning: amount_usdt must be from allowed denominations, idempotency_key explanation for retries, destination_emc_address format examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'Open an order to buy EMC with USDT' and outlines the complete process, distinguishing it from sibling tools like cancel_order, get_order_status, and get_swap_config.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It advises to use get_swap_config first to pick a valid amount, explains idempotency for retries, and warns that wrong amounts are not refunded. It covers when to use but could be more explicit about when not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_orderCancel an unpaid EMC orderA
Destructive

Cancel a still-unpaid buy_emc order by its token, expiring it now and freeing its slot ahead of the TTL. Use this only before you pay; once a payment is in flight or confirmed it is too late and this errors. A payment sent after cancellation matches nothing and is NOT refunded. To only inspect an order without changing it, use get_order_status.

ParametersJSON Schema
NameRequiredDescriptionDefault
tokenYesopaque order handle returned by buy_emc; pass it back unchanged

Output Schema

ParametersJSON Schema
NameRequiredDescription
order_idYeshuman-quotable order number (DB id)
statusYes
amount_usdtYes
emc_amountYes
destination_emc_addressYes
deposit_addressYes
emc_txidNo
expires_atYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true. Description adds that it errors if payment is in flight/confirmed and that payments after cancellation are not refunded. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core action and effect. Every sentence is essential and free of fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple one-parameter input and the presence of annotations and output schema, the description fully covers usage context, prerequisites, consequences, and error scenarios.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter (token) with 100% schema coverage. The description does not add new detail beyond what the schema provides (opaque handle, from buy_emc). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it cancels an unpaid buy_emc order by token, expiring it and freeing its slot. Distinguishes from sibling get_order_status for inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says use only before payment, warns against using after payment is in flight/confirmed, and notes that post-cancellation payments are not refunded. Provides alternative tool get_order_status for inspection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_order_statusGet EMC order statusA
Read-onlyIdempotent

Return the current status of a buy_emc order by its token: the status, the exact amount, the EMC amount and destination address, and the emc_txid once delivered. Use this to poll after buy_emc — status progresses awaiting_payment → confirmed → emc_delivered → notified (done). Read-only; to cancel an unpaid order use cancel_order instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
tokenYesopaque order handle returned by buy_emc; pass it back unchanged

Output Schema

ParametersJSON Schema
NameRequiredDescription
order_idYeshuman-quotable order number (DB id)
statusYes
amount_usdtYes
emc_amountYes
destination_emc_addressYes
deposit_addressYes
emc_txidNo
expires_atYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds the status lifecycle, the specific returned fields (amount, EMC amount, destination address, emc_txid), and that it is used for polling. This adds meaningful context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences plus a brief note after a dash. The first sentence covers purpose and return values, the second explains usage and status progression. No superfluous words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one parameter, high schema coverage, existing annotations, and an output schema, the description fully explains when to use (polling after buy_emc), what it returns, and how statuses evolve. It also provides cancellation guidance. Completeness is excellent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description for the token parameter. The tool description echoes the schema's 'by its token' but adds no new meaning. Baseline 3 is appropriate as the schema already documents it well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Return the current status of a buy_emc order by its token', specifying the verb (return), resource (buy_emc order), and key parameter (token). It distinguishes from siblings by mentioning cancel_order for cancellation and implies buy_emc as preceding step.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use this to poll after buy_emc' and describes the status progression (awaiting_payment → confirmed → emc_delivered → notified). Also states 'to cancel an unpaid order use cancel_order instead', providing clear context and alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_swap_configGet EMC swap limits and rateA
Read-onlyIdempotent

Return the current order denominations and fixed rate for buying EMC with USDT. allowed_amounts is the exact set of USDT values buy_emc accepts (fixed denominations, not a free range) — pick one of these; min_usdt/max_usdt are its bounds and emc_per_usdt is the rate (EMC you receive = amount_usdt × emc_per_usdt). Call this first to choose a valid amount for buy_emc. Read-only — it neither creates nor changes an order. support_email is the operator contact for manual cases (e.g. an order on aml_hold or a late/mismatched payment).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
min_usdtYes
max_usdtYes
allowed_amountsNothe fixed USDT denominations a buyer may pick
emc_per_usdtYes
support_emailNooperator contact for manual cases

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint. Description adds that it 'neither creates nor changes an order' and explains the support_email for manual cases, going beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence adds value. Well-structured: purpose, field explanations, usage guidance, read-only note, support contact. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters, rich annotations, and low complexity, the description fully covers what the tool does and how to use it. Output schema exists but description complements it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters, so baseline is 4. Description adds value by explaining output fields, which helps in understanding the tool's result.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it returns current order denominations and fixed rate for buying EMC with USDT. It distinguishes itself from sibling buy_emc by implying it's a prerequisite.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Call this first to choose a valid amount for buy_emc.' Provides clear context for when to use it relative to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updates
    • Changedbuy_emc1 field changed
      • changedInput schema / properties / amount_usdt / description
        Previous value: -"USDT to pay; must be within min/max from get_swap_config"New value: +"USDT to pay; must be one of the allowed denominations from get_swap_config (currently 5 or 10)"
    • Changedget_swap_config1 field changed
      • addedOutput schema / properties / allowed_amounts
        Added value: +{
        +  "description": "the fixed USDT denominations a buyer may pick",
        +  "items": {
        +    "type": "number"
        +  },
        +  "title": "Allowed Amounts",
        +  "type": "array"
        +}
  2. 4 tool updatesv0.1.0
    • First observedbuy_emc
    • First observedcancel_order
    • First observedget_order_status
    • First observedget_swap_config

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: initiating an order, canceling unpaid orders, checking status, and retrieving configuration. No functional overlap.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern (buy_emc, cancel_order, get_order_status, get_swap_config), making it easy to predict functionality.

Tool Count5/5

With 4 tools covering the core swap workflow, the count is well-scoped and each tool earns its place without excess or deficiency.

Completeness4/5

The set covers order creation, cancellation, status polling, and configuration retrieval. Minor gap: no tool for listing a user's full order history, but the core lifecycle is complete.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides complete HTTP/JSON access to all 100+ Emercoin RPC endpoints with integrated formatting utilities. Enables blockchain operations, name system management, wallet functions, and mining operations through a comprehensive REST API interface.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    AI-to-AI marketplace MCP server with 46 tools — swap 65+ crypto tokens on 7 chains, rent GPUs, trade 25 tokenized stocks, on-chain escrow (Solana + Base), DeFi yields, sentiment analysis, wallet monitoring, and image generation. Supports USDC payments across 14 blockchains.
    MIT