Skip to main content
Glama
Mming-Lab
by Mming-Lab

system

Manage in-game elements like scoreboards, screen displays, and player interfaces in Minecraft Bedrock. Organize objectives, display titles, action bars, and sequences to enhance gameplay and server interactions.

Instructions

System features: scoreboards, screen displays (titles, action bars), player UI, game management

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform within the category
categoryYesSystem category to use
display_nameNoDisplay name for objective
display_slotNoDisplay slot for scoreboard
fade_inNoFade in duration in ticks (default: 10)
fade_outNoFade out duration in ticks (default: 20)
messageNoAction bar message
objective_idNoScoreboard objective ID
player_nameNoTarget player name (optional, defaults to local player)
scoreNoScore value
sort_orderNoSort order for scoreboard
stayNoStay duration in ticks (default: 70)
stepsNoArray of system actions for sequence. Each step should have "category" and "action" fields and relevant parameters.
subtitleNoSubtitle text
titleNoTitle text

Implementation Reference

  • Main handler function 'execute' that dispatches 'system' tool operations based on category: scoreboard, screen, or sequence.
    async execute(args: {
        category: string;
        action: string;
        objective_id?: string;
        display_name?: string;
        player_name?: string;
        score?: number;
        display_slot?: string;
        sort_order?: string;
        title?: string;
        subtitle?: string;
        message?: string;
        fade_in?: number;
        stay?: number;
        fade_out?: number;
        steps?: SequenceStep[];
    }): Promise<ToolCallResult> {
        if (!this.world) {
            return { success: false, message: 'World not available for system operations.' };
        }
    
        try {
            const { category, action } = args;
    
            switch (category) {
                case 'scoreboard':
                    return await this.executeScoreboardOperation(action, args);
                case 'screen':
                    return await this.executeScreenOperation(action, args);
                case 'sequence':
                    if (!args.steps) {
                        return this.createErrorResponse('steps array is required for sequence category');
                    }
                    return await this.executeSequence(args.steps as SequenceStep[]);
                default:
                    return { success: false, message: `Unknown category: ${category}. Use: scoreboard, screen, sequence` };
            }
    
        } catch (error) {
            return {
                success: false,
                message: `System operation error: ${error instanceof Error ? error.message : String(error)}`
            };
        }
    }
  • Input schema defining parameters for categories (scoreboard, screen, sequence) and their actions.
    readonly inputSchema: InputSchema = {
        type: 'object',
        properties: {
            category: {
                type: 'string',
                description: 'System category to use',
                enum: ['scoreboard', 'screen', 'sequence']
            },
            action: {
                type: 'string',
                description: 'Action to perform within the category'
            },
            // Scoreboard parameters
            objective_id: {
                type: 'string',
                description: 'Scoreboard objective ID'
            },
            display_name: {
                type: 'string',
                description: 'Display name for objective'
            },
            player_name: {
                type: 'string',
                description: 'Target player name (optional, defaults to local player)'
            },
            score: {
                type: 'number',
                description: 'Score value'
            },
            display_slot: {
                type: 'string',
                description: 'Display slot for scoreboard',
                enum: ['sidebar', 'list', 'belowname']
            },
            sort_order: {
                type: 'string',
                description: 'Sort order for scoreboard',
                enum: ['ascending', 'descending']
            },
            // Screen display parameters
            title: {
                type: 'string',
                description: 'Title text'
            },
            subtitle: {
                type: 'string',
                description: 'Subtitle text'
            },
            message: {
                type: 'string',
                description: 'Action bar message'
            },
            fade_in: {
                type: 'number',
                description: 'Fade in duration in ticks (default: 10)',
                default: 10
            },
            stay: {
                type: 'number',
                description: 'Stay duration in ticks (default: 70)',
                default: 70
            },
            fade_out: {
                type: 'number',
                description: 'Fade out duration in ticks (default: 20)',
                default: 20
            },
            steps: {
                type: 'array',
                description: 'Array of system actions for sequence. Each step should have "category" and "action" fields and relevant parameters.'
            }
        },
        required: ['category', 'action']
    };
  • Handler for scoreboard operations including create/edit/delete objectives, set/get scores, display settings.
    private async executeScoreboardOperation(action: string, args: any): Promise<ToolCallResult> {
        const scoreboard = this.world!.scoreboard;
        let result: any;
        let message: string;
    
        switch (action) {
            case 'list_objectives':
                result = await scoreboard.getObjectives();
                message = 'Scoreboard objectives listed';
                break;
    
            case 'create_objective':
                if (!args.objective_id) return { success: false, message: 'objective_id required for create_objective' };
                result = await scoreboard.addObjective(args.objective_id, args.display_name);
                message = `Objective ${args.objective_id} created`;
                break;
    
            case 'remove_objective':
                if (!args.objective_id) return { success: false, message: 'objective_id required for remove_objective' };
                result = await scoreboard.removeObjective(args.objective_id);
                message = `Objective ${args.objective_id} removed`;
                break;
    
            case 'get_score':
                if (!args.objective_id) return { success: false, message: 'objective_id required for get_score' };
                const targetForGet = args.player_name || this.world!.localPlayer?.name;
                if (!targetForGet) return { success: false, message: 'No player available' };
                result = await scoreboard.getScore(targetForGet, args.objective_id);
                message = `Score retrieved for ${targetForGet} in ${args.objective_id}: ${result}`;
                break;
    
            case 'set_score':
                if (!args.objective_id || args.score === undefined) {
                    return { success: false, message: 'objective_id and score required for set_score' };
                }
                const targetForSet = args.player_name || this.world!.localPlayer?.name;
                if (!targetForSet) return { success: false, message: 'No player available' };
                result = await scoreboard.setScore(targetForSet, args.objective_id, args.score);
                message = `Score set to ${args.score} for ${targetForSet} in ${args.objective_id}`;
                break;
    
            case 'add_score':
                if (!args.objective_id || args.score === undefined) {
                    return { success: false, message: 'objective_id and score required for add_score' };
                }
                const targetForAdd = args.player_name || this.world!.localPlayer?.name;
                if (!targetForAdd) return { success: false, message: 'No player available' };
                result = await scoreboard.addScore(targetForAdd, args.objective_id, args.score);
                message = `Added ${args.score} to ${targetForAdd} in ${args.objective_id}`;
                break;
    
            case 'remove_score':
                if (!args.objective_id || args.score === undefined) {
                    return { success: false, message: 'objective_id and score required for remove_score' };
                }
                const targetForRemove = args.player_name || this.world!.localPlayer?.name;
                if (!targetForRemove) return { success: false, message: 'No player available' };
                result = await scoreboard.removeScore(targetForRemove, args.objective_id, args.score);
                message = `Removed ${args.score} from ${targetForRemove} in ${args.objective_id}`;
                break;
    
            case 'reset_score':
                const targetForReset = args.player_name || this.world!.localPlayer?.name;
                if (!targetForReset) return { success: false, message: 'No player available' };
                await scoreboard.resetScore(targetForReset, args.objective_id);
                message = `Score reset for ${targetForReset}`;
                break;
    
            case 'set_display':
                if (!args.display_slot) return { success: false, message: 'display_slot required for set_display' };
                await scoreboard.setDisplay(args.display_slot as any, args.objective_id, args.sort_order as any);
                message = `Display set for ${args.display_slot}`;
                break;
    
            case 'get_all_scores':
                const targetForAll = args.player_name || this.world!.localPlayer?.name;
                if (!targetForAll) return { success: false, message: 'No player available' };
                result = await scoreboard.getScores(targetForAll);
                message = `All scores retrieved for ${targetForAll}`;
                break;
    
            default:
                return { success: false, message: `Unknown scoreboard action: ${action}` };
        }
    
        return {
            success: true,
            message: message,
            data: { category: 'scoreboard', action, result, timestamp: Date.now() }
        };
    }
  • Handler for screen display operations like titles, subtitles, action bars with fade timings.
    private async executeScreenOperation(action: string, args: any): Promise<ToolCallResult> {
        // Get target player
        let player = this.world!.localPlayer;
        if (args.player_name) {
            const players = await this.world!.getPlayers();
            const targetPlayer = players.find(p => p.name === args.player_name);
            if (!targetPlayer) {
                return { success: false, message: `Player ${args.player_name} not found` };
            }
            player = targetPlayer;
        }
    
        // Null check for player
        if (!player) {
            return { success: false, message: 'No player available' };
        }
    
        const screen = player.onScreenDisplay;
        let message: string;
        let result: any;
    
        switch (action) {
            case 'show_title':
                if (!args.title) return { success: false, message: 'title required for show_title' };
                const titleOptions = {
                    subtitle: args.subtitle,
                    times: {
                        fadeIn: args.fade_in || 10,
                        stay: args.stay || 70,
                        fadeOut: args.fade_out || 20
                    }
                };
                await screen.setTitle(args.title, titleOptions);
                message = `Title displayed to ${player.name}: "${args.title}"`;
                if (args.subtitle) message += ` with subtitle: "${args.subtitle}"`;
                break;
    
            case 'update_subtitle':
                if (!args.subtitle) return { success: false, message: 'subtitle required for update_subtitle' };
                await screen.updateSubtitle(args.subtitle);
                message = `Subtitle updated for ${player.name}: "${args.subtitle}"`;
                break;
    
            case 'show_action_bar':
                if (!args.message) return { success: false, message: 'message required for show_action_bar' };
                await screen.setActionBar(args.message);
                message = `Action bar shown to ${player.name}: "${args.message}"`;
                break;
    
            case 'set_title_duration':
                if (args.fade_in === undefined || args.stay === undefined || args.fade_out === undefined) {
                    return { success: false, message: 'fade_in, stay, and fade_out required for set_title_duration' };
                }
                await screen.setTitleDuration({
                    fadeIn: args.fade_in,
                    stay: args.stay,
                    fadeOut: args.fade_out
                });
                message = `Title duration set for ${player.name}: fadeIn=${args.fade_in}, stay=${args.stay}, fadeOut=${args.fade_out}`;
                break;
    
            case 'clear_title':
                await screen.clearTitle();
                message = `Title cleared for ${player.name}`;
                break;
    
            case 'reset_title':
                await screen.resetTitle();
                message = `Title reset for ${player.name}`;
                break;
    
            case 'check_screen_valid':
                result = screen.isValid;
                message = `Screen display validity checked for ${player.name}: ${result}`;
                break;
    
            default:
                return { success: false, message: `Unknown screen action: ${action}` };
        }
    
        return {
            success: true,
            message: message,
            data: { category: 'screen', action, result, targetPlayer: player.name, timestamp: Date.now() }
        };
    }
  • src/server.ts:348-372 (registration)
    Instantiation of SystemTool in the tools array, which is later registered to MCP server.
    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(), // ✅ 新規追加(可変制御点ベジェ曲線)
    ];
  • src/server.ts:30-30 (registration)
    Import of SystemTool class.
    import { SystemTool } from "./tools/core/system";
  • src/server.ts:492-573 (registration)
    Generic registration loop that registers all tools including 'system' to the MCP server.
    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}`,
                },
              ],
            };
          }
        }
      );
    });
Install Server

Other Tools

Related Tools

  • @Mming-Lab/minecraft-bedrock-mcp-server
  • @Mming-Lab/minecraft-bedrock-mcp-server
  • @Mming-Lab/minecraft-bedrock-mcp-server
  • @Mming-Lab/minecraft-bedrock-mcp-server
  • @Mming-Lab/minecraft-bedrock-mcp-server
  • @Mming-Lab/minecraft-bedrock-mcp-server

Latest Blog Posts

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