This release is a pre-release and may not be stable for production use.
marionette-mc
Typed asyncio client for the Marionette Minecraft bridge. Python 3.11+, protocol 2, package 0.1.0a1 (independent of mod versions). MIT, confirmed by the project owner. This is an unpublished alpha candidate; no package upload or published-consumer acceptance is claimed.
From this checkout, install for development with python -m pip install -e ./python.
After an explicitly authorized publication, consumers must pin
marionette-mc==0.1.0a1 rather than silently accepting new prereleases.
A local wheel installation verifies packaging only.
import asyncio
from marionette_mc import connect
async def main():
async with connect(required_capabilities=["bridgeSafety", "playerState"]) as client:
print(client.hello)
await client.configure(rate_divisor=1, sections=["player"])
print(await client.next_observation(timeout=5))
try:
await client.input(forward=True)
await asyncio.sleep(0.2)
finally:
await client.release()
asyncio.run(main())
Run only against a disposable, rendered world with a clear walking area.
Context exit closes the session even on exceptions/cancellation; controller loss
triggers the mod's release-all safety. release() explicitly clears queued
controller intent. Neither sending nor closing is an action acknowledgment.
Keep the asyncio event loop responsive: move blocking/CPU work off the loop.
The websockets library answers server pings automatically; there is no reconnect
or command replay policy in this package. Native connections omit Origin and
ignore environment proxies. Current local trust has no authentication.
API and outcomes
connect(uri=..., role="controller" | "observer", sections=..., required_capabilities=...)yields oneClientafter validating protocol 2 and required capability flags.client.require(...)checks additional capabilities. Missing flags are unsupported.input(forward=..., back=..., left=..., right=..., jump=..., sneak=..., sprint=..., attack=..., use=..., tap=["jump", "attack", "use"], hotbar=0)applies only supplied fields. Methods check capabilities for taps/interactions and guard observer roles.look(yaw=..., pitch=..., mode="instant" | "delta" | "smooth", speed=...)orlook(mode="smooth", x=..., y=..., z=..., speed=...)controls the camera. Success is silent; use observations for convergence. No completion event exists.configure(rate_divisor=1, sections=["player"])selects this session's stream.sections=[]requests cadence-only frames. Omitted arguments leave settings unchanged.inventory(op, menu=..., source=..., destination=..., hotbar=..., all=False, animated=False, timeout=...)supports open/inspect/move/swap/equip/drop/close. Obtainmenu_ref(result["menu"])from a recent inspect before mutations. Results describe client prediction, not authoritative server acknowledgment.next_observation(timeout=...)/observations()consume latest observations. A slow consumer skips frames;observations_coalescedcounts replacements.next_reply(timeout=...)/replies()consume uncorrelated errors and late or unmatched inventory results. Awaited inventory errors raiseServerErrorwith the original typed.error; uncorrelated errors remain in this reliable stream. Applications should service it alongside their observation/gameplay loop.wait_closed()returns localDisconnect(code, reason, cause);Disconnected.outcomecarries it when an operation/stream cannot continue. This is a Python lifecycle outcome, never a fabricated protocol event. Reliable replies already received can be drained after closure. Observations cannot be read as live state after disconnect.
TypedDict wire models (including nested player, effects, inventory menus/slots,
commands and all four incoming types) live in marionette_mc.messages. Decoding
checks required fields/types and retains unknown additive fields. ServerError,
VersionError, CapabilityError, RoleError, CapacityError and InvalidMessage
(the latter in messages) distinguish failure causes. Opening failures preserve
websockets/OS exceptions; handshake timeout is TimeoutError.
Each inventory call uses a unique session ID. RequestTimeout.request_id lets a
caller identify the later reply. Timeout or task cancellation does not cancel
server work. Late results/errors go to next_reply(); do not blindly resend a
move/drop. A disconnect leaves outstanding outcomes unknown. Re-inspect state
in a separately chosen new session before deciding what to do. To stop current
controller work, use release or close, understanding already-completed world
changes cannot be undone. An unmatched reply is not proof that it is safe to retry.
Default bounds: 64 reliable replies, 32 pending requests, one latest observation,
128 KiB incoming frames, 16 transport frames, 32 KiB write high-water mark,
64 KiB outgoing commands, 5-second connect/hello timeout, 10-second request/write
timeout and 1-second close timeout. Queue limits are configurable integers 1–1024.
Reliable overflow closes with an explicit local CapacityError cause; replies
beyond capacity are lost with unknown outcomes. The reader never waits for a
consumer queue and therefore continues servicing WebSocket liveness. Streams have
one logical consumer each; concurrent readers compete rather than receive broadcasts.
Local verification and publication candidate
From the repository root:
python3.11 -m venv .venv
.venv/bin/pip install -r python/requirements-dev.txt
.venv/bin/pip install --no-build-isolation -e ./python
.venv/bin/python -m unittest discover -s python/tests -v
(cd python && ../.venv/bin/mypy)
.venv/bin/python -m build --no-isolation python
./gradlew build
requirements-dev.txt pins build/test dependencies, including transitives.
The shared tests/fixtures/protocol2.json ships in the sdist; Java's
PythonCompatibilityTest parses those commands and compares its actual message
builders to the same expected frames. Offline tests use real local WebSockets.
The wheel contains only the client, type marker and license/metadata. The sdist
also contains self-contained offline tests and fixtures. Neither includes worlds,
private harnesses, consumer policy, caches, credentials or mod build output.
Before publishing: review exact distributions and SHA256 hashes, resolve release prerequisites (including the project's authentication/provisioning gate), establish PyPI project ownership/credentials, obtain explicit upload authorization, then upload only the reviewed artifacts. Registration alone is not upload permission. After publication, a clean environment must install the exact published version and pass rendered observation/movement/release smoke acceptance. Local wheel or sdist success does not satisfy that milestone or consumer integration gate.
Metadata
Release files for marionette-mc 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| marionette_mc-0.1.0a1.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| marionette_mc-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.4 kB
Release files / marionette_mc-0.1.0a1.tar.gz
| Download URL | marionette_mc-0.1.0a1.tar.gz |
|---|---|
| Size | 15.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de7f464ebbac2676920a41a2981280671b2640badb382665c3a8f25b2410a180
|
|
BLAKE2b-256 checksum How to use checksums |
eba1727ad190954e75fcaaf5cefbcd14e21e3d0ee08aa1c9677a8a025e9ee893
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / marionette_mc-0.1.0a1-py3-none-any.whl
| Download URL | marionette_mc-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d084f4fd104b2b200724359c9dff0bc3b6572ad6deab0c327f5760aa63c2beca
|
|
BLAKE2b-256 checksum How to use checksums |
ce24b6de82827fd260442c1a9268875371050cf69467faa243980af839103f11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|