이 문서에서는 .NET을 사용하여 MCP(모델 컨텍스트 프로토콜) 에이전트를 빌드하는 방법을 보여 줍니다. 이 샘플에서 MCP 클라이언트(C#/.NET으로 작성됨)는 MCP 서버(TypeScript로 작성됨)에 연결하여 할 일 목록을 관리합니다. 클라이언트는 서버에서 사용 가능한 도구를 찾아서 Azure OpenAI 모델로 보냅니다. 그런 다음 사용자는 일상적인 언어를 사용하여 할 일 시스템과 통신할 수 있습니다.
코드 가져오기
OpenAI MCP 에이전트 구성 요소 AI 템플릿을 확인합니다. 이 예제에서는 MCP 클라이언트를 사용하여 기존 MCP 서버를 사용하는 OpenAI 에이전트를 빌드하는 방법을 보여줍니다.
코드 연습 섹션으로 이동하여 이 샘플의 작동 방식을 이해합니다.
아키텍처 개요
다음 다이어그램은 샘플 앱의 간단한 아키텍처를 보여줍니다.
- MCP 클라이언트: MCP 서버에 연결하고 사용 가능한 도구를 찾습니다.
- 채팅 클라이언트: Azure OpenAI와 협력하여 자연어 이해
- Blazor UI: 사용자가 채팅할 수 있는 웹 인터페이스를 제공합니다.
- 전송 계층: SSE(Server-Sent 이벤트)를 사용하여 실시간으로 메시지 보내기
- 인증: JWT 토큰을 사용하여 연결 보안 유지
MCP 서버는 ACA(Azure Container Apps)에서 컨테이너화된 앱으로 실행됩니다. TypeScript 백 엔드를 사용하여 모델 컨텍스트 프로토콜을 통해 MCP 클라이언트에 도구를 제공합니다. 모든 도구는 백 엔드 SQLite 데이터베이스에서 작동합니다.
비고
Azure Container Apps를 사용하여 TypeScript MCP 서버 빌드를 방문하여 이 문서에 사용된 TypeScript MCP 서버의 코드 연습을 확인합니다.
비용
비용을 낮게 유지하기 위해 이 샘플은 대부분의 리소스에 대해 기본 또는 소비 가격 책정 계층을 사용합니다. 필요에 따라 계층을 조정하고 요금이 부과되지 않도록 완료되면 리소스를 삭제합니다.
필수 조건
- Visual Studio Code - MCP 서버 개발을 지원하는 최신 버전입니다.
- .NET 9 SDK
- Visual Studio Code용 C# 개발 키트 Visual Studio Code 확장
- GitHub Copilot Visual Studio Code 확장
- GitHub 코필로트 채팅 Visual Studio Code 확장
- Azure Developer CLI(azd)
- AI Foundry 확장 Visual Studio Code 확장
- 배포된 AI Foundry gpt-5-mini 모델
개발 컨테이너에는 이 문서에 필요한 모든 종속성이 포함됩니다. GitHub Codespaces(브라우저에서) 또는 Visual Studio Code를 사용하여 로컬로 실행할 수 있습니다.
이 문서를 따르려면 다음 필수 구성 요소를 충족하는지 확인합니다.
AI Foundry VS Code 확장을 사용하여 AI Foundry gpt-5-mini 모델 배포
gpt-5-mini 다음 단계를 사용하여 Visual Studio Code에서 AI Foundry 확장을 사용하여 모델을 배포합니다.
AI Foundry 프로젝트 만들기 및 모델 배포
- AI Foundry 프로젝트를 만들고 모델을 배포
gpt-5-mini하려면 Azure AI Foundry for Visual Studio Code 확장(미리 보기) 문서의 시작 지침을 따릅니다.
OpenAI 모델 연결 문자열 만들기
gpt-5-mini모델이 배포되면 AI Foundry 확장에서 모델을 마우스 오른쪽 단추로 클릭하고 API 키 복사를 선택하여 모델의 API 키를 클립보드에 복사합니다.다음으로, 다음 스크린샷과 같이 AI Foundry 확장에서 배포된
gpt-5-mini모델을 마우스 오른쪽 단추로 클릭하고 엔드포인트 복사 를 선택하여 모델의 엔드포인트를 클립보드에 복사합니다.마지막으로 복사한 엔드포인트 및 API 키를 사용하여 배포된
gpt-5-mini모델에 대한 연결 문자열을 다음과 같은 형식Endpoint=<AZURE_OPENAI_ENDPOINT>;Key=<AZURE_OPENAI_API_KEY>으로 만듭니다. 이 연결 문자열은 문서의 뒷부분에서 필요합니다.
- Azure 구독 – 무료로 구독 만들기
- Azure 계정 권한 – Azure 계정에
Microsoft.Authorization/roleAssignments/write, 사용자 액세스 관리자 또는 소유자와 같은 권한이 있어야 합니다. 구독 수준 권한이 없는 경우 기존 리소스 그룹에 대한 RBAC 를 부여하고 해당 그룹에 배포해야 합니다.- Azure 계정에는 구독 수준의 권한도 필요합니다
Microsoft.Resources/deployments/write.
- Azure 계정에는 구독 수준의 권한도 필요합니다
- GitHub 계정
개발 환경 열기
필요한 모든 종속성을 사용하여 미리 구성된 개발 환경을 설정하려면 다음 단계를 수행합니다.
GitHub Codespaces는웹용 Visual Studio Code 를 인터페이스로 사용하여 GitHub에서 관리하는 개발 컨테이너를 실행합니다. 이 문서에 미리 설치된 필수 도구 및 종속성과 함께 제공되는 가장 간단한 설정에는 GitHub Codespaces를 사용합니다.
중요합니다
모든 GitHub 계정은 두 개의 핵심 인스턴스를 사용하여 매월 최대 60시간 동안 Codespaces를 무료로 사용할 수 있습니다. 자세한 내용은 GitHub Codespaces 월별 포함된 스토리지 및 코어 시간을 참조하세요.
다음 단계를 사용하여 GitHub 리포지토리의 분기에 새 GitHub Codespace main 를 Azure-Samples/openai-mcp-agent-dotnet 만듭니다.
다음 단추를 마우스 오른쪽 단추로 클릭하고 새 창에서 링크 열기를 선택합니다. 이 작업을 통해 개발 환경과 설명서를 나란히 열 수 있습니다.
코드스페이스 만들기 페이지에서 새 코드스페이스 만들기를 검토한 다음 선택합니다.
코드스페이스가 시작될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
배포된 모델 이름이
gpt-5-mini.인지 확인합니다. 배포된 모델이 다른 경우 올바른 배포 이름으로 업데이트src/McpTodo.ClientApp/appsettings.json합니다.{ "OpenAI": { // Make sure this is the right deployment name. "DeploymentName": "gpt-5-mini" } }화면 맨 아래에 있는 터미널에서 Azure 개발자 CLI를 사용하여 Azure에 로그인합니다.
azd auth login터미널에서 코드를 복사한 다음 브라우저에 붙여넣습니다. 지침에 따라 Azure 계정으로 인증합니다.
이 개발 컨테이너에서 나머지 작업을 수행합니다.
비고
MCP 에이전트를 로컬로 실행하려면 다음을 수행합니다.
- 샘플 리포지토리의 시작 섹션에 설명 된 대로 환경을 설정합니다.
- 샘플 리포지토리의 MCP 서버 앱 가져오기 섹션에 있는 지침에 따라 MCP 서버를 설치합니다.
- 샘플 리포지토리의 로컬 실행 섹션에 있는 지침에 따라 MCP 에이전트를 로컬로 실행합니다.
- 계속하려면 TODO MCP 에이전트 사용 섹션으로 건너뜁니다.
배포 및 실행
샘플 리포지토리에는 MCP 에이전트 Azure 배포에 대한 모든 코드 및 구성 파일이 포함되어 있습니다. 다음 단계에서는 샘플 MCP 에이전트 Azure 배포 프로세스를 안내합니다.
Azure에 배포
중요합니다
이 섹션의 Azure 리소스는 명령이 완료되기 전에 중지하더라도 즉시 비용이 들기 시작합니다.
JWT 토큰 설정
화면 아래쪽의 터미널에서 다음 명령을 실행하여 MCP 서버에 대한 JWT 토큰을 설정합니다.
# zsh/bash ./scripts/set-jwttoken.sh# PowerShell ./scripts/Set-JwtToken.ps1
azd 환경 구성에 JWT 토큰 추가
화면 아래쪽의 터미널에서 다음 명령을 실행하여 Azd 환경 구성에 JWT 토큰을 추가합니다.
# zsh/bash env_dir=".azure/$(azd env get-value AZURE_ENV_NAME)" mkdir -p "$env_dir" cat ./src/McpTodo.ServerApp/.env >> "$env_dir/.env"# PowerShell $dotenv = Get-Content ./src/McpTodo.ServerApp/.env $dotenv | Add-Content -Path ./.azure/$(azd env get-value AZURE_ENV_NAME)/.env -Encoding utf8 -Force비고
기본적으로 MCP 클라이언트 앱은 ACA 기본 제공 인증 기능으로 보호됩니다. 다음을 설정하여 실행
azd up하기 전에 이 기능을 해제할 수 있습니다.azd env set USE_LOGIN falseAzure 리소스 프로비저닝 및 소스 코드 배포에 대해 다음 Azure Developer CLI 명령을 실행합니다.
azd up다음 표를 사용하여 프롬프트에 응답합니다.
프롬프트 답변 환경 이름 짧은 소문자 이름을 사용합니다. 이름 또는 별칭을 추가합니다. 예: my-mcp-agent. 환경 이름은 리소스 그룹 이름의 일부가 됩니다.Subscription 리소스를 만들려는 구독을 선택합니다. 위치(호스팅용) 목록에서 모델 배포 위치를 선택합니다. OpenAI 연결 문자열 앞에서 만든 OpenAI 모델 연결 문자열 만들기 섹션에서 만든 OpenAI 모델의 연결 문자열을 붙여넣습니다. 앱 배포에는 5~10분이 걸립니다.
배포가 완료되면 출력의 URL을 사용하여 MCP 에이전트에 액세스할 수 있습니다. URL은 다음과 같습니다.
https://<env-name>.<container-id>.<region>.azurecontainerapps.ioMCP 에이전트를 사용하려면 웹 브라우저에서 URL을 엽니다.
TODO MCP 에이전트 사용
MCP 에이전트가 실행되면 에이전트 모드에서 제공하는 도구를 사용할 수 있습니다. 에이전트 모드에서 MCP 도구를 사용하려면 다음을 수행합니다.
클라이언트 앱 URL로 이동하고 앱에 로그인합니다.
비고
값을
USE_LOGIN설정false하면 로그인하라는 메시지가 표시되지 않을 수 있습니다.채팅 입력 상자에 "수요일에 관리자에게 전자 메일을 보내야 합니다."와 같은 프롬프트를 입력하고 필요에 따라 도구가 자동으로 호출되는 방식을 확인합니다.
MCP 에이전트는 MCP 서버에서 제공하는 도구를 사용하여 요청을 수행하고 채팅 인터페이스에서 응답을 반환합니다.
다음과 같은 다른 프롬프트를 사용해 보세요.
Give me a list of to dos. Set "meeting at 1pm". Give me a list of to dos. Mark #1 as completed. Delete #1 from the to-do list.
코드 탐색
샘플 리포지토리에는 MCP 에이전트 Azure 배포에 대한 모든 코드 및 구성 파일이 포함되어 있습니다. 다음 섹션에서는 MCP 에이전트 코드의 주요 구성 요소를 안내합니다.
MCP 클라이언트 구성 및 설정
애플리케이션에서 MCP 클라이언트 Program.cs를 설정합니다. 이 구성은 연결하는 방법과 사용할 옵션을 정의합니다. 이 코드는 .NET Aspire 통합 및 서비스 기본값을 비롯한 여러 고급 패턴을 사용합니다.
builder.Services.AddSingleton<IMcpClient>(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var loggerFactory = sp.GetRequiredService<ILoggerFactory>();
var uri = new Uri(config["McpServers:TodoList"]!);
var clientTransportOptions = new SseClientTransportOptions()
{
Endpoint = new Uri($"{uri.AbsoluteUri.TrimEnd('/')}/mcp"),
AdditionalHeaders = new Dictionary<string, string>
{
{ "Authorization", $"Bearer {config["McpServers:JWT:Token"]!}" }
}
};
var clientTransport = new SseClientTransport(clientTransportOptions, loggerFactory);
var clientOptions = new McpClientOptions()
{
ClientInfo = new Implementation()
{
Name = "MCP Todo Client",
Version = "1.0.0",
}
};
return McpClientFactory.CreateAsync(clientTransport, clientOptions, loggerFactory).GetAwaiter().GetResult();
});
주요 구현 세부 정보:
-
전송 구성:
SseClientTransportOptionsSSE(Server-Sent 이벤트) 및 스트리밍 가능한 HTTP 전송을 모두 지원합니다. 전송 방법은 엔드포인트 URL에 따라 달라집니다. 엔드포인트는 Server-Sent 이벤트 사용으로/sse끝나는 반면 엔드포인트는 스트리밍 가능한 HTTP를/mcp사용합니다. 이 방법을 사용하면 클라이언트와 서버 간의 실시간 통신이 가능합니다. -
인증 헤더: JWT 토큰은 서버 통신을
AdditionalHeaders안전하게 유지하기 위해 진행됩니다. -
클라이언트 정보:
McpClientOptions서버에 클라이언트의 이름 및 버전을 알려줍니다. -
팩터리 패턴:
McpClientFactory.CreateAsync()프로토콜 핸드셰이크를 연결하고 완료합니다.
.NET Aspire 서비스 기본 통합
애플리케이션은 교차 절단 문제에 대해 .NET Aspire의 서비스 기본값 패턴을 사용합니다.
// McpTodo.ServiceDefaults/Extensions.cs
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Turn on service discovery by default
http.AddServiceDiscovery();
});
return builder;
}
서비스는 기본적으로 다음과 같은 이점을 제공합니다.
- 구성 가능한 확장 메서드: 시스템에서 클린 빌더 패턴을 사용하여 공유 기능을 추가합니다.
- 표준 복원력 처리기: 시스템에서 기본 제공 재시도, 회로 차단기 및 시간 제한 규칙을 추가합니다.
- 서비스 검색 통합: 시스템은 컨테이너 환경에서 자동으로 서비스를 찾습니다.
- OpenTelemetry 기본적으로: 시스템은 설치 작업 없이 전체 모니터링을 가져옵니다.
다음 다이어그램은 교차 절삭 문제와 애플리케이션 서비스 간의 관계를 보여 줍니다.
구성 URL 확인
샘플에는 다양한 환경에 대한 정교한 URL 확인이 포함됩니다.
// AspireUrlParserExtensions.cs
public static Uri Resolve(this Uri uri, IConfiguration config)
{
var absoluteUrl = uri.ToString();
if (absoluteUrl.StartsWith("https+http://"))
{
var appname = absoluteUrl.Substring("https+http://".Length).Split('/')[0];
var https = config[$"services:{appname}:https:0"]!;
var http = config[$"services:{appname}:http:0"]!;
return string.IsNullOrWhiteSpace(https) ? new Uri(http) : new Uri(https);
}
// Handle other URL formats...
}
구성 관리 기능:
- 서비스 검색 추상화: 시스템은 개발 및 프로덕션 URL을 깔끔하게 처리합니다.
- 프로토콜 협상: 시스템에서 먼저 HTTPS를 선택한 다음 HTTP로 돌아갑니다.
- 구성 규칙: 시스템에서 표준 .NET Aspire 서비스 설정 패턴을 사용합니다.
인증 구현
이 샘플에서는 JWT(JSON 웹 토큰) 인증을 사용하여 MCP 클라이언트와 서버 간의 연결을 보호합니다.
dotnet user-secrets --project ./src/McpTodo.ClientApp set McpServers:JWT:Token "$TOKEN"
비고
스크립트는 Azure에 $TOKEN 배포 섹션의 앞부분에서 Bash(set-jwttoken.sh) 또는 PowerShell(Set-JwtToken.ps1) 스크립트를 실행할 때 변수 를 자동으로 만들었습니다.
이러한 스크립트는 다음 단계를 수행합니다.
- MCP 서버 앱에서 실행
npm run generate-token하여 JWT 토큰 만들기 - 생성된
.env파일을 구문 분석하여 JWT_TOKEN 값 추출 - MCPClient에 대한 .NET 사용자 비밀에 자동으로 저장
MCP 클라이언트는 구성에서 JWT 토큰을 검색하고 MCP 서버에 연결할 때 인증을 위해 HTTP 헤더에 포함합니다.
AdditionalHeaders = new Dictionary<string, string>
{
{ "Authorization", $"Bearer {config["McpServers:JWT:Token"]!}" }
}
이 방법은 다음을 보장합니다.
- 보안 통신: 시스템은 유효한 토큰을 가진 클라이언트만 MCP 서버에 연결할 수 있도록 허용합니다.
- Token-Based 권한 부여: JWT 토큰을 통해 시스템에서 세션 데이터를 저장하지 않고 사용자를 확인할 수 있습니다.
- 구성 관리: 시스템은 개발 중에 중요한 토큰을 사용자 비밀에 안전하게 저장합니다.
Azure Container Apps 인증 통합
인프라는 Azure Container Apps 기본 제공 인증 및 권한 부여 기능("간편한 인증")을 사용하는 고급 인증 패턴을 보여 줍니다.
// containerapps-authconfigs.bicep
resource containerappAuthConfig 'Microsoft.App/containerApps/authConfigs@2024-10-02-preview' = {
properties: {
identityProviders: {
azureActiveDirectory: {
enabled: true
registration: {
clientId: clientId
openIdIssuer: openIdIssuer
}
}
}
login: {
tokenStore: {
enabled: true
azureBlobStorage: {
blobContainerUri: '${storageAccount.properties.primaryEndpoints.blob}/token-store'
managedIdentityResourceId: userAssignedIdentity.id
}
}
}
}
}
고급 인증 기능:
- Zero-Code 인증: Azure Container Apps는 기본 제공 인증을 제공합니다.
- 스토리지용 관리 ID: 시스템은 연결 문자열 없이 토큰을 안전하게 저장합니다.
- 페더레이션 ID 자격 증명: 시스템에서 Kubernetes 스타일 인증에 대한 워크로드 ID를 사용하도록 설정합니다.
다음 다이어그램은 구성 요소 간의 보안 핸드셰이크를 보여 줍니다.
도구 검색 및 등록
MCP 클라이언트는 다음에서 구성 요소를 초기화하는 동안 서버에서 사용 가능한 도구를 검색합니다.Chat.razor
protected override async Task OnInitializedAsync()
{
messages.Add(new(ChatRole.System, SystemPrompt));
tools = await McpClient.ListToolsAsync();
chatOptions.Tools = [.. tools];
}
도구 검색 작동 방식:
-
서버 쿼리:
McpClient.ListToolsAsync()MCP 서버에 요청을 보내 사용 가능한 도구를 나열합니다. - 스키마 검색: 서버는 이름, 설명 및 입력 스키마를 사용하여 도구 정의를 다시 보냅니다.
-
도구 등록: 시스템에서 개체에 도구를
ChatOptions등록하여 OpenAI 클라이언트에서 사용할 수 있도록 합니다. -
형식 안전성: 클래스가
McpClientTool상속되어AIFunctionMicrosoft.Extensions.AI
다음 다이어그램에서는 도구 스키마를 구문 분석하고 등록하는 방법을 보여 줍니다.
OpenAI 통합 및 함수 호출
채팅 클라이언트 구성은 MCP 도구가 Azure OpenAI와 통합되는 방법을 보여 줍니다.
var chatClient = openAIClient.GetChatClient(config["OpenAI:DeploymentName"]).AsIChatClient();
builder.Services.AddChatClient(chatClient)
.UseFunctionInvocation()
.UseLogging();
통합 이점:
-
자동 함수 호출: 확장은
.UseFunctionInvocation()LLM 결정에 따라 자동 도구 실행을 켭니다. - 간편한 도구 액세스: MCP 도구는 OpenAI 모델에 대한 기본 제공 함수로 작동합니다.
- 응답 처리: 시스템이 자동으로 도구 결과를 대화 흐름에 추가합니다.
Real-Time 채팅 구현
채팅 인터페이스 Chat.razor 는 고급 Blazor 패턴을 사용하여 스트리밍 응답 및 도구 실행을 보여 줍니다.
private async Task AddUserMessageAsync(ChatMessage userMessage)
{
CancelAnyCurrentResponse();
// Add the user message to the conversation
messages.Add(userMessage);
chatSuggestions?.Clear();
await chatInput!.FocusAsync();
// Stream and display a new response from the IChatClient
var responseText = new TextContent("");
currentResponseMessage = new ChatMessage(ChatRole.Assistant, [responseText]);
currentResponseCancellation = new();
await foreach (var update in ChatClient.GetStreamingResponseAsync([.. messages], chatOptions, currentResponseCancellation.Token))
{
messages.AddMessages(update, filter: c => c is not TextContent);
responseText.Text += update.Text;
ChatMessageItem.NotifyChanged(currentResponseMessage);
}
// Store the final response in the conversation, and begin getting suggestions
messages.Add(currentResponseMessage!);
currentResponseMessage = null;
chatSuggestions?.Update(messages);
}
스트리밍 구현 기능:
-
Real-Time 업데이트:
GetStreamingResponseAsync()응답 업데이트를 비트별로 보냅니다. - 도구 실행: 시스템은 스트리밍 중에 함수 호출을 자동으로 처리합니다.
-
UI 응답성:
ChatMessageItem.NotifyChanged()실시간으로 UI 업데이트 - 취소 지원: 사용자는 장기 실행 작업을 취소할 수 있습니다.
고급 Blazor UI 패턴
구현은 실시간 업데이트에 고급 UI 패턴을 사용합니다.
Memory-Safe 이벤트 처리:
// ChatMessageItem.razor
private static readonly ConditionalWeakTable<ChatMessage, ChatMessageItem> SubscribersLookup = new();
public static void NotifyChanged(ChatMessage source)
{
if (SubscribersLookup.TryGetValue(source, out var subscriber))
{
subscriber.StateHasChanged();
}
}
사용자 지정 웹 구성 요소 통합:
// ChatMessageList.razor.js
window.customElements.define('chat-messages', class ChatMessages extends HTMLElement {
connectedCallback() {
this._observer = new MutationObserver(mutations => this._scheduleAutoScroll(mutations));
this._observer.observe(this, { childList: true, attributes: true });
}
_scheduleAutoScroll(mutations) {
// Debounce the calls and handle smart auto-scrolling
cancelAnimationFrame(this._nextAutoScroll);
this._nextAutoScroll = requestAnimationFrame(() => {
const addedUserMessage = mutations.some(m =>
Array.from(m.addedNodes).some(n =>
n.parentElement === this && n.classList?.contains('user-message')));
// Smart scrolling logic...
});
}
});
고급 상태 관리:
// Chat.razor
private void CancelAnyCurrentResponse()
{
// If a response was cancelled while streaming, include it in the conversation so it's not lost
if (currentResponseMessage is not null)
{
messages.Add(currentResponseMessage);
}
currentResponseCancellation?.Cancel();
currentResponseMessage = null;
}
Blazor UI 이점:
- 하이브리드 웹 구성 요소: 시스템은 성능 향상을 위해 Blazor Server를 사용자 지정 요소와 결합합니다.
- Memory-Safe 이벤트 처리: 시스템에서 ConditionalWeakTable을 사용하여 메모리 누수 방지
- 스마트 자동 스크롤: 시스템은 디버닝을 통해 사용자에게 친숙한 채팅 동작을 제공합니다.
- 정상 취소: 사용자가 작업을 취소할 때 시스템에서 부분 작업을 저장합니다.
요청/응답 흐름
일반적인 사용자 상호 작용이 시스템을 통과하는 방법은 다음과 같습니다.
- 사용자 입력: 사용자가 "내 할 일 목록에 '식료품 구입' 추가"와 같은 메시지를 입력합니다.
- 메시지 처리: 시스템에서 대화 기록에 메시지를 추가합니다.
- LLM 분석: Azure OpenAI는 요청을 분석하고 사용할 도구를 결정합니다.
-
도구 검색: 모델은 올바른 MCP 도구를 찾습니다(예:
addTodo). - 도구 실행: MCP 클라이언트가 필요한 매개 변수를 사용하여 서버를 호출합니다.
- 응답 처리: 시스템에서 대화에 서버 응답을 추가합니다.
- UI 업데이트: 시스템에서 사용자에게 실시간으로 결과를 표시합니다.
다음 다이어그램은 메시지가 사용자 입력에서 OpenAI를 통해 도구 실행으로, 그리고 사용자 인터페이스로 다시 이동하는 방법을 보여 줍니다.
비동기 패턴 관리
애플리케이션은 백그라운드 작업에 대한 정교한 비동기 패턴을 보여 줍니다.
// ChatSuggestions.razor
public void Update(IReadOnlyList<ChatMessage> messages)
{
// Runs in the background and handles its own cancellation/errors
_ = UpdateSuggestionsAsync(messages);
}
private async Task UpdateSuggestionsAsync(IReadOnlyList<ChatMessage> messages)
{
cancellation?.Cancel();
cancellation = new CancellationTokenSource();
try
{
var response = await ChatClient.GetResponseAsync<string[]>(
[.. ReduceMessages(messages), new(ChatRole.User, Prompt)],
cancellationToken: cancellation.Token);
// Handle response...
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
await DispatchExceptionAsync(ex);
}
}
백그라운드 작업 이점:
-
안전으로 화재 및 잊어 버리기: 시스템은 적절한 예외 처리와 패턴을 사용합니다
_ =. - 스마트 컨텍스트 감소: 시스템은 토큰 오버플로를 방지하기 위해 대화 기록을 제한합니다.
- 스마트 취소: 시스템이 경쟁 작업을 제대로 정리합니다.
오류 처리 및 복원력
구현에는 다음과 같은 몇 가지 복원력 패턴이 포함됩니다.
private void CancelAnyCurrentResponse()
{
// If a response was cancelled while streaming, include it in the conversation so it's not lost
if (currentResponseMessage is not null)
{
messages.Add(currentResponseMessage);
}
currentResponseCancellation?.Cancel();
currentResponseMessage = null;
}
복원력 기능:
- 정상 취소: 사용자가 취소할 때 시스템에서 진행 중인 응답을 저장합니다.
- 연결 복구: SSE 전송이 자동으로 연결 삭제를 처리합니다.
- 상태 관리: 오류 발생 시 UI 상태가 일관되게 유지됩니다.
- 로깅 통합: 시스템은 디버깅 및 모니터링을 위한 전체 로깅을 제공합니다.
관찰 가능성 및 상태 검사
애플리케이션에는 정교한 관찰 패턴이 포함됩니다.
Smart Health Check 구성:
// Extensions.cs
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
if (app.Environment.IsDevelopment())
{
// All health checks must pass for app to be considered ready
app.MapHealthChecks(HealthEndpointPath);
// Only health checks tagged with "live" must pass for app to be considered alive
app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
}
return app;
}
지능형 필터링을 사용하여 OpenTelemetry:
// Extensions.cs
.AddAspNetCoreInstrumentation(tracing =>
// Exclude health check requests from tracing
tracing.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)
관찰 가능성 이점:
- Environment-Aware 엔드포인트: 보안에 민감한 상태 검사 노출
- 활동성 및 준비: Kubernetes 스타일 상태 검사 패턴
- 원격 분석 노이즈 감소: 추적에서 일상적인 상태 검사 필터링
구성 및 환경 설정
애플리케이션은 구성을 통해 여러 환경을 지원합니다.
var openAIClient = Constants.GitHubModelEndpoints.Contains(endpoint.TrimEnd('/'))
? new OpenAIClient(credential, openAIOptions)
: new AzureOpenAIClient(new Uri(endpoint), credential);
구성 옵션:
- Azure OpenAI: 프로덕션 배포는 일반적으로 Azure OpenAI 서비스를 사용합니다.
- GitHub 모델: 개발 시나리오에서 GitHub 모델을 사용할 수 있습니다.
- 로컬 개발: 로컬 MCP 서버 인스턴스 지원
- 컨테이너 배포: 프로덕션 호스팅을 위한 Azure Container Apps
자원을 정리하세요
MCP 에이전트 사용을 마친 후 불필요한 비용이 발생하지 않도록 만든 리소스를 정리합니다.
리소스를 정리하려면 다음 단계를 수행합니다.
화면 아래쪽의 터미널에서 다음 명령을 실행하여 Azure Developer CLI에서 만든 Azure 리소스를 삭제합니다.
azd down --purge --force
GitHub Codespaces 정리
GitHub Codespaces 환경을 삭제하여 코어당 무료 시간을 최대화합니다.
중요합니다
GitHub 계정의 무료 스토리지 및 코어 시간에 대한 자세한 내용은 GitHub Codespaces 월별 포함된 스토리지 및 코어 시간을 참조하세요.
GitHub 리포지토리에서
Azure-Samples/openai-mcp-agent-dotnet만든 활성 Codespace를 찾습니다.코드스페이스의 상황에 맞는 메뉴를 열고 삭제를 선택합니다.
도움받기
리포지토리의 문제에 문제를 기록합니다.