IA Intermedio

MCP con Python: permite que una IA consulte tu inventario

Aprende a construir StockBridge, un servidor MCP con Python que permite a una inteligencia artificial consultar productos, precios y existencias desde un inventario JSON. Descubre cómo funcionan las herramientas MCP, cómo probarlas …

Publicado: 30/10/2026 Por: Juan Felipe Orozco Cortés Duración: 30 minutos Nivel: Intermedio
☰ Contenido del tutorial ⌄

01 · El problema

¿Y si una IA consultara tu inventario en lugar de adivinar?

Imagina que administras una tienda. Necesitas saber qué productos se están agotando, pero no quieres revisar cada referencia manualmente.

«¿Qué productos tienen menos de cinco unidades y cuánto cuestan?»

La diferencia está en consultar datos mediante una herramienta, no en inventar una respuesta convincente. Para demostrarlo crearemos StockBridge: un servidor MCP local que conecta un asistente con un inventario JSON ficticio.

Así viaja la consulta
Tu pregunta Asistente de IA Servidor MCP Inventario JSON

02 · Una prueba real

✓ Herramienta MCP ejecutada

La IA consultó el inventario y obtuvo esta respuesta

En Visual Studio Code, GitHub Copilot invocó productos_por_agotarse con limite=5. El resultado coincidió con nuestro archivo de ejemplo:

Producto Unidades Precio (COP)
Miel 250 g 0 · Agotado $18.000
Café en grano 500 g 2 $28.000
Café molido 500 g 3 $24.000
Registro de la llamada Ran productos_por_agotarse stockbridge (MCP Server)

Usamos la condición stock < limite; por eso un producto con cinco unidades no aparece. Los precios y productos son ficticios.

03 · Qué aprenderás

Construiremos cinco piezas, paso a paso

El objetivo no es crear otra tienda: es aprender cómo una IA descubre herramientas, les envía argumentos y recibe información comprobable.

  1. 01 Inventario JSON Cinco artículos con identificador, precio en COP y existencias.
  2. 02 Búsqueda de productos buscar_producto(nombre) encuentra coincidencias parciales.
  3. 03 Alerta de existencias productos_por_agotarse(limite=5) detecta artículos por debajo del umbral.
  4. 04 Servidor MCP Un proceso Python local que utiliza stdio, sin API web.
  5. 05 Validación con IA Pruebas automáticas, MCP Inspector y ejecución real desde un asistente.
Idea clave: no basta con que la IA muestre datos correctos: verificaremos que haya invocado realmente la herramienta.

04 · Antes de programar

Un laboratorio pequeño y reproducible

El proyecto usa datos ficticios y funciona localmente. No modificará existencias ni dependerá de una tienda real.

Lenguaje Python 3.11+
SDK mcp==2.3.0
Comunicación stdio
Datos inventario.json
Solo lectura: StockBridge consulta productos. No registra ventas, no crea artículos ni altera cantidades.
¿Necesito pagar una API de IA?

No para construir el servidor ni para probar sus herramientas con MCP Inspector. Una prueba conversacional requiere un cliente compatible y acceso a un modelo.

Versión demostrativa 0.1.0. La validación original se realizó en Windows con Python 3.13.15 y once pruebas locales.

Arquitectura de StockBridge: un asistente de IA utiliza herramientas de un servidor MCP en Python para consultar un inventario JSON local.
Figura 1. Flujo de una consulta MCP: el asistente invoca una herramienta de StockBridge, que obtiene información del inventario local y devuelve los resultados.

05 · Comprender MCP

El protocolo que conecta una IA con tus herramientas

Un modelo de lenguaje puede interpretar preguntas y generar respuestas, pero no conoce automáticamente el contenido actualizado de los archivos de tu equipo. Para consultar esos datos necesita una forma de acceder a herramientas externas.

Model Context Protocol (MCP) establece una forma estandarizada para que una aplicación de IA descubra herramientas disponibles, les envíe argumentos y reciba sus resultados.

01 · Asistente Interpreta la pregunta

El modelo determina si necesita consultar una herramienta para responder.

02 · Cliente MCP Gestiona la conexión

Descubre las herramientas, envía las llamadas y recibe las respuestas del servidor.

03 · Servidor MCP Ejecuta Python

StockBridge recibe una solicitud y ejecuta la función correspondiente.

04 · Fuente de datos Proporciona información

Nuestro archivo JSON contiene los productos, las existencias y sus precios.

La diferencia fundamental: MCP no es un modelo de inteligencia artificial. Es un protocolo que permite conectar aplicaciones y herramientas de forma estructurada.

En StockBridge utilizaremos el transporte stdio: el cliente inicia un proceso local y se comunica con él mediante la entrada y salida estándar.

06 · Preparación

Prepara tu entorno de desarrollo

Para construir nuestro servidor necesitaremos Python 3.11 o superior, un editor como Visual Studio Code y una terminal. Los siguientes comandos están preparados para Windows y PowerShell.

Crearemos una carpeta llamada stockbridge-mcp y, dentro de ella, un entorno virtual .venv. Esto permite instalar las dependencias sin mezclarlas con las de otros proyectos.

Al completar esta sección tendrás tres archivos fundamentales:

  • requirements.txt: versión del SDK que utilizaremos.
  • inventario.json: información ficticia de cinco productos.
  • server.py: las funciones y el servidor MCP.

Más adelante añadiremos los archivos de pruebas y la configuración del cliente MCP.

PowerShell
mkdir stockbridge-mcp
cd stockbridge-mcp

py -m venv .venv

07 · Dependencias

Una sola dependencia para comenzar

StockBridge utiliza el SDK de MCP para Python. Esta biblioteca proporciona los componentes necesarios para declarar herramientas y atender solicitudes de un cliente compatible.

Crearemos requirements.txt en la raíz del proyecto. Fijaremos la versión 2.3.0 para que el ejercicio corresponda con la implementación que hemos probado.

Fijar una versión reduce diferencias entre instalaciones, aunque no garantiza que todas las plataformas tengan exactamente el mismo entorno.

Texto plano
mcp==2.3.0
PowerShell
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

.\.venv\Scripts\python.exe -m pip check

08 · Modelo de datos

Un inventario sencillo, pero estructurado

Nuestro servidor necesita una fuente de información reproducible. Utilizaremos JSON: un formato que permite almacenar objetos mediante pares de claves y valores.

Cada producto tendrá exactamente cuatro propiedades:

Identificador id

Código único para reconocer el producto.

Descripción nombre

Texto utilizado durante las búsquedas.

Precio precio_cop

Valor entero expresado en pesos colombianos.

Inventario stock

Cantidad disponible de unidades.

¿Por qué JSON? Porque podemos concentrarnos en MCP sin configurar PostgreSQL, credenciales, una API o una base de datos.
JSON
[
  {
    "id": "P001",
    "nombre": "Café molido 500 g",
    "precio_cop": 24000,
    "stock": 3
  },
  {
    "id": "P002",
    "nombre": "Miel 250 g",
    "precio_cop": 18000,
    "stock": 0
  },
  {
    "id": "P003",
    "nombre": "Chocolate 250 g",
    "precio_cop": 12000,
    "stock": 5
  },
  {
    "id": "P004",
    "nombre": "Panela 500 g",
    "precio_cop": 6000,
    "stock": 12
  },
  {
    "id": "P005",
    "nombre": "Café en grano 500 g",
    "precio_cop": 28000,
    "stock": 2
  }
]

09 · Leer nuestros datos

¿Qué información podrá consultar el servidor?

El archivo contiene una lista de cinco objetos. Cada objeto representa un producto con su nombre, su precio y la cantidad disponible.

Por ejemplo, el producto P002 tiene stock=0; está agotado. El producto P003 tiene stock=5, mientras que P004 tiene stock=12.

Nuestra herramienta buscará productos cuya cantidad disponible sea estrictamente menor que el límite. Si el límite es cinco, devolverá tres productos: miel, café en grano y café molido.

Observa: el inventario contiene cinco productos, pero una consulta filtrada puede devolver solamente algunos. El servidor deberá calcular ese resultado; no lo escribiremos manualmente en las respuestas.

10 · El servidor MCP

Convirtamos nuestro inventario en herramientas para una IA

Hasta ahora tenemos datos, pero todavía no existe una forma de consultarlos mediante MCP. Esa será la responsabilidad de server.py.

El archivo realizará cuatro tareas:

  • Cargar y validar el inventario desde JSON.
  • Definir estructuras para los productos y las respuestas.
  • Registrar dos herramientas que el cliente MCP podrá descubrir.
  • Iniciar un servidor local utilizando el transporte stdio.

Crea un archivo llamado server.py junto a inventario.json. Copia el código completo del siguiente bloque. Después analizaremos cada una de sus partes.

Python
"""StockBridge: inventario de ejemplo consultable mediante MCP local."""

import json
from pathlib import Path
from typing import TypedDict

from mcp.server.mcpserver import MCPServer
from mcp.server.mcpserver.exceptions import ToolError


class Producto(TypedDict):
    id: str
    nombre: str
    precio_cop: int
    stock: int


class Busqueda(TypedDict):
    productos: list[Producto]
    total: int


class BajoStock(Busqueda):
    limite: int


def cargar_inventario(ruta: Path | None = None) -> list[Producto]:
    """Carga y valida el JSON antes de atender cualquier consulta."""
    ruta = ruta or Path(__file__).resolve().with_name("inventario.json")
    try:
        datos = json.loads(ruta.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError) as exc:
        raise ValueError(f"No se pudo cargar {ruta}: {exc}") from exc
    if not isinstance(datos, list):
        raise ValueError("inventario.json debe contener una lista de productos")

    ids: set[str] = set()
    for numero, producto in enumerate(datos, start=1):
        if not isinstance(producto, dict) or set(producto) != {"id", "nombre", "precio_cop", "stock"}:
            raise ValueError(f"Producto {numero}: se esperan id, nombre, precio_cop y stock")
        if (not isinstance(producto["id"], str) or not producto["id"].strip()
                or producto["id"] in ids
                or not isinstance(producto["nombre"], str) or not producto["nombre"].strip()
                or type(producto["precio_cop"]) is not int or producto["precio_cop"] < 0
                or type(producto["stock"]) is not int or producto["stock"] < 0):
            raise ValueError(f"Producto {numero}: id/nombre inválido, id duplicado o precio/stock inválido")
        ids.add(producto["id"])
    return datos


INVENTARIO = cargar_inventario()
mcp = MCPServer("StockBridge", version="0.1.0")


@mcp.tool()
def buscar_producto(nombre: str) -> Busqueda:
    """Busca productos por parte del nombre, sin distinguir mayúsculas; no modifica datos."""
    if not isinstance(nombre, str) or not nombre.strip():
        raise ToolError("nombre debe ser un texto no vacío")
    encontrados = [p for p in INVENTARIO if nombre.strip().casefold() in p["nombre"].casefold()]
    return {"productos": encontrados, "total": len(encontrados)}


@mcp.tool()
def productos_por_agotarse(limite: int = 5) -> BajoStock:
    """Lista productos con stock estrictamente menor al límite, incluyendo agotados."""
    if type(limite) is not int or limite < 0:
        raise ToolError("limite debe ser un entero mayor o igual que cero")
    encontrados = sorted((p for p in INVENTARIO if p["stock"] < limite),
                         key=lambda p: (p["stock"], p["id"]))
    return {"productos": encontrados, "total": len(encontrados), "limite": limite}


if __name__ == "__main__":
    mcp.run(transport="stdio")

11 · Comprender Python

Cómo valida StockBridge los datos antes de utilizarlos

1. Importaciones

json permite convertir el contenido del archivo JSON en objetos Python. Path facilita localizar archivos y TypedDict describe la estructura esperada de nuestros diccionarios.

MCPServer proporciona el servidor MCP y ToolError permite señalar argumentos inválidos durante una llamada a una herramienta.

2. Estructuras de respuesta

Producto describe un diccionario con cuatro campos: id, nombre, precio_cop y stock.

Busqueda representa una respuesta con la lista productos y el contador total. BajoStock reutiliza esa estructura y agrega limite.

Detalle importante: TypedDict sirve para describir tipos y apoyar el análisis estático; no valida automáticamente los datos mientras el programa se ejecuta. Por eso tenemos una función de validación.

3. Carga del inventario

cargar_inventario() construye la ruta utilizando __file__. Así encuentra inventario.json junto a server.py, aunque ejecutemos Python desde otra carpeta.

read_text(encoding="utf-8") lee el archivo y json.loads() interpreta su contenido. Si falta el archivo o el JSON tiene errores de sintaxis, se genera una excepción explicativa.

4. Validaciones y errores

Primero comprobamos que el documento sea una lista. Después recorremos cada producto con enumerate(), verificando que sea un diccionario con las cuatro propiedades esperadas.

El conjunto ids detecta identificadores repetidos. Los campos id y nombre deben ser textos no vacíos. El precio y las existencias deben ser enteros no negativos.

La expresión type(valor) is int es deliberada: en Python, bool es una subclase de int. Así evitamos aceptar True como si fuera un precio o una cantidad válida.

Resultado: la función devuelve una lista de productos válidos o detiene el proceso con ValueError. No intenta corregir silenciosamente datos incorrectos.

12 · Herramientas MCP

Dos funciones Python que un asistente puede ejecutar

Después de cargar el inventario, inicializamos el servidor con MCPServer("StockBridge", version="0.1.0"). Su nombre y versión identifican esta implementación ante el cliente.

El decorador @mcp.tool() registra una función como herramienta MCP. Su nombre, descripción, argumentos y anotaciones de tipos ayudan al cliente a descubrir cómo utilizarla.

  1. 01 buscar_producto(nombre) Recibe una cadena de texto y devuelve los productos cuyo nombre contiene la expresión buscada.
  2. 02 strip() y casefold() strip elimina espacios exteriores; casefold permite comparar sin diferenciar mayúsculas y minúsculas.
  3. 03 productos_por_agotarse() Recibe un límite entero, que por defecto es cinco, y filtra productos con existencias inferiores a ese valor.
  4. 04 sorted() y lambda Ordena primero por cantidad disponible. Si dos productos tienen el mismo stock, usa su identificador como segundo criterio.
  5. 05 Resultados estructurados Las herramientas devuelven diccionarios con productos, total y, cuando corresponde, el límite utilizado en la consulta.
Dos reglas importantes: una búsqueda vacía produce ToolError y un límite negativo o no entero también. Además, casefold no elimina las tildes: "CAFÉ" coincide con "Café", pero "cafe" no es la misma cadena.

13 · Ejecutar MCP

¿Qué hace la última línea de server.py?

La condición if __name__ == "__main__" permite distinguir entre ejecutar el archivo directamente e importarlo desde otro módulo.

Cuando ejecutamos server.py como programa principal, la instrucción mcp.run(transport="stdio") inicia la comunicación MCP mediante entrada y salida estándar.

Entrada estándar stdin

El servidor recibe solicitudes enviadas por el cliente MCP.

Salida estándar stdout

El servidor entrega las respuestas del protocolo al cliente.

Cuidado con print(): no utilices la salida estándar para mensajes de depuración mientras funciona el transporte stdio. Podrías interferir con los mensajes que intercambian cliente y servidor. Para registrar eventos, utiliza stderr o un sistema de logging configurado.

¿Cuándo se lee el inventario?

La instrucción INVENTARIO = cargar_inventario() se ejecuta cuando se importa o inicia el módulo. Por tanto, si editas el archivo JSON mientras el servidor sigue abierto, deberás reiniciar el proceso para cargar esos cambios.

Hasta este punto hemos construido el servidor y explicado todo el código de server.py. Ahora podemos comprobar sus funciones antes de conectarlas a un cliente MCP.

PowerShell
.\.venv\Scripts\python.exe -c "from server import buscar_producto, productos_por_agotarse; print(buscar_producto('CAFÉ')); print(productos_por_agotarse(5))"
Prueba de StockBridge en Python: búsqueda de café y consulta de productos con menos de cinco unidades.
Figura 2. Primera ejecución funcional de StockBridge: las funciones Python consultan el inventario JSON y devuelven resultados estructurados.

14 · Validación del proyecto

Que funcione una vez no significa que funcione siempre

Nuestra primera prueba mostró dos resultados correctos. Pero todavía quedan preguntas importantes: ¿qué ocurre si el usuario escribe espacios?, ¿si el archivo JSON contiene datos inválidos?, ¿si el límite de existencias es negativo?

Para responderlas utilizaremos pruebas automatizadas. Una prueba ejecuta una operación, compara su resultado con lo esperado y señala cualquier diferencia.

Nivel 01 Funciones Python

Verificaremos búsquedas, filtros, validaciones y protección de datos.

Nivel 02 Protocolo MCP

Iniciaremos un servidor real y comprobaremos sus herramientas mediante un cliente MCP.

Nuestra meta: diez pruebas funcionales de Python y una prueba de integración MCP. En total, once verificaciones automatizadas.

Utilizaremos unittest, que viene incluido con Python. No necesitamos instalar pytest ni añadir nuevas dependencias al proyecto.

Python
"""Pruebas funcionales del contrato de StockBridge."""

import json
import os
import tempfile
import unittest
from pathlib import Path

from mcp.server.mcpserver.exceptions import ToolError

import server


class PruebasInventario(unittest.TestCase):

    def test_busqueda_simple(self):
        self.assertEqual(
            [p["id"] for p in server.buscar_producto("miel")["productos"]],
            ["P002"]
        )

    def test_mayusculas_y_espacios(self):
        resultado = server.buscar_producto("  CAFÉ  ")
        self.assertEqual(
            [p["id"] for p in resultado["productos"]],
            ["P001", "P005"]
        )
        self.assertEqual(resultado["total"], 2)

    def test_sin_coincidencias(self):
        self.assertEqual(
            server.buscar_producto("arroz"),
            {"productos": [], "total": 0}
        )

    def test_busqueda_vacia(self):
        for valor in ("", "   "):
            with self.subTest(valor=valor), self.assertRaisesRegex(
                ToolError, "no vacío"
            ):
                server.buscar_producto(valor)

    def test_umbral_exclusivo_y_ordenado(self):
        resultado = server.productos_por_agotarse(5)

        self.assertEqual(
            [p["id"] for p in resultado["productos"]],
            ["P002", "P005", "P001"]
        )

        self.assertEqual(
            (resultado["total"], resultado["limite"]),
            (3, 5)
        )

        self.assertNotIn(
            "P003",
            [p["id"] for p in resultado["productos"]]
        )

    def test_umbral_por_defecto_y_cero(self):
        self.assertEqual(
            server.productos_por_agotarse(),
            server.productos_por_agotarse(5)
        )

        self.assertEqual(
            server.productos_por_agotarse(0),
            {"productos": [], "total": 0, "limite": 0}
        )

    def test_limite_invalido(self):
        for valor in (-1, 2.5, True, False, "5"):
            with self.subTest(valor=valor), self.assertRaisesRegex(
                ToolError, "entero"
            ):
                server.productos_por_agotarse(valor)

    def test_no_se_modifica_inventario(self):
        ruta = Path(server.__file__).with_name("inventario.json")
        antes = ruta.read_bytes()

        server.buscar_producto("café")
        server.productos_por_agotarse(5)

        self.assertEqual(ruta.read_bytes(), antes)

    def test_carga_desde_otra_carpeta(self):
        actual = Path.cwd()

        with tempfile.TemporaryDirectory() as carpeta:
            try:
                os.chdir(carpeta)
                self.assertEqual(
                    len(server.cargar_inventario()),
                    5
                )
            finally:
                os.chdir(actual)

    def test_datos_invalidos(self):
        casos = [
            "{",
            "{}",
            '[{"id":"P001"}]',
            json.dumps([
                {
                    "id": "P001",
                    "nombre": "Miel",
                    "precio_cop": 1,
                    "stock": -1
                }
            ]),
            json.dumps([
                {
                    "id": "P001",
                    "nombre": "Miel",
                    "precio_cop": True,
                    "stock": 0
                }
            ]),
            json.dumps([
                {
                    "id": "P001",
                    "nombre": "Miel",
                    "precio_cop": 1,
                    "stock": 0
                }
            ] * 2)
        ]

        with tempfile.TemporaryDirectory() as carpeta:
            ruta = Path(carpeta) / "inventario.json"

            with self.assertRaisesRegex(
                ValueError, "No se pudo cargar"
            ):
                server.cargar_inventario(ruta)

            for contenido in casos:
                with self.subTest(contenido=contenido):
                    with self.assertRaises(ValueError):
                        ruta.write_text(
                            contenido,
                            encoding="utf-8"
                        )
                        server.cargar_inventario(ruta)


if __name__ == "__main__":
    unittest.main()

15 · Comprender las pruebas

Diez verificaciones que protegen nuestro inventario

El archivo test_server.py utiliza unittest.TestCase. Cada método cuyo nombre comienza con test_ representa un caso que Python puede ejecutar automáticamente.

Revisemos qué comprueba cada uno:

  1. Búsqueda simple: consultar "miel" debe devolver P002.
  2. Mayúsculas y espacios: " CAFÉ " debe encontrar los dos cafés.
  3. Sin coincidencias: una búsqueda inexistente devuelve una lista vacía y total cero.
  4. Búsqueda vacía: una cadena vacía o formada por espacios debe producir ToolError.
  5. Umbral y orden: con límite cinco aparecen P002, P005 y P001, en ese orden. P003 queda excluido porque tiene exactamente cinco unidades.
  6. Valores por defecto: omitir el límite equivale a usar cinco. Un límite de cero devuelve una lista vacía.
  7. Límites inválidos: se rechazan números negativos, decimales, booleanos y cadenas.
  8. Solo lectura: después de consultar las herramientas, el contenido del JSON permanece idéntico.
  9. Rutas independientes: el servidor encuentra el inventario aunque cambiemos de directorio.
  10. Datos inválidos: el servidor rechaza JSON mal formado, estructuras incompletas, existencias negativas, precios booleanos e identificadores duplicados.

Las instrucciones que hacen posibles estas comprobaciones

assertEqual() compara el valor obtenido con el resultado esperado. assertNotIn() comprueba que un elemento esté ausente. assertRaisesRegex() verifica que ocurra una excepción y que su mensaje contenga una expresión determinada.

subTest() permite evaluar varios valores dentro de una prueba e identificar cuál falló. TemporaryDirectory() crea una carpeta temporal para probar datos incorrectos sin modificar el inventario original.

Finalmente, read_bytes() permite comparar el contenido exacto del archivo antes y después de ejecutar las consultas.

Estas pruebas demuestran que las funciones se comportan según nuestras reglas. Sin embargo, todavía no verifican que un cliente MCP pueda descubrirlas y ejecutarlas mediante el protocolo.

Python
"""Integración real: lanza server.py como subprocess y habla MCP por stdio."""

import sys
import unittest
from pathlib import Path

from mcp import Client, StdioServerParameters


class PruebasMCP(unittest.IsolatedAsyncioTestCase):

    async def test_descubrimiento_y_consultas_stdio(self):
        servidor = Path(__file__).resolve().with_name("server.py")

        proceso = StdioServerParameters(
            command=sys.executable,
            args=[str(servidor)]
        )

        async with Client(proceso) as cliente:

            herramientas = await cliente.list_tools()

            self.assertEqual(
                {t.name for t in herramientas.tools},
                {"buscar_producto", "productos_por_agotarse"}
            )

            for herramienta in herramientas.tools:
                self.assertIsNotNone(herramienta.input_schema)
                self.assertIsNotNone(herramienta.output_schema)

            bajos = await cliente.call_tool(
                "productos_por_agotarse",
                {"limite": 5}
            )

            self.assertFalse(bajos.is_error)

            self.assertEqual(
                [
                    p["id"]
                    for p in bajos.structured_content["productos"]
                ],
                ["P002", "P005", "P001"]
            )

            self.assertEqual(
                bajos.structured_content["total"],
                3
            )

            buscados = await cliente.call_tool(
                "buscar_producto",
                {"nombre": "  CAFÉ  "}
            )

            self.assertFalse(buscados.is_error)

            self.assertEqual(
                [
                    p["id"]
                    for p in buscados.structured_content["productos"]
                ],
                ["P001", "P005"]
            )

            error = await cliente.call_tool(
                "buscar_producto",
                {"nombre": "   "}
            )

            self.assertTrue(error.is_error)

            self.assertIn(
                "no vacío",
                str(error.content)
            )


if __name__ == "__main__":
    unittest.main()

16 · Prueba de integración

Ahora comprobamos el protocolo, no solamente las funciones

En las pruebas anteriores llamábamos directamente a las funciones Python. Ahora haremos algo diferente: iniciaremos server.py como un proceso independiente y nos comunicaremos con él mediante un cliente MCP.

1. Ejecutar un proceso independiente

StdioServerParameters describe cómo iniciar el servidor. Utilizamos sys.executable para ejecutar el mismo intérprete Python que está corriendo las pruebas.

Esto evita depender de una ruta fija del equipo y permite usar el entorno virtual correspondiente.

2. Abrir la sesión con el servidor

async with Client(proceso) establece la conexión con el servidor. El cliente se encarga de iniciar el proceso y gestionar el intercambio de mensajes MCP.

La prueba utiliza IsolatedAsyncioTestCase porque la comunicación con el servidor se realiza mediante operaciones asíncronas. Por eso aparecen async y await.

3. Descubrir herramientas

cliente.list_tools() solicita al servidor su catálogo. Verificamos que incluya exactamente buscar_producto y productos_por_agotarse.

También comprobamos que cada herramienta publique esquemas de entrada y salida. Estos esquemas describen los argumentos que acepta y la estructura de sus resultados.

4. Invocar herramientas

cliente.call_tool() realiza una llamada a una herramienta utilizando su nombre y un diccionario con los argumentos.

El campo is_error indica si la ejecución devolvió un error. structured_content contiene los datos estructurados que podemos validar.

Comprobamos que el filtro de existencias devuelva P002, P005 y P001 y que la búsqueda de café devuelva P001 y P005.

5. Comprobar un error real

Finalmente, enviamos una búsqueda formada únicamente por espacios. El servidor debe devolver una respuesta de error, sin detener inesperadamente toda la prueba.

Lo que acabamos de demostrar: un cliente pudo iniciar el servidor, descubrir herramientas, enviar argumentos y recibir resultados MCP estructurados. Esta prueba todavía no utiliza un modelo de inteligencia artificial.

17 · Verificación automatizada

Ejecutemos las once pruebas

Guarda test_server.py y test_protocol.py en la misma carpeta que server.py.

Abre PowerShell dentro de stockbridge-mcp y ejecuta el siguiente comando. Utilizaremos el Python del entorno virtual creado al inicio.

Estás viendo solo el 60% del contenido. Hazte Premium para acceder al tutorial completo.

Comunidad

Comentarios y valoraciones

No hay comentarios aún. ¡Sé el primero en opinar!