Поделиться через


Краткое руководство. Создание пользовательского удаленного сервера MCP с помощью Функций Azure

В этом кратком руководстве вы создадите настраиваемый удаленный сервер протокола Model Context Protocol (MCP) из проекта-шаблона, используя CLI для разработчиков Azure (azd). Сервер MCP использует расширение сервера MCP функций Azure для предоставления средств для моделей ИИ, агентов и помощников. После локального запуска проекта и проверки кода с помощью GitHub Copilot вы развернете его в новом бессерверном приложении-функции в Функциях Azure, которое следует текущим рекомендациям по безопасным и масштабируемым развертываниям.

Подсказка

Функции также позволяют развертывать существующий проект кода сервера MCP в приложении плана потребления Flex без необходимости вносить изменения в проект кода. Дополнительные сведения см. в кратком руководстве по размещению существующих серверов MCP в Функциях Azure.

Поскольку новое приложение работает на плане Flex Consumption, который следует модели выставления счетов с оплатой за фактическое использование, выполнение этого быстрого старта обойдется в небольшую сумму — несколько центов или менее с вашей учетной записью в Azure.

Это важно

Создание пользовательских серверов MCP поддерживается для всех языков функций; однако в этом сценарии быстрого старта на данный момент содержатся только примеры для C#, Python и TypeScript. Чтобы завершить работу с этим кратким руководством, выберите один из этих поддерживаемых языков в верхней части статьи.

Эта статья поддерживает версию 4 модели программирования Node.js для Функции Azure.

Эта статья поддерживает версию 2 модели программирования Python для Функции Azure.

Предпосылки

  • Пакет разработчиков Java 17
    • Если вы используете другую поддерживаемую версию Java, необходимо обновить файл pom.xml проекта.
    • JAVA_HOME Установите переменную среды в расположение установки правильной версии пакета средств разработки Java (JDK).
  • Apache Maven 3.8.x

Инициализируйте проект

azd init Используйте команду для создания локального проекта кода Функций Azure из шаблона.

  1. В Visual Studio Code откройте папку или рабочую область, в которой вы хотите создать проект.
  1. В терминале выполните следующую azd init команду:

    azd init --template remote-mcp-functions-dotnet -e mcpserver-dotnet
    

    Эта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг -e задает имя текущей среды. В azd среде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Он также используется в имени группы ресурсов, создаваемой в Azure.

  1. В локальном терминале или командной строке выполните следующую azd init команду:

    azd init --template remote-mcp-functions-java -e mcpserver-java 
    

    Эта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг -e задает имя текущей среды. В azd среде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Он также используется в именах ресурсов, создаваемых в Azure.

  1. В локальном терминале или командной строке выполните следующую azd init команду:

    azd init --template remote-mcp-functions-typescript -e mcpserver-ts
    

    Эта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг -e задает имя текущей среды. В azd среде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Он также используется в именах ресурсов, создаваемых в Azure.

  1. В локальном терминале или командной строке выполните следующую azd init команду:

    azd init --template remote-mcp-functions-python -e mcpserver-python
    

    Эта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг -e задает имя текущей среды. В azd среде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Он также используется в именах ресурсов, создаваемых в Azure.

Запуск эмулятора хранилища

Используйте эмулятор Azurite для имитации подключения учетной записи хранения Azure при локальном запуске проекта кода.

  1. Если вы еще не сделали этого, установите Azurite.

  2. Нажмите клавишу F1. В палитре команд найдите и запустите команду Azurite: Start , чтобы запустить локальный эмулятор хранилища.

Локальное выполнение сервера MCP

Visual Studio Code интегрируется с инструментами Azure Functions Core , чтобы позволить запускать этот проект на локальном компьютере разработки с помощью эмулятора Azurite.

  1. Чтобы запустить функцию локально, нажмите клавишу F5 или значок запуска и отладки на панели действий слева. На панели терминала отображаются выходные данные основных инструментов. Приложение запускается на панели терминала и отображается имя функций, выполняемых локально.

  2. Запишите локальную конечную точку сервера MCP (например http://localhost:7071/runtime/webhooks/mcp), которая используется для настройки GitHub Copilot в Visual Studio Code.

Проверьте с помощью GitHub Copilot

Чтобы проверить код, добавьте выполняющийся проект в качестве сервера MCP для GitHub Copilot в Visual Studio Code:

  1. Нажмите клавишу F1. В палитре команд найдите и запустите MCP: добавить сервер.

  2. Выберите HTTP (Server-Sent Events) в качестве вида транспорта.

  3. Введите URL-адрес конечной точки MCP, скопированной на предыдущем шаге.

  4. Используйте созданный идентификатор сервера и выберите рабочую область , чтобы сохранить подключение сервера MCP к параметрам рабочей области.

  5. Откройте палитру команд и запустите MCP: список серверов и убедитесь, что добавленный сервер указан и запущен.

  6. В чате Copilot выберите режим агента и выполните следующую команду:

    Say Hello
    

    При появлении запроса на запуск средства нажмите кнопку "Разрешить в этой рабочей области ", чтобы вам не нужно предоставлять разрешение. Запрос выполняется и возвращает ответ Hello World, а информация о выполнении функций записывается в журналы.

  7. Теперь выберите код в одном из файлов проекта и выполните следующую команду:

    Save this snippet as snippet1
    

    Copilot хранит фрагмент и отвечает на ваш запрос с информацией о том, как получить его с помощью getSnippets инструмента. Опять же, можно просмотреть выполнение функции в журналах и убедиться, что функция запущена saveSnippets .

  8. В чате Copilot выполните следующую команду:

    Retrieve snippet1 and apply to NewFile
    

    Copilot получает фрагменты кода, добавляет их в файл с именем NewFile и делает все, что, по его мнению, необходимо для работы фрагмента кода в проекте. В журналах функций показано, что getSnippets конечная точка была вызвана.

  9. После завершения тестирования нажмите клавиши CTRL+C, чтобы остановить хост функций.

Просмотр кода (необязательно)

Вы можете просмотреть код, определяющий средства сервера MCP:

Код функции для средств сервера MCP определен в папке src . Атрибут McpToolTrigger предоставляет функции в виде средств MCP Server:

[Function(nameof(SayHello))]
public string SayHello(
    [McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
    logger.LogInformation("Saying hello");
    return "Hello I am MCP Tool!";
}
    [Function(nameof(GetSnippet))]
    public object GetSnippet(
        [McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)]
            ToolInvocationContext context,
        [BlobInput(BlobPath)] string snippetContent
    )
    {
        return snippetContent;
    }

    [Function(nameof(SaveSnippet))]
    [BlobOutput(BlobPath)]
    public string SaveSnippet(
        [McpToolTrigger(SaveSnippetToolName, SaveSnippetToolDescription)]
            ToolInvocationContext context,
        [McpToolProperty(SnippetNamePropertyName, SnippetNamePropertyDescription, true)]
            string name,
        [McpToolProperty(SnippetPropertyName, SnippetPropertyDescription, true)]
            string snippet
    )
    {
        return snippet;
    }
}

Полный шаблон проекта можно просмотреть в репозитории GitHub Azure Functions .NET MCP Server.

Код функции для средств сервера MCP определен в папке src/main/java/com/function/ . Заметка @McpToolTrigger предоставляет функции в виде средств MCP Server:

            description = "The messages to be logged.",
            isRequired = true,
            isArray = true)
        String messages,
        final ExecutionContext functionExecutionContext
) {
    functionExecutionContext.getLogger().info("Hello, World!");
    functionExecutionContext.getLogger().info("Tool Name: " + mcpToolInvocationContext.getName());
    functionExecutionContext.getLogger().info("Transport Type: " + mcpToolInvocationContext.getTransportType());
    
    // Handle different transport types
    if (mcpToolInvocationContext.isHttpStreamable()) {
        functionExecutionContext.getLogger().info("Session ID: " + mcpToolInvocationContext.getSessionid());
    } else if (mcpToolInvocationContext.isHttpSse()) {
        if (mcpToolInvocationContext.getClientinfo() != null) {
            functionExecutionContext.getLogger().info("Client: " + 
                mcpToolInvocationContext.getClientinfo().get("name").getAsString() + " v" +
    // Write the snippet content to the output blob
    outputBlob.setValue(snippet);
    
    return "Successfully saved snippet '" + snippetName + "' with " + snippet.length() + " characters.";
}

/**
 * Azure Function that handles retrieving a text snippet from Azure Blob Storage.
 * <p>
 * The function is triggered by an MCP Tool Trigger. The snippet name is provided
 * as an MCP tool property, and the snippet content is read from the blob at the 
 * path derived from the snippet name.
 *
 * @param mcpToolInvocationContext The JSON input from the MCP tool trigger.
 * @param snippetName   The name of the snippet to retrieve, provided as an MCP tool property.
 * @param inputBlob     The Azure Blob input binding that fetches the snippet content.
 * @param functionExecutionContext       The execution context for logging.
 */
@FunctionName("GetSnippets")
@StorageAccount("AzureWebJobsStorage")
public String getSnippet(
        @McpToolTrigger(
            name = "getSnippets",
            description = "Gets a text snippet from your snippets collection.")
        String mcpToolInvocationContext,
        @McpToolProperty(
            name = SNIPPET_NAME_PROPERTY_NAME,
            propertyType = "string",
            description = "The name of the snippet.",
            isRequired = true)
        String snippetName,
        @BlobInput(name = "inputBlob", path = BLOB_PATH)
        String inputBlob,
        final ExecutionContext functionExecutionContext
) {
    // Log the entire incoming JSON for debugging
    functionExecutionContext.getLogger().info(mcpToolInvocationContext);

    // Log the snippet name and the fetched snippet content from the blob

Полный шаблон проекта можно просмотреть в репозитории GitHub для сервера Azure Functions Java MCP.

Код функции для серверных средств MCP определен в src/function_app.py файле. Аннотации функций MCP представляют эти функции как инструменты сервера MCP.

tool_properties_save_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_save_snippets_object])
tool_properties_get_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_get_snippets_object])


@app.generic_trigger(
    arg_name="context",
    type="mcpToolTrigger",
    toolName="hello_mcp",
    description="Hello world.",
    toolProperties="[]",
)
def hello_mcp(context) -> None:
    """

@app.generic_trigger(
    arg_name="context",
    type="mcpToolTrigger",
    toolName="save_snippet",
    description="Save a snippet with a name.",
    toolProperties=tool_properties_save_snippets_json,
)
@app.generic_output_binding(arg_name="file", type="blob", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def save_snippet(file: func.Out[str], context) -> str:
    content = json.loads(context)
    snippet_name_from_args = content["arguments"][_SNIPPET_NAME_PROPERTY_NAME]
    snippet_content_from_args = content["arguments"][_SNIPPET_PROPERTY_NAME]

    if not snippet_name_from_args:
        return "No snippet name provided"

    if not snippet_content_from_args:
        return "No snippet content provided"

    file.set(snippet_content_from_args)
    logging.info(f"Saved snippet: {snippet_content_from_args}")
    return f"Snippet '{snippet_content_from_args}' saved successfully"

Полный шаблон проекта можно просмотреть в репозитории GitHub серверной части Python для функции Azure на платформе MCP.

Код функции для средств сервера MCP определен в папке src . Регистрация функции MCP предоставляет эти функции в качестве средств СЕРВЕРА MCP:

export async function mcpToolHello(_toolArguments:unknown, context: InvocationContext): Promise<string> {
    console.log(_toolArguments);
    // Get name from the tool arguments
    const mcptoolargs = context.triggerMetadata.mcptoolargs as {
        name?: string;
    };
    const name = mcptoolargs?.name;

    console.info(`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 responses with a hello message.',
    toolProperties:{
        name: arg.string().describe('Required property to identify the caller.').optional()
    },
    handler: mcpToolHello
});
// SaveSnippet function - saves a snippet with a name
export async function saveSnippet(
  _toolArguments: unknown,
  context: InvocationContext
): Promise<string> {
  console.info("Saving snippet");

  // Get snippet name and content from the tool arguments
  const mcptoolargs = context.triggerMetadata.mcptoolargs as {
    snippetname?: string;
    snippet?: string;
  };

  const snippetName = mcptoolargs?.snippetname;
  const snippet = mcptoolargs?.snippet;

  if (!snippetName) {
    return "No snippet name provided";
  }

  if (!snippet) {
    return "No snippet content provided";
  }

  // Save the snippet to blob storage using the output binding
  context.extraOutputs.set(blobOutputBinding, snippet);

  console.info(`Saved snippet: ${snippetName}`);
  return snippet;
}

Полный шаблон проекта можно просмотреть в репозитории GitHub сервера Функций Azure TypeScript MCP .

После локальной проверки средств сервера MCP можно опубликовать проект в Azure.

Развертывание в Azure

Этот проект настроен для azd up развертывания этого проекта в новом приложении-функции в плане потребления Flex в Azure. Проект включает набор файлов Bicep, используемых azd для создания безопасного развертывания в плане потребления Flex, который следует наилучшей практике.

  1. В Visual Studio Code нажмите клавишу F1, чтобы открыть палитру команд. Найдите и выполните команду Azure Developer CLI (azd): Package, Provison and Deploy (up). Затем войдите с помощью учетной записи Azure.

  2. Если вы еще не выполнили вход, выполните проверку подлинности с помощью учетной записи Azure.

  3. При появлении запроса укажите следующие необходимые параметры развертывания:

    Параметр Description
    Подписка Azure Подписка, в которой создаются ресурсы.
    Расположение Azure Регион Azure, в котором создается группа ресурсов, содержащая новые ресурсы Azure. Отображаются только регионы, поддерживающие план потребления Flex.

    После успешного завершения команды вы увидите ссылки на созданные ресурсы.

Подключение к удаленному серверу MCP

Сервер MCP теперь работает в Azure. При доступе к средствам необходимо включить системный ключ в запрос. Этот ключ обеспечивает степень контроля доступа для клиентов, обращаюющихся к удаленному серверу MCP. После получения этого ключа вы можете подключить GitHub Copilot к удаленному серверу.

  1. Запустите этот скрипт, который использует azd и Azure CLI, чтобы распечатать URL-адрес сервера MCP и системный ключ (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 "MCP Server URL: %s\n" "https://$SERVICE_API_NAME.azurewebsites.net/runtime/webhooks/mcp"
    printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY"
    
  2. В Visual Studio Code нажмите клавишу F1 , чтобы открыть палитру команд, выполните поиск и выполните команду MCP: Open Workspace Folder MCP Configuraton, которая открывает mcp.json файл конфигурации.

  3. mcp.json В конфигурации найдите добавленный ранее сервер MCP, измените url значение на URL-адрес удаленного сервера MCP и добавьте headers.x-functions-key элемент, содержащий скопированный ключ доступа к серверу MCP, как показано в следующем примере:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Нажмите кнопку "Пуск " над именем сервера в открытом режиме mcp.json , чтобы перезапустить удаленный сервер MCP, на этот раз с помощью развернутого приложения.

Проверьте ваше развертывание

Теперь вы можете использовать GitHub Copilot для удаленных средств MCP так же, как и локально, но теперь код выполняется безопасно в Azure. Воспроизвести те же команды, которые вы использовали ранее, чтобы убедиться, что все работает правильно.

Очистите ресурсы

Когда вы закончите работу с сервером MCP и связанными ресурсами, используйте эту команду, чтобы удалить приложение-функцию и связанные ресурсы из Azure, чтобы избежать дополнительных затрат:

azd down --no-prompt

Замечание

Параметр --no-prompt указывает azd удалить группу ресурсов без подтверждения. Эта команда не влияет на локальный проект кода.

Дальнейшие шаги