mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Added inventory manipulation to the MCP, improved the test harness
This commit is contained in:
parent
7f9023e7bb
commit
cf382122e9
5 changed files with 948 additions and 7 deletions
|
|
@ -295,16 +295,53 @@ internal sealed class DeterministicCapabilities : IMccMcpCapabilities
|
|||
public MccMcpResult LookAt(double x, double y, double z) =>
|
||||
MccMcpResult.Ok(new { looked = true, x = C(x), y = C(y), z = C(z) });
|
||||
|
||||
public MccMcpResult ListInventories() =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
count = 2,
|
||||
inventories = new object[]
|
||||
{
|
||||
new { id = 0, type = "PlayerInventory", title = "Player Inventory", slotCount = 46, nonEmptySlots = 1, active = false },
|
||||
new { id = 1, type = "Generic_9x3", title = "Chest", slotCount = 63, nonEmptySlots = 2, active = true }
|
||||
}
|
||||
});
|
||||
|
||||
public MccMcpResult GetInventorySnapshot(int inventoryId) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
id = inventoryId,
|
||||
type = inventoryId == 0 ? "PlayerInventory" : "Generic_9x3",
|
||||
title = inventoryId == 0 ? "Player Inventory" : "Chest",
|
||||
slotCount = inventoryId == 0 ? 46 : 63,
|
||||
slots = new[]
|
||||
{
|
||||
new { slot = 0, type = "Stone", count = 64 }
|
||||
}
|
||||
});
|
||||
|
||||
public MccMcpResult OpenContainerAt(int x, int y, int z, int timeoutMs, bool closeCurrent) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
success = true,
|
||||
openAccepted = true,
|
||||
opened = true,
|
||||
timeoutMs = timeoutMs <= 0 ? 5000 : timeoutMs,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
block = new { material = "Chest", typeLabel = "Chest", blockId = 0, blockMeta = 0 },
|
||||
inventory = new { id = 1, type = "Generic_9x3", title = "Chest", slotCount = 63, nonEmptySlots = 2 }
|
||||
});
|
||||
|
||||
public MccMcpResult CloseContainer(int inventoryId, int timeoutMs) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
success = true,
|
||||
closed = true,
|
||||
inventoryId = inventoryId <= 0 ? 1 : inventoryId,
|
||||
timeoutMs = timeoutMs <= 0 ? 5000 : timeoutMs
|
||||
});
|
||||
|
||||
public MccMcpResult InventoryWindowAction(int inventoryId, int slotId, string actionType) =>
|
||||
MccMcpResult.Ok(new { success = true, inventoryId, slotId, actionType });
|
||||
|
||||
|
|
@ -322,6 +359,42 @@ internal sealed class DeterministicCapabilities : IMccMcpCapabilities
|
|||
preferStack
|
||||
});
|
||||
|
||||
public MccMcpResult DepositContainerItem(string itemType, int count, int inventoryId, bool preferLargestStack) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
success = true,
|
||||
direction = "deposit",
|
||||
itemType,
|
||||
requestedCount = count,
|
||||
movedCount = count,
|
||||
beforePlayerCount = 64,
|
||||
afterPlayerCount = Math.Max(0, 64 - count),
|
||||
beforeContainerCount = 0,
|
||||
afterContainerCount = count,
|
||||
inventoryId = inventoryId <= 0 ? 1 : inventoryId,
|
||||
containerType = "Generic_9x3",
|
||||
touchedSourceSlots = new[] { 36 },
|
||||
touchedTargetSlots = new[] { 0 }
|
||||
});
|
||||
|
||||
public MccMcpResult WithdrawContainerItem(string itemType, int count, int inventoryId, bool preferLargestStack) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
success = true,
|
||||
direction = "withdraw",
|
||||
itemType,
|
||||
requestedCount = count,
|
||||
movedCount = count,
|
||||
beforePlayerCount = 0,
|
||||
afterPlayerCount = count,
|
||||
beforeContainerCount = 64,
|
||||
afterContainerCount = Math.Max(0, 64 - count),
|
||||
inventoryId = inventoryId <= 0 ? 1 : inventoryId,
|
||||
containerType = "Generic_9x3",
|
||||
touchedSourceSlots = new[] { 0 },
|
||||
touchedTargetSlots = new[] { 36 }
|
||||
});
|
||||
|
||||
public MccMcpResult QueryEntities(int maxCount) =>
|
||||
MccMcpResult.Ok(new
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.AddHttpClient("openrouter");
|
||||
builder.Services.AddHttpClient("openrouter", client =>
|
||||
{
|
||||
client.Timeout = TimeSpan.FromMinutes(15);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
app.UseDefaultFiles();
|
||||
|
|
@ -46,6 +49,7 @@ Todo policy
|
|||
Tool-use policy
|
||||
- Use MCP tools for MCC/game-state questions and actions.
|
||||
- Prefer the most direct high-signal tool first.
|
||||
- Prefer structured inventory/container tools over raw window-click tools for chest or container management.
|
||||
- If a tool result says success=false or includes an errorCode, treat that as a failed observation even if the transport call itself succeeded.
|
||||
- Do not guess tool arguments repeatedly. If a tool returns invalid_args:
|
||||
- simplify to the minimum required arguments,
|
||||
|
|
@ -73,6 +77,12 @@ Action-specific guidance
|
|||
- dig in a sensible order,
|
||||
- re-check remaining blocks,
|
||||
- re-check inventory or nearby item entities before finishing.
|
||||
- Container inventory:
|
||||
- locate the target container block,
|
||||
- open the container first,
|
||||
- inspect player and container inventory state,
|
||||
- use structured deposit or withdraw tools instead of raw window clicks,
|
||||
- verify both player and container counts changed before finishing.
|
||||
- Search:
|
||||
- start with the most direct search tool,
|
||||
- use the user's requested radius when supported,
|
||||
|
|
@ -97,6 +107,13 @@ Good examples
|
|||
Good:
|
||||
- finish with a short greeting
|
||||
- no MCP tools
|
||||
4) User: "Put 5 diamonds in the chest."
|
||||
Good:
|
||||
- open the chest
|
||||
- inspect inventory state
|
||||
- deposit exactly 5 diamonds
|
||||
- verify the chest count increased and player count decreased by 5
|
||||
- then finish
|
||||
|
||||
Wrong examples
|
||||
1) Wrong:
|
||||
|
|
@ -165,9 +182,9 @@ app.MapPost("/api/chat/stream", async (ChatStreamRequest request, IHttpClientFac
|
|||
}
|
||||
|
||||
string model = GetModel();
|
||||
int maxIterations = GetBoundedInt("MCC_WEB_MAX_ITERATIONS", 24, 4, 80);
|
||||
int maxToolCalls = GetBoundedInt("MCC_WEB_MAX_TOOL_CALLS", 80, 4, 256);
|
||||
TimeSpan maxWallTime = TimeSpan.FromSeconds(GetBoundedInt("MCC_WEB_MAX_SECONDS", 120, 10, 300));
|
||||
int maxIterations = GetBoundedInt("MCC_WEB_MAX_ITERATIONS", 96, 4, 256);
|
||||
int maxToolCalls = GetBoundedInt("MCC_WEB_MAX_TOOL_CALLS", 320, 4, 1024);
|
||||
TimeSpan maxWallTime = TimeSpan.FromSeconds(GetBoundedInt("MCC_WEB_MAX_SECONDS", 900, 10, 3600));
|
||||
|
||||
await using McpClient mcp = await CreateMcpClientAsync(cancellationToken);
|
||||
IList<McpClientTool> mcpTools = await mcp.ListToolsAsync(cancellationToken: cancellationToken);
|
||||
|
|
@ -1005,9 +1022,9 @@ Answer:
|
|||
|
||||
static bool ShouldInjectReminder(int iteration, int maxIterations, int toolCallCount, int maxToolCalls, TimeSpan elapsed, TimeSpan maxWallTime)
|
||||
{
|
||||
return iteration >= maxIterations - 2
|
||||
|| toolCallCount >= maxToolCalls - 4
|
||||
|| elapsed >= maxWallTime - TimeSpan.FromSeconds(10);
|
||||
return iteration >= maxIterations - 6
|
||||
|| toolCallCount >= maxToolCalls - 12
|
||||
|| elapsed >= maxWallTime - TimeSpan.FromSeconds(45);
|
||||
}
|
||||
|
||||
static string BuildForcedFinalAnswer(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue