From 641cbd2fb1042c3065720cd3e662dc078022b9d8 Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 16:03:47 -0700 Subject: [PATCH 1/7] feat: add vscode.dev and localhost redirect URIs to public clients app Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index 59cf8d16..9289693b 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -617,7 +617,7 @@ private void DisplayRegistrationSummary(ResolvedInput input) var copilotRedirectUri = $"ms-appx-web://Microsoft.AAD.BrokerPlugin/{publicClientsClientId}"; try { - await _graphApiService.UpdateAppPublicClientRedirectUrisAsync(tenantId, publicClientsObjectId, new[] { copilotRedirectUri, "http://localhost:8080/callback" }); + await _graphApiService.UpdateAppPublicClientRedirectUrisAsync(tenantId, publicClientsObjectId, new[] { copilotRedirectUri, "http://localhost:8080/callback", "https://vscode.dev/redirect", "http://localhost" }); _logger.LogDebug("Set redirect URI on '{AppName}' ({ObjectId}): {Uri}", publicClientsAppName, publicClientsObjectId, copilotRedirectUri); } catch (Exception ex) From e85a421b73d58fdec41f4fd1008ac3cc9a4a42c8 Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 16:06:36 -0700 Subject: [PATCH 2/7] fix: remove unused --config option from register-external-mcp-server command Co-Authored-By: Claude Opus 4.6 --- .../Commands/DevelopMcpCommand.cs | 3 --- .../Commands/DevelopMcpCommandTests.cs | 18 ------------------ 2 files changed, 21 deletions(-) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs index b5d7f916..3695ff7e 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs @@ -850,9 +850,6 @@ private static Command CreateRegisterExternalMcpServerSubcommand( var serviceTreeIdOption = new Option("--service-tree-id", description: "ServiceTree ID for Entra app registration (required in Microsoft corporate tenants)"); command.AddOption(serviceTreeIdOption); - var configOption = new Option(["-c", "--config"], getDefaultValue: () => "a365.config.json", description: "Configuration file path"); - command.AddOption(configOption); - var publisherOption = new Option("--publisher", description: "Publisher name (required, used in MOS package metadata)"); command.AddOption(publisherOption); diff --git a/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs b/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs index 7980cd6a..a78c190e 100644 --- a/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs +++ b/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs @@ -249,20 +249,6 @@ public void AllSubcommands_SupportDryRunOption() } } - [Theory] - [InlineData("register-external-mcp-server")] - public void ConfigDependentSubcommands_SupportConfigOption(string subcommandName) - { - // Act - var command = DevelopMcpCommand.CreateCommand(_mockLogger, _mockToolingService); - var subcommand = command.Subcommands.First(sc => sc.Name == subcommandName); - - // Assert - var configOption = subcommand.Options.FirstOrDefault(o => o.Name == "config"); - configOption.Should().NotBeNull($"Subcommand '{subcommandName}' should have --config option"); - configOption!.Aliases.Should().Contain("-c", $"Config option should have -c alias in '{subcommandName}'"); - } - [Fact] public void RegisterExternalMcpServerSubcommand_HasAllExpectedOptions() { @@ -291,7 +277,6 @@ public void RegisterExternalMcpServerSubcommand_HasAllExpectedOptions() optionNames.Should().Contain("remote-scopes"); optionNames.Should().Contain("tenant-id"); optionNames.Should().Contain("service-tree-id"); - optionNames.Should().Contain("config"); optionNames.Should().Contain("publisher"); optionNames.Should().Contain("description"); optionNames.Should().Contain("dry-run"); @@ -314,9 +299,6 @@ public void RegisterExternalMcpServerSubcommand_HasAllExpectedOptions() var tenantIdOption = options.First(o => o.Name == "tenant-id"); tenantIdOption.Aliases.Should().Contain("-t"); - var configOption = options.First(o => o.Name == "config"); - configOption.Aliases.Should().Contain("-c"); - var verboseOption = options.First(o => o.Name == "verbose"); verboseOption.Aliases.Should().Contain("-v"); } From d5f488e3e553f416c9b355a4320ee512f475a073 Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 18:59:30 -0700 Subject: [PATCH 3/7] fix: show friendly error for duplicate server name registration Detect database constraint violation from the API and display a clean user-facing message instead of raw error details. Raw details are still available with --verbose. Also demote ValidateResponseAsync body-level errors to debug so callers control the user-facing message. Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 18 +++++++++++++++--- .../Services/Agent365ToolingService.cs | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index 9289693b..f4cfd2c3 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -143,15 +143,27 @@ internal async Task ExecuteAsync(RawRegisterArgs args) { _logger.LogError("Failed to register MCP server '{ServerName}': {Error}", input.ServerName, ex.Message); _logger.LogDebug("Exception details: {Exception}", ex.ToString()); - _logger.LogWarning("Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); + _logger.LogWarning("Entra app registrations were NOT rolled back. Use 'cleanup-external-mcp-server-resources' to remove them if needed."); return; } if (addResponse is null || !addResponse.IsSuccess) { var errorMsg = addResponse?.Message ?? "No response received"; - _logger.LogError("Failed to add MCP server {ServerName}: {Error}", input.ServerName, errorMsg); - _logger.LogWarning("Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); + + if (errorMsg.Contains("violates a database constraint", StringComparison.OrdinalIgnoreCase) + || errorMsg.Contains("delete the existing record", StringComparison.OrdinalIgnoreCase)) + { + Console.WriteLine(); + Console.WriteLine($"ERROR: A server named '{input.ServerName}' already exists. Please choose a different name."); + _logger.LogDebug("Raw server error: {Error}", errorMsg); + } + else + { + _logger.LogError("Failed to add MCP server {ServerName}: {Error}", input.ServerName, errorMsg); + } + + Console.WriteLine($"Entra app registrations were NOT rolled back. Use 'cleanup-external-mcp-server-resources' to remove them if needed."); return; } diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs index 462b6606..9d82cea1 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs @@ -97,10 +97,10 @@ public Agent365ToolingService( errorMessage += $" - {statusResponse.Error}"; } - _logger.LogError("{Operation} failed: {Message}", operationName, errorMessage); + _logger.LogDebug("{Operation} failed: {Message}", operationName, errorMessage); if (!string.IsNullOrWhiteSpace(serverCorrelationId)) { - _logger.LogError("Server correlation ID (x-ms-correlation-id): {CorrelationId}", serverCorrelationId); + _logger.LogDebug("Server correlation ID (x-ms-correlation-id): {CorrelationId}", serverCorrelationId); } return (false, responseContent); } From 765b891f4c5271a28a4e74c3f4016a857ccd5d98 Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 19:05:52 -0700 Subject: [PATCH 4/7] fix: show duplicate server name error in red Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index f4cfd2c3..643245fc 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -155,7 +155,10 @@ internal async Task ExecuteAsync(RawRegisterArgs args) || errorMsg.Contains("delete the existing record", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine(); + var prevColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"ERROR: A server named '{input.ServerName}' already exists. Please choose a different name."); + Console.ForegroundColor = prevColor; _logger.LogDebug("Raw server error: {Error}", errorMsg); } else From 421044a820c672973aa0c5a0e38e14cbd6882bb9 Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 19:14:30 -0700 Subject: [PATCH 5/7] fix: remove reference to deleted cleanup command in error messages Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index 643245fc..b9330540 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -143,7 +143,7 @@ internal async Task ExecuteAsync(RawRegisterArgs args) { _logger.LogError("Failed to register MCP server '{ServerName}': {Error}", input.ServerName, ex.Message); _logger.LogDebug("Exception details: {Exception}", ex.ToString()); - _logger.LogWarning("Entra app registrations were NOT rolled back. Use 'cleanup-external-mcp-server-resources' to remove them if needed."); + _logger.LogWarning("Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); return; } @@ -166,7 +166,7 @@ internal async Task ExecuteAsync(RawRegisterArgs args) _logger.LogError("Failed to add MCP server {ServerName}: {Error}", input.ServerName, errorMsg); } - Console.WriteLine($"Entra app registrations were NOT rolled back. Use 'cleanup-external-mcp-server-resources' to remove them if needed."); + Console.WriteLine($"Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); return; } From 0e25c0a7f95ae45b5c532dc0d6c7d0a512f3d7af Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 19:24:36 -0700 Subject: [PATCH 6/7] fix: address PR review - add config negative assertion, log duplicate error, correlation ID at warning Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 1 + .../Services/Agent365ToolingService.cs | 2 +- .../Commands/DevelopMcpCommandTests.cs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index b9330540..1e7f0403 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -159,6 +159,7 @@ internal async Task ExecuteAsync(RawRegisterArgs args) Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"ERROR: A server named '{input.ServerName}' already exists. Please choose a different name."); Console.ForegroundColor = prevColor; + _logger.LogError("A server named '{ServerName}' already exists. Please choose a different name.", input.ServerName); _logger.LogDebug("Raw server error: {Error}", errorMsg); } else diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs index 9d82cea1..374357e9 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Services/Agent365ToolingService.cs @@ -100,7 +100,7 @@ public Agent365ToolingService( _logger.LogDebug("{Operation} failed: {Message}", operationName, errorMessage); if (!string.IsNullOrWhiteSpace(serverCorrelationId)) { - _logger.LogDebug("Server correlation ID (x-ms-correlation-id): {CorrelationId}", serverCorrelationId); + _logger.LogWarning("Server correlation ID (x-ms-correlation-id): {CorrelationId}", serverCorrelationId); } return (false, responseContent); } diff --git a/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs b/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs index a78c190e..9e1d2416 100644 --- a/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs +++ b/src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/DevelopMcpCommandTests.cs @@ -281,6 +281,7 @@ public void RegisterExternalMcpServerSubcommand_HasAllExpectedOptions() optionNames.Should().Contain("description"); optionNames.Should().Contain("dry-run"); optionNames.Should().Contain("verbose"); + optionNames.Should().NotContain("config"); // Verify critical aliases var serverNameOption = options.First(o => o.Name == "server-name"); From 32376a00c5a72634d7fde22efd5f5aea46caac6f Mon Sep 17 00:00:00 2001 From: Bhaarath Raguru Date: Wed, 29 Apr 2026 19:31:29 -0700 Subject: [PATCH 7/7] fix: also log rollback warning so it appears in file logs Co-Authored-By: Claude Opus 4.6 --- .../Commands/RegisterCommandExecutor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs index 1e7f0403..dacfc8a1 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs @@ -167,6 +167,7 @@ internal async Task ExecuteAsync(RawRegisterArgs args) _logger.LogError("Failed to add MCP server {ServerName}: {Error}", input.ServerName, errorMsg); } + _logger.LogWarning("Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); Console.WriteLine($"Entra app registrations were NOT rolled back. Delete them manually in the Azure portal if needed."); return; }