久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    MCP協(xié)議從原理到開發(fā):一文讀懂大模型交互的標(biāo)準(zhǔn)化革命!

     羅宋湯的味道 2025-04-19 發(fā)布于青海

    ??目錄

    什么是 MCP

    MCP Server 開發(fā)

    MCP Client 開發(fā)

    MCP的工作原理

    效果呈現(xiàn)

    寫在最后




    本文系統(tǒng)介紹了MCP協(xié)議在大模型交互標(biāo)準(zhǔn)化中的創(chuàng)新應(yīng)用,通過技術(shù)解析+實踐案例的方式,闡述了MCP協(xié)議的架構(gòu)設(shè)計、開發(fā)實現(xiàn)原理及實際應(yīng)用效果。重點探討了MCP如何解決AI工具調(diào)用碎片化問題,并通過企業(yè)微信機器人開發(fā)實例展示MCP服務(wù)端/客戶端開發(fā)全流程,干貨滿滿點贊收藏!





    01



    什么是 MCP

       1.1 MCP 介紹

    MCP(Model Context Protocol,模型上下文協(xié)議) 起源于 2024 年 11 月 25 日 Anthropic 發(fā)布的文章:Introducing the Model Context Protocol。

    可以用“AI 擴(kuò)展塢”來比喻 MCP 在 AI 領(lǐng)域的作用。就像現(xiàn)代擴(kuò)展塢可以連接顯示器、鍵盤、移動硬盤等多種外設(shè),為筆記本電腦瞬間擴(kuò)展功能一樣,MCP Server 作為一個智能中樞平臺,能夠動態(tài)接入各類專業(yè)能力模塊(如知識庫、計算工具、領(lǐng)域模型等)。當(dāng) LLM 需要完成特定任務(wù)時,可以像'即插即用'般調(diào)用這些模塊,實時獲得精準(zhǔn)的上下文支持,從而實現(xiàn)能力的彈性擴(kuò)展。這種架構(gòu)打破了傳統(tǒng) AI 模型的封閉性,讓大語言模型像搭載了多功能擴(kuò)展塢的超級工作站,隨時都能獲取最合適的專業(yè)工具。

    圖片
       1.2 為什么要有 MCP

    終結(jié)工具調(diào)用碎片化

    不同模型在定義 Function Call(函數(shù)調(diào)用)時,采用的結(jié)構(gòu)和參數(shù)格式各不相同,使得對多模型集成、統(tǒng)一管理和標(biāo)準(zhǔn)化接入變得復(fù)雜而繁瑣。

    屬性維度OpenAIClaudeGeminiLLaMA
    調(diào)用結(jié)構(gòu)名稱tool_callstool_usefunctionCallfunction_call
    參數(shù)格式JSON字符串JSON對象JSON對象JSON對象
    特殊字段finish_reason字段包含id<thinking>args字段命名與OpenAI結(jié)構(gòu)相似
    圖片

    對于開發(fā)者來說,針對不同模型去實現(xiàn)不同的工具調(diào)用方法,所謂的定制化開發(fā)不僅消耗大量時間和資源,而且維護(hù)也變得困難。

    而 MCP 作為一種 AI 模型的標(biāo)準(zhǔn)化接入?yún)f(xié)議,能夠顯著簡化模型之間的集成。

    實現(xiàn)多功能應(yīng)用與創(chuàng)新體驗的突破

    MCP 的潛力不僅限于連接現(xiàn)有工具,它還在推動客戶端應(yīng)用向“萬能應(yīng)用”演進(jìn),并創(chuàng)造全新的用戶體驗。

    以代碼編輯器 Cursor 為例,作為 MCP 客戶端,用戶可以通過集成不同的 MCP 服務(wù)器,將其轉(zhuǎn)變?yōu)榫邆?Slack 消息收發(fā)、郵件發(fā)送(Resend MCP)、甚至圖像生成(Replicate MCP)等多種功能的綜合工作站。

    更具創(chuàng)造力的是,在單一客戶端中組合多個 MCP 服務(wù)器可以解鎖復(fù)雜的新流程。例如,AI 代理可以一邊生成前端界面代碼,一邊調(diào)用圖像生成服務(wù)器為主頁創(chuàng)作視覺元素。這種模式超越了傳統(tǒng)應(yīng)用的單一功能限制,為用戶帶來多樣化的操作體驗。



    02



    MCP Server 開發(fā)

    MCP server 是 MCP 架構(gòu)中的關(guān)鍵組件,目前提供 3 種主要類型的功能,

    • 資源(Resources):類似文件的數(shù)據(jù),可以被客戶端讀取,如 文件內(nèi)容。

    • 工具(Tools):可以被 LLM 調(diào)用的函數(shù)。

    • 提示(Prompts):預(yù)先編寫的prompt模板,幫助用戶完成特定任務(wù)。

    還有其他兩種(samping 和 roots)但是目前還沒被很好的支持。

    圖片

    以開發(fā)一個企業(yè)微信機器人 mcp server 為例,用到的是社區(qū)sdk typescript-sdk 。(https://github.com/modelcontextprotocol/typescript-sdk)

       2.1 項目搭建開發(fā)

    可以參考官方 quickstart(https:///quickstart/server)

    環(huán)境:nodejs > v16 (我用的是 v22.6)

    npm init -y
    # Install dependenciesnpm install @modelcontextprotocol/sdk zodnpm install -D @types/node typescriptmkdir srctouch src/index.ts
    創(chuàng)建 mcp-server 實例
    import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';export const server = new McpServer({  name'wechat-mcp-server',  version'0.0.1',});

    可以直接使用 sdk 封裝好的 McpServer 函數(shù)。

    創(chuàng)建 tools 工具


    定義 mcp 提供給 client 或者 llm 使用的工具,企業(yè)微信機器人主要就是 發(fā)送文本、發(fā)送 markdown、發(fā)送圖片等等,這里我們舉例一個發(fā)送文本的工具實現(xiàn)

    text.ts

    // Helper function for sending WeChat messagesexport async function sendWeChatTextMessage(webhookKey: string, content: string, chatid: string = '@all_group', mentioned_list?: string[], mentioned_mobile_list?: string[], visible_to_user?: string): Promise<boolean> {  const WECHAT_API_BASE = ` http://in.qyapi.wbin/webhook/send?key=${ webhookKey}`;  const headers = {      'Content-Type''application/json',  };      const body = JSON.stringify({       'msgtype''text',       'text': {             'content': content,             'mentioned_list': mentioned_list,             'mentioned_mobile_list': mentioned_mobile_list       },       'chatid': chatid,       'visible_to_user': visible_to_user ? visible_to_user.split('|') : undefined   });      try {       const response = await fetch(WECHAT_API_BASE, { headers, method'POST', body });       if (!response.ok) {             throw new Error(`HTTP error! status: ${response.status}`);       }       return true;       } catch (error) {         console.error('Error sending WeChat message:', error);         return false;         }   }

    通過 server.tool 注冊發(fā)送文本工具,注冊工具有四個函數(shù),比如有些可以加描述,有些是0參數(shù)調(diào)用等等,選一個合適自己的即可。我們這里必須需要知道回調(diào)的 webhook key 和 content 。

    圖片
    import { sendWeChatTextMessage } from './text.js';// Register WeChat message toolserver.tool(  'sendWeChatTextMessage',  'send WeChat text message',  {      webhookKey: z.string().describe('WeChat webhook key'), // 必填      content: z.string().describe('WeChat message content'),// 必填      chatid: z.string().describe('WeChat message chatid').optional(), // optional 選填      mentioned_list: z.array(z.string()).describe('WeChat message mentioned list').optional(),      mentioned_mobile_list: z.array(z.string()).describe('WeChat message mentioned mobile list').optional(),  },    async ({ webhookKey, content, chatid, mentioned_list, mentioned_mobile_list }) => {        const success await sendWeChatTextMessage(webhookKey, content, chatid, mentioned_list,    mentioned_mobile_list);           if (!success) {          return {                content: [                          {                              type: 'text'                              text: 'Failed to send WeChat message',                    },               ],           };       }          return {            content: [                {                    type: 'text',                    text: 'WeChat message sent successfully',                 },           ],         };       },    );

    發(fā)送文本工具就注冊好了,其他功能工具開發(fā)類似。

    創(chuàng)建resource資源

    這里我們放一個企業(yè)微信機器人的文檔。

    server.resource(  'api',  'file:///api.md',  async (uri) => {      try {          console.info(uri)          const __filename = fileURLToPath(import.meta.url);          const __dirname = path.dirname(__filename);          const filePath = path.join(__dirname.replace('build''assets'), 'api.md');          const content = await fs.promises.readFile(filePath, 'utf-8');
              return {              contents: [{                  uri: uri.href,                  text: content              }]          };      } catch (error) {          return {              contents: [{                  uri: uri.href,                  text'讀取文件失敗'              }]          };      }  });

    創(chuàng)建prompt

    提示符是可重用的模板,可以幫助LLMs有效地與服務(wù)器交互。這里我們可以做一個參數(shù)檢查的prompt。

    server.prompt(  'parameter_check',  '參數(shù)檢查',  {     param: z.string().describe('參數(shù)'),    apiContent: z.string().describe('API文檔')  },  ({ param,apiContent }) => ({      messages: [{          role: 'user',          content: {              type'text',              text: `              <instruction>                <instructions>                    1. 接收API文檔文本和用戶數(shù)據(jù)作為輸入。                    2. 從API文檔中提取所有參數(shù)的要求,包括參數(shù)名稱、類型、是否必需、默認(rèn)值等信息。                    3. 對照用戶提供的數(shù)據(jù),檢查每個參數(shù)是否滿足API的要求。                    4. 對于每個參數(shù),記錄以下信息:                        - 參數(shù)名稱                        - 用戶提供的值                        - 是否滿足API要求(是/否)                        - 如果不滿足,說明原因                    5. 將所有檢查結(jié)果整理成一個清晰的報告,確保輸出不包含任何XML標(biāo)簽。                    6. 確保報告的格式簡潔明了,便于用戶理解。                </instructions>                <examples>                   <example>                      <input>                          API文檔文本: '參數(shù): username, 類型: string, 必需: 是; 參數(shù): age, 類型: integer, 必需: 否;'                          用戶數(shù)據(jù): '{\'username\': john_doe, \'age\': 25}'                      </input>                      <output>                          '參數(shù): username, 用戶提供的值: john_doe, 滿足要求: 是; 參數(shù): age, 用戶提供的值: 25, 滿足要求: 是;'                      </output>                  </example>                </examples>              </instruction>              API文檔文本:${apiContent}              用戶數(shù)據(jù):${param}              `          }      }]  }));
       2.2 運行調(diào)試

    可以使用社區(qū)Inspector工具來調(diào)試我們的mcp。我使用的版本是v0.6.0,如果是用devcloud開發(fā)的同學(xué)可能會無法調(diào)試使用,因為代理地址寫死了是localhost,導(dǎo)致連接失敗,已經(jīng)給社區(qū)提了PR #201并合并,遠(yuǎn)程開發(fā)的同學(xué)可以直接拉源碼或者等待工具發(fā)布新版本。(寫完的時候發(fā)現(xiàn)已經(jīng)發(fā)布v0.7.0,大家可以直接用最新版本了https://github.com/modelcontextprotocol/inspector)

    調(diào)試tools

    圖片
    圖片

    調(diào)試resource

    圖片

    調(diào)試prompt

    圖片


    03



    MCP Client 開發(fā)

    MCP Client的主要任務(wù)是連接到MCP Server,可以通過標(biāo)準(zhǔn)輸入/輸出或 SSE (Server-Sent Events) 與 MCP 服務(wù)器進(jìn)行通信。

       3.1 實現(xiàn)步驟

    初始化客戶端和會話對象

    class MCPClient:    def __init__(self):        # 初始化 session 和 client 對象        self.session: Optional[ClientSession] = None        self._streams_context: Optional[sse_client] = None        self._session_context: Optional[ClientSession] = None        self.exit_stack = AsyncExitStack()  # 初始化異步退出棧

    連接到MCP服務(wù)

    async def connect_to_sse_server(self, server_url: str):    '''連接到使用 SSE 傳輸?shù)?MCP 服務(wù)器'''    if not server_url.startswith(' http://' ) and not server_url.startswith(' https://' ):        raise ValueError('服務(wù)器 URL 必須以 ' http://'  或 'https://' 開頭')
        # 存儲上下文管理器以保持其存活    self._streams_context = sse_client(url=server_url)    streams = await self._streams_context.__aenter__()
        self._session_context = ClientSession(*streams)    self.session: ClientSession = await self._session_context.__aenter__()
        # 初始化    await self.session.initialize()    async def connect_to_server(self, server_script_path: str):        '''        連接到通過標(biāo)準(zhǔn)輸入/輸出通信的 MCP 服務(wù)器                參數(shù):            server_script_path: 服務(wù)器腳本路徑(.py 或 .js 文件)                示例: 'server.py' 或 'server.js'        '''        is_python = server_script_path.endswith('.py')        is_js = server_script_path.endswith('.js')        if not (is_python or is_js):            raise ValueError('Server script must be a .py or .js file')
            command = 'python' if is_python else 'node'        server_params = StdioServerParameters(            command=command,            args=[server_script_path],            env=None        )
            stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))        self.stdio, self.write = stdio_transport        self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
            await self.session.initialize()

    有兩種連接方式,分別是:

    1. stdio(標(biāo)準(zhǔn)輸入輸出通信)。

    2. HTTP with Server-Sent Events (SSE)(HTTP 服務(wù)端發(fā)送事件)。

    清理資源

    class MCPClient:    def __init__(self):        # 初始化 session 和 client 對象        self.session: Optional[ClientSession] = None
        async def connect_to_sse_server(self, server_url: str):        '''連接到使用 SSE 傳輸?shù)?MCP 服務(wù)器'''        if not server_url.startswith(' http://' ) and not server_url.startswith(' https://' ):            raise ValueError('服務(wù)器 URL 必須以 ' http://'  或 'https://' 開頭')
            # 存儲上下文管理器以保持其存活        self._streams_context = sse_client(url=server_url)        streams = await self._streams_context.__aenter__()
            self._session_context = ClientSession(*streams)        self.session: ClientSession = await self._session_context.__aenter__()
            # 初始化        await self.session.initialize()
        async def cleanup(self):        '''清理 session 和 streams'''        if self._session_context:            await self._session_context.__aexit__(NoneNoneNone)        if self._streams_context:            await self._streams_context.__aexit__(NoneNoneNone)
       3.2 調(diào)用
    async def main():    if len(sys.argv) < 2:        print('用法: uv run client.py <SSE MCP 服務(wù)器的 URL (例如 ' '=''> http://localhost:8080/sse)>' )        print('或: uv run client.py <MCP 服務(wù)器腳本路徑 (例如 server.py)>')        sys.exit(1)
        client = MCPClient()    try:        # stdio 連接方式        # await client.connect_to_server(server_script_path=sys.argv[1])        # sse 連接方式        await client.connect_to_sse_server(server_url=sys.argv[1])        print('\n連接到服務(wù)器...')                        response = await client.session.list_prompts()        response1 = await client.session.list_tools()        response2 = await client.session.list_resources()        print('response', response)        print('response1', response1)        print('response2', response2)        
        finally:        try:            await client.cleanup()        except Exception as e:            print(f'清理錯誤: {e}')
    圖片


    04



    MCP的工作原理

       4.1 MCP架構(gòu)

    MCP采用的是C/S結(jié)構(gòu),一個MCP host應(yīng)用可以鏈接多個MCP servers。

    圖片
    • Host(主機):例如cursor、cline,負(fù)責(zé)接收你的提問并與模型交互。

    • Client(客戶端):運行在Host內(nèi),mcp client 與 mcp server保持 1:1 連接,當(dāng)用戶在交互界面輸入問題時,模型來決定使用1個或者多個工具,通過client來調(diào)用server執(zhí)行具體操作。

    • Server(服務(wù)):在這個例子中,文件系統(tǒng) MCP Server 會被調(diào)用。它負(fù)責(zé)執(zhí)行實際的文件掃描操作,訪問你的桌面目錄,并返回找到的文檔列表。

    圖片
       4.2 json-rpc

    在我們用inspector調(diào)試我們的mcp-server時,請求參數(shù)里會有jsonrpc字段,在mcp中 client 和 server 之間的傳輸均采用了JSON-RPC 2.0 來交換消息。

    圖片

    主要特點包括:

    1. 簡單易用:相比于其他 XML-RPC 協(xié)議,JSON-RPC 使用 JSON 格式更容易理解和處理,因為 JSON 是一種人類可讀的文本格式,同時被多種編程語言廣泛支持。

    2. 輕量級:JSON-RPC 沒有復(fù)雜的格式和規(guī)則,是一種輕量級的協(xié)議,非常適合嵌入式系統(tǒng)和網(wǎng)絡(luò)環(huán)境不理想的情況下使用。

    3. 無狀態(tài):JSON-RPC 是無狀態(tài)的協(xié)議,每次請求都是獨立的,不依賴于之前的通信。

    4. 語言中立:不限于某一種編程語言,被各種編程語言廣泛支持。

    5. 支持批處理:JSON-RPC 還支持批處理模式,即在一個請求中發(fā)送多個 RPC 調(diào)用,以提高效率。

       4.3 模型如何選擇工具

    有了MCP Server 提供的眾多工具,模型如何確定該使用哪些工具?

    這里可以參考 官方 python-sdk 給的一個example示例:mcp_simple_chatbot(https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/clients/simple-chatbot/mcp_simple_chatbot)

    #... 省略了無關(guān)緊要的代碼    async def start(self) -> None:        '''Main chat session handler.'''        try:            #... 省略了無關(guān)緊要的代碼            all_tools = [] # 獲取現(xiàn)在所有的工具列表            for server in self.servers:                tools = await server.list_tools()                all_tools.extend(tools)
                tools_description = '\n'.join([tool.format_for_llm() for tool in all_tools])            # 定義一個善于調(diào)用各種工具的助手prompt            system_message = (                'You are a helpful assistant with access to these tools:\n\n'                f'{tools_description}\n'                'Choose the appropriate tool based on the user's question. '                'If no tool is needed, reply directly.\n\n'                'IMPORTANT: When you need to use a tool, you must ONLY respond with '                'the exact JSON object format below, nothing else:\n'                '{\n'                '    'tool': 'tool-name',\n'                '    'arguments': {\n'                '        'argument-name': 'value'\n'                '    }\n'                '}\n\n'                'After receiving a tool's response:\n'                '1. Transform the raw data into a natural, conversational response\n'                '2. Keep responses concise but informative\n'                '3. Focus on the most relevant information\n'                '4. Use appropriate context from the user's question\n'                '5. Avoid simply repeating the raw data\n\n'                'Please use only the tools that are explicitly defined above.'            )
                messages = [{'role''system''content': system_message}]
                while True:                try:                    user_input = input('You: ').strip().lower()                     #... 省略了無關(guān)緊要的代碼                    messages.append({'role''user''content': user_input})                     #問模型我現(xiàn)在應(yīng)該執(zhí)行哪些工具                    llm_response = self.llm_client.get_response(messages)                    # 執(zhí)行工具                    result = await self.process_llm_response(llm_response)                    #... 省略了無關(guān)緊要的代碼                                    except KeyboardInterrupt:                    #... 省略了無關(guān)緊要的代碼        finally:            await self.cleanup_servers()
       4.4 模型如何執(zhí)行工具
    async def process_llm_response(self, llm_response: str) -> str:        '''Process the LLM response and execute tools if needed.
            Args:            llm_response: The response from the LLM.
            Returns:            The result of tool execution or the original response.        '''        import json
            try:            tool_call = json.loads(llm_response)            #如果有工具被選中,開始執(zhí)行工具            if 'tool' in tool_call and 'arguments' in tool_call:                logging.info(f'Executing tool: {tool_call['tool']}')                logging.info(f'With arguments: {tool_call['arguments']}')                #這里的server是通過mcp client 發(fā)現(xiàn)的                for server in self.servers:                    tools = await server.list_tools()                    if any(tool.name == tool_call['tool'for tool in tools):                        try:                            # 執(zhí)行工具                            result = await server.execute_tool(                                tool_call['tool'], tool_call['arguments']                            )
                                #... 省略了無關(guān)緊要的代碼                            return f'Tool execution result: {result}'                        except Exception as e:                            error_msg = f'Error executing tool: {str(e)}'                            logging.error(error_msg)                            return error_msg
                    return f'No server found with tool: {tool_call['tool']}'            # 沒有工具執(zhí)行就直接輸出模型的回答            return llm_response        except json.JSONDecodeError:            return llm_response
       4.5 總結(jié)

    Host應(yīng)用(如Cursor)作為交互入口,通過內(nèi)置的Client模塊與多個專用Server建立一對一連接。當(dāng)用戶提問時,Host借助大模型分析請求并選擇工具:首先獲取所有Server注冊的工具列表,通過結(jié)構(gòu)化提示詞引導(dǎo)模型生成JSON格式的調(diào)用指令,再通過JSON-RPC 2.0協(xié)議將指令路由到對應(yīng)Server執(zhí)行具體操作(如文件掃描)。執(zhí)行結(jié)果經(jīng)Host處理后轉(zhuǎn)化為自然語言響應(yīng)返回用戶,實現(xiàn)模型決策與工具執(zhí)行的解耦,通過輕量級通信協(xié)議完成分布式任務(wù)處理。



    05



    效果呈現(xiàn)

    結(jié)合我們的mcp server 和 mcp client的示例,實現(xiàn)一個通過查詢知識庫數(shù)據(jù)后將結(jié)果通過企業(yè)微信機器人群聊內(nèi)。

    圖片
    圖片


    06



    寫在最后

    這篇文章是記錄自己在學(xué)習(xí)MCP過程中的一些感受和想法,可能存在疏漏和不準(zhǔn)確的地方。如果有不對的地方,還請各位批評指正。同時,也歡迎大家一起交流討論,共同探索MCP及其應(yīng)用的更多可能性。

    -End-
    原創(chuàng)作者|劉家旻
    圖片

      本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
      轉(zhuǎn)藏 分享 獻(xiàn)花(0

      0條評論

      發(fā)表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 男女动态无遮挡动态图| 免费国产VA在线观看视频| 福利在线视频一区二区| 亚洲尤码不卡av麻豆| 欧美福利电影A在线播放| 日本一区不卡高清更新二区| 美日韩在线视频一区二区三区| 国产午夜亚洲精品不卡网站| 国产乱人伦偷精品视频下| 性做久久久久久久久| 亚洲av日韩在线资源| 做暖暖视频在线看片免费| 人妻无码久久中文字幕专区| 少妇熟女久久综合网色欲| 最新偷拍一区二区三区| 99久久无色码中文字幕| 四虎国产精品永久入口| 婷婷丁香五月六月综合激情啪| 手机看片AV永久免费| 377P欧洲日本亚洲大胆| 六月丁香婷婷色狠狠久久| 一区二区三区精品偷拍| 成人欧美一区二区三区在线观看 | 国产成人AV一区二区三区在线 | 亚洲男女内射在线播放| 久久精品国产中文字幕| 久久经精品久久精品免费观看| 最新国产精品中文字幕| 最爽无遮挡行房视频| 国产成人精品午夜2022| 亚洲AV中文无码字幕色最新| 亚洲伊人久久综合影院| 开心一区二区三区激情| 99久久久精品免费观看国产| 国产亚洲欧美另类一区二区| 国产精品人妻中文字幕| 国内精品久久久久久无码不卡 | 717午夜伦伦电影理论片| 日韩在线视频线观看一区| 在线 | 18精品免费1区2| 影音先锋女人AA鲁色资源|