diff --git a/MinecraftClient/Mcp/MccMcpGuidanceProvider.cs b/MinecraftClient/Mcp/MccMcpGuidanceProvider.cs index 285a6d31..232c1bd1 100644 --- a/MinecraftClient/Mcp/MccMcpGuidanceProvider.cs +++ b/MinecraftClient/Mcp/MccMcpGuidanceProvider.cs @@ -10,7 +10,7 @@ namespace MinecraftClient.Mcp; public sealed class MccMcpGuidanceProvider { - private const string EmbeddedSkillResourceSuffix = "MccMcpOperatorSkill.md"; + private const string EmbeddedPromptResourceSuffix = "MccMcpOperatorPrompt.md"; private const string BestPracticesHeading = "## Best Practices"; private const string ExampleScenariosHeading = "## Example Scenarios"; @@ -23,7 +23,7 @@ public sealed class MccMcpGuidanceProvider guidanceDocument = new Lazy(LoadGuidanceDocument); } - public string SkillName => "mcc-mcp-operator"; + public string PromptName => "mcc_operator_prompt"; public string GetSystemPrompt() { @@ -31,7 +31,7 @@ public sealed class MccMcpGuidanceProvider MccMcpAgentCapabilityStatus capabilityStatus = BuildCapabilityStatus(); StringBuilder builder = new(); builder.AppendLine("You are an external agent controlling Minecraft Console Client (MCC) through its built-in MCP server."); - builder.AppendLine("Use the following operator guide as your system prompt. Treat the capability snapshot as authoritative and do not invent unsupported actions."); + builder.AppendLine("Use the following MCP Operator Prompt as your system prompt. Treat the capability snapshot as authoritative and do not invent unsupported actions."); builder.AppendLine(); builder.AppendLine(document.BodyMarkdown); builder.AppendLine(); @@ -49,8 +49,8 @@ public sealed class MccMcpGuidanceProvider GuidanceDocument document = guidanceDocument.Value; return new MccMcpAgentGuidancePayload { - SkillName = SkillName, - SkillMarkdown = document.SkillMarkdown, + PromptName = PromptName, + PromptMarkdown = document.PromptMarkdown, SystemPrompt = GetSystemPrompt(), BestPractices = document.BestPractices, ExampleScenarios = document.ExampleScenarios, @@ -62,21 +62,21 @@ public sealed class MccMcpGuidanceProvider { Assembly assembly = typeof(MccMcpGuidanceProvider).Assembly; string resourceName = assembly.GetManifestResourceNames() - .FirstOrDefault(name => name.EndsWith(EmbeddedSkillResourceSuffix, StringComparison.Ordinal)) - ?? throw new InvalidOperationException($"Embedded MCP skill resource '{EmbeddedSkillResourceSuffix}' was not found."); + .FirstOrDefault(name => name.EndsWith(EmbeddedPromptResourceSuffix, StringComparison.Ordinal)) + ?? throw new InvalidOperationException($"Embedded MCP operator prompt resource '{EmbeddedPromptResourceSuffix}' was not found."); using Stream? stream = assembly.GetManifestResourceStream(resourceName); if (stream is null) - throw new InvalidOperationException($"Embedded MCP skill resource '{resourceName}' could not be opened."); + throw new InvalidOperationException($"Embedded MCP operator prompt resource '{resourceName}' could not be opened."); using StreamReader reader = new(stream, Encoding.UTF8); - string skillMarkdown = reader.ReadToEnd(); - string bodyMarkdown = StripFrontmatter(skillMarkdown); + string promptMarkdown = reader.ReadToEnd(); + string bodyMarkdown = StripFrontmatter(promptMarkdown); string bestPracticesSection = ExtractSection(bodyMarkdown, BestPracticesHeading); string exampleScenariosSection = ExtractSection(bodyMarkdown, ExampleScenariosHeading); return new GuidanceDocument( - skillMarkdown.Replace("\r\n", "\n").Trim(), + promptMarkdown.Replace("\r\n", "\n").Trim(), bodyMarkdown, ExtractBulletList(bestPracticesSection), ExtractExampleScenarios(exampleScenariosSection)); @@ -181,7 +181,7 @@ public sealed class MccMcpGuidanceProvider } private sealed record GuidanceDocument( - string SkillMarkdown, + string PromptMarkdown, string BodyMarkdown, string[] BestPractices, MccMcpAgentScenario[] ExampleScenarios); @@ -189,11 +189,11 @@ public sealed class MccMcpGuidanceProvider public sealed class MccMcpAgentGuidancePayload { - [JsonPropertyName("skillName")] - public string SkillName { get; init; } = string.Empty; + [JsonPropertyName("promptName")] + public string PromptName { get; init; } = string.Empty; - [JsonPropertyName("skillMarkdown")] - public string SkillMarkdown { get; init; } = string.Empty; + [JsonPropertyName("promptMarkdown")] + public string PromptMarkdown { get; init; } = string.Empty; [JsonPropertyName("systemPrompt")] public string SystemPrompt { get; init; } = string.Empty; diff --git a/MinecraftClient/Mcp/MccMcpPromptSet.cs b/MinecraftClient/Mcp/MccMcpPromptSet.cs index 564e6f7f..970528a6 100644 --- a/MinecraftClient/Mcp/MccMcpPromptSet.cs +++ b/MinecraftClient/Mcp/MccMcpPromptSet.cs @@ -12,8 +12,8 @@ public sealed class MccMcpPromptSet this.guidanceProvider = guidanceProvider; } - [McpServerPrompt(Name = "mcc_operator_guide"), Description("Get the canonical MCC operator guidance prompt for external agents using this MCP server.")] - public string OperatorGuide() + [McpServerPrompt(Name = "mcc_operator_prompt"), Description("Get the canonical MCC MCP Operator Prompt for external agents using this MCP server.")] + public string OperatorPrompt() { return guidanceProvider.GetSystemPrompt(); } diff --git a/MinecraftClient/Mcp/MccMcpToolSet.cs b/MinecraftClient/Mcp/MccMcpToolSet.cs index 8da6b413..84305e34 100644 --- a/MinecraftClient/Mcp/MccMcpToolSet.cs +++ b/MinecraftClient/Mcp/MccMcpToolSet.cs @@ -105,7 +105,7 @@ public sealed class MccMcpToolSet return capabilities.GetInternalCommands(); } - [McpServerTool(Name = "mcc_agent_guidance"), Description("Get the canonical MCC operator guidance bundle for external agents using this MCP server.")] + [McpServerTool(Name = "mcc_agent_guidance"), Description("Get the canonical MCC MCP Operator Prompt bundle for external agents using this MCP server.")] public object AgentGuidance() { return guidanceProvider.GetToolPayload(); diff --git a/.skills/mcc-mcp-operator/SKILL.md b/MinecraftClient/Mcp/Prompts/MccMcpOperatorPrompt.md similarity index 62% rename from .skills/mcc-mcp-operator/SKILL.md rename to MinecraftClient/Mcp/Prompts/MccMcpOperatorPrompt.md index 2e2e734a..b2dabd79 100644 --- a/.skills/mcc-mcp-operator/SKILL.md +++ b/MinecraftClient/Mcp/Prompts/MccMcpOperatorPrompt.md @@ -1,9 +1,4 @@ ---- -name: mcc-mcp-operator -description: Operate Minecraft Console Client through the built-in MCP server. Use this whenever the user wants an agent to inspect MCC state, move, search the world, interact with players or entities, dig, pick up items, manage containers, or carry out Minecraft tasks through MCP tools, even if they do not explicitly say "use MCP" or "control MCC". Prefer this skill over ad hoc tool guessing for agentic MCC and Minecraft control work. ---- - -# MCC MCP Operator +# MCC MCP Operator Prompt Use the MCC MCP toolset as the source of truth for game state and action results. Do not guess what happened from intent alone. @@ -21,20 +16,31 @@ If the request is purely conversational and does not require MCC state, answer d ## Tool Selection Rules - Start with `mcc_session_status` whenever connection state, enabled capabilities, or feature availability is uncertain. -- Prefer direct inspection tools such as `mcc_player_state`, `mcc_players_list`, `mcc_entities_list`, `mcc_blocks_find`, `mcc_items_list`, and `mcc_inventory_snapshot` before taking physical actions. +- Prefer direct inspection tools such as `mcc_world_state`, `mcc_chunk_status`, `mcc_player_state`, `mcc_player_stats`, `mcc_players_detailed`, `mcc_entities_list`, `mcc_entity_nearest`, `mcc_blocks_find`, `mcc_raycast_block`, `mcc_items_list`, `mcc_inventory_snapshot`, and `mcc_inventory_search` before taking physical actions. - Prefer purpose-built action tools over low-level escape hatches. - Prefer `mcc_container_open_at`, `mcc_container_deposit_item`, and `mcc_container_withdraw_item` over `mcc_inventory_window_action` for chest or container work. -- Use `mcc_can_reach_position` or a locating tool before pathing when reachability is uncertain. +- Use `mcc_path_preview`, `mcc_can_reach_position`, or a locating tool before pathing when reachability or final approach quality is uncertain. +- Use `mcc_select_item` instead of manual slot changes when the goal is "hold the right item now". +- Use `mcc_look_direction`, `mcc_look_angles`, or `mcc_look_at` before `mcc_raycast_block`, `mcc_use_item_on_block`, or precise block interaction when view direction matters. +- Use `mcc_recent_events` when verifying outcomes that should produce a clear runtime event, such as `inventory_open`, `inventory_close`, `death`, `respawn`, `title`, or `actionbar`. +- Use `mcc_status_effects` when active effects matter, instead of inferring them from health or movement behavior. +- Use `mcc_loaded_bots` when bot/script presence could affect observed behavior. - Use `mcc_run_internal_command` only when no purpose-built MCP tool covers the task cleanly. - Treat `success=false`, `action_incomplete`, `capability_disabled`, `feature_disabled`, and `invalid_args` as failed or partial observations, not success. - After `invalid_args`, simplify the call and try at most one nearby variant. Do not spam near-duplicate guesses. ## Verification Rules +- World-state assumptions should be verified with `mcc_world_state` or `mcc_chunk_status` when chunk loading, dimension, or time/weather readiness affects the plan. - Movement is not complete just because a move request was accepted. Confirm `arrived=true` or verify the new location with a fresh state read. +- A path preview is not proof of arrival. Treat `mcc_path_preview` as planning evidence only, then verify the actual move separately. - Digging is not complete just because `mcc_dig_block` was invoked. Re-check the target block or nearby block search results. +- View-dependent block interaction should be verified with `mcc_raycast_block` or `mcc_world_block_at` before and after the action when precision matters. - Item pickup is not complete just because the bot moved over an item. Re-check inventory state or nearby dropped-item entities. +- Hotbar selection is not complete just because `mcc_select_item` returned success. Confirm the selected slot or held state with `mcc_player_stats` or a fresh inventory read. - Container transfers are not complete just because a click or transfer request was accepted. Verify the resulting counts after the transfer. +- Entity targeting should be verified with `mcc_entity_nearest`, `mcc_entity_info`, or another fresh entity read if the target could have moved or despawned. +- Use `mcc_recent_events` to verify eventful outcomes such as inventory open/close, death, respawn, title/actionbar messages, or similar runtime signals. - Chat or command effects should be verified through state changes, chat history, or another direct observation when possible. - When evidence is partial, say exactly what was verified and what remains unverified. @@ -43,6 +49,7 @@ If the request is purely conversational and does not require MCC state, answer d - Query first, act second, verify third. - Keep plans short and concrete. Long speculative tool chains usually make the result worse. - Prefer high-signal tools that answer the real question directly. +- Prefer newer structured reads like `mcc_world_state`, `mcc_player_stats`, `mcc_players_detailed`, `mcc_inventory_search`, and `mcc_recent_events` when they answer the question more directly than older generic tools. - Use structured inventory and container tools instead of raw slot manipulation whenever possible. - Do not claim success from acceptance alone. Always pair actions with a follow-up observation. - Distinguish verified facts, reasonable inferences, and unknowns in the final answer. @@ -59,9 +66,9 @@ User intent: "Find Zarko and move near them." Good flow: - call `mcc_player_locate` or `mcc_players_list` to confirm the player is known -- if needed, call `mcc_can_reach_position` for the target area +- if needed, call `mcc_players_detailed` for exact coordinates and `mcc_path_preview` or `mcc_can_reach_position` for the target area - call `mcc_move_to_player` -- verify `arrived=true` or confirm the new position with `mcc_player_state` +- verify `arrived=true` or confirm the new position with `mcc_player_stats` - report whether proximity was verified or only partially achieved ### Open a chest, move an exact item count, and verify the result @@ -70,9 +77,9 @@ User intent: "Put 5 diamonds in the chest at 11000 64 11021." Good flow: - call `mcc_container_open_at` -- inspect current state with `mcc_inventory_snapshot` if item availability is unclear +- inspect current state with `mcc_inventory_search` or `mcc_inventory_snapshot` if item availability is unclear - call `mcc_container_deposit_item` or `mcc_container_withdraw_item` -- verify the resulting counts from the transfer result and, when useful, a fresh inventory snapshot +- verify the resulting counts from the transfer result and, when useful, a fresh inventory snapshot or `mcc_recent_events` - report the exact verified delta, not just that the action was attempted ### Collect nearby dropped items or dig target blocks and verify the outcome @@ -80,7 +87,7 @@ Good flow: User intent: "Pick up nearby apples" or "Break those logs and collect them." Good flow: -- call `mcc_items_list` or `mcc_blocks_find` to locate the target +- call `mcc_items_list`, `mcc_blocks_find`, or `mcc_raycast_block` to locate the target - move only if the target is not already reachable from the current position - call `mcc_items_pickup` for dropped items, or `mcc_dig_block` in a sensible order for blocks - verify the result with `mcc_items_list`, `mcc_inventory_snapshot`, or a fresh block query diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 68b31912..4fdf6c94 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -20,7 +20,7 @@ - +