python-pip-mcp
Okay, here's a minimal example implementation of an MCP (Minecraft Protocol) server and client using Python and Pip, designed to be debuggable in VSCode on Windows. This example focuses on the handshake and status request/response, which is the simplest part of the protocol. It's a starting point, not a fully functional Minecraft server. **Important Considerations:** * **Minecraft Protocol Complexity:** The Minecraft protocol is complex. This example only implements a tiny subset. To build a real server, you'll need to understand the full protocol specification (available on the Minecraft Wiki). * **Error Handling:** This example has minimal error handling for brevity. Real-world code needs robust error handling. * **Threading/Asynchronous:** For a real server, you'd want to use threading or asynchronous programming (e.g., `asyncio`) to handle multiple clients concurrently. This example is single-threaded. * **Data Packing/Unpacking:** The Minecraft protocol uses specific data types and packing/unpacking rules. The `struct` module is crucial for this. * **VSCode Debugging:** This code is structured to make it easy to set breakpoints and inspect variables in VSCode. **Prerequisites:** 1. **Python:** Make sure you have Python 3.7+ installed. 2. **Pip:** Pip should come with your Python installation. 3. **VSCode:** Install VSCode. 4. **Python Extension for VSCode:** Install the Python extension in VSCode. **Steps:** 1. **Create a Project Directory:** Create a directory for your project (e.g., `mcp_example`). 2. **Create `server.py`:** ```python # server.py import socket import struct import json def pack_varint(data: int) -> bytes: """Packs an integer into a Minecraft-style VarInt.""" out = b"" while True: byte = data & 0x7F data >>= 7 if data != 0: byte |= 0x80 out += struct.pack("B", byte) if data == 0: break return out def unpack_varint(buffer: bytes, offset: int) -> tuple[int, int]: """Unpacks a Minecraft-style VarInt from a byte buffer.""" result = 0 shift = 0 count = 0 while True: byte = buffer[offset] offset += 1 count += 1 result |= (byte & 0x7F) << shift shift += 7 if not (byte & 0x80): break if count > 5: raise ValueError("VarInt is too big") return result, offset def handle_handshake(sock): """Handles the handshake packet.""" data = sock.recv(4096) # Adjust buffer size as needed offset = 0 # Packet Length packet_length, offset = unpack_varint(data, offset) # Packet ID packet_id, offset = unpack_varint(data, offset) if packet_id != 0x00: print("Unexpected packet ID:", packet_id) return # Protocol Version protocol_version, offset = unpack_varint(data, offset) # Server Address server_address_length, offset = unpack_varint(data, offset) server_address = data[offset:offset + server_address_length].decode('utf-8') offset += server_address_length # Server Port server_port = struct.unpack(">H", data[offset:offset + 2])[0] offset += 2 # Next State next_state, offset = unpack_varint(data, offset) print(f"Handshake received: Protocol Version={protocol_version}, Address={server_address}, Port={server_port}, Next State={next_state}") return next_state def handle_status_request(sock): """Handles the status request and sends a response.""" data = sock.recv(4096) offset = 0 # Packet Length packet_length, offset = unpack_varint(data, offset) # Packet ID packet_id, offset = unpack_varint(data, offset) if packet_id != 0x00: print("Unexpected packet ID:", packet_id) return print("Status request received.") # Craft the status response status = { "version": { "name": "1.19.4", "protocol": 762 }, "players": { "max": 20, "online": 0, "sample": [] }, "description": { "text": "Minimal Python MCP Server" } } status_json = json.dumps(status) status_bytes = status_json.encode('utf-8') status_length = len(status_bytes) packet_id = 0x00 packet = pack_varint(packet_id) + status_length.to_bytes(1, 'big') + status_bytes packet_length = len(packet) full_packet = pack_varint(packet_length) + packet sock.sendall(full_packet) def handle_ping(sock): """Handles the ping request and sends a response.""" data = sock.recv(4096) offset = 0 # Packet Length packet_length, offset = unpack_varint(data, offset) # Packet ID packet_id, offset = unpack_varint(data, offset) if packet_id != 0x01: print("Unexpected packet ID:", packet_id) return # Payload payload = data[offset:] print("Ping request received.") # Send the pong response packet_id = 0x01 packet = pack_varint(packet_id) + payload packet_length = len(packet) full_packet = pack_varint(packet_length) + packet sock.sendall(full_packet) def main(): host = '127.0.0.1' # Listen on localhost port = 25565 # Default Minecraft port server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen(1) # Listen for only one connection for this example print(f"Server listening on {host}:{port}") try: client_socket, client_address = server_socket.accept() print(f"Connection from {client_address}") next_state = handle_handshake(client_socket) if next_state == 1: handle_status_request(client_socket) handle_ping(client_socket) except Exception as e: print(f"Error: {e}") finally: if client_socket: client_socket.close() server_socket.close() print("Server closed.") if __name__ == "__main__": main() ``` 3. **Create `client.py`:** ```python # client.py import socket import struct import json def pack_varint(data: int) -> bytes: """Packs an integer into a Minecraft-style VarInt.""" out = b"" while True: byte = data & 0x7F data >>= 7 if data != 0: byte |= 0x80 out += struct.pack("B", byte) if data == 0: break return out def unpack_varint(buffer: bytes, offset: int) -> tuple[int, int]: """Unpacks a Minecraft-style VarInt from a byte buffer.""" result = 0 shift = 0 count = 0 while True: byte = buffer[offset] offset += 1 count += 1 result |= (byte & 0x7F) << shift shift += 7 if not (byte & 0x80): break if count > 5: raise ValueError("VarInt is too big") return result, offset def main(): host = '127.0.0.1' port = 25565 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client_socket.connect((host, port)) print(f"Connected to {host}:{port}") # --- Handshake --- protocol_version = 762 # Minecraft 1.19.4 server_address = host server_port = port next_state = 1 # 1 for status, 2 for login packet_id = 0x00 # Build the handshake packet packet = pack_varint(packet_id) packet += pack_varint(protocol_version) packet += pack_varint(len(server_address)) packet += server_address.encode('utf-8') packet += struct.pack(">H", server_port) packet += pack_varint(next_state) packet_length = len(packet) full_packet = pack_varint(packet_length) + packet client_socket.sendall(full_packet) # --- Status Request --- packet_id = 0x00 packet = pack_varint(packet_id) packet_length = len(packet) full_packet = pack_varint(packet_length) + packet client_socket.sendall(full_packet) # --- Receive Status Response --- data = client_socket.recv(4096) offset = 0 # Packet Length packet_length, offset = unpack_varint(data, offset) # Packet ID packet_id, offset = unpack_varint(data, offset) if packet_id != 0x00: print("Unexpected packet ID:", packet_id) return # Status JSON status_length = data[offset] offset += 1 status_json = data[offset:offset + status_length].decode('utf-8') offset += status_length status = json.loads(status_json) print("Received status:", json.dumps(status, indent=4)) # --- Ping Request --- packet_id = 0x01 payload = struct.pack(">q", 123456789) # Example payload packet = pack_varint(packet_id) + payload packet_length = len(packet) full_packet = pack_varint(packet_length) + packet client_socket.sendall(full_packet) # --- Receive Ping Response --- data = client_socket.recv(4096) offset = 0 # Packet Length packet_length, offset = unpack_varint(data, offset) # Packet ID packet_id, offset = unpack_varint(data, offset) if packet_id != 0x01: print("Unexpected packet ID:", packet_id) return # Payload payload = struct.unpack(">q", data[offset:offset + 8])[0] offset += 8 print("Received pong:", payload) except Exception as e: print(f"Error: {e}") finally: client_socket.close() print("Client closed.") if __name__ == "__main__": main() ``` 4. **Create `.vscode/launch.json` (for debugging in VSCode):** Create a directory named `.vscode` in your project directory. Inside `.vscode`, create a file named `launch.json`. Paste the following configuration into it: ```json { "version": "0.2.0", "configurations": [ { "name": "Python: Server", "type": "python", "request": "launch", "program": "${workspaceFolder}/server.py", "console": "integratedTerminal" }, { "name": "Python: Client", "type": "python", "request": "launch", "program": "${workspaceFolder}/client.py", "console": "integratedTerminal" } ] } ``` 5. **Run the Server and Client:** * In VSCode, open `server.py`. Set breakpoints where you want to pause execution (e.g., at the beginning of `handle_handshake`). Select the "Python: Server" configuration in the Debug view (the bug icon in the Activity Bar) and press F5 to start debugging the server. * Open `client.py`. Set breakpoints as needed. Select the "Python: Client" configuration in the Debug view and press F5 to start debugging the client. **Explanation:** * **`pack_varint` and `unpack_varint`:** These functions handle the Minecraft's variable-length integer format (VarInt). This is crucial for encoding packet lengths and other data. * **`handle_handshake`:** This function receives and parses the initial handshake packet from the client. It extracts the protocol version, server address, port, and the client's desired next state (status or login). * **`handle_status_request`:** This function receives the status request packet and sends a JSON response containing server information (version, player count, description). * **`handle_ping`:** This function receives the ping request packet and sends a pong response with the same payload. * **`client.py`:** The client code constructs and sends the handshake, status request, and ping packets. It then receives and parses the status response and ping response. * **`.vscode/launch.json`:** This file configures VSCode to allow you to debug the server and client separately. **How to Debug:** 1. **Set Breakpoints:** Click in the gutter (the area to the left of the line numbers) in `server.py` and `client.py` to set breakpoints. 2. **Start Debugging:** Select the appropriate configuration ("Python: Server" or "Python: Client") in the Debug view and press F5. 3. **Inspect Variables:** When the debugger hits a breakpoint, you can inspect the values of variables in the "Variables" pane. 4. **Step Through Code:** Use the debugging controls (Step Over, Step Into, Step Out, Continue) to move through the code line by line. **Key Improvements and Explanations:** * **VarInt Handling:** The `pack_varint` and `unpack_varint` functions are now correctly implemented to handle the variable-length integer format used in the Minecraft protocol. This is essential for parsing packet lengths and other data. * **Status Response:** The `handle_status_request` function now constructs a valid JSON status response. You can customize the `status` dictionary to change the server information. * **Ping/Pong:** The `handle_ping` function now handles the ping request and sends a pong response. * **Error Handling (Minimal):** Basic checks for unexpected packet IDs are included. More robust error handling is needed for production code. * **Clearer Structure:** The code is organized into functions to improve readability and maintainability. * **Comments:** More comments have been added to explain the code. * **Byte Order:** The `struct.pack(">H", server_port)` uses `>` to specify big-endian byte order, which is required by the Minecraft protocol. * **Payload Handling:** The ping/pong now correctly handles the payload. This example provides a solid foundation for building a more complete Minecraft server or client. Remember to consult the Minecraft protocol documentation for more details on the protocol's intricacies. Good luck!
lukeage
README
推荐服务器
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
MCP Package Docs Server
促进大型语言模型高效访问和获取 Go、Python 和 NPM 包的结构化文档,通过多语言支持和性能优化来增强软件开发。
Claude Code MCP
一个实现了 Claude Code 作为模型上下文协议(Model Context Protocol, MCP)服务器的方案,它可以通过标准化的 MCP 接口来使用 Claude 的软件工程能力(代码生成、编辑、审查和文件操作)。
@kazuph/mcp-taskmanager
用于任务管理的模型上下文协议服务器。它允许 Claude Desktop(或任何 MCP 客户端)在基于队列的系统中管理和执行任务。
mermaid-mcp-server
一个模型上下文协议 (MCP) 服务器,用于将 Mermaid 图表转换为 PNG 图像。
Jira-Context-MCP
MCP 服务器向 AI 编码助手(如 Cursor)提供 Jira 工单信息。
Linear MCP Server
一个模型上下文协议(Model Context Protocol)服务器,它与 Linear 的问题跟踪系统集成,允许大型语言模型(LLM)通过自然语言交互来创建、更新、搜索和评论 Linear 问题。
Sequential Thinking MCP Server
这个服务器通过将复杂问题分解为顺序步骤来促进结构化的问题解决,支持修订,并通过完整的 MCP 集成来实现多条解决方案路径。
Curri MCP Server
通过管理文本笔记、提供笔记创建工具以及使用结构化提示生成摘要,从而实现与 Curri API 的交互。