最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Python從零實(shí)現(xiàn)一個(gè)最基礎(chǔ)的MCP協(xié)議

 更新時(shí)間:2026年04月30日 08:35:43   作者:TestCopilot  
模型上下文協(xié)議是?Anthropic?在2024年提出的一種開(kāi)放標(biāo)準(zhǔn)協(xié)議,用于標(biāo)準(zhǔn)化?AI?模型與外部工具和數(shù)據(jù)源的集成方式,本示例將展示如何使用?Python?實(shí)現(xiàn)一個(gè)最基礎(chǔ)的?MCP?協(xié)議,包括?MCP?服務(wù)器和?MCP?客戶端兩部分,需要的朋友可以參考下

模型上下文協(xié)議(MCP, Model Context Protocol)是 Anthropic 在2024年提出的一種開(kāi)放標(biāo)準(zhǔn)協(xié)議,用于標(biāo)準(zhǔn)化 AI 模型與外部工具和數(shù)據(jù)源的集成方式。

可以將 MCP 類比為 AI 世界中的 “USB-C 接口”:它為大型語(yǔ)言模型(LLM)連接各種工具和數(shù)據(jù)源提供了一種統(tǒng)一的方法。

MCP 使用 JSON-RPC 2.0 作為消息格式,在客戶端和服務(wù)器之間傳遞請(qǐng)求和響應(yīng)。

本示例將展示如何使用 Python 實(shí)現(xiàn)一個(gè)最基礎(chǔ)的 MCP 協(xié)議,包括 MCP 服務(wù)器和 MCP 客戶端兩部分。

我們將支持

  • discovery(發(fā)現(xiàn))
  • invoke(調(diào)用)
  • retrieve(獲?。?/li>

等基本操作,并通過(guò)一個(gè)簡(jiǎn)單的“計(jì)算器”工具(支持加法和乘法)演示協(xié)議的工作原理。

背景和設(shè)計(jì)概述

MCP 協(xié)議采用 客戶端-服務(wù)器 架構(gòu)。

MCP服務(wù)器提供一組工具(tools)或資源(resources),MCP客戶端可以發(fā)現(xiàn)服務(wù)器提供的功能并進(jìn)行調(diào)用 。

兩者之間通過(guò)JSON-RPC進(jìn)行通信,以標(biāo)準(zhǔn)的請(qǐng)求/響應(yīng)消息交換指令和數(shù)據(jù)。

按照 MCP 規(guī)范:

發(fā)現(xiàn)(Discovery):客戶端能夠查詢服務(wù)器,獲取其提供的工具列表、資源列表等。這通常通過(guò)調(diào)用 tools/list 或 resources/list 等方法實(shí)現(xiàn)。

調(diào)用(Invoke):客戶端可以請(qǐng)求執(zhí)行服務(wù)器上的某個(gè)工具功能,例如調(diào)用計(jì)算器的加法或乘法操作。規(guī)范中約定使用 tools/call 方法來(lái)調(diào)用指定名稱的工具,并傳遞所需參數(shù)。

獲?。≧etrieve):客戶端能夠檢索數(shù)據(jù)內(nèi)容,例如獲取某個(gè)資源的具體內(nèi)容。規(guī)范中提供了如 resources/read 等方法用于檢索資源內(nèi)容。

在簡(jiǎn)單工具調(diào)用場(chǎng)景下,調(diào)用的結(jié)果會(huì)直接作為響應(yīng)返回;但對(duì)于長(zhǎng)任務(wù)或資源內(nèi)容,常采用單獨(dú)的檢索步驟獲取結(jié)果。

實(shí)現(xiàn)思路

我們將使用 Python 標(biāo)準(zhǔn)庫(kù)構(gòu)建一個(gè)簡(jiǎn)易的 MCP 服務(wù)器和客戶端。

服務(wù)器會(huì)注冊(cè)至少一個(gè)工具——一個(gè)簡(jiǎn)單計(jì)算器,包含加法和乘法 功能。

客戶端可以通過(guò)發(fā)現(xiàn)操作獲取服務(wù)器上可用的工具列表,并通過(guò)調(diào)用操作執(zhí)行這些工具函數(shù)并得到結(jié)果。

為了盡量減少依賴并簡(jiǎn)化部署,我們將直接使用 Python 自帶的 HTTPServer 來(lái)處理 JSON-RPC 請(qǐng)求,使用內(nèi)置的 json 和 http.client 模塊實(shí)現(xiàn)通信。

代碼結(jié)構(gòu)將力求清晰,方便日后擴(kuò)展更多功能(例如增加新的工具、資源或更復(fù)雜的異步處理)。

主要功能模塊:

MCPServer

處理客戶端請(qǐng)求的服務(wù)器類。

維護(hù)可用的工具和資源列表,能夠響應(yīng) tools/list、tools/call、resources/list、resources/read 等 JSON-RPC 方法。

MCPClient

客戶端類或腳本,用于連接MCP服務(wù)器發(fā)送JSON-RPC請(qǐng)求。支持發(fā)現(xiàn)工具列表、調(diào)用指定工具、(可選)獲取資源內(nèi)容等操作。

通信格式

遵循JSON-RPC 2.0規(guī)范,每個(gè)請(qǐng)求包含 jsonrpc 版本、請(qǐng)求 id、方法名和參數(shù),響應(yīng)則包含對(duì)應(yīng)的 id以及結(jié)果或錯(cuò)誤信息。例如,列出工具的請(qǐng)求方法為 tools/list;

調(diào)用工具的請(qǐng)求方法為 tools/call,需要提供工具名稱和參數(shù)。

本示例中,我們的實(shí)現(xiàn)將返回簡(jiǎn)化的結(jié)果格式,以便直觀展示功能(實(shí)際MCP可能返回更結(jié)構(gòu)化的內(nèi)容,如帶有類型說(shuō)明的內(nèi)容列表)。

下面我們分別給出 MCP 服務(wù)器和客戶端的代碼實(shí)現(xiàn),并包含必要的注釋和使用說(shuō)明。

MCP服務(wù)器實(shí)現(xiàn) (Server)

首先,實(shí)現(xiàn)MCP服務(wù)器。我們創(chuàng)建一個(gè) MCPServer 類用于注冊(cè)工具和資源,并處理傳入的請(qǐng)求。

然后使用 Python 的 BaseHTTPRequestHandler 來(lái)構(gòu)建HTTP接口,使服務(wù)器能夠通過(guò)HTTP接收 JSON-RPC 請(qǐng)求。

計(jì)算器工具將作為示例工具注冊(cè)到服務(wù)器上。

import json
from http.server import BaseHTTPRequestHandler, HTTPServer
# 定義一個(gè)Tool類,用于存儲(chǔ)工具的元數(shù)據(jù)和執(zhí)行函數(shù)
class Tool:
    def __init__(self, name, description, input_schema, output_schema, func):
        self.name = name
        self.description = description
        self.input_schema = input_schema    # JSON Schema for input parameters
        self.output_schema = output_schema  # JSON Schema for output
        self.func = func                   # Function to execute the tool
# MCP服務(wù)器類,維護(hù)工具和資源,并處理JSON-RPC請(qǐng)求
class MCPServer:
    def __init__(self):
        # 注冊(cè)工具列表:這里添加一個(gè)“計(jì)算器”工具,提供加法和乘法 功能
        def add(a, b):  # 簡(jiǎn)單加法函數(shù)
            return a + b
        def multiply(a, b):  # 簡(jiǎn)單乘法函數(shù)
            return a * b
        # 為演示,將加法和乘法作為兩個(gè)獨(dú)立工具注冊(cè)
        self.tools = {
            "add": Tool(
                name="add",
                description="Add two numbers",
                input_schema={  # 輸入?yún)?shù)的JSON Schema定義
                    "type": "object",
                    "properties": {
                        "a": {"type": "number", "description": "First operand"},
                        "b": {"type": "number", "description": "Second operand"}
                    },
                    "required": ["a", "b"]
                },
                output_schema={  # 輸出結(jié)果的JSON Schema定義
                    "type": "number"
                },
                func=add
            ),
            "multiply": Tool(
                name="multiply",
                description="Multiply two numbers",
                input_schema={
                    "type": "object",
                    "properties": {
                        "a": {"type": "number", "description": "First operand"},
                        "b": {"type": "number", "description": "Second operand"}
                    },
                    "required": ["a", "b"]
                },
                output_schema={
                    "type": "number"
                },
                func=multiply
            )
        }
        # 可選:注冊(cè)資源列表,這里添加一個(gè)簡(jiǎn)單文本資源示例
        self.resources = {
            "mem://greeting": {
                "name": "greeting.txt",
                "title": "Greeting Message",
                "description": "A welcome text message",
                "mimeType": "text/plain",
                "text": "Hello, welcome to the MCP demo!"  # 資源內(nèi)容
            }
        }
    def handle_request(self, request):
        """
        處理JSON-RPC請(qǐng)求,根據(jù)method調(diào)用對(duì)應(yīng)的處理邏輯。
        返回JSON可序列化的響應(yīng)字典。
        """
        # 基礎(chǔ)的JSON-RPC字段解析
        jsonrpc = request.get("jsonrpc")
        req_id = request.get("id")
        method = request.get("method")
        params = request.get("params", {})
        # 確保符合 JSON-RPC 2.0 協(xié)議
        if jsonrpc != "2.0" or req_id is None or method is None:
            # 返回 JSON-RPC 錯(cuò)誤:-32600 = Invalid Request
            return {
                "jsonrpc": "2.0",
                "id": req_id,
                "error": {"code": -32600, "message": "Invalid Request"}
            }
        # 處理方法:tools/list, tools/call, resources/list, resources/read
        try:
            if method == "tools/list":
                # 列出可用工具
                tools_info = []
                for tool in self.tools.values():
                    tools_info.append({
                        "name": tool.name,
                        "description": tool.description,
                        "inputSchema": tool.input_schema,
                        "outputSchema": tool.output_schema
                    })
                return {
                    "jsonrpc": "2.0",
                    "id": req_id,
                    "result": {
                        "tools": tools_info
                    }
                }
            elif method == "tools/call":
                # 調(diào)用指定名稱的工具
                name = params.get("name")
                arguments = params.get("arguments", {})
                if not name or name not in self.tools:
                    # 工具名稱不存在
                    return {
                        "jsonrpc": "2.0",
                        "id": req_id,
                        "error": {"code": -32601, "message": f"Tool '{name}' not found"}
                    }
                # 獲取工具并執(zhí)行
                tool = self.tools[name]
                try:
                    # 調(diào)用工具函數(shù),傳入?yún)?shù)
                    result_value = tool.func(**arguments)
                except TypeError as e:
                    # 參數(shù)不正確或缺失
                    return {
                        "jsonrpc": "2.0",
                        "id": req_id,
                        "error": {"code": -32602, "message": f"Invalid parameters: {str(e)}"}
                    }
                except Exception as e:
                    # 工具執(zhí)行過(guò)程中出現(xiàn)其他異常
                    return {
                        "jsonrpc": "2.0",
                        "id": req_id,
                        "error": {"code": -32000, "message": f"Tool execution error: {str(e)}"}
                    }
                # 返回執(zhí)行結(jié)果(這里結(jié)果直接是數(shù)值,符合 outputSchema 定義)
                return {
                    "jsonrpc": "2.0",
                    "id": req_id,
                    "result": {
                        "output": result_value  # 將結(jié)果包裝在一個(gè)字段中
                    }
                }
            elif method == "resources/list":
                # 列出可用資源
                resources_info = []
                for uri, res in self.resources.items():
                    resources_info.append({
                        "uri": uri,
                        "name": res.get("name"),
                        "title": res.get("title"),
                        "description": res.get("description"),
                        "mimeType": res.get("mimeType")
                    })
                return {
                    "jsonrpc": "2.0",
                    "id": req_id,
                    "result": {
                        "resources": resources_info
                    }
                }
            elif method == "resources/read":
                # 讀取指定URI的資源內(nèi)容
                uri = params.get("uri")
                if not uri or uri not in self.resources:
                    return {
                        "jsonrpc": "2.0",
                        "id": req_id,
                        "error": {"code": -32602, "message": f"Invalid resource URI: {uri}"}
                    }
                res = self.resources[uri]
                # 返回資源內(nèi)容(文本)
                return {
                    "jsonrpc": "2.0",
                    "id": req_id,
                    "result": {
                        "contents": [
                            {
                                "uri": uri,
                                "name": res.get("name"),
                                "title": res.get("title"),
                                "mimeType": res.get("mimeType"),
                                "text": res.get("text")
                            }
                        ]
                    }
                }
            else:
                # 未知的方法
                return {
                    "jsonrpc": "2.0",
                    "id": req_id,
                    "error": {"code": -32601, "message": f"Method '{method}' not found"}
                }
        except Exception as e:
            # 捕獲任何未預(yù)料的異常,返回內(nèi)部錯(cuò)誤
            return {
                "jsonrpc": "2.0",
                "id": req_id,
                "error": {"code": -32603, "message": f"Internal error: {str(e)}"}
            }
# 實(shí)例化 MCPServer,全局使用
mcp_server = MCPServer()
# 定義HTTP請(qǐng)求處理器類
class MCPRequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # 讀取請(qǐng)求體中的JSON數(shù)據(jù)
        content_length = int(self.headers.get('Content-Length', 0))
        request_bytes = self.rfile.read(content_length)
        try:
            request_json = json.loads(request_bytes.decode('utf-8'))
        except json.JSONDecodeError:
            # 如果不是合法的JSON,返回錯(cuò)誤
            response = {
                "jsonrpc": "2.0",
                "id": None,
                "error": {"code": -32700, "message": "Parse error"}
            }
            self._send_response(response)
            return
        # 調(diào)用MCPServer處理請(qǐng)求,獲取響應(yīng)
        response = mcp_server.handle_request(request_json)
        # 將響應(yīng)發(fā)送回客戶端
        self._send_response(response)
    def _send_response(self, response_obj):
        """輔助方法:發(fā)送JSON響應(yīng)。"""
        response_bytes = json.dumps(response_obj).encode('utf-8')
        # 構(gòu)造HTTP響應(yīng)頭
        self.send_response(200)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(response_bytes)))
        self.end_headers()
        # 寫(xiě)出響應(yīng)內(nèi)容
        self.wfile.write(response_bytes)
        self.wfile.flush()
# 啟動(dòng) HTTP 服務(wù)器(監(jiān)聽(tīng) localhost:8000)
if __name__ == "__main__":
    server_address = ('', 8000)  # 監(jiān)聽(tīng)在所有接口的8000端口
    httpd = HTTPServer(server_address, MCPRequestHandler)
    print("MCP Server is running at http://localhost:8000")
    print("Available tools:", [name for name in mcp_server.tools.keys()])
    httpd.serve_forever()

上面的服務(wù)器代碼說(shuō)明:

工具注冊(cè):

在 MCPServer.init 中,我們定義了兩個(gè)簡(jiǎn)單的算術(shù)函數(shù) add 和 multiply,并使用它們分別注冊(cè)了名為 "add" 和 "multiply" 的 Tool。

每個(gè) Tool 包含名稱、描述、輸入?yún)?shù)模式 (input_schema)、輸出結(jié)果模式 (output_schema) 以及執(zhí)行函數(shù) func。

在輸入/輸出模式中,我們使用了簡(jiǎn)化的 JSON Schema 來(lái)描述參數(shù)(要求提供兩個(gè)數(shù)字參數(shù) a 和 b)和返回值類型(數(shù)字)。

這些元數(shù)據(jù)會(huì)在工具發(fā)現(xiàn)時(shí)提供給客戶端,方便客戶端或模型了解如何調(diào)用該工具。

資源注冊(cè):

為了演示 retrieve 操作,我們可選地注冊(cè)了一個(gè)簡(jiǎn)單資源 mem://greeting,表示一段文本內(nèi)容(模擬例如文件或數(shù)據(jù)庫(kù)中的數(shù)據(jù))。該資源包含一個(gè) URI 標(biāo)識(shí)符和元數(shù)據(jù)(名稱、描述、MIME類型等),以及文本內(nèi)容 "Hello, welcome to the MCP demo!"。資源將用于演示客戶端如何列出并讀取服務(wù)器上的數(shù)據(jù)內(nèi)容。

請(qǐng)求處理:

MCPServer.handle_request 方法根據(jù)傳入請(qǐng)求的 method 字段執(zhí)行

相應(yīng)邏輯:

  • tools/list:返回服務(wù)器上所有可用工具的列表,包含每個(gè)工具的名稱、描述、輸入/輸出模式等信息。
  • tools/call:調(diào)用指定的工具。請(qǐng)求需提供參數(shù) name(工具名)和 arguments(參數(shù)字典)。服務(wù)器檢查工具是否存在,參數(shù)是否正確,然后調(diào)用對(duì)應(yīng)的函數(shù)并獲取結(jié)果。

結(jié)果在此示例中直接返回為一個(gè)簡(jiǎn)單數(shù)值,包裝在 result.output 字段中。如出現(xiàn)錯(cuò)誤(未知工具、參數(shù)錯(cuò)誤、執(zhí)行異常等),則返回 JSON-RPC 標(biāo)準(zhǔn)的 error 對(duì)象,包括錯(cuò)誤碼和信息。

resources/list:

返回可用資源列表,每項(xiàng)包含資源的 URI、名稱、描述等元數(shù)據(jù)。

resources/read:

根據(jù)傳入的 uri 參數(shù),返回對(duì)應(yīng)資源的內(nèi)容。

在響應(yīng)中,我們將內(nèi)容放在 contents 列表中,每個(gè)元素包含資源的 meta 信息以及實(shí)際內(nèi)容文本。

未知方法:

如果收到非上述定義的方法,返回 JSON-RPC 的 “Method not found” 錯(cuò)誤(錯(cuò)誤碼 -32601)。

HTTP服務(wù)器:

使用 BaseHTTPRequestHandler 實(shí)現(xiàn)HTTP接口。我們重載了 do_POST 方法來(lái)處理 HTTP POST 請(qǐng)求(JSON-RPC 通常使用 POST 來(lái)發(fā)送請(qǐng)求)。

服務(wù)器從請(qǐng)求體讀取 JSON 數(shù)據(jù)并解析,然后調(diào)用 mcp_server.handle_request 獲得結(jié)果,最后通過(guò) _send_response 返回 JSON 響應(yīng)。

HTTPServer 監(jiān)聽(tīng)在 localhost:8000 端口,啟動(dòng)后打印可用工具列表以供參考。

注意,本實(shí)現(xiàn)為了簡(jiǎn)潔未包含認(rèn)證、權(quán)限控制等機(jī)制,也未實(shí)現(xiàn) MCP 規(guī)范中的會(huì)話管理、通知推送等高級(jí)功能。這是一個(gè)最基礎(chǔ)的示例,展示了 JSON-RPC 通信和工具/資源調(diào)用的基本流程。在實(shí)際應(yīng)用中,可能需要擴(kuò)展支持例如能力協(xié)商(capability negotiation)、異步調(diào)用(如長(zhǎng)時(shí)間運(yùn)行任務(wù)的進(jìn)度和結(jié)果獲?。?、安全認(rèn)證等特性。

MCP客戶端實(shí)現(xiàn) (Client)

接下來(lái),實(shí)現(xiàn)與上述服務(wù)器交互的 MCP 客戶端??蛻舳藢凑枕樞蜓菔疽韵虏僮鳎?/p>

  1. 發(fā)現(xiàn)工具:請(qǐng)求獲取服務(wù)器提供的工具列表(調(diào)用 tools/list)。
  2. 調(diào)用工具:調(diào)用加法和乘法工具(分別調(diào)用 tools/call,傳入相應(yīng)參數(shù))。
  3. 發(fā)現(xiàn)資源:請(qǐng)求獲取服務(wù)器提供的資源列表(調(diào)用 resources/list,可選步驟)。
  4. 獲取資源內(nèi)容:讀取指定資源內(nèi)容(調(diào)用 resources/read,示例讀取 mem://greeting 文本)。

我們使用 Python 內(nèi)置的 http.client 模塊發(fā)送 HTTP POST 請(qǐng)求,獲取并解析 JSON 響應(yīng)。以下是客戶端代碼:

import json
import http.client

# MCP客戶端輔助函數(shù):發(fā)送JSON-RPC請(qǐng)求并返回解析后的結(jié)果或錯(cuò)誤
def send_json_rpc(method, params=None, request_id=1):
    conn = http.client.HTTPConnection("localhost", 8000)
    request_obj = {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": method,
        "params": params or {}
    }
    # 將請(qǐng)求對(duì)象序列化為JSON并發(fā)送
    conn.request("POST", "/", body=json.dumps(request_obj), headers={
        "Content-Type": "application/json"
    })
    # 獲取HTTP響應(yīng)并解析JSON
    response = conn.getresponse()
    data = response.read().decode('utf-8')
    conn.close()
    try:
        return json.loads(data)
    except json.JSONDecodeError:
        print("Invalid JSON response:", data)
        return None

# 1. 發(fā)現(xiàn)可用工具列表
resp = send_json_rpc("tools/list", {}, request_id=1)
print("Available tools:")
if "result" in resp:
    for tool in resp["result"]["tools"]:
        name = tool["name"]
        desc = tool.get("description")
        print(f" - {name}: {desc}")
else:
    # 錯(cuò)誤情況
    print("Error listing tools:", resp.get("error"))

# 2. 調(diào)用加法工具 (例如 3 + 5)
add_params = {"name": "add", "arguments": {"a": 3, "b": 5}}
resp2 = send_json_rpc("tools/call", add_params, request_id=2)
if "result" in resp2:
    result_value = resp2["result"].get("output")
    print(f"Result of add(3, 5): {result_value}")
else:
    print("Error invoking add tool:", resp2.get("error"))

# 3. 調(diào)用乘法工具 (例如 4 * 7)
mul_params = {"name": "multiply", "arguments": {"a": 4, "b": 7}}
resp3 = send_json_rpc("tools/call", mul_params, request_id=3)
if "result" in resp3:
    result_value = resp3["result"].get("output")
    print(f"Result of multiply(4, 7): {result_value}")
else:
    print("Error invoking multiply tool:", resp3.get("error"))

# 4. (可選)列出可用資源
resp4 = send_json_rpc("resources/list", {}, request_id=4)
print("Available resources:")
if "result" in resp4:
    for res in resp4["result"]["resources"]:
        uri = res["uri"]
        desc = res.get("description")
        print(f" - {uri}: {desc}")
else:
    print("Error listing resources:", resp4.get("error"))

# 5. (可選)讀取指定資源內(nèi)容 (例如 mem://greeting)
res_params = {"uri": "mem://greeting"}
resp5 = send_json_rpc("resources/read", res_params, request_id=5)
if "result" in resp5:
    contents = resp5["result"].get("contents", [])
    if contents:
        text = contents[0].get("text")
        print(f"Content of resource mem://greeting: {text}")
else:
    print("Error reading resource:", resp5.get("error"))

說(shuō)明:

  1. send_json_rpc 函數(shù)封裝了發(fā)送請(qǐng)求和接收響應(yīng)的過(guò)程。它建立HTTP連接到 localhost:8000,發(fā)送JSON格式的RPC請(qǐng)求,并返回解析后的Python字典對(duì)象。
  2. 客戶端按照步驟構(gòu)造請(qǐng)求:
  3. tools/list 請(qǐng)求沒(méi)有額外參數(shù),返回服務(wù)器可用工具列表。在示例中,服務(wù)器應(yīng)返回我們注冊(cè)的 "add" 和 "multiply" 工具,各自的描述和參數(shù)模式也包含在結(jié)果中。
  4. tools/call 請(qǐng)求加法工具,提供參數(shù) {a:3, b:5}。服務(wù)器返回結(jié)果,客戶端從響應(yīng)中提取 output 字段即計(jì)算結(jié)果(期望為8)。類似地調(diào)用乘法工具 4*7,應(yīng)得到28。
  5. resources/list 請(qǐng)求返回服務(wù)器可用資源列表。在我們的示例中,應(yīng)當(dāng)包含 mem://greeting 這個(gè)資源及其描述信息。
  6. resources/read 請(qǐng)求讀取 mem://greeting,服務(wù)器將返回其內(nèi)容文本??蛻舳舜蛴〕鲈撐谋緝?nèi)容。

在打印輸出中,我們對(duì)結(jié)果做了簡(jiǎn)單的格式化。例如:

Available tools:
 - add: Add two numbers
 - multiply: Multiply two numbers
Result of add(3, 5): 8
Result of multiply(4, 7): 28
Available resources:
 - mem://greeting: A welcome text message
Content of resource mem://greeting: Hello, welcome to the MCP demo!

這樣,我們就完成了一個(gè)基本的 MCP 協(xié)議交互流程:客戶端發(fā)現(xiàn)服務(wù)器的功能,并成功調(diào)用工具得到計(jì)算結(jié)果,還演示了資源的發(fā)現(xiàn)和獲取。整個(gè)通信過(guò)程采用 JSON-RPC 格式,確保了請(qǐng)求和響應(yīng)的標(biāo)準(zhǔn)化

使用說(shuō)明

要運(yùn)行該示例,請(qǐng)按照以下步驟操作:

  • 啟動(dòng)服務(wù)器:將上述服務(wù)器代碼保存為 mcp_server.py 并運(yùn)行。例如:
python mcp_server.py

服務(wù)器將啟動(dòng)并監(jiān)聽(tīng)端口 8000。在控制臺(tái)上可以看到啟動(dòng)日志,例如可用的工具列表打印:

MCP Server is running at http://localhost:8000
Available tools: ['add', 'multiply']
  • 運(yùn)行客戶端:在服務(wù)器運(yùn)行的同時(shí),打開(kāi)另一個(gè)終端窗口,將上述客戶端代碼保存為 mcp_client.py 并運(yùn)行:
python mcp_client.py

客戶端將依次發(fā)送 JSON-RPC 請(qǐng)求到服務(wù)器,并在終端打印收到的響應(yīng)結(jié)果。

  1. 觀察結(jié)果:你應(yīng)當(dāng)在客戶端終端看到類似輸出:
Available tools:
 - add: Add two numbers
 - multiply: Multiply two numbers
Result of add(3, 5): 8
Result
 
of multiply(4, 7): 28
Available resources:
 - mem://greeting: A welcome text message
Content of resource mem://greeting: Hello, welcome to the MCP demo!

這些輸出對(duì)應(yīng)了我們?cè)诳蛻舳舜a中的打印語(yǔ)句,驗(yàn)證了各項(xiàng)操作成功執(zhí)行。

  1. 交互驗(yàn)證:你也可以使用其他JSON-RPC客戶端(例如cURL或Postman)手動(dòng)發(fā)送請(qǐng)求進(jìn)行測(cè)試。例如,使用 cURL 獲取工具列表:
curl -X POST http://localhost:8000/ -H "Content-Type: application/json" \
     -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

你將收到JSON響應(yīng),包含已注冊(cè)工具的詳細(xì)信息。

擴(kuò)展與總結(jié)

本示例提供了一個(gè)最基礎(chǔ)的 MCP 協(xié)議實(shí)現(xiàn)框架。通過(guò)清晰的結(jié)構(gòu)設(shè)計(jì),擴(kuò)展該實(shí)現(xiàn)非常方便:

增加新工具:

可以在服務(wù)器的 self.tools 字典中添加新的 Tool 實(shí)例,并實(shí)現(xiàn)對(duì)應(yīng)的函數(shù)。例如,可以添加一個(gè)字符串處理工具或數(shù)據(jù)庫(kù)查詢工具??蛻舳税l(fā)現(xiàn)機(jī)制使得新工具能夠被動(dòng)態(tài)發(fā)現(xiàn),無(wú)需更改客戶端代碼。

增加新資源:

同樣地,可擴(kuò)充 self.resources 字典來(lái)暴露新的資源數(shù)據(jù)。結(jié)合客戶端的資源檢索流程,可以為模型提供更多上下文數(shù)據(jù)。

復(fù)雜功能:

可考慮實(shí)現(xiàn)異步調(diào)用。如果某工具執(zhí)行時(shí)間較長(zhǎng),可修改 tools/call 的實(shí)現(xiàn)為立即返回一個(gè)任務(wù)ID,然后通過(guò)新增的 tools/retrieve(或類似方法)根據(jù)ID獲取結(jié)果。這類似于拆分調(diào)用和結(jié)果提取兩個(gè)步驟,在長(zhǎng)任務(wù)場(chǎng)景下很有用。

安全和認(rèn)證:

實(shí)際應(yīng)用中,應(yīng)在傳輸層(如HTTPS)以及協(xié)議層增加身份驗(yàn)證和授權(quán)機(jī)制,確保只有獲得許可的客戶端才能訪問(wèn)敏感工具或數(shù)據(jù)。MCP 規(guī)范在最新版本中也引入了 OAuth2 等認(rèn)證支持。

日志和錯(cuò)誤處理:

可以擴(kuò)展錯(cuò)誤日志記錄、請(qǐng)求計(jì)量等,以提高可監(jiān)控性和可靠性。

通過(guò)上述示例,我們驗(yàn)證了JSON-RPC風(fēng)格的 MCP 通信模型:客戶端可以動(dòng)態(tài)發(fā)現(xiàn)工具并調(diào)用之,從而讓LLM應(yīng)用具備即插即用的擴(kuò)展能力。

雖然我們的實(shí)現(xiàn)是簡(jiǎn)化的,但它奠定了構(gòu)建完整 MCP 服務(wù)器-代理系統(tǒng)的基礎(chǔ)結(jié)構(gòu)。

在未來(lái),你可以逐步按照 MCP 規(guī)范增加Prompts(預(yù)設(shè)提示模板)、更多工具類型以及高級(jí)特性,將其演變?yōu)楣δ芡暾?MCP 服務(wù)。希望這個(gè)示例能幫助你理解 MCP 協(xié)議的核心機(jī)制,并為進(jìn)一步開(kāi)發(fā)打下基礎(chǔ)。

以上就是使用Python從零實(shí)現(xiàn)一個(gè)最基礎(chǔ)的MCP協(xié)議的詳細(xì)內(nèi)容,更多關(guān)于Python實(shí)現(xiàn)MCP協(xié)議的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python中Celery異步任務(wù)隊(duì)列的具體使用

    Python中Celery異步任務(wù)隊(duì)列的具體使用

    Celery是一個(gè)用于處理分布式任務(wù)和作業(yè)隊(duì)列的異步任務(wù)隊(duì)列庫(kù),本文主要介紹了Python中Celery異步任務(wù)隊(duì)列的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • 解決Pytorch在測(cè)試與訓(xùn)練過(guò)程中的驗(yàn)證結(jié)果不一致問(wèn)題

    解決Pytorch在測(cè)試與訓(xùn)練過(guò)程中的驗(yàn)證結(jié)果不一致問(wèn)題

    這篇文章主要介紹了解決Pytorch在測(cè)試與訓(xùn)練過(guò)程中的驗(yàn)證結(jié)果不一致問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Python3中常見(jiàn)配置文件寫(xiě)法匯總

    Python3中常見(jiàn)配置文件寫(xiě)法匯總

    在開(kāi)發(fā)過(guò)程中,我們會(huì)用到一些固定參數(shù)或者是常量。對(duì)于這些較為固定且常用到的部分,往往會(huì)將其寫(xiě)到一個(gè)固定文件中,這些文件就是配置文件。本文為大家匯總了Python3中常見(jiàn)配置文件的寫(xiě)法,感興趣的可以了解一下
    2022-08-08
  • 啟動(dòng)targetcli時(shí)遇到錯(cuò)誤解決辦法

    啟動(dòng)targetcli時(shí)遇到錯(cuò)誤解決辦法

    這篇文章主要介紹了啟動(dòng)targetcli時(shí)遇到錯(cuò)誤解決辦法的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家遇到這樣的錯(cuò)誤解決,需要的朋友可以參考下
    2017-10-10
  • conda安裝GPU版pytorch默認(rèn)卻是cpu版本

    conda安裝GPU版pytorch默認(rèn)卻是cpu版本

    本文主要介紹了遇到Conda安裝PyTorch GPU版本卻默認(rèn)安裝CPU的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-06-06
  • python人民幣小寫(xiě)轉(zhuǎn)大寫(xiě)輔助工具

    python人民幣小寫(xiě)轉(zhuǎn)大寫(xiě)輔助工具

    這篇文章主要為大家詳細(xì)介紹了python人民幣小寫(xiě)轉(zhuǎn)大寫(xiě)輔助工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • python 還原梯度下降算法實(shí)現(xiàn)一維線性回歸

    python 還原梯度下降算法實(shí)現(xiàn)一維線性回歸

    這篇文章主要介紹了python 還原梯度下降算法實(shí)現(xiàn)一維線性回歸,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • python實(shí)現(xiàn)冒泡排序算法的兩種方法

    python實(shí)現(xiàn)冒泡排序算法的兩種方法

    本篇文章主要介紹了python實(shí)現(xiàn)冒泡排序的兩種方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • python單鏈路性能測(cè)試實(shí)踐

    python單鏈路性能測(cè)試實(shí)踐

    這篇文章主要為大家介紹了python單鏈路性能測(cè)試實(shí)踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Django REST框架創(chuàng)建一個(gè)簡(jiǎn)單的Api實(shí)例講解

    Django REST框架創(chuàng)建一個(gè)簡(jiǎn)單的Api實(shí)例講解

    在本篇文章里小編給大家整理的是關(guān)于Django REST框架創(chuàng)建一個(gè)簡(jiǎn)單的Api實(shí)例講解,有需要的朋友們可以學(xué)習(xí)下。
    2019-11-11

最新評(píng)論

龙江县| 江孜县| 监利县| 咸宁市| 山丹县| 阳曲县| 牙克石市| 县级市| 浙江省| 三穗县| 类乌齐县| 汽车| 泽普县| 蒲城县| 湘乡市| 邵东县| 建宁县| 万安县| 东辽县| 饶河县| 拉孜县| 四平市| 合川市| 漳平市| 迁安市| 丘北县| 农安县| 宁乡县| 鹤庆县| 阜新| 十堰市| 疏勒县| 凉城县| 东乡| 钟祥市| 云南省| 讷河市| 广饶县| 揭阳市| 昭平县| 千阳县|