載入中

既然我們的 MCP 伺服器已經運作正常,現在是時候建構客戶端了。客戶端讓我們的應用程式程式碼能夠與 MCP 伺服器通訊並存取其功能。

了解客戶端架構

在大多數實際專案中,您通常只會實作 MCP 客戶端或 MCP 伺服器其中之一,而不會兩者都實作。我們在這個專案中同時建構兩者,只是為了讓您看看它們是如何協同運作的。

圖表說明一個專案通常只會實作 MCP 客戶端或 MCP 伺服器其中之一;我們的專案則兩者都實作,顯示 MCP 客戶端位於我們的伺服器內部並連接到 MCP 伺服器

MCP 客戶端由兩個主要元件組成:

  • MCP Client - 我們建立的自訂類別,用來讓使用 session 更容易
  • Client Session - 與伺服器的實際連線(屬於 MCP Python SDK 的一部分)

mcp_client.py 的圖表,其中包含 MCP Client(我們撰寫的自訂類別,用來讓使用 session 更容易)以及 Client Session(與 MCP 伺服器的實際連線)

客戶端 session 需要謹慎的資源管理——我們需要在完成後妥善清理連線。這就是為什麼我們將它包裝在自己的類別中,以自動處理所有清理工作。

客戶端如何融入我們的應用程式

還記得我們的應用程式流程圖嗎?客戶端讓我們的程式碼能夠在兩個關鍵點與 MCP 伺服器互動:

應用程式流程的序列圖,標註顯示我們的 CLI 程式碼在何處使用客戶端來取得要傳遞給 Claude 的工具清單,以及在何處使用客戶端來呼叫工具

我們的 CLI 程式碼使用客戶端來:

  • 取得可用工具的清單以傳送給 Claude
  • 在 Claude 請求時執行工具

實作核心客戶端函式

我們需要實作兩個必要的函式:list_tools() 和 call_tool()。

List Tools 函式

此函式會從 MCP 伺服器取得所有可用的工具:

python
async def list_tools(self) -> list[types.Tool]:
    result = await self.session().list_tools()
    return result.tools

這很直接——我們存取我們的 session(與伺服器的連線),呼叫內建的 list_tools() 方法,然後從結果中回傳工具。

Call Tool 函式

此函式會在伺服器上執行特定的工具:

python
async def call_tool(
    self, tool_name: str, tool_input: dict
) -> types.CallToolResult | None:
    return await self.session().call_tool(tool_name, tool_input)

我們將工具名稱和輸入參數(由 Claude 提供)傳遞給伺服器,並回傳結果。

測試客戶端

客戶端檔案底部包含一個簡單的測試工具。讓它呼叫您其中一個新方法並印出結果:

python
async with MCPClient(
    command="uv", args=["run", "mcp_server.py"]
) as client:
    result = await client.list_tools()
    print(result)

然後直接執行該檔案以驗證一切正常運作:

uv run mcp_client.py

這會連接到您的 MCP 伺服器並印出可用的工具。您應該會看到顯示您工具定義的輸出,包括描述和輸入結構描述。

整合所有內容

一旦客戶端函式實作完成,您就可以透過執行主應用程式來測試完整的流程:

uv run main.py

試著詢問:

report.pdf 文件的內容是什麼?

以下是幕後發生的事情:

  1. 您的應用程式使用客戶端取得可用的工具
  2. 這些工具連同您的問題一起傳送給 Claude
  3. Claude 決定使用 read_doc_contents 工具
  4. 您的應用程式使用客戶端執行該工具
  5. 結果會回傳給 Claude,然後 Claude 再回應您

客戶端作為您的應用程式邏輯與 MCP 伺服器功能之間的橋樑,讓您能夠輕鬆地將強大的工具整合到您的 AI 工作流程中。