Integración de MCP con SpringBoot para crear asistentes de IA potenciados

Introducción a MCP

El Model Context Protocol (MCP) es un estándar abierto desarrollado por Anthropic que permite a los modelos de lenguaje grandes (LLM) interactuar con fuentes de datos y herramientas externas de manera unificada. Actúa como un "puerto universal" en el ámbito de la IA, facilitando la comunicación entre diferentes modelos y sistemas mediante especificaciones como JSON-RPC 2.0.

En términos prácticos, MCP funciona como un intérprete entre la IA y las herramientas del sistema, estableciendo reglas de conversación estandarizadas. Esto permite que diversos modelos de IA, como ChatGPT o Claude, operen con la misma interfza sin necesidad de adaptaciones específicas para cada uno.

Arquitectura y componentes clave

MCP sigue una arquitectura cliente-servidor compuesta por:

  • MCP Host: Aplicación que integra el modelo de IA (por ejemplo, un IDE o interfaz de chat) y que inicia las solicitudes.
  • MCP Client: Componente que gestiona la comunicación entre el Host y el Server, encargándose de enviar peticiones y procesar respuestas.
  • MCP Server: Programa ligero que expone funcionalidades específicas, como acceso a bases de datos o manipulación de archivos.
  • Fuentes de datos y herramientas: Recursos locales o externos, como bases de datos o APIs de terceros.

El flujo típico involucra la conversión de lenguaje natural a un formato estructurado por parte del Client, el enrutamiento y ejecución por parte del Server, y la transformación de los resultados en una respuesta comprensible para el usuario.

Aplicaciones prácticas

Integrar MCP en sistemas existentes ofrece ventajas significativas:

  • Automatización de operaciones mediante comandos en lenguaje natural, como gestionar pedidos o consultas.
  • Compatibilidad con múltiples modelos de IA sin requerir cambios en el código backend.
  • Extensibilidad dinámica para añadir nuevas funcionalidades, como servicios de mensajería o análisis de datos.

Integración con SpringBoot: Guía paso a paso

1. Configuración de dependencias

Dado que las bibliotecas relevantes aún se encuentran en versiones preliminares, es necesario agregar repositorios adicionales en el archivo pom.xml:

<repositories>
  <repository>
    <id>spring-milestones</id>
    <url>https://repo.spring.io/milestone</url>
  </repository>
  <repository>
    <id>spring-snapshots</id>
    <url>https://repo.spring.io/snapshot</url>
  </repository>
</repositories>

Luego, se incluyen las dependencias de Spring AI y el servidor MCP:

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-core</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>

2. Ajustes de configuración

En el archivo application.properties, se establecen parámetros esenciales para el servidor MCP y el modelo de IA:

spring.ai.anthropic.api-key=tu-api-key-aqui
spring.ai.mcp.server.enabled=true
spring.ai.mcp.server.name=mi-servidor-mcp
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=SYNC
spring.ai.mcp.server.sse-message-endpoint=/mcp/mensajes

3. Adaptación de servicios existentes

Existen dos métodos principales para exponer funcionalidades como herramientas MCP. A continuación, se ejemplifica con un servicio de gestión de productos.

Método mediante anotaciones

Se decoran los métodos del servicio con @Tool y @ToolParam para definir la herramienta y sus parámetros:

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductRepository productRepo;

    @Override
    @Tool(name = "buscarProductosPorNombre", description = "Busca productos usando coincidencia parcial del nombre")
    public List<Product> buscarPorNombre(@ToolParam(description = "Término de búsqueda del nombre") String nombre) {
        return productRepo.findByNombreContaining(nombre);
    }

    @Override
    @Tool(name = "buscarProductosPorCategoria", description = "Busca productos por categoría exacta")
    public List<Product> buscarPorCategoria(@ToolParam(description = "Categoría del producto") String categoria) {
        return productRepo.findByCategoria(categoria);
    }
}

Luego, se registra el servicio en la configuración del servidor MCP:

@Configuration
public class ConfiguracionServidorMcp {

    @Bean
    public ToolCallbackProvider proveedorHerramientas(ProductService productService) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(productService)
                .build();
    }
}

Método mediante beans de función

Alternativamente, se pueden crear beans de función independientes:

@Service
public class ConsultaProductosService {

    @Autowired
    private ProductService productService;

    @Bean
    public Function<String, List<Product>> buscarPorNombre() {
        return nombre -> productService.buscarPorNombre(nombre);
    }

    @Bean
    public Function<String, List<Product>> buscarPorCategoria() {
        return categoria -> productService.buscarPorCategoria(categoria);
    }
}

En este caso, las herramientas se referencian explícitamente al configurar el cliente de chat:

@Configuration
public class ConfiguracionChat {

    @Bean
    public ChatClient clienteChat(ChatClient.Builder builder) {
        return builder
                .defaultSystem("Eres un asistente para gestión de productos. Responde de forma concisa.")
                .defaultTools("buscarPorNombre", "buscarPorCategoria")
                .build();
    }
}

4. Controlador para pruebas

Se define un endpoint REST para interactuar con el cliente de chat:

@RestController
@RequestMapping("/api/chat")
public class ControladorChat {

    @Autowired
    private ChatClient chatClient;

    @PostMapping
    public ResponseEntity<RespuestaChat> procesarMensaje(@RequestBody SolicitudChat solicitud) {
        String mensaje = chatClient.prompt()
                .user(solicitud.getMensaje())
                .call()
                .content();
        return ResponseEntity.ok(new RespuestaChat(mensaje));
    }
}

Consideraciones de implementación

  • Implementar controles de acceso con Spring Security para restringir operaciones sensibles.
  • Manejar errores de manera amigable, traduciendo excepciones técnicas a mensajes comprensibles.
  • Optimizar las descripciones en las aontaciones @Tool para mejorar la precisión en la selección de herramientas por parte de la IA.

Etiquetas: spring-boot MCP spring-ai Anthropic Claude

Publicado el 7-10 17:55