加载中

现在我们的MCP服务器已经可以正常工作了,是时候构建客户端了。客户端是让我们的应用程序代码能够与MCP服务器通信并访问其功能的部分。

理解客户端架构

在大多数实际项目中,您要么实现MCP客户端,要么实现MCP服务器——而不是两者都实现。我们在这个项目中两者都构建,只是为了让您看看它们是如何协同工作的。

图表说明一个项目通常实现MCP客户端或MCP服务器中的一种;我们的项目两者都实现,展示了位于我们服务器内部的MCP客户端连接到MCP服务器

MCP客户端由两个主要组件组成:

  • MCP Client - 我们创建的一个自定义类,用于让使用会话更加方便
  • Client Session - 与服务器的实际连接(属于MCP Python SDK的一部分)

mcp_client.py的图表,其中包含MCP Client(我们编写的一个自定义类,用于让使用会话更加方便)和Client Session(与MCP服务器的实际连接)

客户端会话需要仔细的资源管理——我们需要在完成后正确清理连接。这就是为什么我们将其封装在自己的类中,以自动处理所有清理工作。

客户端如何融入我们的应用程序

还记得我们的应用程序流程图吗?客户端使我们的代码能够在两个关键点与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

这很简单——我们访问我们的会话(与服务器的连接),调用内置的 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工作流程中变得轻松简单。