Skip to main content
Glama
vjh0107
by vjh0107

mc-mcp-server

An MCP server that drives Mineflayer bots, so an AI agent can exercise a Minecraft server directly: join a bot, run commands, open the menus a plugin draws, click their buttons, and read what the server puts on screen.

It runs as a long-lived container and speaks Streamable HTTP, so one deployment serves several agents at once. Bot lifetime is separate from MCP session lifetime, so a bot outlives the session that created it.

Local development only. The bots authenticate offline, so the target server has to run offline-mode.

Install

helm upgrade -i mc-mcp-server oci://junhyung.cloud/library/charts/mc-mcp-server \
  --version <tag> \
  --namespace mcp --create-namespace

The chart version and the image tag are the same value, so leaving image.tag unset runs the matching image. Tags read <version>-<UTC stamp>.g<commit>; CHANGELOG.md says what each version carried. Every value is documented in the chart README.

The chart makes an auth token on first install and keeps it across upgrades. Read it back and point a client at the endpoint:

TOKEN=$(kubectl -n mcp get secret mc-mcp-server-auth -o jsonpath='{.data.token}' | base64 -d)
claude mcp add --transport http mc-mcp-server http://mc-mcp-server.mcp.svc/mcp \
  -H "Authorization: Bearer $TOKEN"

Keeping the token depends on Helm reading the Secret back from a live cluster. ArgoCD and anything else that renders first and applies later gets an empty read and a new token every sync, so pass auth.existingSecret there.

Related MCP server: MCP Minecraft Remote

Configuration

Environment variables are the defaults; the matching flag overrides one.

Environment

Flag

Default

Meaning

MCP_TRANSPORT

--transport

http

http or stdio

MCP_BIND_HOST

--bind-host

0.0.0.0

Address the HTTP server binds to

MCP_PORT

--port

3000

HTTP port

MCP_PATH

--mcp-path

/mcp

Path the MCP endpoint is served at

MCP_AUTH_TOKEN

--auth-token

none

Shared secret checked as Authorization: Bearer. Unset leaves the endpoint open.

SA_AUTH_ENABLED

--sa-auth

false

Also accept Kubernetes service account tokens, checked with a TokenReview

SA_AUTH_ALLOWED

--allowed-service-accounts

none

Comma separated namespace:name. Empty admits any authenticated one.

MCP_LOG_LEVEL

--log-level

info

debug / info / warn / error

POD_NAME

--instance

hostname

Name reported in logs and metrics

SHUTDOWN_READINESS_GRACE_SECONDS

--readiness-grace

5

Keep serving after SIGTERM so endpoints drop this pod

SHUTDOWN_DRAIN_TIMEOUT_SECONDS

--drain-timeout

30

How long to wait for in-flight tool calls

MC_VERSION

--mc-version

none

Pin the protocol version instead of auto-detecting

MC_USERNAME_PREFIX

--username-prefix

mcp

Prefix for generated bot usernames

BOT_MAX

--max-bots

8

How many bots may be connected at once

BOT_IDLE_TIMEOUT_SECONDS

--idle-timeout

1800

Idle seconds before a bot leaves; 0 disables it

POST <mcp-path> is MCP. GET /healthz and /readyz are the probes, /metrics serves Prometheus, and /debug/bots and /whoami sit behind the same authentication as MCP.

Tools

60 tools in total.

Sessions: join-server, leave-server, list-bots, get-bot-status

Server checks: ping-server

Server interaction: run-command, switch-server, wait-for-chat, wait-ticks, detect-gamemode, complete-command, get-world-state

Movement: get-position, move-to-position, look-at, jump, move-in-direction, fly-to, set-stance

World interaction: activate-block, interact-entity, attack-entity, use-held-item, fish

GUI windows: wait-for-window, read-window, close-window

Slots and containers: click-slot, open-container, drop-held-item

Inventory: list-inventory, find-item, equip-item, give-item

Blocks: get-block-info, find-blocks, dig-block, place-block, read-block-entity

Entities: read-displays, find-entity

Chat: send-chat, read-chat

HUD: read-scoreboard, read-boss-bars, read-player-list, read-action-bar, wait-for-action-bar, read-title, wait-for-title, read-dialog, wait-for-dialog, get-player-state

Sounds and particles: read-effects, wait-for-effect

Crafting: list-recipes, get-recipe, can-craft, craft-item

Smelting: smelt-item

Every argument is listed in docs/tools.md. Both are generated by pnpm docs:tools; do not edit them by hand.

join-server takes the server address every time, so a call record says which server it touched.

The GUI window tools are what exercise menu-driven features: wait for the menu, read its slots including custom names and lore, click a button. The reading tools cover the rest of what a player sees -- the scoreboard, boss bars, the action bar, titles, dialogs, the text floating in the world, and the sounds and particles that never become words. A HUD drawn in custom fonts arrives as segments joined with |, each tagged with its font, rather than as one run-together string.

Development

docker compose -f dev/compose.yml up -d   # offline-mode server on 25577
pnpm install
pnpm dev

The server carries no default Minecraft address; join-server names one on every call, so point a bot at 127.0.0.1:25577 once it is up. See dev/README.md for the test server.

make check runs typecheck, lint, tests, the version check, and fails if the generated tool docs drifted.

Notes

docs/protocol-notes.md records where this server works around mineflayer or the 26.1 protocol, and the known limits, with the measurements behind each.

Images and charts are built and signed by GitHub Actions with cosign, keyless:

cosign verify junhyung.cloud/library/mc-mcp-server:<tag> \
  --certificate-identity-regexp '^https://github.com/vjh0107/mc-mcp-server/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers