Skip to main content
Glama

pm-minecraft

MCPクライアント向けの自己完結型Minecraftサバイバルボディです。

Mineflayer、Prismarine Viewer、ローカルWeb UI、Streamable HTTP MCPサーバーを実行します。

エージェント、モデル、認知ランタイムは含まれていません。選択したエージェントにMCPの使い方、スクリーンショットの見方、MCP経由で実行できるカスタムTypeScriptスクリプトの作成方法を指示する最小限の指示のみが含まれています。

https://github.com/minedojo/voyager と https://github.com/Mega-Gorilla/Discovery に多大な感謝を :3

これは、私が一緒にMinecraftをプレイできる楽しい認知アーキテクチャAIコンパニオンを作るための継続的な取り組みの一部です。単体でも動作します ^_^

セットアップ

要件: Windows PowerShell、Node.js 20+、py 経由のPython 3.12、そしてサバイバルモードのキャラクターがいる到達可能なMinecraft Java 1.19.xサーバー。

Set-Location C:\workspace\pm-minecraft-mcp
.\setup.ps1

セットアップは共有PMワークフローに従います: uv を使用してこのリポジトリのPython 3.12 .venv を作成し、ロックファイルを同期し、ロックされたNodeパッケージをインストールします。scripts/setup.ps1 は互換性ラッパーとして残ります。

うまくいかない場合は、コーディングエージェントに修正を依頼してください。

Related MCP server: Renge Bot

Minecraft

セットアップは https://github.com/Mega-Gorilla/Discovery から拝借しました。

私は手動でMinecraftをMODしたことがありません。私にとってうまくいく方法は次のとおりです:

  • Prismをダウンロード

  • 1.19.4をインストール

  • Fabric Loader 0.19.3をインストール

  • Prism経由でこれらのMODをインストール:

    • Fabric API

    • CompleteConfig

    • Mod Menu

    • Multiplayer Server Pause (Forge)

    • wenhaoによるitem-pickup-range (/setPickupRange 5)

  • サバイバルワールドを作成、チート有効、ピースフル

  • 入ってポート12345で「LANに公開」

キャラクターの作成と起動

.\scripts\init_character.ps1 `
  -Name Floppa `
  -AgentRoot C:/Temp/Floppa `
  -ArtifactRoot C:/Temp/Floppa/artifacts/minecraft

.\scripts\start_minecraft_mcp.ps1 `
  -Name Floppa `
  -MinecraftHost 127.0.0.1 `
  -MinecraftPort 12345 `
  -AgentRoot C:/Temp/Floppa `
  -ArtifactRoot C:/Temp/Floppa/artifacts/minecraft

初期化子はエージェントワークスペース、memory/minecraft/、drafts/、skills/、lib/minecraft.ts、.mcp.json を作成します。ランチャーはローカルWeb UI、Prismarine viewer、MCP URLを出力します。複数のキャラクターには、一意の -WebPort、-ViewerPort、-McpPort 値を使用してください。

deploy/drafts/*.ts のすべての例はワークスペースの drafts/ にコピーされ、その AGENTS.md にリストされます。これらは minecraft_execute_typescript を通じてそのまま実行されるため、エージェントは直接実行するか、そのガードと検証の形状を新しいドラフトにコピーできます。deploy/drafts/ に例を追加すると、新しいキャラクターごとに同梱されます。

エージェントは新しい動作を書く前に minecraft_list_capabilities を呼び出すことができます。適合する機能がない場合、エージェントは一般的なボディアクションからTypeScriptドラフトを書きます。エージェントは決定的な事後条件でドラフトを実行します。実行が成功した後、minecraft_promote_skill はドラフトを skills/ にコピーします。昇格レコードにはソースハッシュ、実行ID、事後条件が含まれます。

エンティティの観測には、各エンティティが読み込まれている間、安定したランタイムIDが含まれます。一般的な attack_entity アクションは、観測されたIDに対して1回の通常のサバイバル攻撃を実行します。キル目標の場合、エージェントはインベントリの増加などのサバイバル結果を検証する必要があります。スキルは、観測、移動、装備、攻撃、検証を組み合わせて、狩猟などの動作にすることができます。

インスタンスを停止するには:

.\scripts\stop_minecraft_mcp.ps1 -ArtifactRoot C:/Temp/Floppa/artifacts/minecraft

次に、ワークスペースから使用します:

Set-Location C:/Temp/Floppa
codex

Codexは .mcp.json を読み取ります。minecraft サーバーを使用するようにプロンプトします。状態ログとスクリーンショットは ./artifacts/minecraft にあります。

知覚とビューアモード

minecraft_find_block はデフォルトで require_visible: true です。これは通常のサバイバル設定です: キャラクターの頭から遮るもののない光線があるブロックのみを返します。エージェントは、ターゲットが見えない場合、探索、より良い視点への移動、または別の観測を使用する必要があります。長距離計画の場合、require_visible: false を設定します。結果は読み込まれたワールド内の位置のみであり、採掘前に到達して視覚的に検証する必要があります。

ディスク上のロギング

すべてはキャラクターのアーティファクトルート (artifacts/minecraft/) の下に書き込まれます:

  • states/ — スナップショットごとに1つの生の完全な状態ファイル (<timestamp>-mcstate-<id>.yaml)。各状態には、その状態で最初に見られたチャットメッセージのみが保存されるため、すべてのチャットメッセージはツリー全体で正確に1回だけ存在します。ファイルを順にたどることでトランスクリプトを再構築できます。各状態はスクリーンショットにリンクします。画像バイトや重複したスクリーンショットメタデータは含まれません。current_state.yaml は、最新の状態の相対パスのみを含むポインタファイルです。

  • screenshots/ — 画像が存在する唯一の場所 (.png とフレームごとの小さなメタデータサイドカー)。状態とアクションはこれらにリンクするだけです。

  • actions/ — MCPツール呼び出しごとに1つのフラットなyaml。<timestamp>_<tool>.yaml という名前で、その場で書き込まれます (呼び出しが開始された瞬間にツールと入力を持つスターターファイルが表示され、スナップショットが発生するたびに前後の状態+スクリーンショットリンクが追加され、生のプリティプリントされたツール出力、期間、例外が最終的な書き換えで追加されます)。フィールド: tool、tool_input、tool_output (両方ともプリティJSONブロックスカラー)、4つのリンク before_state_path / before_screenshot_path / after_state_path / after_screenshot_path (ツールが状態を作成しなかった場合は空、minecraft_observe のように1つ作成するツールの場合は前のみ)、およびスキル用の execution_id / skill_path などのルックアップヘッダー。成功または失敗は tool_output の戻りデータから直接読み取られます。例外は error: ブロックに記録されます。

  • mcp-server.log — 捕捉されたすべてのボディ/ネットワークエラーと、すべての未処理の例外 (トレースバック付き) がここに記録されます。

ツールの結果は、状態全体をインライン化する代わりに、同じリンク (beforeStatePath / afterStatePath / beforeScreenshotPath / afterScreenshotPath) を返すため、モデルは詳細が必要なときにファイルをたどります。

スクリーンショットは、すべての状態に対して artifacts/minecraft/screenshots にキャプチャされ書き込まれます — すべてのアクションの前後、すべての minecraft_observe 呼び出しで — include_image に関係なく、サーバーが画像キャプチャを有効にして起動されている限り (デフォルト、--no-images で無効化)。これにより、エージェントが自分で見なかった状態でも、後で分析するための完全でシームレスなディスク上の視覚履歴が得られます。

include_image は、ピクセルバイトがその特定のツール呼び出しの応答にも添付されるかどうかのみを制御し、エージェントが今すぐ見られるようにします。minecraft_observe はデフォルトで include_image=true (他のすべてのツールは、日常的なアクションをコンテキストで安価に保つためにデフォルトで include_image=false)。状態のみが必要な場合は、minecraft_observe に include_image=false を渡して、応答に画像を含めないようにします — スクリーンショットはどちらの場合でもキャプチャされディスクに保存されます。要求されたがキャプチャに失敗したスクリーンショット (ビューア/ボットが準備できていない、サポートされているブラウザが見つからない) は、screenshot: {"error": ..., "message": ...} として報告され、screenshot: null (画像キャプチャが --no-images でサーバー全体で無効化されている) とは区別されます。

ナビゲーション (歩行のみ)

minecraft_walk_to は歩行のみです。1ブロックの段差を登り、1ブロック下がることができますが、掘る、足場を置く、タワーを作る、パルクール、ドアを開けることはできません。水平位置を目標とし (GoalNearXZ、地形の高さは自動的に選択されます)、開始中心の chunk_limit チャンク領域 (デフォルト3、サーバーの設定最大値で上限) 内の静的目標を使用します。ターゲットがその領域外にある場合、近くに立つことのできる床がない場合、または徒歩での経路がない場合、呼び出しは待機せずにすぐに失敗します。

tolerance のデフォルトは 1.5 です。検索A*予算 (walkSearchTimeoutMs、デフォルト1000) は、パスファインディングが「近づいてください」というメッセージで失敗するまでの時間を制限します。

トンネリングと長距離ナビゲーション

  • minecraft_mine_block は通常、頭の視線を必要としますが、1幅のシャフト内の隣接する足レベルのブロックでは不可能です。--mine-visibility-ignore-distance ブロック (デフォルト 3、開始スクリプトに -MineVisibilityIgnoreDistance を渡す) 内のターゲットに対してはそのゲートをスキップするため、1幅のトンネルからまっすぐ掘り進むことができます。

  • minecraft_walk_to は --max-chunk-limit (デフォルト 8) までの chunk_limit を受け入れます。それより大きい要求は error: requested chunk limit (N) greater than allowed (M) で拒否されます。

  • minecraft_pillar_up は、保持しているアイテムが設置可能なブロックでない場合、明確な pillar_up_needs_placeable_block エラーを報告し、着地のヘッドルームを先にクリアする必要があることを説明します。dig_up はホップごとにヘッドルームをクリアします。

  • すべてのキャラクターに同梱されるドラフト (drafts/ に自動デプロイ):

    • dig_staircase(height, distance, stop) — 歩行可能な2タイルの下降ランプ。

    • clear_room(width, depth, height) — 1幅のトンネルを部屋に拡張します。

    • dig_up(targetY) / descend_to_depth(targetY, stopOnOre) — 掘る前に溶岩/水を検査するハザードセーフなシングルホップの上昇/下降。

    • tunnel_forward / tunnel_iron / branch_mine_safe_iron — トンネリングと鉱石採掘、すべてハザードガード付き (水/溶岩に掘る前に停止します)。

    • place_crafting_table / place_block / climb_pillar / find_village (村人を見たときに報告する長距離パトロール)。

停止した実行、タイムアウト、アンチストールガード

  • minecraft_stop はアクティブなMineflayerコマンドを停止し、実行中のTypeScriptスキルプロセスも終了します (両方を強制終了)。minecraft_kill_command は現在の物理コマンドのみを停止します。minecraft_kill_skill は実行中のスキルプロセスのみを終了します。

  • 協調的キャンセル: スキルはすべてのAPI呼び出し/スリープでキルシグナルマーカーをチェックし、停止されたときにクリーンに抜け出します (SkillCancelledError)。そのため、minecraft_stop/kill_skill (およびクライアントの切断) はスキルを迅速に停止し、結果を書き込ませます — ランナーはマーカーを無視した場合にのみハードキルされます。

  • 設定可能なスキルタイムアウト: minecraft_set_skill_timeout(seconds) (1..3600) は minecraft_execute_typescript と minecraft_collect_blocks の最大時間を設定します (デフォルト90、起動時デフォルトは -SkillTimeoutSeconds / --skill-timeout-seconds)。長いスキルは別のサブプロセスで実行され、そのタイムアウトでサーバー側で終了されます。

  • クライアントウィンドウに合わせる: エージェントの .mcp.json の requestTimeoutMs (キャラクターデフォルト 200000) はサーバーのスキルタイムアウトより上に保つ必要があります。そうしないと、長いスキルが完了する前にクライアント側で遮断されます。経験則: minecraft_set_skill_timeout を requestTimeoutMs - 10s に設定します。

  • 繰り返しの無益なサーキットブレーカーはデフォルトで無効です。これは、同一の無益な操作をループで再試行する古い弱いモデルの名残でした。単一の「関連アイテム」にキー設定されていたため、無関係なスキル操作を誤ってブロックしていました。明示的に必要な場合にのみ、--enable-anti-stall-guard MCP引数 (開始スクリプトでは -EnableAntiStallGuard) で再度有効にします。

状態の透明性

  • すべての状態 (完全およびデルタ) は常にプレイヤーの position、health、food、foodSaturation を保持し、すべての結果は常に現在の heldItem を報告するため、エージェントは差分から自分のバイタルや保持ツールを推測する必要がありません。

  • minecraft_collect_blocks は、ターゲットブロックを収穫する最も安価なツールを事前に装備し (実行中に unharvestable 拒否で死ぬ代わりに)、ボディは collect_blocks が別のツールを必要とする場合を除いて、保持アイテムを交換しなくなりました。

ライブテストからのヒント (エージェントの人間工学)

これらはコーディングエージェントとの実際のゲーム内セッションから得られたもので、エージェントのAGENTS.mdやスキルプロンプトにエンコードする価値があります:

  • 座標はフラット ラッパーツールでは: minecraft_walk_to(x,y,z,…) / minecraft_mine_block(x,y,z,…) は個別の数値を受け取り、position/block オブジェクトではありません。ネストされたアクションスキーマには minecraft_call を minecraft_info のシェイプとともに使用します(例: {"action":"place_block","parameters":{"referenceBlock":{…}}})。

  • 掘る前に調査: トンネルを掘る前に hazards(水/溶岩)を読み、次の セルを inspect します。採掘ドラフトはハザードで停止します。生の mine_block を水/溶岩に向かって行うとボットが立ち往生します。

  • 手持ちツールのずれ: よじ登り系の mine_block や pillar_up は、 ツールの代わりに設置可能なブロック(土/丸石)を手に残すことがあります。 よじ登り系の採掘後は再装備して確認します。ツールは耐久度でも壊れるため、 予備のピッケルを用意してください。

  • 1マス幅ではなく広く採掘: 1マス幅のトンネルは前面しか露出せず、 側壁の鉱石を通り過ぎてしまいます。clear_room/branch_mine_safe_iron(3マス幅)を 使用して鉱石を露出させ、find_block の視線(アンチX線)結果は 「見に行く/露出させるために採掘する」と扱います。

  • 長距離の地上移動は機能します 動的チャンクストリーミング歩行で。 各 walk_to をクライアントウィンドウ内に収めれば、1チャンクずつの移動より はるかに広い範囲をカバーできます。

  • タイムアウト: minecraft_set_skill_timeout を requestTimeoutMs - 10s に 維持して、長いスキルが途中で切られずに完了するようにします。minecraft_info は 現在値を報告します。ドキュメントがずれたら再読取してください。

  • 1つの巨大な不可逆スキルより、小さな可逆スキルを多数 好みます。それぞれに 決定的な事後条件が必要です。minecraft_observe + minecraft_stop で 逸れた実行を追跡して停止できます。

クールな機能

ここにWebUIがあります。キャラクターを手動で操作したり、コーディングエージェントがMCPをどう使っているかを見たりできます。

そしてこちらはCodexが私のキャラクターのスキンを説明しているところです。PrismarineはデフォルトのSteveしかレンダリングしません :(

開発

npm test
npm run build
.\.venv\Scripts\python.exe -m compileall mcp

プログラムでの使用(pip install)

pm-minecraft は別のPythonプロジェクトに直接埋め込むことができます。例えば、 デーモンスレッドでMinecraftキャラクターを生かし続ける認知アーキテクチャなどです。 ps1スクリプトも、ランチャーの subprocess.Popen も、分離された子プロセスも一切ありません。 すべてのNodeプロセスは stdinライフサイクルパイプ を通じてPythonの親プロセスに接続されています。 親プロセスが(正常に、または強制終了で)死ぬと、OSがパイプを閉じ、NodeはEOFを検出して クリーンにシャットダウンします。WindowsとLinuxで同じセマンティクスです。

インストール

pip install git+https://github.com/flamingrickpat/pm-minecraft.git

対象マシンの要件:

  • Python 3.12、およびPATH上のNode.js 20+(node と npm)。

  • Python環境でキャラクターが初めて起動するとき、パッケージはNodeの依存関係ツリーを 一度だけ <venv>/pm-minecraft-runtime/<version>/ にインストールします (ファイルロックの下で npm ci を実行。一度きりで、数分かかります)。 以降の起動は即座です。pm_minecraft_mcp.ensure_node_runtime() で事前にウォームアップできます。

  • 到達可能なMinecraft Java 1.19.xサーバーで、キャラクターがサバイバルモードであること (スタンドアロン設定と同じ)。

エントリーポイント

すべては1つの型付き設定オブジェクトと、デーモンスレッドで実行するように設計されたブロッキング関数です:

  • pm_minecraft_mcp.ServerConfig(...) — すべての設定: Minecraftホスト/ポート、 ユーザー名、エージェントホーム、アーティファクトルート、web/viewer/MCPホスト+ポート、 起動タイムアウト、画像キャプチャ、スキル制限、視距離。

  • pm_minecraft_mcp.execute_node_main_loop(config) — Minecraftボディ (1つのNodeプロセス)を実行し、終了するまでブロックします。

  • pm_minecraft_mcp.execute_python_main_loop(config, manage_body=True) — MCPサーバーを実行し、サービス中はブロックします。デフォルトの manage_body=True では、ボディ自体も起動して所有します(1スレッドで十分)。 manage_body=False では、ボディがコンパニオンの execute_node_main_loop スレッドによって管理されることを期待し、準備完了になるのを待ちます。

  • pm_minecraft_mcp.init_character(name, agent_root, artifact_root, ...) — scripts/init_character.ps1 のPython移植: エージェントワークスペースを作成します (AGENTS.md、.mcp.json、lib/minecraft.ts、drafts/、skills/、 memory/minecraft/)。空でないエージェントルートは拒否します。

  • pm_minecraft_mcp.check_prerequisites(config) — フェイルファストチェック。 何かを起動する前にも自動的に実行されます: エージェントホームの初期化、 MinecraftサーバーへのTCP到達可能性、ローカルサービスポートの空き、PATH上の node。 各失敗は特定のメッセージとともに即座に例外を発生させます。ボディが参加した後、 ネゴシエートされたバージョンが1.19.xでゲームモードがサバイバルでなければ、 エントリーポイントは例外を発生させます。

例

examples/main.py は2つのデーモンスレッドでキャラクターを起動し、Ctrl-Dでシャットダウンします:

import threading
from pathlib import Path

from pm_minecraft_mcp import (
    ServerConfig,
    execute_node_main_loop,
    execute_python_main_loop,
    init_character,
)

AGENT_ROOT = Path.home() / "characters" / "Floppa"

if not (AGENT_ROOT / "AGENTS.md").exists():
    init_character(
        name="Floppa",
        agent_root=AGENT_ROOT,
        artifact_root=AGENT_ROOT / "artifacts" / "minecraft",
        minecraft_host="127.0.0.1",
        minecraft_port=12345,
        web_port=3000,
        viewer_port=3007,
        mcp_port=8765,
    )

config = ServerConfig(
    minecraft_host="127.0.0.1",
    minecraft_port=12345,
    username="Floppa",
    agent_home=AGENT_ROOT,
    artifact_root=AGENT_ROOT / "artifacts" / "minecraft",
    web_host="127.0.0.1",
    web_port=3000,
    viewer_port=3007,
    mcp_host="127.0.0.1",
    mcp_port=8765,
    startup_timeout_seconds=90,
    capture_images=True,
    max_skill_characters=50000,
    viewer_scale=1,
    viewer_fov=80,
    view_distance=24,
)

threading.Thread(target=execute_node_main_loop, args=(config,), daemon=True).start()
threading.Thread(
    target=execute_python_main_loop, args=(config,), kwargs={"manage_body": False}, daemon=True
).start()

try:
    while True:
        input()  # Ctrl-D (EOF) ends the process; children follow via stdin EOF
except (EOFError, KeyboardInterrupt):
    pass

シングルスレッドの変種も機能します: execute_python_main_loop(config) 上の1つのデーモンスレッドが ボディとMCPの両方を起動します。

複数キャラクター

キャラクターごとに1つの設定(一意のユーザー名 + 一意のweb/viewer/MCPポート)を使用し、 それぞれに独自のデーモンスレッドのペアを与えます。Nodeランタイムは同じPython環境内の すべてのキャラクター間で読み取り専用で共有されます。

エージェント側の動作は変更なし

MCPクライアントの視点からは何も変わりません: 同じツール名、スキーマ、.mcp.json レイアウト、 minecraft_execute_typescript コントラクトです。エージェントは引き続き任意のTypeScriptドラフトを ワークスペースに書き込み、サーバーに対して実行できます。ドラフトはパッケージのtsxランタイムを 通じて、キャラクターホームの lib/minecraft.ts とともに実行されます。

ライフサイクルの保証

  • ボディは1つのNodeプロセスです(npm/tsxラッパープロセスはありません)。スキル実行も それぞれ1プロセスです。追跡すべきプロセスツリーはありません。

  • 子プロセスは CREATE_NEW_PROCESS_GROUP を取得せず、taskkill されることもありません。 シャットダウンはまずstdin-EOF、最後の手段としてプレーンな kill() です。

  • 埋め込みプロセスをいつでも(taskkill /F や kill -9 を含む)強制終了しても、 ボディを孤児化できません: ライフサイクルパイプが壊れ、Nodeは数秒以内に終了します。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables controlling a semi-autonomous Minecraft bot via MCP, supporting tasks like movement, combat, farming, and chatting.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A production-ready MCP server that gives an LLM agent standalone-equivalent control over a Mineflayer Minecraft bot — movement, mining, crafting, inventory, combat, containers, chat, and much more — exposed as 110 strongly-typed tools across 23 groups, with full bot lifecycle management and dual (poll + push) event streaming.
    80 npm
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP-capable AI clients to control a Minecraft bot in a Java world, providing tools for movement, observation, inventory, chat, crafting, mining, and placing.
    4
    MIT