現在我們的 MCP 伺服器已經運作,是時候建構客戶端了。客戶端是讓我們的應用程式能夠與 MCP 伺服器通訊並存取其功能的部分。
理解客戶端架構
在深入程式碼之前,讓我們先釐清一個關於 MCP 專案的重要觀點。通常,您會實作 MCP 客戶端或 MCP 伺服器的其中一個,而不是兩者都實作。我們在這個專案中同時建構兩者,只是為了讓您看看它們如何協同運作。

MCP 客戶端由兩個主要元件組成:
- MCP 客戶端(MCP Client) - 我們建立的一個自訂類別,用來讓使用 session 更輕鬆
- 客戶端 Session(Client Session) - 與伺服器的實際連線(屬於 MCP Python SDK 的一部分)

客戶端 session 在我們使用完畢後需要進行資源清理,這就是為什麼我們將它包裝在自訂類別中的原因。這會自動處理連線管理和清理工作。
客戶端如何融入我們的應用程式
還記得我們的應用程式流程嗎?我們的 CLI 程式碼需要以兩種關鍵方式與 Claude 互動:

客戶端透過將伺服器的功能暴露給我們的程式碼庫,來實現這兩種互動。
實作核心客戶端函式
我們需要實作兩個必要的函式:list_tools 和 call_tool。
List Tools 函式
這個函式會從伺服器取得所有可用的工具:
async def list_tools(self) -> list[types.Tool]:
result = await self.session().list_tools()
return result.tools這個很直接明瞭——我們存取我們的 session(與 MCP 伺服器的連線),呼叫內建的 list_tools 函式,然後從結果中回傳工具清單。
Call Tool 函式
這個函式會在伺服器上執行特定的工具:
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 提供)傳遞給伺服器,並回傳結果。
測試客戶端
為了驗證我們的實作是否正常運作,我們可以直接進行測試。客戶端檔案包含一個測試工具,用來連接到 MCP 伺服器並對其執行命令。讓它呼叫 list_tools() 並印出結果:
async with MCPClient(
command="uv", args=["run", "mcp_server.py"]
) as client:
result = await client.list_tools()
print(result)執行 uv run mcp_client.py 應該會回傳一份可用工具的清單,包含其描述和輸入 schema。您應該會看到我們在伺服器中定義的工具,例如 read_doc_contents 和 edit_document。
端對端測試
現在客戶端和伺服器都已經運作,我們可以測試完整的流程。執行我們的主應用程式並詢問 Claude「report.pdf 文件的內容是什麼?」應該會:
- 將可用工具清單傳送給 Claude
- Claude 決定使用
read_doc_contents工具 - 我們的客戶端在伺服器上呼叫該工具
- 伺服器回傳文件內容
- Claude 根據該資訊進行回應
客戶端充當您的應用程式程式碼與 MCP 伺服器之間的橋樑,讓您能夠輕鬆存取伺服器功能,而不需要直接處理底層的連線細節。