Minecraft-Console-Client/MinecraftClient/ChatBots/McpServer.cs

147 lines
4.5 KiB
C#

using System;
using MinecraftClient.Mcp;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
public class McpServer : ChatBot
{
public static Configs Config = new();
[TomlDoNotInlineObject]
public class Configs
{
[NonSerialized]
private const string BotName = "McpServer";
[TomlInlineComment("$ChatBot.McpServer.Enabled$")]
public bool Enabled = false;
[TomlPrecedingComment("$ChatBot.McpServer.Transport$")]
public MccMcpTransportConfig Transport = new();
[TomlPrecedingComment("$ChatBot.McpServer.Capabilities$")]
public MccMcpCapabilityToggles Capabilities = new();
public void OnSettingUpdate()
{
Transport ??= new MccMcpTransportConfig();
Capabilities ??= new MccMcpCapabilityToggles();
if (Transport.Port is < 1 or > 65535)
Transport.Port = 33333;
if (string.IsNullOrWhiteSpace(Transport.BindHost))
Transport.BindHost = "127.0.0.1";
if (string.IsNullOrWhiteSpace(Transport.Route))
Transport.Route = "/mcp";
if (!Transport.Route.StartsWith('/'))
Transport.Route = "/" + Transport.Route;
if (string.IsNullOrWhiteSpace(Transport.AuthTokenEnvVar))
Transport.AuthTokenEnvVar = "MCC_MCP_AUTH_TOKEN";
}
}
private MccEmbeddedMcpHost? host;
public override void Initialize()
{
Config.OnSettingUpdate();
}
public override void AfterGameJoined()
{
if (!Config.Enabled)
return;
MccMcpChatHistoryStore.Clear();
MccMcpConfig mcpConfig = new()
{
Enabled = Config.Enabled,
Transport = Config.Transport,
Capabilities = Config.Capabilities
};
host ??= new MccEmbeddedMcpHost(mcpConfig, new MccMcpCapabilities(() => Config.Capabilities));
if (host.IsRunning)
return;
LogToConsole(Translations.bot_mcpserver_starting);
if (!host.Start(out string? error))
{
if (error == "missing_auth_token")
LogToConsole(string.Format(Translations.bot_mcpserver_missing_auth_token, Config.Transport.AuthTokenEnvVar));
LogToConsole(string.Format(Translations.bot_mcpserver_start_failed, error ?? "unknown"));
return;
}
LogToConsole(string.Format(Translations.bot_mcpserver_started, host.Endpoint));
}
public override bool OnDisconnect(DisconnectReason reason, string message)
{
StopHost();
MccMcpChatHistoryStore.Clear();
return false;
}
public override void OnUnload()
{
StopHost();
MccMcpChatHistoryStore.Clear();
}
public override void GetText(string text, string? json)
{
string clean = GetVerbatim(text);
if (string.IsNullOrWhiteSpace(clean))
return;
string kind = "system";
string? sender = null;
string? message = null;
string parsedMessage = string.Empty;
string parsedSender = string.Empty;
if (IsPrivateMessage(clean, ref parsedMessage, ref parsedSender))
{
kind = "private";
sender = parsedSender;
message = parsedMessage;
}
else if (IsChatMessage(clean, ref parsedMessage, ref parsedSender))
{
kind = "chat";
sender = parsedSender;
message = parsedMessage;
}
MccMcpChatHistoryStore.Add(new MccMcpChatHistoryEntry
{
TimestampUtc = DateTimeOffset.UtcNow,
Kind = kind,
Text = clean,
Sender = sender,
Message = message,
Json = json
});
}
private void StopHost()
{
if (host is null || !host.IsRunning)
return;
if (host.Stop(out string? error))
LogToConsole(Translations.bot_mcpserver_stopped);
else
LogToConsole(string.Format(Translations.bot_mcpserver_stop_failed, error ?? "unknown"));
}
}
}