Async Python SDK for connecting Discord bots and automation to Minecraft servers through a CraftCord plugin API.
Project description
CraftCord
CraftCord is a Python SDK for Discord bot developers who want to connect their bot to Minecraft. It is to be used with Craftcord plugin, you can find it in https://github.com/rytisltu09/CraftcordPlugin
IT IS HIGHLY RECOMMENDED THAT YOU SETUP YOUR CRAFTCORD PLUGIN FIRST BEFORE CONTINUING!
If you are new, the fastest way to understand CraftCord is:
- Run the example bot.
- Use
!mc_onlinein Discord. - See Minecraft player data in your Discord channel.
Who This Is For
CraftCord is a good fit if you want to:
- build a Discord bot in Python
- read Minecraft server events
- run Minecraft actions from Discord commands
- keep bot logic clean and reusable
What You Get
- async Python client (
Client) - two transport options: WebSocket or HTTP
- typed Minecraft events and models
- CraftCord command system (
@client.command) - Discord adapter for
discord.py(DiscordPyAdapter) - plugin system (
client.plugins.load(...))
Beginner 5-Minute Setup
1. Install Dependencies
From your virtual environment
pip install craftcord
2. Configure Environment Variables
Set these before running examples/basic_bot.py:
DISCORD_TOKEN(required)CRAFTCORD_HOST(default:127.0.0.1)CRAFTCORD_PORT(default:8080)CRAFTCORD_TOKEN(default:secret)CRAFTCORD_TRANSPORT(wsorhttp, default:ws)CRAFTCORD_DEFAULT_CHANNEL(optional Discord channel id)
Example:
export DISCORD_TOKEN="your-discord-bot-token"
export CRAFTCORD_HOST="127.0.0.1"
export CRAFTCORD_PORT="8080"
export CRAFTCORD_TOKEN="secret"
export CRAFTCORD_TRANSPORT="ws"
3. Start The Bot
python examples/basic_bot.py
4. Test It In Discord
In a channel where your bot can read and send messages, run:
!mc_online
If everything is connected, the bot responds with online player names.
How Commands Work (Simple Mental Model)
@bot.commandis Discord-facing.@client.commandis CraftCord-facing shared logic.
Typical flow:
- User types a Discord command like
!mc_online. - Discord handler calls
await client.invoke_command("online"). - CraftCord command runs and returns data.
- Discord handler sends the result back to chat.
This is why you avoid duplicating business logic.
Minimal Example
import asyncio
from craftcord import Client
async def main() -> None:
client = Client(host="127.0.0.1", port=8080, token="secret")
@client.command("online")
async def online_players() -> list[str]:
players = await client.minecraft.players()
return [player.username for player in players]
await client.start()
asyncio.run(main())
Minecraft Features Available
From client.minecraft:
players()/get_players()server_info()/get_server_info()send_message(message, target=None)execute(command)kick(username, reason=None)ban(username, reason=None)
Events You Can Listen To
Typed built-in events include:
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
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 are classes with setup(client) and optional teardown(client).
class GreetingExtension:
async def setup(self, client) -> None:
@client.on("player_join")
async def greet(event) -> None:
await client.minecraft.send_message(f"Welcome {event.player.username}!")
await client.plugins.load(GreetingExtension())
Protocol Contract (For Java Plugin Authors)
Expected API behavior:
- Bearer token auth for HTTP and WebSocket
- WebSocket action:
auth.validate - HTTP endpoint:
GET /api/v1/auth/validate - HTTP endpoint:
POST /api/v1/rpc - WebSocket event envelope support
Request envelope:
{
"type": "request",
"id": "uuid",
"action": "minecraft.get_players",
"payload": {}
}
Response envelope:
{
"type": "response",
"id": "uuid",
"status": "ok",
"data": {}
}
Event envelope:
{
"type": "event",
"event": "player_join",
"data": {
"player": {
"uuid": "3b5e4f2d-8e34-4ad1-848f-b9d66fd07a4f",
"username": "Alex",
"health": 20.0,
"world": "world",
"location": {"x": 0.0, "y": 64.0, "z": 0.0}
}
}
}
Development
Run tests:
pytest
Run lint:
ruff check .
Repository Layout
craftcord/
docs/
examples/
tests/
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.1.2.tar.gz.
File metadata
- Download URL: craftcord-0.1.2.tar.gz
- Upload date:
- Size: 15.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d03e33cec43187e5b1ce280301208286b34d0045a128e7412a9bf04198ed6122
|
|
| MD5 |
d87b82f87eeb8db8005ed8feef613a6f
|
|
| BLAKE2b-256 |
f7822175437b741b56924f26b8aeece44a709bef5759e1abf11b9d97c3eecb05
|
Provenance
The following attestation bundles were made for craftcord-0.1.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.1.2.tar.gz -
Subject digest:
d03e33cec43187e5b1ce280301208286b34d0045a128e7412a9bf04198ed6122 - Sigstore transparency entry: 2130349742
- Sigstore integration time:
-
Permalink:
rytisltu09/Craftcord@06e07fac26474935ce9230841797e2d954b50a73 -
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@06e07fac26474935ce9230841797e2d954b50a73 -
Trigger Event:
push
-
Statement type:
File details
Details for the file craftcord-0.1.2-py3-none-any.whl.
File metadata
- Download URL: craftcord-0.1.2-py3-none-any.whl
- Upload date:
- Size: 16.0 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 |
6cf9fb7bec0a3ca071d078b9d485e2fc363459ce57dcef749ab38f1dab8e81da
|
|
| MD5 |
9349a9671f59d924ad204d66223daeb6
|
|
| BLAKE2b-256 |
3aceb4479955727c42666d31543da5e2a8e3829e7dfc07241cf3bb96b08f7bd9
|
Provenance
The following attestation bundles were made for craftcord-0.1.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.1.2-py3-none-any.whl -
Subject digest:
6cf9fb7bec0a3ca071d078b9d485e2fc363459ce57dcef749ab38f1dab8e81da - Sigstore transparency entry: 2130349833
- Sigstore integration time:
-
Permalink:
rytisltu09/Craftcord@06e07fac26474935ce9230841797e2d954b50a73 -
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@06e07fac26474935ce9230841797e2d954b50a73 -
Trigger Event:
push
-
Statement type: