sequence
Chain actions from multiple tools to automate complex tasks in Minecraft Bedrock, such as teleporting players, building structures, and capturing media, with precise timing and error handling.
Instructions
Execute CROSS-TOOL SEQUENCES: Chain actions from multiple tools together with timing control. Perfect for complex automation like "teleport player → wait 2s → build cube → take screenshot → say message". Supports all tools: player(teleport/move/say), agent(move/turn), camera(shot/video), blocks(setblock/fill), world(time/weather), building(cube/sphere/line). Use wait_time for delays, on_error for handling failures.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | No | Optional description of what this sequence does | |
| steps | Yes | Array of sequence steps. Each step needs: "tool" (player/agent/camera/blocks/world/building), "type" (action like teleport/move/shot/setblock/build), and tool-specific params. Optional: "wait_time" (seconds to wait after), "on_error" (continue/stop/retry), "retry_count" (max retries). Example: [{tool:"player",type:"teleport",x:0,y:70,z:0,wait_time:2},{tool:"blocks",type:"setblock",x:0,y:70,z:0,block:"diamond_block"}] |
Implementation Reference
- src/tools/core/sequence.ts:78-160 (handler)Main handler function for the 'sequence' tool. Orchestrates execution of multiple tool steps in sequence, handling timing (wait_time), error handling (on_error: continue/stop/retry), retries, logging, and aggregation of results.async execute(args: { steps: GlobalSequenceStep[]; description?: string; }): Promise<ToolCallResult> { const { steps, description } = args; if (!steps || !Array.isArray(steps) || steps.length === 0) { return this.createErrorResponse('steps array is required for sequence execution'); } try { let totalDuration = 0; const results: string[] = []; const sequenceId = Date.now().toString(36); if (description) { results.push(`Sequence: ${description}`); } for (let i = 0; i < steps.length; i++) { const step = steps[i]; // デバッグログは標準エラー出力に送信(MCPモードでは非表示) if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Executing step ${i + 1}/${steps.length}: ${step.tool}.${step.type}`); } const stepResult = await this.executeGlobalSequenceStep(step, i); if (!stepResult.success) { const errorAction = step.on_error || 'stop'; switch (errorAction) { case 'continue': results.push(`Step ${i + 1} (${step.tool}.${step.type}): Failed but continuing - ${stepResult.message}`); if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Step ${i + 1} failed but continuing`); } break; case 'retry': const retryResult = await this.retryGlobalSequenceStep(step, i); if (!retryResult.success) { return this.createErrorResponse(`Step ${i + 1} (${step.tool}.${step.type}) failed after retries: ${retryResult.message}`); } results.push(`Step ${i + 1} (${step.tool}.${step.type}): Succeeded after retry - ${retryResult.message}`); if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Step ${i + 1} succeeded after retry`); } break; case 'stop': default: return this.createErrorResponse(`Step ${i + 1} (${step.tool}.${step.type}) failed: ${stepResult.message}`); } } else { results.push(`Step ${i + 1} (${step.tool}.${step.type}): ${stepResult.message || 'Executed'}`); if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Step ${i + 1} completed successfully`); } } // 待ち時間処理 const waitTime = step.wait_time || 0; if (waitTime > 0 && i < steps.length - 1) { if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Waiting ${waitTime}s before next step`); } await this.delay(waitTime); totalDuration += waitTime; } } if (process.stdin.isTTY !== false) { console.error(`[Sequence ${sequenceId}] Completed all ${steps.length} steps`); } return this.createSuccessResponse( `Cross-tool sequence completed: ${steps.length} steps executed over ${totalDuration.toFixed(1)}s\n` + results.join('\n') ); } catch (error) { return this.createErrorResponse(`Cross-tool sequence execution failed: ${error instanceof Error ? error.message : String(error)}`); } }
- src/tools/core/sequence.ts:21-66 (schema)Input schema defining the structure for sequence execution: required 'steps' array of objects with 'tool', 'type', optional 'wait_time', 'on_error', 'retry_count', and optional 'description'.readonly inputSchema: InputSchema = { type: 'object', properties: { steps: { type: 'array', description: 'Array of sequence steps. Each step needs: "tool" (player/agent/camera/blocks/world/building), "type" (action like teleport/move/shot/setblock/build), and tool-specific params. Optional: "wait_time" (seconds to wait after), "on_error" (continue/stop/retry), "retry_count" (max retries). Example: [{tool:"player",type:"teleport",x:0,y:70,z:0,wait_time:2},{tool:"blocks",type:"setblock",x:0,y:70,z:0,block:"diamond_block"}]', items: { type: 'object', description: 'Individual cross-tool sequence step', properties: { tool: { type: 'string', description: 'Tool name: player, agent, camera, blocks, world, or any building tool (build_cube, build_sphere, etc.)' }, type: { type: 'string', description: 'Action type: depends on tool - player(teleport/move/say), agent(move/turn), camera(shot/video), blocks(setblock/fill), world(time/weather/gamemode), building(build)' }, wait_time: { type: 'number', description: 'Seconds to wait after this step (default: 0)', minimum: 0, maximum: 60 }, on_error: { type: 'string', description: 'Error handling: continue (ignore errors), stop (halt sequence), retry (try again)', enum: ['continue', 'stop', 'retry'] }, retry_count: { type: 'number', description: 'Max retry attempts when on_error=retry (default: 3)', minimum: 1, maximum: 10 } }, required: ['tool', 'type'] } }, description: { type: 'string', description: 'Optional description of what this sequence does' } }, required: ['steps'] };
- src/server.ts:347-397 (registration)Instantiates SequenceTool as part of the tools array and configures it specifically by setting the tool registry (required for cross-tool sequencing), along with common setups like commandExecutor.private initializeTools(): void { this.tools = [ // Socket-BE Core API ツール(推奨 - シンプルでAI使いやすい) new AgentTool(), new WorldTool(), new PlayerTool(), new BlocksTool(), new SystemTool(), new CameraTool(), new SequenceTool(), new MinecraftWikiTool(), // Advanced Building ツール(高レベル建築機能) new BuildCubeTool(), // ✅ 完全動作 new BuildLineTool(), // ✅ 完全動作 new BuildSphereTool(), // ✅ 完全動作 new BuildCylinderTool(), // ✅ 修正済み new BuildParaboloidTool(), // ✅ 基本動作 new BuildHyperboloidTool(), // ✅ 基本動作 new BuildRotateTool(), // ✅ 基本動作 new BuildTransformTool(), // ✅ 基本動作 new BuildTorusTool(), // ✅ 修正完了 new BuildHelixTool(), // ✅ 修正完了 new BuildEllipsoidTool(), // ✅ 修正完了 new BuildBezierTool(), // ✅ 新規追加(可変制御点ベジェ曲線) ]; // 全ツールにコマンド実行関数とSocket-BEインスタンスを設定 const commandExecutor = async ( command: string ): Promise<ToolCallResult> => { return this.executeCommand(command); }; this.tools.forEach((tool) => { tool.setCommandExecutor(commandExecutor); tool.setSocketBEInstances(this.currentWorld, this.currentAgent); }); // SequenceToolにツールレジストリを設定 const sequenceTool = this.tools.find( (tool) => tool.name === "sequence" ) as SequenceTool; if (sequenceTool) { const toolRegistry = new Map<string, BaseTool>(); this.tools.forEach((tool) => { toolRegistry.set(tool.name, tool); }); sequenceTool.setToolRegistry(toolRegistry); } }
- src/server.ts:491-573 (registration)Registers all tools including 'sequence' to the MCP server using mcpServer.registerTool with converted Zod schema and execution wrapper.private registerModularTools(): void { const schemaConverter = new SchemaToZodConverter(); this.tools.forEach((tool) => { // inputSchemaをZod形式に変換(SchemaToZodConverterを使用) const zodSchema = schemaConverter.convert(tool.inputSchema); // ツールを登録 this.mcpServer.registerTool( tool.name, { title: tool.name, description: tool.description, inputSchema: zodSchema, }, async (args: any) => { try { const result = await tool.execute(args); let responseText: string; if (result.success) { // 建築ツールの場合は最適化 if (tool.name.startsWith('build_')) { const optimized = optimizeBuildResult(result); responseText = `✅ ${optimized.message}`; if (optimized.summary) { responseText += `\n\n📊 Summary:\n${JSON.stringify(optimized.summary, null, 2)}`; } } else { // 通常ツールの場合 responseText = result.message || `Tool ${tool.name} executed successfully`; if (result.data) { // データサイズチェック const dataStr = JSON.stringify(result.data, null, 2); const sizeWarning = checkResponseSize(dataStr); if (sizeWarning) { // 大きすぎる場合はデータタイプのみ表示 responseText += `\n\n${sizeWarning}`; responseText += `\nData type: ${Array.isArray(result.data) ? `Array[${result.data.length}]` : typeof result.data}`; } else { responseText += `\n\nData: ${dataStr}`; } } } } else { // エラーメッセージにヒントを追加 const errorMsg = result.message || "Tool execution failed"; const enrichedError = enrichErrorWithHints(errorMsg); responseText = `❌ ${enrichedError}`; if (result.data) { responseText += `\n\nDetails:\n${JSON.stringify(result.data, null, 2)}`; } } return { content: [ { type: "text", text: responseText, }, ], }; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); const errorStack = error instanceof Error ? error.stack : undefined; const exceptionMessage = `Tool execution failed with exception: ${errorMsg}${errorStack ? `\n\nStack trace:\n${errorStack}` : ""}`; return { content: [ { type: "text", text: `❌ ${exceptionMessage}`, }, ], }; } } ); });
- src/tools/core/sequence.ts:165-189 (helper)Helper method to execute a single global sequence step by looking up the specified tool from the registry and calling its execute method with prepared arguments.private async executeGlobalSequenceStep(step: GlobalSequenceStep, index: number): Promise<ToolCallResult> { // wait ステップは特別処理 if (step.type === 'wait') { const waitTime = step.wait_time || 1; await this.delay(waitTime); return this.createSuccessResponse(`Waited ${waitTime}s`); } // 指定されたツールを取得 const tool = this.toolRegistry.get(step.tool); if (!tool) { return this.createErrorResponse(`Tool '${step.tool}' not found in registry`); } // ツール用の引数を準備 (tool フィールドを除外) const { tool: toolName, ...toolArgs } = step; const executeArgs = { action: step.type, ...toolArgs }; try { // 指定されたツールでアクションを実行 return await tool.execute(executeArgs); } catch (error) { return this.createErrorResponse(`Tool ${step.tool} execution error: ${error instanceof Error ? error.message : String(error)}`); } }