이 빠른 시작에서는 Azure 개발자 CLI(azd)를 사용하여 템플릿 프로젝트에서 사용자 지정 MCP(원격 모델 컨텍스트 프로토콜) 서버를 만듭니다. 이 MCP 서버는 Azure Functions MCP 서버 확장을 사용하여 AI 모델, 에이전트 및 도우미용 도구를 제공합니다. MCP 서버 확장을 사용하여 대화형 MCP 앱을 만들 수도 있습니다.
프로젝트를 로컬로 실행하고 GitHub Copilot 사용하여 코드를 확인한 후에는 안전하고 확장 가능한 배포에 대한 현재 모범 사례를 따르는 Azure Functions 새 서버리스 함수 앱에 배포합니다.
새 앱은 pay for-what-you-use 청구 모델을 따르는 Flex Consumption 계획에서 실행되므로 이 빠른 시작을 완료하면 Azure 계정에서 몇 USD 센트 이하의 비용이 발생합니다.
중요합니다
사용자 지정 MCP 서버 만들기는 모든 Functions 언어에서 지원되지만 이 빠른 시작 시나리오에는 현재 C#, Java, Python 및 TypeScript에 대한 예제만 있습니다. 이 빠른 시작을 완료하려면 문서 맨 위에서 지원되는 언어 중 하나를 선택합니다.
이 문서에서는 Azure Functions Node.js 프로그래밍 모델의 버전 4를 지원합니다.
이 문서에서는 Azure Functions Python 프로그래밍 모델의 버전 2를 지원합니다.
필수 조건
-
Java 17 개발자 키트
- 다른 지원되는 버전의 Java 사용하는 경우 프로젝트의
pom.xml파일을 업데이트합니다. -
JAVA_HOME환경 변수를 올바른 버전의 JDK(Java Development Kit)의 설치 위치로 설정합니다.
- 다른 지원되는 버전의 Java 사용하는 경우 프로젝트의
- Apache Maven 3.8.x
다음 확장이 포함된 Visual Studio Code
Azure Functions 확장. 이 확장을 사용하려면 Azure Functions Core Tools가 필요하며 사용할 수 없는 경우 설치를 시도합니다.
Azure CLI. Azure Cloud Shell Azure CLI 명령을 실행할 수도 있습니다.
활성 구독이 있는 Azure 계정입니다. 무료로 계정을 만듭니다.
프로젝트 시작
azd init 명령을 사용하여 템플릿에서 로컬 Azure Functions 코드 프로젝트를 만듭니다.
- Visual Studio Code에서 프로젝트를 만들고자 하는 폴더나 작업 영역을 엽니다.
터미널에서 다음
azd init명령을 실행합니다.azd init --template remote-mcp-functions-dotnet -e mcpserver-dotnet이 명령은 template 리포지토리에서 프로젝트 파일을 끌어와 현재 폴더에서 프로젝트를 초기화합니다.
-e플래그는 현재 환경의 이름을 설정합니다. 환경에서azd는 앱에 대한 고유한 배포 컨텍스트를 유지 관리하며 둘 이상을 정의할 수 있습니다. 또한 Azure 만드는 리소스 그룹 이름의 일부이기도 합니다.
로컬 터미널 또는 명령 프롬프트에서 다음
azd init명령을 실행합니다.azd init --template remote-mcp-functions-java -e mcpserver-java이 명령은 template 리포지토리에서 프로젝트 파일을 끌어와 현재 폴더에서 프로젝트를 초기화합니다.
-e플래그는 현재 환경의 이름을 설정합니다. 환경에서azd는 앱에 대한 고유한 배포 컨텍스트를 유지 관리하며 둘 이상을 정의할 수 있습니다. 또한 Azure 만드는 리소스 이름의 일부이기도 합니다.
로컬 터미널 또는 명령 프롬프트에서 다음
azd init명령을 실행합니다.azd init --template remote-mcp-functions-typescript -e mcpserver-ts이 명령은 template 리포지토리에서 프로젝트 파일을 끌어와 현재 폴더에서 프로젝트를 초기화합니다.
-e플래그는 현재 환경의 이름을 설정합니다. 환경에서azd는 앱에 대한 고유한 배포 컨텍스트를 유지 관리하며 둘 이상을 정의할 수 있습니다. 또한 Azure 만드는 리소스 이름의 일부이기도 합니다.
로컬 터미널 또는 명령 프롬프트에서 다음
azd init명령을 실행합니다.azd init --template remote-mcp-functions-python -e mcpserver-python이 명령은 template 리포지토리에서 프로젝트 파일을 끌어와 현재 폴더에서 프로젝트를 초기화합니다.
-e플래그는 현재 환경의 이름을 설정합니다. 환경에서azd는 앱에 대한 고유한 배포 컨텍스트를 유지 관리하며 둘 이상을 정의할 수 있습니다. 또한 Azure 만드는 리소스 이름의 일부이기도 합니다.
스토리지 에뮬레이터 시작
Azurite 에뮬레이터를 사용하여 코드 프로젝트를 로컬로 실행할 때 Azure Storage 계정 연결을 시뮬레이션합니다.
아직 설치하지 않은 경우 Azurite를 설치합니다.
F1 키를 누릅니다. 명령 팔레트에서 명령을
Azurite: Start검색하고 실행하여 로컬 스토리지 에뮬레이터를 시작합니다.
로컬로 MCP 서버 실행
터미널 창에서 프로젝트 폴더로 FunctionsMcpTool 이동합니다.
cd src/FunctionsMcpTool
터미널 창에서 프로젝트 폴더로 FunctionsMcpTool 이동합니다.
cd samples/FunctionsMcpTool
Visual Studio Code Azure Functions Core 도구 통합하여 로컬 개발 컴퓨터에서 이 프로젝트를 실행할 수 있습니다. Functions 앱을 로컬로 시작하려면 F5 키를 누르거나 왼쪽 작업 표시줄에서 실행 및 디버그 아이콘을 선택합니다.
터미널 패널에는 Core Tools의 출력이 표시됩니다. 앱이 터미널 패널에서 시작되고 로컬로 실행되는 함수의 이름을 볼 수 있습니다.
GitHub Copilot 사용하여 확인
프로젝트 템플릿에는 .vscode/mcp.json 파일이 포함되어 있으며, 이는 로컬 MCP 엔드포인트를 가리키는 local-mcp-function 서버를 이미 정의합니다. 이 구성을 사용하여 Visual Studio Code GitHub Copilot 사용하여 코드를 확인합니다.
.vscode/mcp.json파일을 열고 구성 위의local-mcp-function단추를 선택합니다.Copilot Chat 창에서 Agent 모드가 선택되어 있는지 확인하고, Configure 도구 아이콘을 선택하고, 채팅에서
MCP Server:local-mcp-function사용하도록 설정되어 있는지 확인합니다.다음 프롬프트를 실행합니다.
Say Hello도구를 실행하라는 메시지가 표시되면 권한을 계속 부여할 필요가 없도록 이 작업 영역에서 허용 을 선택합니다. 프롬프트가 실행되고
헬로 월드응답 및 함수 실행 정보가 로그에 기록됩니다.이제 프로젝트 파일 중 하나에서 일부 코드를 선택하고 다음 프롬프트를 실행합니다.
Save this snippet as snippet1Copilot 코드 조각을 저장하고
getSnippets도구를 사용하여 코드 조각을 검색하는 방법에 대한 정보를 사용하여 요청에 응답합니다. 로그에서 함수 실행을 다시 검토하고saveSnippets함수가 실행되었는지 확인할 수 있습니다.Copilot 채팅에서 다음 프롬프트를 실행합니다.
Retrieve snippet1 and apply to NewFileCopilot 코드 조각을 검색하고,
NewFile파일에 추가하고, 코드 조각이 프로젝트에서 작동하도록 하는 데 필요한 다른 작업을 수행합니다. Functions 로그는 엔드포인트가getSnippets호출되었음을 보여 줍니다.테스트를 마쳤으면 Ctrl+C를 눌러 Functions 호스트를 중지합니다.
코드 검토(선택 사항)
MCP 서버 도구를 정의하는 코드를 검토할 수 있습니다.
MCP 서버 도구에 대한 함수 코드는 폴더에 src 정의되어 있습니다. 이 특성은 McpToolTrigger 함수를 MCP 서버 도구로 노출합니다.
[Function(nameof(SayHello))]
public string SayHello(
[McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
logger.LogInformation("C# MCP tool trigger function processed a request.");
return "Hello I am MCP Tool!";
}
public class SnippetsTool(ILogger<SnippetsTool> logger)
{
private const string BlobPath = "snippets/{mcptoolargs.Name}.json";
private static BlobServiceClient GetBlobServiceClient() =>
new(Environment.GetEnvironmentVariable("AzureWebJobsStorage"));
[Function(nameof(GetSnippet))]
public Snippet? GetSnippet(
[McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)]
ToolInvocationContext context,
[McpToolProperty(SnippetNamePropertyName, SnippetNamePropertyDescription, true)]
string name,
[BlobInput(BlobPath)] string? snippetContent
)
{
if (snippetContent is null)
{
return null;
}
return new Snippet { Name = name, Content = snippetContent };
}
전체 프로젝트 템플릿은 Azure Functions .NET MCP Server GitHub 리포지토리에서 볼 수 있습니다.
MCP 서버 도구에 대한 함수 코드는 폴더에 samples/FunctionsMcpTool/src/main/java/com/function/ 정의되어 있습니다. 주석은 @McpToolTrigger 함수를 MCP 서버 도구로 노출합니다.
@FunctionName("HelloWorld")
public String logCustomTriggerInput(
@McpToolTrigger(
name = "helloWorld",
description = "Says hello and logs the messages that are provided.")
McpToolInvocationContext mcpToolInvocationContext,
@McpToolProperty(
name = "messages",
propertyType = "string",
description = "The messages to be logged.",
isRequired = true,
isArray = true)
String messages,
final ExecutionContext functionExecutionContext
) {
@FunctionName("SaveSnippets")
@StorageAccount("AzureWebJobsStorage")
public String saveSnippet(
@McpToolTrigger(
name = "saveSnippets",
description = "Saves a text snippet to your snippets collection.")
String mcpToolInvocationContext,
@McpToolProperty(
name = SNIPPET_NAME_PROPERTY_NAME,
propertyType = "string",
description = "The name of the snippet.",
isRequired = true)
String snippetName,
@McpToolProperty(
name = SNIPPET_PROPERTY_NAME,
propertyType = "string",
description = "The content of the snippet.",
isRequired = true)
String snippet,
@BlobOutput(name = "outputBlob", path = BLOB_PATH)
OutputBinding<String> outputBlob,
final ExecutionContext functionExecutionContext
) {
// Log the entire incoming JSON for debugging
functionExecutionContext.getLogger().info(mcpToolInvocationContext);
// Log the snippet name and content
functionExecutionContext.getLogger().info("Saving snippet with name: " + snippetName);
functionExecutionContext.getLogger().info("Snippet content:\n" + snippet);
// Write the snippet content to the output blob
outputBlob.setValue(snippet);
return "Successfully saved snippet '" + snippetName + "' with " + snippet.length() + " characters.";
전체 프로젝트 템플릿은 Azure Functions Java MCP Server GitHub 리포지토리에서 볼 수 있습니다.
MCP 서버 도구에 대한 함수 코드는 파일에 정의되어 있습니다 src/function_app.py . MCP 함수 주석은 이러한 함수를 MCP 서버 도구로 노출합니다.
@app.mcp_tool()
@app.mcp_tool_property(arg_name="snippetname", description="The name of the snippet.")
@app.blob_input(arg_name="file", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def get_snippet(file: func.InputStream, snippetname: str) -> str:
"""Retrieve a snippet by name from Azure Blob Storage."""
snippet_content = file.read().decode("utf-8")
logging.info(f"Retrieved snippet: {snippet_content}")
return snippet_content
@app.mcp_tool()
@app.mcp_tool_property(arg_name="snippetname", description="The name of the snippet.")
@app.mcp_tool_property(arg_name="snippet", description="The content of the snippet.")
@app.blob_output(arg_name="file", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def save_snippet(file: func.Out[str], snippetname: str, snippet: str) -> str:
"""Save a snippet with a name to Azure Blob Storage."""
if not snippetname:
return "No snippet name provided"
if not snippet:
return "No snippet content provided"
file.set(snippet)
logging.info(f"Saved snippet: {snippet}")
return f"Snippet '{snippet}' saved successfully"
Azure Functions Python MCP Server GitHub 리포지토리에서 전체 프로젝트 템플릿을 볼 수 있습니다.
MCP 서버 도구에 대한 함수 코드는 폴더에 mcp-tools/src 정의되어 있습니다. MCP 함수 등록은 이러한 함수를 MCP 서버 도구로 노출합니다.
// Hello function - responds with hello message
export async function mcpToolHello(_toolArguments: unknown, context: InvocationContext): Promise<string> {
const mcptoolargs = context.triggerMetadata.mcptoolargs as {
name?: string;
};
const name = mcptoolargs?.name;
context.log(`Hello ${name}, I am MCP Tool!`);
return `Hello ${name || 'World'}, I am MCP Tool!`;
}
// Register the hello tool
app.mcpTool('hello', {
toolName: 'hello',
description: 'Simple hello world MCP Tool that responds with a hello message.',
toolProperties: {
name: arg.string().describe('Required property to identify the caller.').optional()
},
handler: mcpToolHello
});
// Register the GetSnippet tool
app.mcpTool("getSnippet", {
toolName: GET_SNIPPET_TOOL_NAME,
description: GET_SNIPPET_TOOL_DESCRIPTION,
toolProperties: {
[SNIPPET_NAME_PROPERTY_NAME]: arg.string().describe(SNIPPET_NAME_PROPERTY_DESCRIPTION)
},
extraInputs: [blobInputBinding],
handler: getSnippet,
});
// Register the SaveSnippet tool
app.mcpTool("saveSnippet", {
toolName: SAVE_SNIPPET_TOOL_NAME,
description: SAVE_SNIPPET_TOOL_DESCRIPTION,
toolProperties: {
[SNIPPET_NAME_PROPERTY_NAME]: arg.string().describe(SNIPPET_NAME_PROPERTY_DESCRIPTION),
[SNIPPET_PROPERTY_NAME]: arg.string().describe(SNIPPET_PROPERTY_DESCRIPTION)
},
extraOutputs: [blobOutputBinding],
handler: saveSnippet,
});
전체 프로젝트 템플릿은 Azure Functions TypeScript MCP Server GitHub 리포지토리에서 볼 수 있습니다.
MCP 서버 도구를 로컬로 확인한 후 프로젝트를 Azure 게시할 수 있습니다.
Azure에 배포
이 프로젝트는 azd 사용하여 Azure Flex Consumption 계획의 새 함수 앱에 이 프로젝트를 배포하도록 구성됩니다. 이 프로젝트에는 azd가 모범 사례를 따르는 Flex 소비 계획에 대한 보안 배포를 만드는 데 사용하는 Bicep 파일들이 포함되어 있습니다.
Visual Studio Code F1 키를 눌러 명령 팔레트를 엽니다. 명령
Azure Developer CLI (azd): Package, Provision and Deploy (up)검색하고 실행합니다. 그런 다음 Azure 계정을 사용하여 로그인합니다.메시지가 표시되면 다음 필수 배포 매개 변수를 선택합니다.
매개 변수 Description Azure 구독 리소스가 만들어지는 구독. Azure 위치 새 Azure 리소스가 포함될 리소스 그룹을 만들 Azure 지역입니다. 현재 Flex 사용량 플랜을 지원하는 지역만 표시됩니다. vnetEnabled False가상 네트워크 리소스 만들기를 건너뛰면 배포가 간소화됩니다.명령이 성공적으로 완료되면, 만든 리소스에 대한 링크가 표시됩니다.
원격 MCP 서버에 연결
이제 MCP 서버가 Azure 실행 중입니다. 프로젝트 템플릿에는 원격 서버에 연결하도록 이미 구성된 remote-mcp-function 항목이 .vscode/mcp.json에 포함되어 있습니다. 이 서버를 시작하면 VS Code에서 원격 MCP 엔드포인트에 액세스하는 데 필요한 함수 앱 이름 및 시스템 키를 묻는 메시지를 표시합니다.
azd및 Azure CLI 사용하여 도구에 액세스하는 데 필요한 함수 앱 이름과 시스템 키(mcp_extension)를 모두 출력하는 이 스크립트를 실행합니다.eval $(azd env get-values --output dotenv) MCP_EXTENSION_KEY=$(az functionapp keys list --resource-group $AZURE_RESOURCE_GROUP \ --name $AZURE_FUNCTION_NAME --query "systemKeys.mcp_extension" -o tsv) printf "Function app name: %s\n" "$SERVICE_API_NAME" printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY".vscode/mcp.json구성 위의 시작을 선택합니다.메시지가 표시되면 이전 단계의 함수 앱 이름 및 시스템 키 값을 입력합니다.
배포를 확인하십시오
이제 로컬에서 했던 것처럼 원격 MCP 도구를 GitHub Copilot 사용할 수 있지만 이제 코드는 Azure 안전하게 실행됩니다. 앞에서 사용한 것과 동일한 명령을 재생하여 모든 것이 올바르게 작동하는지 확인합니다.
자원을 정리하세요
MCP 서버 및 관련 리소스 작업을 마쳤으면 이 명령을 사용하여 Azure 함수 앱 및 관련 리소스를 삭제하여 추가 비용이 발생하지 않도록 합니다.
azd down