Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ protected override void RegisterOptions(Command command)
protected override ThreadCreateOptions BindOptions(ParseResult parseResult)
{
var options = base.BindOptions(parseResult);
options.Endpoint = parseResult.GetValueOrDefault<string>(FoundryOptionDefinitions.EndpointOption);
options.UserMessage = parseResult.GetValueOrDefault<string>(FoundryOptionDefinitions.UserMessage);
options.Endpoint = parseResult.GetValueOrDefault(FoundryOptionDefinitions.EndpointOption);
options.UserMessage = parseResult.GetValueOrDefault(FoundryOptionDefinitions.UserMessageOption);
return options;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,8 @@ public async Task<ThreadCreateResult> CreateThread(
var thread = await CreateThreadCore(projectEndpoint, userMessage, credential, cancellationToken: cancellationToken);
return new ThreadCreateResult()
{
ThreadId = thread.Id
ThreadId = thread.Id,
ProjectEndpoint = projectEndpoint
};
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,37 @@ public async Task Should_list_openai_models()
Assert.Equal(resourceName, commandResourceName.GetString());
}

[Fact]
[Trait("Category", "Live")]
public async Task Should_create_agent()
{
var projectName = $"{Settings.ResourceBaseName}-ai-projects";
var accounts = Settings.ResourceBaseName;
var agentName = $"test-agent-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
var endpoint = $"https://{accounts}.services.ai.azure.com/api/projects/{projectName}";
// Model deployment name hardcoded in the test-resources.bicep
var modelDeploymentName = "gpt-4o";
var systemInstruction = "Help user with your knowledge";
var result = await CallToolAsync(
"foundry_agents_create",
new()
{
{ "endpoint", endpoint },
{ "model-deployment", modelDeploymentName },
{ "agent-name", agentName },
{ "system-instruction", systemInstruction }
});

var agentIdResult = result.AssertProperty("agentId");
var agentNameResult = result.AssertProperty("agentName");
var projectEndpointResult = result.AssertProperty("projectEndpoint");
var modelDeploymentNameResult = result.AssertProperty("modelDeploymentName");
Assert.Equal(JsonValueKind.String, agentIdResult.ValueKind);
Assert.Equal(JsonValueKind.String, agentNameResult.ValueKind);
Assert.Equal(JsonValueKind.String, projectEndpointResult.ValueKind);
Assert.Equal(JsonValueKind.String, modelDeploymentNameResult.ValueKind);
}

[Fact]
[Trait("Category", "Live")]
public async Task Should_connect_agent()
Expand Down Expand Up @@ -1008,6 +1039,65 @@ public async Task Should_get_foundry_resource_using_static_resources()
}
}

[Fact]
[Trait("Category", "Live")]
public async Task Should_create_thread()
{
var projectName = $"{Settings.ResourceBaseName}-ai-projects";
var accounts = Settings.ResourceBaseName;
var endpoint = $"https://{accounts}.services.ai.azure.com/api/projects/{projectName}";
var userMessage = "Message from user";
var result = await CallToolAsync(
"foundry_threads_create",
new()
{
{ "endpoint", endpoint },
{ "user-message", userMessage }
});
var threadIdResult = result.AssertProperty("threadId");
var projectEndpointResult = result.AssertProperty("projectEndpoint");
Assert.Equal(JsonValueKind.String, threadIdResult.ValueKind);
Assert.Equal(JsonValueKind.String, projectEndpointResult.ValueKind);
}

[Fact]
[Trait("Category", "Live")]
public async Task Should_list_threads()
{
var projectName = $"{Settings.ResourceBaseName}-ai-projects";
var accounts = Settings.ResourceBaseName;
var endpoint = $"https://{accounts}.services.ai.azure.com/api/projects/{projectName}";
var result = await CallToolAsync(
"foundry_threads_list",
new()
{
{ "endpoint", endpoint }
});
var threads = result.AssertProperty("threads");
Assert.Equal(JsonValueKind.Array, threads.ValueKind);
}

[Fact]
[Trait("Category", "Live")]
public async Task Should_get_messages()
{
var projectName = $"{Settings.ResourceBaseName}-ai-projects";
var accounts = Settings.ResourceBaseName;
var endpoint = $"https://{accounts}.services.ai.azure.com/api/projects/{projectName}";
var threadId = await CreateThread("Hello from user", endpoint);
var result = await CallToolAsync(
"foundry_threads_get-messages",
new()
{
{ "endpoint", endpoint },
{ "thread-id", threadId }
});
var threadIdResult = result.AssertProperty("threadId");
var messagesResult = result.AssertProperty("messages");
Assert.Equal(JsonValueKind.String, threadIdResult.ValueKind);
Assert.Equal(JsonValueKind.Array, messagesResult.ValueKind);
}

private async Task<string> CreateAgent(string agentName, string projectEndpoint, string deploymentName)
{
var tokenProvider = new SingleIdentityTokenCredentialProvider(NullLoggerFactory.Instance);
Expand All @@ -1029,4 +1119,17 @@ [new BingGroundingSearchConfiguration(bingConnectionId)]
tools: [new BingGroundingToolDefinition(bingGroundingToolParameters)]);
return agent.Id;
}

private async Task<string> CreateThread(string userMessage, string projectEndpoint)
{
var tokenProvider = new SingleIdentityTokenCredentialProvider(NullLoggerFactory.Instance);

var client = new PersistentAgentsClient(
projectEndpoint,
await tokenProvider.GetTokenCredentialAsync(default, default));

PersistentAgentThread thread = await client.Threads.CreateThreadAsync([
new(MessageRole.User, userMessage)]);
return thread.Id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

using System.Net;
using Azure.Mcp.Core.Models.Command;
using Azure.Mcp.Core.Services.Azure.Subscription;
using Azure.Mcp.Core.Services.Azure.Tenant;
using Azure.Mcp.Core.Services.Http;
using Azure.Mcp.Tools.Foundry.Commands;
using Azure.Mcp.Tools.Foundry.Models;
using Azure.Mcp.Tools.Foundry.Options;
using Azure.Mcp.Tools.Foundry.Services;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -16,14 +18,17 @@ namespace Azure.Mcp.Tools.Foundry.UnitTests;
public class AgentsGetSdkCodeSampleCommandTests
{
private readonly IServiceProvider _serviceProvider;
private readonly IFoundryService _foundryService;

public AgentsGetSdkCodeSampleCommandTests()
{
_foundryService = Substitute.For<IFoundryService>();

var collection = new ServiceCollection();
collection.AddSingleton(_foundryService);
var httpClientService = Substitute.For<IHttpClientService>();
var subscriptionService = Substitute.For<ISubscriptionService>();
var tenantService = Substitute.For<ITenantService>();
collection.AddSingleton(httpClientService);
collection.AddSingleton(subscriptionService);
collection.AddSingleton(tenantService);
collection.AddSingleton<IFoundryService, FoundryService>();

_serviceProvider = collection.BuildServiceProvider();
}
Expand All @@ -49,16 +54,6 @@ public async Task ExecuteAsync_Fails_WhenMissingRequiredParameter(string argsStr

public async Task ExecuteAsync_ReturnsSdkCodeSample(string programmingLanguage)
{
var expectedResult = new AgentsGetSdkCodeSampleResult()
{
CodeSampleText = "code sample text"
};

_foundryService.GetSdkCodeSample(
Arg.Is(programmingLanguage)
)
.Returns(expectedResult);

var command = new AgentsGetSdkSampleCommand();
var args = command.GetCommand().Parse(["--programming-language", programmingLanguage]);
var context = new CommandContext(_serviceProvider);
Expand Down
Loading