Skip to main content
Glama

Minecraft Bedrock MCP Server

by Mming-Lab
blocks.ts9.48 kB
import { BaseTool, SequenceStep } from '../base/tool'; import { ToolCallResult, InputSchema } from '../../types'; import { SetBlockMode, FillBlocksMode } from 'socket-be'; /** * Block操作高レベルツール * ブロック設置・塗りつぶし・情報取得に特化 */ export class BlocksTool extends BaseTool { readonly name = 'blocks'; readonly description = 'Block operations: single block placement, area filling, terrain analysis. Actions: set_block(single), fill_area(large_regions), get_top_solid_block(surface_level), query_block_data(block_info). Perfect for construction, terraforming, or analyzing terrain. Examples: set_block(x,y,z,stone), fill_area(x1,y1,z1 to x2,y2,z2,dirt), supports replace/keep/destroy modes'; readonly inputSchema: InputSchema = { type: 'object', properties: { action: { type: 'string', description: 'Block operation to perform', enum: [ 'set_block', 'fill_area', 'get_top_solid_block', 'query_block_data', 'query_item_data', 'query_mob_data', 'sequence' ] }, x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' }, z: { type: 'number', description: 'Z coordinate' }, x2: { type: 'number', description: 'Second X coordinate for area operations' }, y2: { type: 'number', description: 'Second Y coordinate for area operations' }, z2: { type: 'number', description: 'Second Z coordinate for area operations' }, block_id: { type: 'string', description: 'Block ID (e.g., minecraft:stone, minecraft:dirt, minecraft:air)' }, mode: { type: 'string', description: 'Block placement/fill mode', enum: ['replace', 'keep', 'destroy', 'hollow', 'outline'] }, steps: { type: 'array', description: 'Array of block actions for sequence. Each step should have "type" field and relevant parameters.' } }, required: ['action'] }; /** * ブロック操作を実行します * * @param args - ブロック操作パラメータ * @param args.action - 実行するアクション(set_block, fill_area, get_top_solid_block等) * @param args.x - X座標 * @param args.y - Y座標 * @param args.z - Z座標 * @param args.x2 - 終了X座標(fill_area時) * @param args.y2 - 終了Y座標(fill_area時) * @param args.z2 - 終了Z座標(fill_area時) * @param args.block_id - ブロックID(set_block, fill_area時) * @param args.mode - 設置モード(replace, hollow, keep等) * @returns ツール実行結果 */ async execute(args: { action: string; x?: number; y?: number; z?: number; x2?: number; y2?: number; z2?: number; block_id?: string; mode?: string; steps?: SequenceStep[]; }): Promise<ToolCallResult> { if (!this.world) { return { success: false, message: 'World not available. Ensure Minecraft is connected.' }; } try { const { action } = args; let result: any; let message: string; switch (action) { case 'set_block': if (args.x === undefined || args.y === undefined || args.z === undefined || !args.block_id) { return { success: false, message: 'Coordinates (x,y,z) and block_id required for set_block' }; } if (!this.validateCoordinates(args.x, args.y, args.z)) { return { success: false, message: 'Invalid coordinates. Y must be between -64 and 320.' }; } const setOptions = args.mode && args.mode !== 'replace' ? { mode: args.mode as SetBlockMode } : undefined; await this.world.setBlock( { x: args.x, y: args.y, z: args.z }, this.normalizeBlockId(args.block_id), setOptions ); message = `Block ${args.block_id} set at (${args.x}, ${args.y}, ${args.z})`; if (args.mode && args.mode !== 'replace') { message += ` with mode: ${args.mode}`; } break; case 'fill_area': if (args.x === undefined || args.y === undefined || args.z === undefined || args.x2 === undefined || args.y2 === undefined || args.z2 === undefined || !args.block_id) { return { success: false, message: 'All coordinates (x,y,z,x2,y2,z2) and block_id required for fill_area' }; } if (!this.validateCoordinates(args.x, args.y, args.z) || !this.validateCoordinates(args.x2, args.y2, args.z2)) { return { success: false, message: 'Invalid coordinates. Y values must be between -64 and 320.' }; } // Calculate volume for safety check const volume = Math.abs(args.x2 - args.x + 1) * Math.abs(args.y2 - args.y + 1) * Math.abs(args.z2 - args.z + 1); if (volume > 32768) { return { success: false, message: `Area too large (${volume} blocks). Maximum is 32768 blocks.` }; } let fillOptions: any = undefined; if (args.mode && args.mode !== 'replace') { fillOptions = { mode: args.mode as FillBlocksMode }; } result = await this.world.fillBlocks( { x: args.x, y: args.y, z: args.z }, { x: args.x2, y: args.y2, z: args.z2 }, this.normalizeBlockId(args.block_id), fillOptions ); message = `Filled ${result} blocks with ${args.block_id} from (${args.x},${args.y},${args.z}) to (${args.x2},${args.y2},${args.z2})`; if (args.mode && args.mode !== 'replace') { message += ` with mode: ${args.mode}`; } break; case 'get_top_solid_block': const location = (args.x !== undefined && args.z !== undefined) ? { x: args.x, y: args.y || 320, z: args.z } : undefined; result = await this.world.getTopSolidBlock(location); if (location) { message = `Top solid block found at (${args.x}, ${result?.y || 'none'}, ${args.z})`; } else { message = 'Top solid block found at current location'; } break; case 'query_block_data': result = await this.world.queryData('block'); message = 'Block data retrieved'; break; case 'query_item_data': result = await this.world.queryData('item'); message = 'Item data retrieved'; break; case 'query_mob_data': result = await this.world.queryData('mob'); message = 'Mob data retrieved'; break; case 'sequence': if (!args.steps) { return this.createErrorResponse('steps array is required for sequence action'); } return await this.executeSequence(args.steps as SequenceStep[]); default: return { success: false, message: `Unknown action: ${action}` }; } return { success: true, message: message, data: { action, result, volume: result, timestamp: Date.now() } }; } catch (error) { return { success: false, message: `Block operation error: ${error instanceof Error ? error.message : String(error)}` }; } } /** * ブロック専用のシーケンスステップ実行 * * @param step - 実行するステップ * @param index - ステップのインデックス * @returns ステップ実行結果 * * @protected * @override */ protected async executeSequenceStep(step: SequenceStep, index: number): Promise<ToolCallResult> { // wait ステップは基底クラスで処理される if (step.type === 'wait') { return await super.executeSequenceStep(step, index); } // ブロック特有のステップを実行 const blocksArgs = { action: step.type, ...step }; return await this.execute(blocksArgs); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mming-Lab/minecraft-bedrock-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server