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}`,
                },
              ],
            };
          }
        }
      );
    });
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden for behavioral disclosure. The description fails to indicate whether this tool performs read-only operations, mutations, or both. It doesn't mention permissions needed, side effects, error conditions, or what happens when operations are performed. For a complex 15-parameter tool with no annotations, this is a critical gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief (8 words) but under-specified rather than concise. It's structured as a feature list without clear organization. While not verbose, it fails to communicate essential information, making its brevity a liability rather than a strength.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 15 parameters, no annotations, and no output schema, the description is completely inadequate. It doesn't explain what the tool does, when to use it, what behaviors to expect, or how parameters interact. The feature list provides minimal context that doesn't help an agent understand this tool's role in the system.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no parameter-specific information beyond what's in the schema. The baseline score of 3 reflects adequate schema coverage, but the description contributes zero additional parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description lists system features (scoreboards, screen displays, player UI, game management) but doesn't state what the tool actually does. It's a vague feature list rather than specifying a verb+resource action. The name 'system' is generic, and the description doesn't clarify whether this is for configuring, querying, or manipulating these features.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. The description provides no context about appropriate use cases, prerequisites, or distinctions from sibling tools like 'player', 'sequence', or 'send_message' that might overlap with UI/messaging functionality.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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