Azure AI Foundry Agent Service MCP クライアント サポートを .NET(C#) コンソール アプリで実装する方法

2025/07/27
★★

Azure AI Foundry Agent Service の MCP クライアント サポート

2025 年 6 月末に Azure AI Foundry Agent Service の MCP クライアント サポート(プレビュー)が発表されました。

現時点(2025/07/28)では、日本リージョンでのサポートはなく、いくつかのリージョンでの限定的なサポートとなっています。

Connect to Model Context Protocol servers (preview) Note

また、UI ベースでの MCP サーバー追加も現状ではできないようです。 Azure AI Foundry Project エージェント ナレッジ Azure AI Foundry Project エージェント アクション

今後、[ナレッジ] もしくは、[アクション] の選択肢として MCP サーバーが追加されると思われます。

よって、今回は、MCP サーバーを参照するエージェントの作成及び実行をコード ベース(C#)で行う方法を説明したいと思います。.NET(C#) コンソールアプリで、ユーザーの問い合わせに関連する情報を MCP サーバーから取得し回答を生成するエージェントの作成と実行を行う方法を説明します。

Azure AI Persistent Agents client library for .NET

Azure AI Foundry Agenet Service には、Python, C#, JavaScrpit の SDK が提供されています。

C#(.NET) の SDK は、Azure AI Persistent Agents client library for .NET として提供されています。

現時点(2025/07/28)での最新の安定リリースは、Azure.AI.Agents.Persistent 1.1.0 で、最新のプレリリースは、Azure.AI.Agents.Persistent 1.2.0-beta.1 です。

現状の安定リリース 1.1.0 には、MCP クライアント サポートがないようなので、最新のプレリリース Azure.AI.Agents.Persistent 1.2.0-beta.1 を使用します。

Microsoft Learn Docs MCP Server

エージェントが参照する MCP サーバーには、Microsoft Learn Docs MCP Server を使用します。

Microsoft Learn Docs MCP Server は、クラウド上にホストされている MCP サーバーであり、Microsoft の公式ドキュメントからクエリに関連する情報を取得できます。以下のエンドポイント、ツール名で公開されています。

Azure AI Foundry Agent Service での MCP サーバーを参照したエージェントの作成

Azure.AI.Agents.Persistent, Azure.Identity を Nuget からインストールします。

dotnet add package Azure.AI.Agents.Persistent --version 1.2.0-beta.1
dotnet add package Azure.Identity --version 1.14.2

以下のコードで Microsoft Learn Docs MCP Server を参照するエージェントを作成します。

string tenantId = "<Azure AI Foundry Project のテナント ID>";
string projectEndpoint = "<Azure AI Foundry Project エンドポイント>";
string modelDeploymentName = "<エージェントに使用するモデルの配置名>";

// Microsoft Learn Docs MCP Server
string mcpServerLabel = "microsoft_docs_search";
string mcpServerUrl = "https://learn.microsoft.com/api/mcp";

CancellationTokenSource cancellationTokenSource = new();
CancellationToken cancellationToken = cancellationTokenSource.Token;

InteractiveBrowserCredential credential = new(new InteractiveBrowserCredentialOptions()
{
	TenantId = tenantId,
});

// エージェント クライアント
PersistentAgentsClient agentsClient = new(projectEndpoint, credential);

// MCP ツール の定義
MCPToolDefinition mcpToolDefinition = new(mcpServerLabel, mcpServerUrl);

string agentName = "mcp-agent-demo-001";
string agentInstructions = """
	あなたは MCP ツールを使用してユーザーを支援するエージェントです。
	MCP ツールを使用し、質問への回答及びタスクの実行をしてください。
	""";

// エージェントの作成
PersistentAgent agent = await agentsClient.Administration.CreateAgentAsync(
	model: modelDeploymentName,
	name: agentName,
	instructions: agentInstructions,		
	tools: [mcpToolDefinition],
	cancellationToken: cancellationToken);

ここまでのコードを実行すると、Azure AI Foundry Project にエージェントが作成されます。UI からも作成したエージェントを確認できます。ナレッジのところに MCP という文字列がみえます。 Azure AI Foundry Project エージェント ナレッジ

この状態でプレイグラウンドから質問を行ってやることもできますが、エラーとなってしまいます。現状のプレイグラウンドでは、RequiresAction を処理できずエラーになっていると思われます。 Azure AI Foundry Project エージェント スレッド ログ

Agent Service での MCP サーバーを参照したエージェントの実行

プレイグラウンドからの実行ではできないようなので、続けて作成したエージェントへユーザーメッセージを送信し、回答を表示する処理をコードで書きます。

string userQuery = "Azure AI Foundry Agent Service MCP サーバー接続では、日本リージョンをサポートしていますか?";

// スレッドの作成
PersistentAgentThread thread = await agentsClient.Threads.CreateThreadAsync(cancellationToken: cancellationToken);

// メッセージの作成
PersistentThreadMessage threadMessage = await agentsClient.Messages.CreateMessageAsync(
	thread.Id,
	MessageRole.User,
	userQuery);

// スレッド実行時に使用する MCP ツールの設定
MCPToolResource mcpToolResource = new(mcpServerLabel);
// MCP ツールの実行時に承認を要求しない
mcpToolResource.RequireApproval = MCPToolResourceRequireApproval.Never;
// スレッド実行時に使用するツールの設定
ToolResources toolResources = mcpToolResource.ToToolResources();

// スレッドの実行
ThreadRun run = await agentsClient.Runs.CreateRunAsync(
	thread,
	agent,
	toolResources,
	cancellationToken);

do
{
	run = await agentsClient.Runs.GetRunAsync(thread.Id, run.Id, cancellationToken);
	Console.WriteLine($"[{DateTimeOffset.UtcNow:yyyy-MM-dd HH:mm:ss}] RunId: {run.Id}, Status: {run.Status}");	

	await Task.Delay(TimeSpan.FromMilliseconds(500));
}
while (run.Status == RunStatus.Queued
|| run.Status == RunStatus.RequiresAction
|| run.Status == RunStatus.InProgress);

if (run.Status != RunStatus.Completed)
{
	throw new InvalidOperationException($"Run failed or was canceled: {run.LastError?.Message}");
}

// メッセージの取得
AsyncPageable<PersistentThreadMessage> messages = agentsClient.Messages.GetMessagesAsync(
	thread.Id, order: ListSortOrder.Ascending, cancellationToken: cancellationToken);

// メッセージの表示
await foreach (PersistentThreadMessage message in messages)
{
	Console.Write($"[{message.CreatedAt:yyyy-MM-dd HH:mm:ss}] {message.Role}: ");

	foreach (MessageContent contentItem in message.ContentItems)
	{
		if (contentItem is MessageTextContent textItem)
		{
			Console.WriteLine(textItem.Text);
		}				
	}			
}

今回は、MCP ツールの実行時に許可を求めないようにしています。ここで、MCPToolResourceRequireApproval.Never を設定しないと、MCP ツールの実行時に スレッドのステータスが、RunStatus.RequiresAction となり、MCP ツールの実行を許可する必要があります。この場合、ユーザーと対話して許可を要求するコードが必要となります。

// MCP ツールの実行時に承認を要求しない
mcpToolResource.RequireApproval = MCPToolResourceRequireApproval.Never;

実行結果は以下となります。

コード実行結果

また、Azure AI Foundry Project のスレッド ログを参照すると、MCP サーバーへの接続ログが確認できます。 Azure AI Foundry Project エージェント スレッド ログ

Azure AI Foundry Agent Service での MCP サーバーを参照したエージェントの作成と実行

一連のコードは以下となります。

using Azure;
using Azure.AI.Agents.Persistent;
using Azure.Identity;

namespace AzFoundryAgentDemo;

internal class Program
{
	static async Task Main(string[] args)
	{
		string tenantId = "<Azure AI Foundry Project のテナント ID>";
        string projectEndpoint = "<Azure AI Foundry Project エンドポイント>";
        string modelDeploymentName = "<エージェントに使用するモデルの配置名>";

        // Microsoft Learn Docs MCP Server
        string mcpServerLabel = "microsoft_docs_search";
        string mcpServerUrl = "https://learn.microsoft.com/api/mcp";

		CancellationTokenSource cancellationTokenSource = new();
		CancellationToken cancellationToken = cancellationTokenSource.Token;

		InteractiveBrowserCredential credential = new(new InteractiveBrowserCredentialOptions()
		{
			TenantId = tenantId,
		});

		// エージェント クライアント
		PersistentAgentsClient agentsClient = new(projectEndpoint, credential);
		
		// MCP ツール の定義
		MCPToolDefinition mcpToolDefinition = new(mcpServerLabel, mcpServerUrl);		

		string agentName = "mcp-agent-demo-001";
		string agentInstructions = """
			あなたは MCP ツールを使用してユーザーを支援するエージェントです。
			MCP ツールを使用し、質問への回答及びタスクの実行をしてください。
			""";
		
		// エージェントの作成
		PersistentAgent agent = await agentsClient.Administration.CreateAgentAsync(
			model: modelDeploymentName,
			name: agentName,
			instructions: agentInstructions,		
			tools: [mcpToolDefinition],
			cancellationToken: cancellationToken);


		
		string userQuery = "Azure AI Foundry Agent Service MCP サーバー接続では、日本リージョンをサポートしていますか?";

		// スレッドの作成
		PersistentAgentThread thread = await agentsClient.Threads.CreateThreadAsync(cancellationToken: cancellationToken);

		// メッセージの作成
		PersistentThreadMessage threadMessage = await agentsClient.Messages.CreateMessageAsync(
			thread.Id,
			MessageRole.User,
			userQuery);

		// スレッド実行時に使用する MCP ツールの設定
		MCPToolResource mcpToolResource = new(mcpServerLabel);
		// MCP ツールの実行時に承認を要求しない
		mcpToolResource.RequireApproval = MCPToolResourceRequireApproval.Never;
		// スレッド実行時に使用するツールの設定
		ToolResources toolResources = mcpToolResource.ToToolResources();

		// スレッドの実行
		ThreadRun run = await agentsClient.Runs.CreateRunAsync(
			thread,
			agent,
			toolResources,
			cancellationToken);

		do
		{
			run = await agentsClient.Runs.GetRunAsync(thread.Id, run.Id, cancellationToken);
			Console.WriteLine($"[{DateTimeOffset.UtcNow:yyyy-MM-dd HH:mm:ss}] RunId: {run.Id}, Status: {run.Status}");			

			await Task.Delay(TimeSpan.FromMilliseconds(500));
		}
		while (run.Status == RunStatus.Queued
		|| run.Status == RunStatus.RequiresAction
		|| run.Status == RunStatus.InProgress);

		if (run.Status != RunStatus.Completed)
		{
			throw new InvalidOperationException($"Run failed or was canceled: {run.LastError?.Message}");
		}

		// メッセージの取得
		AsyncPageable<PersistentThreadMessage> messages = agentsClient.Messages.GetMessagesAsync(
			thread.Id, order: ListSortOrder.Ascending, cancellationToken: cancellationToken);

		// メッセージの表示
		await foreach (PersistentThreadMessage message in messages)
		{
			Console.Write($"[{message.CreatedAt:yyyy-MM-dd HH:mm:ss}] {message.Role}: ");

			foreach (MessageContent contentItem in message.ContentItems)
			{
				if (contentItem is MessageTextContent textItem)
				{
					Console.WriteLine(textItem.Text);
				}				
			}			
		}
	}
}

将来的には、Azure AI Foundry Project の UI から MCP サーバーの追加ができ、プレイグラウンドで動作確認もできるようになると思います。それまでの対処としてコードベースでのエージェントの作成と、エージェントの実行方法を説明しました。

コメント (0)

コメントの投稿