Skip to main content
Glama

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

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