Koskamo

ChangeNOW MCP

A hosted remote MCP server that enables agents to perform non-custodial crypto swaps. It supports asset lookup, retrieving quotes, creating transactions, and tracking status without requiring user authentication or API keys.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

ChangeNOW MCP logo, by ChangeNOWVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-06Operated by ChangeNOW
MCP endpoint (Streamable HTTP)
https://mcp.changenow.io/mcp
Vendor documentation

What its tools do

7 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

Can change data (1)

7 of 7 have a description · 7 of 7 declare behavior hints · 7 of 7 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to changenow.io ·
  • Passed Endpoint is on the registry namespace domain ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Lookup available crypto assets
  • Get exchange quotes
  • Create crypto swap transactions
  • Track transaction status

Source and maintenance

Vendor evidenceRegistry 2.1.1

Protocol and capabilities

Server
chn-mcp-server 2.1.2
MCP protocol negotiated in check
2025-11-25
Tools
7 advertised
Resources
5 advertised
Resource templates
0 advertised
Prompts
1 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  },
  "prompts": {},
  "resources": {}
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

ChangeNOW is a non-custodial crypto exchange: the user sends one asset to a deposit address and receives another asset at an address they control. No account, no API key and no KYC for standard swaps. Nothing here takes custody of user funds and no tool moves money on its own. Assets are identified by a canonical id "ticker.network", for example btc.btc, usdt.trx, usdc.sol. The same ticker exists on several networks, and sending to the wrong network loses the funds, so always resolve what the user named with list_assets before quoting anything. Normal flow: 1. list_assets resolve the user's words into canonical ids 2. quote_swap rate, amount out, pair minimum, and whether the rate can be fixed 3. validate_address check the recipient address, and the memo when the asset needs one 4. swap_link hand the user a page to review and confirm themselves (default, safest) create_swap only when the user has explicitly approved this amount and this address Amounts are decimal strings. Minimums and maximums belong to the pair, not to the asset, so they come from quote_swap. A float rate is final when the deposit arrives. A fixed rate requires passing the rate_id from quote_swap into create_swap, and whether a pair can hold one is decided by the quote, not by any flag in the catalogue. Two different deadlines carry the name valid_until, and they are not the same thing. The one in a quote is the life of its rate_id: about two minutes. The one in a created order is how long the user has to send the deposit at the locked rate: ten to twenty minutes, set by whoever executes the order. Read the field, never assume a number, and if the user needed time to think, call quote_swap again before create_swap instead of reusing an old rate_id. After create_swap the user must send exactly amount_from to payin_address before valid_until. Track the order with check_swap_status. Some orders are executed by a partner aggregator instead of ChangeNOW; the provider field of quote_swap and create_swap says which, and it must be relayed to the user rather than hidden. Never invent a deposit address, never edit one, and never tell the user to send funds anywhere other than the payin_address this server returned.

Tools

7 advertised

list_assets — List exchangeable assets
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Find the assets ChangeNOW can exchange and turn what the user said into a canonical asset id. Search by ticker, name or network, filter by network, by fiat or crypto, and by whether a fixed rate is possible. Always call this before quoting: the same ticker exists on several networks and only the canonical id "ticker.network" identifies one of them. When has_more is false the response is the complete answer and no paging is needed.

list_assets input schema
{
  "type": "object",
  "properties": {
    "q": {
      "type": "string",
      "description": "Substring search over canonical id, legacy ticker, name and network. Case insensitive. Example: \"usdt\", \"bitcoin\", \"tron\"."
    },
    "kind": {
      "enum": [
        "crypto",
        "fiat",
        "all"
      ],
      "type": "string",
      "default": "crypto",
      "description": "crypto for swappable coins and tokens, fiat for currencies that can only start a purchase, all for both."
    },
    "limit": {
      "type": "integer",
      "default": 50,
      "maximum": 500,
      "minimum": 1,
      "description": "How many assets to return. Default 50, maximum 500."
    },
    "cursor": {
      "type": "string",
      "description": "Cursor from next_cursor of the previous page. Only needed when has_more is true."
    },
    "network": {
      "type": "string",
      "description": "Keep only assets on this network, for example \"eth\", \"trx\", \"sol\"."
    },
    "popular": {
      "type": "boolean",
      "default": false,
      "description": "Return the short curated list. Use this to answer \"what can I swap\" without paging."
    },
    "fixed_rate": {
      "type": "boolean",
      "default": false,
      "description": "Keep only assets the catalogue flags as fixed rate capable. The flag is a hint: a pair flagged false can still get a fixed rate, so confirm with quote_swap rather than filtering a user out."
    }
  },
  "additionalProperties": false
}
list_assets output schema
{
  "type": "object",
  "required": [
    "assets",
    "returned",
    "total",
    "has_more",
    "next_cursor",
    "catalogue_version"
  ],
  "properties": {
    "total": {
      "type": "number"
    },
    "assets": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "asset",
          "ticker",
          "name",
          "network",
          "kind",
          "fixed_rate",
          "memo"
        ],
        "properties": {
          "kind": {
            "type": "string"
          },
          "memo": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "asset": {
            "type": "string"
          },
          "ticker": {
            "type": "string"
          },
          "network": {
            "type": "string"
          },
          "fixed_rate": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      }
    },
    "has_more": {
      "type": "boolean"
    },
    "returned": {
      "type": "number"
    },
    "next_cursor": {
      "type": [
        "string",
        "null"
      ]
    },
    "catalogue_version": {
      "type": "string"
    }
  },
  "additionalProperties": false
}
list_assets annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_asset — Asset details
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Everything needed to build a swap for one asset: the canonical id, the legacy ticker used in website links, decimals, whether a memo is required and what the receiving side calls it, the address format, the token contract and the warnings to relay to the user. Minimum and maximum amounts are not here because they belong to the pair, not to the asset: get them from quote_swap.

get_asset input schema
{
  "type": "object",
  "required": [
    "asset"
  ],
  "properties": {
    "asset": {
      "type": "string",
      "description": "Canonical id \"usdt.trx\". A legacy ticker \"usdttrc20\" or a page slug \"tether-trc20\" is also accepted."
    }
  },
  "additionalProperties": false
}
get_asset output schema
{
  "type": "object",
  "required": [
    "asset",
    "ticker",
    "name",
    "network",
    "kind",
    "fixed_rate",
    "memo",
    "slug",
    "decimals",
    "memo_name",
    "address_regex",
    "memo_regex",
    "token_contract",
    "warning_send",
    "warning_receive",
    "explorer_address_url",
    "explorer_tx_url",
    "price_usd"
  ],
  "properties": {
    "kind": {
      "type": "string"
    },
    "memo": {
      "type": "boolean"
    },
    "name": {
      "type": "string"
    },
    "slug": {
      "type": [
        "string",
        "null"
      ]
    },
    "asset": {
      "type": "string"
    },
    "ticker": {
      "type": "string"
    },
    "network": {
      "type": "string"
    },
    "decimals": {
      "type": [
        "number",
        "null"
      ]
    },
    "memo_name": {
      "type": [
        "string",
        "null"
      ]
    },
    "price_usd": {
      "type": [
        "number",
        "null"
      ]
    },
    "fixed_rate": {
      "type": "boolean"
    },
    "memo_regex": {
      "type": [
        "string",
        "null"
      ]
    },
    "warning_send": {
      "type": [
        "string",
        "null"
      ]
    },
    "address_regex": {
      "type": [
        "string",
        "null"
      ]
    },
    "token_contract": {
      "type": [
        "string",
        "null"
      ]
    },
    "explorer_tx_url": {
      "type": [
        "string",
        "null"
      ]
    },
    "warning_receive": {
      "type": [
        "string",
        "null"
      ]
    },
    "explorer_address_url": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": false
}
get_asset annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
quote_swap — Quote a swap
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Ask what a swap would give, in either direction: pass amount_from to learn what the user receives, or amount_to to learn what the user must send. Returns the rate, the pair minimum and maximum, who would execute the order, and the warnings to relay. With rate_type "fixed" it also returns the rate_id that create_swap needs; that lock lasts about two minutes, so quote again right before creating the order. A fixed rate is not offered on every pair and the tool says so rather than quietly falling back to a float rate. Nothing is created and no funds move.

quote_swap input schema
{
  "type": "object",
  "required": [
    "from",
    "to"
  ],
  "properties": {
    "to": {
      "type": "string",
      "description": "Asset the user receives, canonical id, for example \"usdt.trx\"."
    },
    "from": {
      "type": "string",
      "description": "Asset the user sends, canonical id, for example \"btc.btc\"."
    },
    "amount_to": {
      "type": "string",
      "description": "Amount the user wants to receive, as a decimal string. The answer then says how much to send."
    },
    "rate_type": {
      "enum": [
        "float",
        "fixed"
      ],
      "type": "string",
      "default": "float",
      "description": "float: the rate is settled when the deposit arrives. fixed: the rate is held until valid_until, about two minutes, and returns the rate_id create_swap needs, usually at a slightly worse rate. Ask for fixed whenever the user wants a guaranteed number; if this pair cannot hold one the answer says so instead of quietly returning a float rate."
    },
    "promo_code": {
      "type": "string",
      "description": "Promo code to apply, if the user has one."
    },
    "amount_from": {
      "type": "string",
      "description": "Amount the user sends, as a decimal string. Pass this or amount_to, never both."
    }
  },
  "additionalProperties": false
}
quote_swap output schema
{
  "type": "object",
  "required": [
    "from",
    "to",
    "from_name",
    "to_name",
    "amount_from",
    "amount_to",
    "rate",
    "rate_type",
    "rate_id",
    "valid_until",
    "min_amount",
    "max_amount",
    "limits_in",
    "provider",
    "high_network_fee",
    "speed_forecast_minutes",
    "quote_id",
    "warnings"
  ],
  "properties": {
    "to": {
      "type": "string"
    },
    "from": {
      "type": "string"
    },
    "rate": {
      "type": [
        "string",
        "null"
      ]
    },
    "rate_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "to_name": {
      "type": "string"
    },
    "provider": {
      "enum": [
        "changenow",
        "third-party",
        "unknown"
      ],
      "type": "string"
    },
    "quote_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "amount_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "from_name": {
      "type": "string"
    },
    "limits_in": {
      "type": "string"
    },
    "rate_type": {
      "enum": [
        "float",
        "fixed"
      ],
      "type": "string"
    },
    "max_amount": {
      "type": [
        "string",
        "null"
      ]
    },
    "min_amount": {
      "type": [
        "string",
        "null"
      ]
    },
    "amount_from": {
      "type": [
        "string",
        "null"
      ]
    },
    "valid_until": {
      "type": [
        "string",
        "null"
      ]
    },
    "high_network_fee": {
      "type": "boolean"
    },
    "speed_forecast_minutes": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": false
}
quote_swap annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
validate_address — Validate a recipient address
Advertised by the server during the last successful anonymous check.
Advertised read-only

Check a recipient address, and its memo when the asset needs one, against the format the network requires, before any order exists. Call this on every address the user gives. A valid-looking address on the wrong network is the one mistake in a swap that destroys the funds with no way back, so when the address belongs to another network the answer names that network instead of just refusing. A few assets carry no address format in the catalogue; for those the answer says the address could not be checked rather than calling it valid.

validate_address input schema
{
  "type": "object",
  "required": [
    "asset",
    "address"
  ],
  "properties": {
    "memo": {
      "type": "string",
      "description": "Memo or destination tag, when the asset needs one."
    },
    "asset": {
      "type": "string",
      "description": "Asset that will be received at this address, canonical id."
    },
    "address": {
      "type": "string",
      "description": "Recipient address to check."
    }
  },
  "additionalProperties": false
}
validate_address output schema
{
  "type": "object",
  "required": [
    "asset",
    "network",
    "valid",
    "format_checked",
    "reason",
    "memo_required",
    "memo_name",
    "memo_valid",
    "network_hint",
    "warning"
  ],
  "properties": {
    "asset": {
      "type": "string"
    },
    "valid": {
      "type": "boolean"
    },
    "reason": {
      "type": [
        "string",
        "null"
      ]
    },
    "network": {
      "type": "string"
    },
    "warning": {
      "type": [
        "string",
        "null"
      ]
    },
    "memo_name": {
      "type": [
        "string",
        "null"
      ]
    },
    "memo_valid": {
      "type": [
        "boolean",
        "null"
      ]
    },
    "network_hint": {
      "type": [
        "string",
        "null"
      ]
    },
    "memo_required": {
      "type": "boolean"
    },
    "format_checked": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}
validate_address annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
swap_link — Build a confirmation link
Advertised by the server during the last successful anonymous check.
Advertised read-only

Build a changenow.io link with the pair, the amount, the recipient address and the memo already filled in, so the user checks the numbers on the real page and presses Confirm themselves. Opening the link creates nothing. This is the recommended way to finish a swap: the user sees the rate and the address with their own eyes, which no amount of care in a chat transcript can replace. Use create_swap instead only when the user has explicitly approved this exact amount and address.

swap_link input schema
{
  "type": "object",
  "required": [
    "from",
    "to"
  ],
  "properties": {
    "to": {
      "type": "string",
      "description": "Asset the user receives, canonical id."
    },
    "from": {
      "type": "string",
      "description": "Asset the user sends, canonical id."
    },
    "memo": {
      "type": "string",
      "description": "Memo or destination tag to prefill."
    },
    "locale": {
      "type": "string",
      "maxLength": 2,
      "minLength": 2,
      "description": "Two letter locale for the page, for example \"es\". English needs no locale."
    },
    "address": {
      "type": "string",
      "description": "Recipient address to prefill. The user can still change it on the page."
    },
    "amount_to": {
      "type": "string",
      "description": "Amount to prefill as the amount received. Implies a fixed rate on the page."
    },
    "rate_type": {
      "enum": [
        "float",
        "fixed"
      ],
      "type": "string",
      "default": "float",
      "description": "Which rate the page opens with."
    },
    "amount_from": {
      "type": "string",
      "description": "Amount to prefill as the amount sent."
    },
    "refund_address": {
      "type": "string",
      "description": "Refund address to prefill."
    }
  },
  "additionalProperties": false
}
swap_link output schema
{
  "type": "object",
  "required": [
    "url",
    "prefilled",
    "creates_order",
    "notes"
  ],
  "properties": {
    "url": {
      "type": "string"
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "prefilled": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "creates_order": {
      "type": "boolean",
      "const": false
    }
  },
  "additionalProperties": false
}
swap_link annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
create_swap — Create a swap order
Advertised by the server during the last successful anonymous check.
Open-world

Create a real swap order and return the deposit address the user has to send funds to. This call moves no money by itself, but the order is real: it exists in support, it can expire, and a fixed rate is locked against it. Quote the swap first, validate the recipient address, and confirm the amount and the address with the user before calling this. If the user has not explicitly approved both, use swap_link instead and let them confirm on the page. The answer names who executes the order, and that has to be relayed: some orders are routed to a partner aggregator rather than ChangeNOW.

create_swap input schema
{
  "type": "object",
  "required": [
    "from",
    "to",
    "address"
  ],
  "properties": {
    "to": {
      "type": "string",
      "description": "Asset the user receives, canonical id, for example \"usdt.trx\"."
    },
    "from": {
      "type": "string",
      "description": "Asset the user sends, canonical id, for example \"eth.eth\"."
    },
    "memo": {
      "type": "string",
      "description": "Memo or destination tag for the recipient address, when the asset needs one."
    },
    "address": {
      "type": "string",
      "description": "Address that receives the swapped asset. Check it with validate_address first; a wrong network here loses the funds."
    },
    "rate_id": {
      "type": "string",
      "description": "The rate_id from quote_swap with rate_type \"fixed\". Required for a fixed rate order. It holds for about two minutes, so quote again right before this call if the user needed time to decide."
    },
    "amount_to": {
      "type": "string",
      "description": "Amount the user wants to receive. Requires rate_id from quote_swap."
    },
    "promo_code": {
      "type": "string",
      "description": "Promo code to apply, if the user has one."
    },
    "amount_from": {
      "type": "string",
      "description": "Amount the user sends. Pass this or amount_to, never both."
    },
    "refund_memo": {
      "type": "string",
      "description": "Memo for the refund address."
    },
    "contact_email": {
      "type": "string",
      "format": "email",
      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
      "description": "Optional email for status notifications about this order."
    },
    "refund_address": {
      "type": "string",
      "description": "Where the deposit returns if the swap cannot complete. Strongly recommended: without it a failed swap needs support."
    }
  },
  "additionalProperties": false
}
create_swap output schema
{
  "type": "object",
  "required": [
    "id",
    "status",
    "provider",
    "from",
    "to",
    "amount_from",
    "amount_to",
    "rate_type",
    "payin_address",
    "payin_extra_id",
    "payout_address",
    "payout_extra_id",
    "refund_address",
    "refund_memo",
    "valid_until",
    "created_at",
    "track_url",
    "warnings"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "to": {
      "type": "string"
    },
    "from": {
      "type": "string"
    },
    "status": {
      "type": [
        "string",
        "null"
      ]
    },
    "provider": {
      "enum": [
        "changenow",
        "third-party",
        "unknown"
      ],
      "type": "string"
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "amount_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "rate_type": {
      "enum": [
        "float",
        "fixed"
      ],
      "type": "string"
    },
    "track_url": {
      "type": "string"
    },
    "created_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "amount_from": {
      "type": [
        "string",
        "null"
      ]
    },
    "refund_memo": {
      "type": [
        "string",
        "null"
      ]
    },
    "valid_until": {
      "type": [
        "string",
        "null"
      ]
    },
    "payin_address": {
      "type": "string"
    },
    "payin_extra_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "payout_address": {
      "type": "string"
    },
    "refund_address": {
      "type": [
        "string",
        "null"
      ]
    },
    "payout_extra_id": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": false
}
create_swap annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
check_swap_status — Check a swap order
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Follow an existing order by id: where it stands, what the deposit and payout amounts turned out to be, the transaction hashes, and a plain-language explanation of what the current stage means and what happens next. Use it after create_swap, and again whenever the user asks where their swap is.

check_swap_status input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Order id returned by create_swap."
    },
    "sub_id": {
      "type": "string",
      "description": "Sub order id, for an order the provider split in two."
    }
  },
  "additionalProperties": false
}
check_swap_status output schema
{
  "type": "object",
  "required": [
    "id",
    "status",
    "stage_explanation",
    "provider",
    "from",
    "to",
    "expected_amount_from",
    "expected_amount_to",
    "amount_from",
    "amount_to",
    "payin_address",
    "payin_extra_id",
    "payout_address",
    "payout_extra_id",
    "refund_address",
    "refund_memo",
    "payin_hash",
    "payout_hash",
    "refund_hash",
    "refund_amount",
    "deposit_received_at",
    "valid_until",
    "created_at",
    "updated_at",
    "track_url"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "to": {
      "type": "string"
    },
    "from": {
      "type": "string"
    },
    "status": {
      "type": "string"
    },
    "provider": {
      "enum": [
        "changenow",
        "third-party",
        "unknown"
      ],
      "type": "string"
    },
    "amount_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "track_url": {
      "type": "string"
    },
    "created_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "payin_hash": {
      "type": [
        "string",
        "null"
      ]
    },
    "updated_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "amount_from": {
      "type": [
        "string",
        "null"
      ]
    },
    "payout_hash": {
      "type": [
        "string",
        "null"
      ]
    },
    "refund_hash": {
      "type": [
        "string",
        "null"
      ]
    },
    "refund_memo": {
      "type": [
        "string",
        "null"
      ]
    },
    "valid_until": {
      "type": [
        "string",
        "null"
      ]
    },
    "payin_address": {
      "type": "string"
    },
    "refund_amount": {
      "type": [
        "string",
        "null"
      ]
    },
    "payin_extra_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "payout_address": {
      "type": "string"
    },
    "refund_address": {
      "type": [
        "string",
        "null"
      ]
    },
    "payout_extra_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "stage_explanation": {
      "type": "string"
    },
    "expected_amount_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "deposit_received_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "expected_amount_from": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": false
}
check_swap_status annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

1 advertised

exchange_crypto — Swap one crypto asset for another

Advertised by the server during the last successful anonymous check.

Walk the user through a swap end to end: resolve the assets, quote the rate, check the recipient address, and hand over a confirmation page or create the order once the user has approved it.

from
What the user wants to send, in their own words or as a canonical id.
to
What the user wants to receive.
amount
How much the user wants to send, if they said.

Resources

5 advertised

assets.csv — Whole asset catalogue as CSV

Advertised by the server during the last successful anonymous check.

Every exchangeable asset in four columns: canonical id, legacy ticker, name and flags (F fiat, R fixed rate available, M memo required). One response, no paging, about a tenth of the tokens the same list costs as JSON. Read this when the whole catalogue is genuinely needed; for a handful of assets use the list_assets tool instead.

assets.csv URI
changenow://assets.csv

MIME type: text/csv

networks — Networks and how many assets each carries

Advertised by the server during the last successful anonymous check.

Networks derived from the catalogue itself, with the number of assets on each, so that a network name can be checked before it is used as a filter.

networks URI
changenow://assets/networks

MIME type: text/plain

limits — Amount limits, precision and rate types

Advertised by the server during the last successful anonymous check.

What the minimum and maximum amounts mean, why they belong to the pair rather than the asset, how a fixed rate differs from a float one, and what memo and decimals do.

limits URI
changenow://policy/limits

MIME type: text/plain

compliance-holds — Why a swap can be paused and what to do

Advertised by the server during the last successful anonymous check.

What it means when an order goes to verifying or hold, what resolves it, and what an agent should and should not tell the user. Answer with this text rather than with a guess.

compliance-holds URI
changenow://policy/aml

MIME type: text/plain

quickstart — The swap flow, step by step

Advertised by the server during the last successful anonymous check.

The full sequence from what the user said to a tracked order, with the mistakes each step exists to prevent.

quickstart URI
changenow://docs/quickstart

MIME type: text/plain

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (2 of 2 answered).

  1. 2026-11-06: 1 of 1 checks answered
  2. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1626 ms
95th percentile latency
1626 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1626 ms · metadata changed · 7 tool(s), 5 resource(s), 0 resource template(s), 1 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http changenow-mcp https://mcp.changenow.io/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add changenow-mcp --url https://mcp.changenow.io/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable changenow-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "changenow-mcp": {
      "url": "https://mcp.changenow.io/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "changenow-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.changenow.io/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start changenow-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "changenow-mcp": {
      "type": "http",
      "url": "https://mcp.changenow.io/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http changenow-mcp https://mcp.changenow.io/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://mcp.changenow.io/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "changenow-mcp": {
      "serverUrl": "https://mcp.changenow.io/mcp"
    }
  }
}

Let your agent find its tools

Find servers like ChangeNOW MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run ChangeNOW MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing