Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public ClaudeCodeConfigurator() : base(new McpClient
public override IList<string> GetInstallationSteps() => new List<string>
{
"Ensure Claude CLI is installed (comes with Claude Code)",
"Click Register to add UnityMCP via 'claude mcp add'",
"Click Configure to add UnityMCP via 'claude mcp add'",
"The server will be automatically available in Claude Code",
"Use Unregister to remove via 'claude mcp remove'"
};
Expand Down
553 changes: 406 additions & 147 deletions MCPForUnity/Editor/Clients/McpClientConfiguratorBase.cs

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions MCPForUnity/Editor/Models/McpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public string GetStatusDisplayString()
McpStatus.UnsupportedOS => "Unsupported OS",
McpStatus.MissingConfig => "Missing MCPForUnity Config",
McpStatus.Error => configStatus?.StartsWith("Error:") == true ? configStatus : "Error",
McpStatus.VersionMismatch => "Version Mismatch",
_ => "Unknown",
};
}
Expand All @@ -44,9 +45,9 @@ public void SetStatus(McpStatus newStatus, string errorDetails = null)
{
status = newStatus;

if (newStatus == McpStatus.Error && !string.IsNullOrEmpty(errorDetails))
if ((newStatus == McpStatus.Error || newStatus == McpStatus.VersionMismatch) && !string.IsNullOrEmpty(errorDetails))
{
configStatus = $"Error: {errorDetails}";
configStatus = errorDetails;
}
else
{
Expand Down
1 change: 1 addition & 0 deletions MCPForUnity/Editor/Models/McpStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum McpStatus
MissingConfig, // Config file exists but missing required elements
UnsupportedOS, // OS is not supported
Error, // General error state
VersionMismatch, // Configuration version doesn't match expected version
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ public class McpClientConfigSection
/// </summary>
public event Action<string, ConfiguredTransport> OnClientTransportDetected;

/// <summary>
/// Fired when a config mismatch is detected (e.g., version mismatch).
/// The parameter contains the client name and the mismatch message (null if no mismatch).
/// </summary>
public event Action<string, string> OnClientConfigMismatch;

public VisualElement Root { get; private set; }

public McpClientConfigSection(VisualElement root)
Expand Down Expand Up @@ -167,6 +173,7 @@ private string GetStatusDisplayString(McpStatus status)
McpStatus.UnsupportedOS => "Unsupported OS",
McpStatus.MissingConfig => "Missing MCPForUnity Config",
McpStatus.Error => "Error",
McpStatus.VersionMismatch => "Version Mismatch",
_ => "Unknown",
};
}
Expand Down Expand Up @@ -286,7 +293,7 @@ private void ConfigureClaudeCliAsync(IMcpClientConfigurator client)

statusRefreshInFlight.Add(client);
bool isCurrentlyConfigured = client.Status == McpStatus.Configured;
ApplyStatusToUi(client, showChecking: true, customMessage: isCurrentlyConfigured ? "Unregistering..." : "Registering...");
ApplyStatusToUi(client, showChecking: true, customMessage: isCurrentlyConfigured ? "Unregistering..." : "Configuring...");

// Capture ALL main-thread-only values before async task
string projectDir = Path.GetDirectoryName(Application.dataPath);
Expand Down Expand Up @@ -581,6 +588,8 @@ private void ApplyStatusToUi(IMcpClientConfigurator client, bool showChecking =
case McpStatus.IncorrectPath:
case McpStatus.CommunicationError:
case McpStatus.NoResponse:
case McpStatus.Error:
case McpStatus.VersionMismatch:
clientStatusIndicator.AddToClassList("warning");
break;
default:
Expand All @@ -594,6 +603,19 @@ private void ApplyStatusToUi(IMcpClientConfigurator client, bool showChecking =

// Notify listeners about the client's configured transport
OnClientTransportDetected?.Invoke(client.DisplayName, client.ConfiguredTransport);

// Notify listeners about version mismatch if applicable
if (client.Status == McpStatus.VersionMismatch && client is McpClientConfiguratorBase baseConfigurator)
{
// Get the mismatch reason from the configStatus field
string mismatchReason = baseConfigurator.Client.configStatus;
OnClientConfigMismatch?.Invoke(client.DisplayName, mismatchReason);
}
else
{
// Clear any previous mismatch warning
OnClientConfigMismatch?.Invoke(client.DisplayName, null);
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ private enum TransportProtocol
private EnumField transportDropdown;
private VisualElement transportMismatchWarning;
private Label transportMismatchText;
private VisualElement versionMismatchWarning;
private Label versionMismatchText;
private VisualElement httpUrlRow;
private VisualElement httpServerControlRow;
private Foldout manualCommandFoldout;
Expand Down Expand Up @@ -86,6 +88,8 @@ private void CacheUIElements()
transportDropdown = Root.Q<EnumField>("transport-dropdown");
transportMismatchWarning = Root.Q<VisualElement>("transport-mismatch-warning");
transportMismatchText = Root.Q<Label>("transport-mismatch-text");
versionMismatchWarning = Root.Q<VisualElement>("version-mismatch-warning");
versionMismatchText = Root.Q<Label>("version-mismatch-text");
httpUrlRow = Root.Q<VisualElement>("http-url-row");
httpServerControlRow = Root.Q<VisualElement>("http-server-control-row");
manualCommandFoldout = Root.Q<Foldout>("manual-command-foldout");
Expand Down Expand Up @@ -1023,6 +1027,35 @@ public void ClearTransportMismatchWarning()
transportMismatchWarning?.RemoveFromClassList("visible");
}

/// <summary>
/// Updates the version mismatch warning banner based on the client's configuration status.
/// Shows a warning if the client is registered with a different package version than expected.
/// </summary>
/// <param name="clientName">The display name of the client being checked.</param>
/// <param name="mismatchMessage">The mismatch message, or null if no mismatch.</param>
public void UpdateVersionMismatchWarning(string clientName, string mismatchMessage)
{
if (versionMismatchWarning == null || versionMismatchText == null)
return;

if (string.IsNullOrEmpty(mismatchMessage))
{
versionMismatchWarning.RemoveFromClassList("visible");
return;
}

versionMismatchText.text = $"⚠ {clientName}: {mismatchMessage}";
versionMismatchWarning.AddToClassList("visible");
}

/// <summary>
/// Clears the version mismatch warning banner.
/// </summary>
public void ClearVersionMismatchWarning()
{
versionMismatchWarning?.RemoveFromClassList("visible");
}

private static string TransportDisplayName(ConfiguredTransport transport)
{
return transport switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<ui:VisualElement name="transport-mismatch-warning" class="warning-banner">
<ui:Label name="transport-mismatch-text" class="warning-banner-text" />
</ui:VisualElement>
<ui:VisualElement name="version-mismatch-warning" class="warning-banner">
<ui:Label name="version-mismatch-text" class="warning-banner-text" />
</ui:VisualElement>
<ui:VisualElement class="setting-row" name="http-url-row">
<ui:Label text="HTTP URL:" class="setting-label" />
<ui:TextField name="http-url" class="url-field" />
Expand Down
8 changes: 8 additions & 0 deletions MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ public void CreateGUI()
// update the connection section's warning banner if there's a mismatch
clientConfigSection.OnClientTransportDetected += (clientName, transport) =>
connectionSection?.UpdateTransportMismatchWarning(clientName, transport);

// Wire up version mismatch detection: when client status is checked,
// update the connection section's warning banner if there's a version mismatch
clientConfigSection.OnClientConfigMismatch += (clientName, mismatchMessage) =>
connectionSection?.UpdateVersionMismatchWarning(clientName, mismatchMessage);
}

// Load and initialize Validation section
Expand Down Expand Up @@ -263,6 +268,7 @@ public void CreateGUI()
await connectionSection.VerifyBridgeConnectionAsync();
};
advancedSection.OnBetaModeChanged += UpdateVersionLabel;
advancedSection.OnBetaModeChanged += _ => clientConfigSection?.RefreshSelectedClient(forceImmediate: true);

// Wire up health status updates from Connection to Advanced
connectionSection?.SetHealthStatusUpdateCallback((isHealthy, statusText) =>
Expand Down Expand Up @@ -552,6 +558,8 @@ private void SwitchPanel(ActivePanel panel)
{
case ActivePanel.Clients:
if (clientsPanel != null) clientsPanel.style.display = DisplayStyle.Flex;
// Refresh client status when switching to Connect tab (e.g., after changing beta mode in Advanced)
clientConfigSection?.RefreshSelectedClient(forceImmediate: true);
break;
case ActivePanel.Validation:
if (validationPanel != null) validationPanel.style.display = DisplayStyle.Flex;
Expand Down