MCTrade is a commercial, asynchronous item-to-item trading market for Minecraft servers, supporting the SpigotMC, PaperMC, and FoliaMC platforms. Players list an item they are giving away and the item they want in return; anyone can fulfil the offer through a chest GUI, with the proceeds held safely in a secure vault until the merchant claims them.
MCTrade is published by MCHaagenti and is distributed for commercial sale. See the LICENSE file distributed with MCTrade for terms.
Note: In the future I might add some features that only the paid tier can use, but the core system features will be free to use. For example, AI integration like making the AI "find a merchant who offers {item name} that I can exchange with {item name}".
A trade is a one-for-the-other exchange:
Merchant offersN × Item A, and needsM × Item Bin return.
/trade create and chooses both trade items from the whitelist — Choose Item to Offer and Choose Item to Receive each open a category, then that category's item page. The amount for each side is set to any quantity by left/right-clicking its display (±1, or ±10 with shift). Clicking Confirm takes the full offer amount from the merchant's inventory and lists the offer — if they do not actually hold that many, it reports an insufficient amount and nothing is taken. Both amounts can be any number./trade to open the market — a paginated chest GUI of all active global offers, one offer per row (four offers per page). Each row reads left to right as four columns:
/trade vault, withdrawing as much as their inventory can hold at a time. Online merchants are told a sale landed in their vault; offline merchants are reminded the next time they join. Nothing is ever lost to a full inventory, a restart, an item-clearing plugin, or theft.Only items whose base type is on the trade item whitelist may be offered or requested. The whitelist lives in the trade_item_whitelist table, where the Base64 base item is the primary key and each row carries a category (quantities are never part of the whitelist). Storing the item as the key means checking whether something is tradeable is a single key lookup rather than a scan.
The whitelist is grouped into categories (configured under whitelist.categories in config.yml). Both browsing and administration start by choosing a category; items are then shown most-recently-added first, paginated across as many pages as needed. Administrators manage the whitelist in-game via /trade admin:
/trade — open the market of all active offers. Permission mctrade.trade (default: all players)./trade create — open the creation menu to list a new offer. Permission mctrade.trade (default: all players)./trade vault — open your secure vault to claim trade proceeds. Permission mctrade.trade (default: all players)./trade admin — open the whitelist editor. Permission mctrade.admin (default: operators).All actions are driven through chest GUIs, so the commands must be run by a player.
mctrade.trade (default: true) — grants opening the market and creating offers.mctrade.admin (default: op) — grants editing the trade item whitelist.MCTrade follows the MCHaagenti sub-module architecture; the storage core is pure Java and never touches the Bukkit API, and all storage operations are asynchronous and return a CompletableFuture.
api — interfaces and immutable models only (ITradeDatabase, TradeOffer, WhitelistEntry, VaultItem).common — storage implementations: a shared AbstractSqlTradeDatabase plus the SQLite, MySQL, and PostgreSQL backends, a native MongoDB backend, and the MCTradeProvider entry point.bukkit — SpigotMC-API-only core: the chest GUIs, the TradeService orchestrator, item Base64 (de)serialization and inventory helpers, the whitelist/offer/vault flows, the /trade command, listeners, the cancellable TradeCreateEvent, and a SyncExecutor scheduling abstraction.platforms — thin entry points per platform:
spigotmc, papermc — use the regular server scheduler.foliamc — uses a region/entity-aware scheduler so all Bukkit access respects Folia's threading model.Database work runs off the server thread. Any result that touches the Bukkit API is scheduled back through a platform-specific SyncExecutor — the main thread on SpigotMC/PaperMC, or the owning region/entity thread on FoliaMC — so inventory mutations always happen on a thread that may legally perform them. Concurrent accepts of the same offer are made safe by an atomic claim (claimOffer): only the caller that actually deletes the row proceeds, preventing a double-spend.
The storage backend is selected via database.type in config.yml. Supported values are sqlite (default, zero-configuration), mysql, postgresql, and mongodb. For SQLite, the database file name is set under database.sqlite.file (default mctrade.db). The JDBC drivers and the MongoDB driver are declared as libraries in plugin.yml and downloaded by the server at runtime, so no shading of drivers is required.
Three tables (or collections) are created automatically on first start: trade_item_whitelist, trade_offers, and trade_vaults.
This project uses Gradle with the Java 25 toolchain; building the project with the shadowJar task produces a shaded plugin jar per platform (MCTradeSpigotMC, MCTradePaperMC, MCTradeFoliaMC).
plugins/).plugins/MCTrade/config.yml, then set enable: true (and pick a database.type if not using SQLite)./trade admin and whitelist the items you want to be tradeable./trade create to list offers and /trade to browse and accept them.Copyright (c) 2026 MCHaagenti. All rights reserved.
Please see the LICENSE file distributed with MCTrade for details regarding usage and distribution.