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.
Commercial Software — MCTrade is published by MCHaagenti and is distributed for commercial sale. See the LICENSE file 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:
| Command | Permission | Who | Description |
|---|---|---|---|
/trade |
mctrade.trade (default: all) |
Any player | Open the market of all active offers. |
/trade create |
mctrade.trade (default: all) |
Any player | Open the creation menu to list a new offer. |
/trade vault |
mctrade.trade (default: all) |
Any player | Open your secure vault to claim trade proceeds. |
/trade admin |
mctrade.admin (default: op) |
Administrators | Open the whitelist editor. |
All actions are driven through chest GUIs, so the commands must be run by a player.
| Node | Default | Grants |
|---|---|---|
mctrade.trade |
true |
Opening the market and creating offers. |
mctrade.admin |
op |
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. 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.
database:
type: "sqlite"
sqlite:
file: "mctrade.db"
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.
./gradlew build
Each platform produces a shaded plugin jar (MCTradeSpigotMC, MCTradePaperMC, MCTradeFoliaMC) via the shadowJar task.
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 for details regarding usage and distribution.