Async Python SDK for connecting Discord bots and automation to Minecraft servers through a CraftCord plugin API.
Project description
CraftCord
CraftCord is an asynchronous Python SDK for communicating with Minecraft Paper servers through the CraftCordPlugin.
It enables Python applications to interact with Minecraft using a simple, high-level API over HTTP or WebSockets.
Whether you're building a Discord bot, web dashboard, desktop application, mobile app, automation service, or another custom integration, CraftCord provides a clean and modern interface for interacting with your Minecraft server.
Note
CraftCord requires the CraftCordPlugin to be installed on your Paper server.
Plugin Repository: https://github.com/rytisltu09/CraftcordPlugin
Why CraftCord?
CraftCord removes the complexity of talking directly to a Minecraft server.
Instead of implementing HTTP requests, WebSocket connections, authentication, and event parsing yourself, CraftCord provides an intuitive Python API.
With only a few lines of code you can:
- Retrieve online players
- Execute Minecraft commands
- Send chat messages
- Listen for live server events
- Build integrations with any Python application
Perfect For
CraftCord is suitable for:
- Discord bots
- Web dashboards
- Desktop applications
- Mobile applications
- Automation tools
- Monitoring systems
- Economy integrations
- Administrative panels
- Any custom Python application
Features
- Asynchronous Python API
- HTTP and WebSocket transports
- Typed Minecraft models
- Event system
- Built-in command framework
- Plugin/extension system
- Automatic authentication
- Discord.py adapter
- Clean developer-friendly API
Installation
pip install craftcord
Quick Start
1. Configure Environment Variables
export CRAFTCORD_HOST="127.0.0.1"
export CRAFTCORD_PORT="8080"
export CRAFTCORD_TOKEN="your-api-token"
export CRAFTCORD_TRANSPORT="ws"
Local vs Global Plugin Exposure
The Java CraftCord plugin now controls network exposure with:
bindMode=local-> plugin binds to127.0.0.1(same machine only)bindMode=global-> plugin binds to0.0.0.0(all interfaces)host=<non-empty-ip-or-hostname>-> overridesbindModeand binds that specific interface
SDK connection guidance:
- Client targets must be reachable from where your Python app runs.
- Do not use
0.0.0.0as a client target address. It is a server bind wildcard, not a routable destination. - API endpoints and paths are unchanged (
/api/v1/*,/ws).
Use these connection URLs as a reference:
- Local same-machine:
http://127.0.0.1:8080/api/v1 - LAN client:
http://<server-lan-ip>:8080/api/v1 - Reverse proxy/public endpoint:
https://craftcord.example.com/api/v1
Plugin startup logs now include binding type (local-only, global-all-interfaces, or specific-interface) so you can confirm exposure mode quickly.
2. Minimal Example
import asyncio
from craftcord import Client
async def main():
client = Client(
host="127.0.0.1",
port=8080,
token="secret"
)
@client.command("online")
async def online():
return [
player.username
for player in await client.minecraft.players()
]
await client.start()
asyncio.run(main())
Minecraft API
The client.minecraft service exposes high-level methods.
Players
await client.minecraft.players()
await client.minecraft.get_players()
Server Information
await client.minecraft.server_info()
await client.minecraft.get_server_info()
Chat
await client.minecraft.send_message("Hello!")
await client.minecraft.send_message(
"Welcome!",
target="Steve"
)
Commands
await client.minecraft.execute("time set day")
Moderation
await client.minecraft.kick("Steve")
await client.minecraft.ban(
"Steve",
reason="Griefing"
)
Events
Subscribe to real-time Minecraft events.
@client.on("player_join")
async def joined(event):
print(event.player.username)
Built-in events:
player_joinplayer_leaveplayer_chatplayer_deathserver_startserver_stop
Unknown event names arrive as GenericEvent.
Transport Choice
- Use
wsfor real-time events and long-running bot sessions. - Use
httpfor simple request/response integrations.
Set with:
export CRAFTCORD_TRANSPORT="ws"
or
export CRAFTCORD_TRANSPORT="http"
Troubleshooting
Connection refused or timeout
Check this order:
- Verify Java plugin
bindModeand optionalhostvalues. - Confirm your SDK
CRAFTCORD_HOSTpoints to a reachable address from the client machine. - Never set SDK
CRAFTCORD_HOSTto0.0.0.0. - Verify
CRAFTCORD_PORTandCRAFTCORD_TOKENmatch plugin config. - Ensure host firewall rules allow inbound traffic on the plugin port.
- For LAN/WAN access, verify NAT/port-forwarding and routing.
- If using a reverse proxy, ensure
/api/v1/*and/wsroute to the plugin upstream.
Bot starts but keeps retrying WebSocket
Cause: CraftCord API endpoint is not reachable.
Check:
- Is your Java-side CraftCord plugin/API running?
- Do
CRAFTCORD_HOST,CRAFTCORD_PORT, andCRAFTCORD_TOKENmatch? - If your server only supports HTTP, set
CRAFTCORD_TRANSPORT=http.
Discord command does not trigger
Check:
- Message Content Intent is enabled in Discord Developer Portal.
- Bot has permission to read and send in that channel.
- You are using the right prefix (
!) and command (!mc_online).
Import or dataclass errors on Python 3.14
Use the latest code in this repository. Recent updates include Python 3.14 compatibility fixes for event dataclasses.
Plugin System
Extensions can register commands and event listeners.
class GreetingExtension:
async def setup(self, client):
@client.on("player_join")
async def greet(event):
await client.minecraft.send_message(
f"Welcome {event.player.username}!"
)
await client.plugins.load(
GreetingExtension()
)
Protocol Contract (For Java Plugin Authors)
Migration Note (Plugin Networking Update)
- New plugin exposure options:
bindMode(local|global) and optionalhostoverride. - SDK API contract is unchanged: endpoints remain
/api/v1/auth/validate,/api/v1/rpc, and/ws. - Existing users with explicit SDK host/port configuration continue to work unchanged.
- SDK now rejects
0.0.0.0as a client target host with a clear validation error.
Expected API behavior:
- Scripts
- Cron jobs
- Simple integrations
export CRAFTCORD_TRANSPORT=http
Troubleshooting
Connection retries
Verify:
- CraftCordPlugin is running.
- Host and port are correct.
- API token matches.
- Firewall allows the connection.
Discord commands do not respond
If you're using the Discord adapter:
- Enable Message Content Intent.
- Verify bot permissions.
- Check your command prefix.
Protocol
CraftCord communicates using authenticated JSON RPC over HTTP or WebSockets.
Authentication:
- Bearer Token
- HTTP validation endpoint
- WebSocket authentication
Example request:
{
"type": "request",
"id": "uuid",
"action": "minecraft.get_players",
"payload": {}
}
Development
Run tests:
pytest
Run Ruff:
ruff check .
Repository Structure
craftcord/
docs/
examples/
tests/
License
MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file craftcord-0.2.tar.gz.
File metadata
- Download URL: craftcord-0.2.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50080e218cf9e93061b1ff24d8cac5161e71139c63a53d2610a1f8442c0035a2
|
|
| MD5 |
840fb22e51c3f834b9007f6a52456635
|
|
| BLAKE2b-256 |
9317fff91fa482f5d6303fca401b4ba2b59a2417f03f6a4b9ea4c11a7eccb60f
|
Provenance
The following attestation bundles were made for craftcord-0.2.tar.gz:
Publisher:
ci.yml on rytisltu09/Craftcord
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
craftcord-0.2.tar.gz -
Subject digest:
50080e218cf9e93061b1ff24d8cac5161e71139c63a53d2610a1f8442c0035a2 - Sigstore transparency entry: 2136896632
- Sigstore integration time:
-
Permalink:
rytisltu09/Craftcord@fa7f47339293c8347c4a7c3ece9da3350eef13cd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rytisltu09
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@fa7f47339293c8347c4a7c3ece9da3350eef13cd -
Trigger Event:
push
-
Statement type:
File details
Details for the file craftcord-0.2-py3-none-any.whl.
File metadata
- Download URL: craftcord-0.2-py3-none-any.whl
- Upload date:
- Size: 16.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
992eb62f4abbc9693b1a3e00798ed73187b2aab1b7285d1ef1e547e2f8a69937
|
|
| MD5 |
bf957252b30e6cf69482fea48c8aaf6b
|
|
| BLAKE2b-256 |
5420c223268ee190f7c6d7af10b779e17b0094b49cc1c5906b86cb6109816dc0
|
Provenance
The following attestation bundles were made for craftcord-0.2-py3-none-any.whl:
Publisher:
ci.yml on rytisltu09/Craftcord
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
craftcord-0.2-py3-none-any.whl -
Subject digest:
992eb62f4abbc9693b1a3e00798ed73187b2aab1b7285d1ef1e547e2f8a69937 - Sigstore transparency entry: 2136896648
- Sigstore integration time:
-
Permalink:
rytisltu09/Craftcord@fa7f47339293c8347c4a7c3ece9da3350eef13cd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rytisltu09
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@fa7f47339293c8347c4a7c3ece9da3350eef13cd -
Trigger Event:
push
-
Statement type: