Cargando

Implementación de un cliente

Lección 547 min

Ahora que nuestro servidor MCP está funcionando, es momento de construir el lado del cliente. El cliente es lo que permite que nuestra aplicación se comunique con el servidor MCP y acceda a su funcionalidad.

Entendiendo la arquitectura del cliente

Antes de entrar al código, aclaremos un punto importante sobre los proyectos MCP. Normalmente, implementarías un cliente MCP o un servidor MCP, no ambos. Estamos construyendo ambos en este proyecto solo para que puedas ver cómo funcionan juntos.

Diagrama de nuestro servidor que contiene el cliente MCP, el cual se conecta en ambas direcciones a un servidor MCP separado.

El cliente MCP consta de dos componentes principales:

  • MCP Client - Una clase personalizada que creamos para facilitar el uso de la sesión
  • Client Session - La conexión real con el servidor (parte del SDK de Python de MCP)

Diagrama de mcp_client.py que contiene el MCP Client y el Client Session, el cual se conecta a un servidor MCP separado.

La sesión del cliente requiere limpieza de recursos cuando terminamos de usarla, por eso la envolvemos en nuestra clase personalizada. Esto maneja la gestión de la conexión y la limpieza automáticamente.

Cómo encaja el cliente en nuestra aplicación

¿Recuerdas el flujo de nuestra aplicación? Nuestro código CLI necesita interactuar con Claude de dos maneras clave:

Diagrama de secuencia del flujo de la aplicación, resaltando dónde nuestro código CLI usa el cliente para listar herramientas y para llamar a una herramienta.

El cliente habilita ambas interacciones al exponer la funcionalidad del servidor a nuestro código base.

Implementando las funciones principales del cliente

Necesitamos implementar dos funciones esenciales: list_tools y call_tool.

Función List Tools

Esta función obtiene todas las herramientas disponibles del servidor:

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

Es sencillo: accedemos a nuestra sesión (la conexión con el servidor MCP), llamamos a la función integrada list_tools, y devolvemos las herramientas del resultado.

Función Call Tool

Esta función ejecuta una herramienta específica en el servidor:

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)

Pasamos el nombre de la herramienta y los parámetros de entrada (proporcionados por Claude) al servidor y devolvemos el resultado.

Probando el cliente

Para verificar que nuestra implementación funciona, podemos probarla directamente. El archivo del cliente incluye un arnés de pruebas que se conecta al servidor MCP y ejecuta comandos contra él. Haz que llame a list_tools() e imprima el resultado:

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

Ejecutar uv run mcp_client.py debería devolver una lista de herramientas disponibles con sus descripciones y esquemas de entrada. Deberías ver herramientas como read_doc_contents y edit_document que definimos en nuestro servidor.

Prueba de extremo a extremo

Ahora que tanto el cliente como el servidor están funcionando, podemos probar el flujo completo. Ejecutar nuestra aplicación principal y preguntarle a Claude "¿Cuál es el contenido del documento report.pdf?" debería:

  1. Enviar la lista de herramientas disponibles a Claude
  2. Claude decide usar la herramienta read_doc_contents
  3. Nuestro cliente llama a la herramienta en el servidor
  4. El servidor devuelve el contenido del documento
  5. Claude responde con la información

El cliente actúa como el puente entre el código de tu aplicación y el servidor MCP, facilitando el acceso a la funcionalidad del servidor sin tener que lidiar directamente con los detalles de conexión de bajo nivel.