---
title: Versions
description: Which Minecraft versions are built in, how one is picked per connection, and how to pin one.
---

mc-protocol ships one version: **Minecraft Java 26.2, protocol 776**. The code is laid out so a second version is a directory plus a registration, but nothing else is built in yet.

## Pick a version

The root import always tracks the newest built-in version. A subpath pins one:

```ts
import { Server, Client, Proxy, helpers } from "mc-protocol";      // newest (26.2 today)
import { Server, Client, Proxy, helpers } from "mc-protocol/26.2"; // pinned; "mc-protocol/776" is an alias
```

From a subpath, `Server` defaults `versions` to `[776]`, `Client` defaults `version` to `776`, `Proxy` accepts `776` from players, and `helpers` is `helpers.forVersion(776)`. Passing the options explicitly overrides the defaults either way.

The root export also exposes the registry:

```ts
import { versions, getVersion, DEFAULT_PROTOCOL, createVersionedApi } from "mc-protocol";

DEFAULT_PROTOCOL;                       // 776
versions().map((v) => v.name);          // ["26.2"]
getVersion(776).packets.play.clientbound.byName.Login; // { id, packet }
getVersion(999);                        // throws RangeError

const { Server } = createVersionedApi(776); // what "mc-protocol/26.2" does
```

## Negotiation

Every connection starts with `Intension`, which carries `protocolVersion`. The `Client` on each side reads it and switches both packet builders to that version's tables before the next packet is decoded.

On the **server** side, `Server({ versions })` lists the protocols it accepts (default `[DEFAULT_PROTOCOL]`; unknown numbers throw a `RangeError`):

| `protocolVersion` | `nextState` | Result |
| --- | --- | --- |
| in `versions` | any | Tables switch to that version. `client.version` reports it. |
| not in `versions` | `1` (status) | Tables stay on the default. `StatusRequest` and `PingRequest` work, so the list entry can show which versions you accept. |
| not in `versions` | `2` or `3` (login, transfer) | `LoginDisconnect` with the reason `Unsupported protocol version 999; this server supports 776 (26.2)`, the socket ends, and `Server` emits `versionRejected(client, protocol)`. Later bytes on that socket are ignored. |

On the **client** side, `Client({ version })` selects the tables and fills `Intension.protocolVersion` when you leave it out. If you send another built-in protocol number, the client follows it. A number without built-in tables is sent unchanged and the tables stay on `version`; that is enough to ping a server of another version.

`Proxy` gives its player-facing `Server` the proxy's `versions`; the upstream `Client` adopts the player's negotiated version when the forwarded `Intension` goes out.

## Helpers

The data-backed helpers (`getBlockStateId`, `getItemId`, `createSlot`, the map helpers, `ChunkHelper`, and the world generators) are bound to the default version. `helpers.forVersion(protocol)` returns the same helper set bound to another registered version's block states, items, lighting table, and map palette:

```ts
import { helpers } from "mc-protocol";

const h = helpers.forVersion(776);
h.getBlockStateId("oak_stairs", { facing: "east" });
new h.ChunkHelper();                   // same as new helpers.ChunkHelper({ version: 776 })
```

Helpers with no per-version data (commands, particles, entity metadata, flags) are shared as is.

## Layout

```
src/Core/Versions/
  index.ts          registry: registerVersion, getVersion, versions, DEFAULT_PROTOCOL
  api.ts            createVersionedApi(protocol)
  776/
    index.ts        ProtocolVersion for 26.2: name, packet tables, data
    packets.ts      generated: byId / byName per state and bound
    Packets/        <state>/<bound>/<PacketName>.ts, one file per packet
    Helpers/        wire codecs for this version
    Data/           registries, tags, blocks, items, lighting, map colors
src/versions/
  26.2.ts, 776.ts   entry modules for "mc-protocol/26.2" and "mc-protocol/776"
```

Each packet file is named after its `name` and exports its numeric wire ID as `id`. `packets.ts` is generated by `node tools/generate-packet-index.ts`; rerun it after adding, removing, renaming, or changing the ID of a packet. Block and item registries are rebuilt with `tools/generate-blocks.ts` and `tools/generate-items.ts`. Adding a version means creating `src/Core/Versions/<protocol>/` with the same shape, registering it in `src/Core/Versions/index.ts`, and adding an entry module plus a `package.json` export. The packet definition files themselves must be generated from Minecraft's protocol data, and that generator is not in the repository yet.
