Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Azure.Communication.Email;
using Azure.Communication.Sms;
using Azure.Core.Pipeline;
using Azure.Mcp.Core.Options;
using Azure.Mcp.Core.Services.Azure;
using Azure.Mcp.Core.Services.Azure.Tenant;
Expand Down Expand Up @@ -44,7 +45,11 @@ public async Task<List<SmsResult>> SendSmsAsync(
{
// Create SMS client using Azure credential from base class and endpoint
var credential = await GetCredential(tenantId, cancellationToken);
var smsClient = new SmsClient(new Uri(endpoint), credential);

var smsClientOptions = ConfigureRetryPolicy(AddDefaultPolicies(new SmsClientOptions()), retryPolicy);
smsClientOptions.Transport = new HttpClientTransport(TenantService.GetClient());

var smsClient = new SmsClient(new Uri(endpoint), credential, smsClientOptions);

var sendOptions = new SmsSendOptions(enableDeliveryReport)
{
Expand Down Expand Up @@ -124,7 +129,11 @@ public async Task<List<SmsResult>> SendSmsAsync(
{
// Create email client with credential from base class
var credential = await GetCredential(tenantId, cancellationToken);
var emailClient = new EmailClient(new Uri(endpoint), credential);

var emailClientOptions = ConfigureRetryPolicy(AddDefaultPolicies(new EmailClientOptions()), retryPolicy);
emailClientOptions.Transport = new HttpClientTransport(TenantService.GetClient());

var emailClient = new EmailClient(new Uri(endpoint), credential, emailClientOptions);

// Create the email content
var emailContent = new EmailContent(subject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,110 @@
using System.Text.Json;
using Azure.Mcp.Tests;
using Azure.Mcp.Tests.Client;
using Azure.Mcp.Tests.Client.Helpers;
using Azure.Mcp.Tests.Generated.Models;
using Xunit;

namespace Azure.Mcp.Tools.Communication.LiveTests;

[Trait("Command", "SmsSendCommand")]
public class CommunicationCommandTests : CommandTestsBase
public class CommunicationCommandTests(ITestOutputHelper output, TestProxyFixture fixture) : RecordedCommandTestsBase(output, fixture)
{
public CommunicationCommandTests(ITestOutputHelper output) : base(output)
private const string EmptyGuid = "00000000-0000-0000-0000-000000000000";
private string? endpointRecorded;
private string? fromSms;
private string? toSms;
public override bool EnableDefaultSanitizerAdditions => false;

public override async ValueTask InitializeAsync()
{
await LoadSettingsAsync();
if (TestMode == Tests.Helpers.TestMode.Playback)
{
endpointRecorded = "https://sanitized.communication.azure.com";
fromSms = "12345678900";
toSms = "12345678901";
}
else
{
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_ENDPOINT", out endpointRecorded);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_FROM_PHONE", out var tempFromSms);
fromSms = tempFromSms!.Substring(1); // Remove '+' for regex matching
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_TO_PHONE", out var tempToSms);
toSms = tempToSms!.Substring(1); // Remove '+' for regex matching
}

await base.InitializeAsync();
}

public override List<GeneralRegexSanitizer> GeneralRegexSanitizers =>
[
..base.GeneralRegexSanitizers,
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = Settings.ResourceBaseName,
Value = "Sanitized",
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = Settings.SubscriptionId,
Value = EmptyGuid,
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = endpointRecorded,
Value = "https://sanitized.communication.azure.com",
})
];

public override List<BodyKeySanitizer> BodyKeySanitizers =>
[
..base.BodyKeySanitizers,
new BodyKeySanitizer(new BodyKeySanitizerBody("$..to")
{
Value = "12345678901"
}),
new BodyKeySanitizer(new BodyKeySanitizerBody("$.from")
{
Value = "12345678900"
}),
new BodyKeySanitizer(new BodyKeySanitizerBody("$..repeatabilityRequestId")
{
Value = EmptyGuid
}),
new BodyKeySanitizer(new BodyKeySanitizerBody("$..repeatabilityFirstSent")
{
Value = "Fri, 30 Jan 2026 01:02:04 GMT"
})
];

public override List<HeaderRegexSanitizer> HeaderRegexSanitizers =>
[
..base.HeaderRegexSanitizers,
new HeaderRegexSanitizer(new HeaderRegexSanitizerBody("Operation-Id")
{
Value = EmptyGuid
})
];

[Fact]
public async Task Should_SendSms_WithValidParameters()
{
// Get configuration from DeploymentOutputs in Settings
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_ENDPOINT", out var endpoint);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_FROM_PHONE", out var fromPhone);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_TO_PHONE", out var toPhone);
Assert.SkipWhen(string.IsNullOrEmpty(endpoint), "Communication Services endpoint not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(fromPhone), "From phone number not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(toPhone), "To phone number not configured for live testing");

if (TestMode != Tests.Helpers.TestMode.Playback)
{
Assert.SkipWhen(string.IsNullOrEmpty(endpointRecorded), "Communication Services endpoint not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(fromSms), "From phone number not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(toSms), "To phone number not configured for live testing");
}

var result = await CallToolAsync(
"communication_sms_send",
new()
{
{ "endpoint", endpoint },
{ "from", fromPhone },
{ "to", new[] { toPhone } },
{ "endpoint", endpointRecorded },
{ "from", fromSms },
{ "to", new[] { toSms } },
{ "message", "Test SMS from Azure MCP Live Test" },
{ "enable-delivery-report", true },
{ "tag", "live-test" }
Expand All @@ -57,7 +133,7 @@ public async Task Should_SendSms_WithValidParameters()

// Verify the result values
Assert.NotNull(messageId);
Assert.StartsWith("+", to);
Assert.Equal(toSms, to);
Assert.True(successful, "SMS was not sent successfully");
Assert.True(Guid.TryParse(messageId, out _), "MessageId should be a valid GUID");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,100 @@
using System.Text.Json;
using Azure.Mcp.Tests;
using Azure.Mcp.Tests.Client;
using Azure.Mcp.Tests.Client.Helpers;
using Azure.Mcp.Tests.Generated.Models;
using Xunit;

namespace Azure.Mcp.Tools.Communication.LiveTests.Email;

[Trait("Command", "EmailSendCommand")]
public class EmailSendCommandLiveTests : CommandTestsBase
public class EmailSendCommandLiveTests(ITestOutputHelper output, TestProxyFixture fixture) : RecordedCommandTestsBase(output, fixture)
{
public EmailSendCommandLiveTests(ITestOutputHelper output) : base(output)
private const string EmptyGuid = "00000000-0000-0000-0000-000000000000";
private string? endpointRecorded;
private string? fromEmail;
private string? toEmail;
public override bool EnableDefaultSanitizerAdditions => false;

public override async ValueTask InitializeAsync()
{
await LoadSettingsAsync();
if (TestMode == Tests.Helpers.TestMode.Playback)
{
endpointRecorded = "https://sanitized.communication.azure.com";
fromEmail = "DoNotReply@domain.com";
toEmail = "placeholder@microsoft.com";
}
else
{
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_ENDPOINT", out endpointRecorded);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_SENDER_EMAIL", out fromEmail);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_TEST_EMAIL", out toEmail);
}

await base.InitializeAsync();
}

public override List<GeneralRegexSanitizer> GeneralRegexSanitizers =>
[
..base.GeneralRegexSanitizers,
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = Settings.ResourceBaseName,
Value = "Sanitized",
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = Settings.SubscriptionId,
Value = EmptyGuid,
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = endpointRecorded,
Value = "https://sanitized.communication.azure.com",
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = fromEmail,
Value = "DoNotReply@domain.com",
}),
new GeneralRegexSanitizer(new GeneralRegexSanitizerBody()
{
Regex = toEmail,
Value = "placeholder@microsoft.com",
}),
];

public override List<HeaderRegexSanitizer> HeaderRegexSanitizers =>
[
..base.HeaderRegexSanitizers,
new HeaderRegexSanitizer(new HeaderRegexSanitizerBody("Operation-Id")
{
Value = EmptyGuid
})
];

[Fact]
public async Task Should_SendEmail_WithValidParameters()
{
// Get configuration from DeploymentOutputs in Settings
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_ENDPOINT", out var endpoint);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_SENDER_EMAIL", out var senderEmail);
Settings.DeploymentOutputs.TryGetValue("COMMUNICATION_SERVICES_TEST_EMAIL", out var testEmail);

// Output the values for debugging
Output.WriteLine($"Endpoint: {endpoint ?? "null"}");
Output.WriteLine($"Sender Email: {senderEmail ?? "null"}");
Output.WriteLine($"Test Email: {testEmail ?? "null"}");

Assert.SkipWhen(string.IsNullOrEmpty(endpoint), "Communication Services endpoint not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(senderEmail), "Sender email not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(testEmail), "Test recipient email not configured for live testing");
Output.WriteLine($"Endpoint: {endpointRecorded ?? "null"}");
Output.WriteLine($"Sender Email: {fromEmail ?? "null"}");
Output.WriteLine($"Test Email: {toEmail ?? "null"}");

if (TestMode != Tests.Helpers.TestMode.Playback)
{
Assert.SkipWhen(string.IsNullOrEmpty(endpointRecorded), "Communication Services endpoint not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(fromEmail), "Sender email not configured for live testing");
Assert.SkipWhen(string.IsNullOrEmpty(toEmail), "Test recipient email not configured for live testing");
}
var result = await CallToolAsync(
"communication_email_send",
new()
{
{ "endpoint", endpoint },
{ "from", senderEmail },
{ "to", new[] { testEmail } },
{ "endpoint", endpointRecorded },
{ "from", fromEmail },
{ "to", new[] { toEmail } },
{ "subject", "Test Email from Azure MCP Live Test" },
{ "message", "This is a test email sent from Azure MCP Live Test." },
{ "is-html", false }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "",
"TagPrefix": "Azure.Mcp.Tools.Communication.LiveTests",
"Tag": "Azure.Mcp.Tools.Communication.LiveTests_416767ef58"
}