مشاركة عبر


التشغيل السريع: إنشاء خادم MCP بعيد مخصص باستخدام Azure Functions

في هذا التشغيل السريع، يمكنك إنشاء خادم بروتوكول سياق النموذج البعيد (MCP) المخصص من مشروع قالب باستخدام Azure Developer CLI (azd). يستخدم خادم MCP ملحق خادم Azure Functions MCP لتوفير أدوات لنماذج الذكاء الاصطناعي والوكلاء والمساعدين. بعد تشغيل المشروع محليا والتحقق من التعليمات البرمجية الخاصة بك باستخدام GitHub Copilot، يمكنك نشره إلى تطبيق وظائف جديد بلا خادم في Azure Functions يتبع أفضل الممارسات الحالية لعمليات التوزيع الآمنة والقابلة للتطوير.

تلميح

تمكنك Functions أيضا من نشر مشروع كود خادم MCP موجود في تطبيق خطة استهلاك مرنة دون الحاجة لإجراء تغييرات على مشروع الكود الخاص بك. لمزيد من المعلومات، راجع Quickstart: استضافة خوادم MCP الموجودة على Azure Functions.

نظرا لأن التطبيق الجديد يعمل على خطة Flex Consumption، التي تتبع نموذج فوترة الدفع مقابل ما تستخدمه ، فإن إكمال هذا التشغيل السريع يتحمل تكلفة صغيرة تبلغ بضعة سنتات أمريكية أو أقل في حساب Azure الخاص بك.

Important

بينما يدعم إنشاء خوادم MCP مخصصة لجميع لغات Functions، فإن سيناريو البدء السريع هذا يحتوي حاليا فقط على أمثلة ل C# وPython وTypeScript. لإكمال هذه البداية السريعة، اختر إحدى هذه اللغات المدعومة في أعلى المقال.

تدعم هذه المقالة الإصدار 4 من نموذج البرمجة Node.js ل Azure Functions.

تدعم هذه المقالة الإصدار 2 من نموذج برمجة Python ل Azure Functions.

المتطلبات الأساسية

تهيئة المشروع

استخدم الأمر azd init لإنشاء مشروع كود Azure Functions محلي من قالب.

  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 Storage عند تشغيل مشروع الكود محليا.

  1. إذا لم تكن قد قمت بذلك بالفعل، فقم بتثبيت Azurite.

  2. اضغط على F1. في لوحة الأوامر، ابحث عن الأمر Azurite: Start وقم بتشغيله لبدء تشغيل محاكي التخزين المحلي.

تشغيل خادم MCP محليا

يتكامل Visual Studio Code مع أدوات Azure Functions Core للسماح لك بتشغيل هذا المشروع على كمبيوتر التطوير المحلي باستخدام محاكي Azurite.

  1. لبدء تشغيل الوظيفة محليا، اضغط على F5 أو أيقونة Run and Debug في شريط النشاط على الجانب الأيمن. تعرض لوحة Terminal الإخراج من Core Tools. يبدأ تطبيقك في لوحة الوحدة الطرفية ، ويمكنك رؤية اسم الوظائف التي يتم تشغيلها محليا.

  2. قم بتدوين نقطة نهاية خادم MCP المحلية (مثل http://localhost:7071/runtime/webhooks/mcp) ، والتي تستخدمها لتكوين GitHub Copilot في Visual Studio Code.

التحقق باستخدام GitHub Copilot

للتحقق من التعليمات البرمجية الخاصة بك، أضف المشروع قيد التشغيل كخادم MCP ل GitHub Copilot في Visual Studio Code:

  1. اضغط على F1. في لوحة الأوامر، ابحث عن MCP: Add Server وقم بتشغيله.

  2. اختر HTTP (Server-Sent الأحداث) لنوع النقل.

  3. أدخل عنوان URL لنقطة نهاية MCP التي نسختها في الخطوة السابقة.

  4. استخدم معرف الخادم الذي تم إنشاؤه وحدد مساحة العمل لحفظ اتصال خادم MCP بإعدادات مساحة العمل الخاصة بك.

  5. افتح لوحة الأوامر وقم بتشغيل MCP: List Servers وتحقق من إدراج الخادم الذي أضفته وتشغيله.

  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:

[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;
    }
}

يمكنك عرض قالب المشروع الكامل في مستودع Azure Functions .NET MCP Server GitHub.

يتم تعريف التعليمات البرمجية للوظيفة لأدوات خادم MCP في المجلد src/main/java/com/function/ . يعرض التعليق @McpToolTrigger التوضيحي الوظائف كأدوات خادم MCP:

            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

يمكنك عرض قالب المشروع الكامل في مستودع Azure Functions Java MCP Server GitHub.

يتم تعريف التعليمات البرمجية للوظيفة لأدوات خادم 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"

يمكنك عرض قالب المشروع الكامل في مستودع Azure Functions Python MCP Server GitHub.

يتم تعريف التعليمات البرمجية للوظيفة لأدوات خادم 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;
}

يمكنك عرض قالب المشروع الكامل في مستودع Azure Functions TypeScript MCP Server GitHub.

بعد التحقق من أدوات خادم MCP محليا، يمكنك نشر المشروع على Azure.

نشر في Azure

تم تكوين هذا المشروع لاستخدام azd up الأمر لنشر هذا المشروع إلى تطبيق وظائف جديد في خطة استهلاك Flex في Azure. يتضمن المشروع مجموعة من ملفات Bicep التي azd تستخدم لإنشاء نشر آمن لخطة استهلاك Flex التي تتبع أفضل الممارسات.

  1. لفتح لوحة الأوامر في تعليمة Visual Studio البرمجية، اضغط على F1. ابحث عن الأمر Azure Developer CLI (azd): Package, Provison and Deploy (up)وقم بتشغيله. بعد ذلك، قم بتسجيل الدخول باستخدام حساب Azure الخاص بك.

  2. إذا لم تكن قد قمت بتسجيل الدخول بالفعل، فقم بالمصادقة باستخدام حساب Azure الخاص بك.

  3. عند المطالبة، قم بتوفير معلمات النشر المطلوبة هذه:

    المعلمة‬ وصف
    اشتراك 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 المسمى الذي mcp.json أضفته سابقا، وقم بتغيير 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 إلى حذف مجموعة الموارد الخاصة بك دون تأكيد منك. لا يؤثر هذا الأمر على مشروع التعليمات البرمجية المحلية.

الخطوات التالية