Artículo

Visión general de las anotaciones MCP en Spring AI

Visión general de las anotaciones MCP en Spring AI

1. Resumen

El Protocolo de Contexto de Modelo (MCP) ha surgido como un estándar para conectar modelos de IA con datos y herramientas externas. En lugar de construir integraciones personalizadas para cada fuente de datos, MCP permite a los desarrolladores crear conectores universales que funcionan con varios clientes de IA.

Spring AI admite este protocolo a través de un módulo dedicado que introduce un modelo de programación declarativo basado en anotaciones. En lugar de registrar manualmente los callbacks de herramientas o configurar esquemas JSON, podemos anotar métodos Java estándar para exponerlos como capacidades de IA.

En este tutorial, exploraremos las anotaciones principales de MCP en Spring AI*: @McpTool, @McpResource, y @McpPrompt.

2. Dependencias de Maven

Usamos la dependencia spring-ai-starter-mcp-server. Este iniciador gestiona la autoconfiguración y el escaneo de componentes para los beans MCP:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server</artifactId>
    <version>1.1.2</version>
</dependency>

3. Configuración del Servidor

Los servidores MCP a menudo se comunican a través de Entrada/Salida Estándar (Stdio) cuando se ejecutan localmente. Esto significa que el cliente de IA lanza nuestra aplicación Java como un subproceso y "habla" con él a través de la consola.

Para que esto funcione, nuestra aplicación no debe imprimir ningún registro en la consola, ya que esto corrompe los mensajes JSON del protocolo.

Debemos configurar nuestro application.properties para usar Stdio y silenciar los registros:

spring.application.name=my-spring-calculator

# 1. Use STDIO transport
spring.ai.mcp.server.stdio=true

# 2. CRITICAL: Disable the Banner and Web Server
# Any text printed to console will break the connection
spring.main.banner-mode=off
spring.main.web-application-type=none

# 3. Redirect logs away from Console
logging.pattern.console=

4. Exposición de Funcionalidad con @McpTool

La anotación @McpTool es el motor de trabajo del desarrollo de MCP. Marca un método Java como una "herramienta" ejecutable que el modelo de IA puede llamar. Cuando la aplicación inicia, Spring AI analiza la firma del método para crear una definición de herramienta.

4.1. Definición Básica de la Herramienta

Vamos a crear un servicio que exponga una función de calculadora simple. Usamos @McpTool en el método y @McpToolParam en los argumentos para proporcionar metadatos:

@Service
public class CalculatorService {

    @McpTool(
        name = "calculate_sum", 
        description = "Calculates the sum of two integers. Useful for basic arithmetic."
    )
    public int add(
        @McpToolParam(description = "The first number to add", required = true) int a, 
        @McpToolParam(description = "The second number to add", required = true) int b
    ) {
        return a + b;
    }
}

Los campos de descripción son funcionalmente importantes. El LLM los usa para entender cuándo llamar a esta herramienta y qué representan los parámetros. Si se omite el nombre, se usa el nombre del método por defecto.

4.2. Manejo de Objetos Complejos

Para herramientas más sofisticadas, a menudo necesitamos pasar objetos estructurados en lugar de primitivas simples. Spring AI admite Registros Java (y POJOs), serializándolos automáticamente a esquemas JSON. Considera una herramienta de búsqueda de clientes que acepte criterios de filtro:

public record CustomerSearchCriteria(
    String region, 
    boolean activeOnly, 
    @JsonProperty(required = false) Integer limit
) {}

@Service
public class CustomerService {

    @McpTool(description = "Search for customers using structured criteria")
    public List<String> searchCustomers(
        @McpToolParam(description = "The search filters") CustomerSearchCriteria criteria
    ) {
        // In a real app, this would query a database
        return List.of("Customer A", "Customer B");
    }
}

Al usar un Registro, agrupamos parámetros relacionados. El cliente de IA recibe un esquema indicando que debe enviar un objeto JSON que contenga los campos region y activeOnly.

4.3. Accediendo al Contexto de la Solicitud

A veces, una herramienta necesita acceder a la sesión subyacente de MCP, por ejemplo, para registrar mensajes de vuelta al cliente o seguir el progreso. Podemos inyectar McpSyncRequestContext como argumento. Este parámetro forma parte de la infraestructura interna y se excluye del esquema de herramienta generado visible para la IA.

@McpTool(name = "long_running_process")
public String processData(
        String dataId,
        McpSyncRequestContext context
) {
    context.info("Starting processing for ID: " + dataId);

    // Simulate work and report detailed progress
    // 50% complete (0.5 out of 1.0)
    context.progress(p -> p.progress(0.5).total(1.0).message("Processing records..."));

    return "Processed " + dataId;
}

4.4. Habilitar Autocompletado con @McpComplete

Los clientes de IA modernos como Claude admiten autocompletado cuando los usuarios escriben argumentos para un Prompt. La anotación @McpComplete nos permite proporcionar sugerencias dinámicas. Por ejemplo, podemos sugerir lenguajes de programación para nuestro prompt review_code:

@McpComplete(prompt = "review_code")
public List<String> completeLanguage(McpSchema.CompleteRequest.CompleteArgument argument) {
    if (!"language".equals(argument.name())) {
        return List.of();
    }

    String token = argument.value();
    return List.of("Java", "Python", "TypeScript", "Go").stream()
      .filter(lang -> lang.toLowerCase().startsWith(token.toLowerCase()))
      .toList();
}

Spring AI vincula este método al prompt review_code. Cuando el usuario selecciona ese prompt y comienza a escribir en el campo de idioma, este método filtra las sugerencias.

5. Exposición de Datos con @McpResource

Mientras que las herramientas representan acciones, los recursos representan datos. La anotación @McpResource expone datos a la IA en forma de solo lectura, similar a cómo la IA leería un archivo. Cada recurso se asigna a un URI.

5.1. Plantillas URI

Podemos usar plantillas URI para crear recursos dinámicos. Spring AI extrae variables de la plantilla URI y las mapea a parámetros del método:

@Service
public class SystemLogService {

    @McpResource(
        uri = "logs://{serviceName}/{date}", 
        name = "System Logs", 
        description = "Read logs for a specific service and date"
    )
    public String readLog(
        @McpToolParam(description = "Service Name") String serviceName, 
        @McpToolParam(description = "Date YYYY-MM-DD") String date
    ) {
        return "Logs for " + serviceName + " on " + date + ": No errors found.";
    }
}

Cuando un cliente de IA solicita logs://payment-service/2023-12-01, este método se invoca con los valores extraídos.

5.2. Devolución de Datos Binarios

Los recursos pueden incluir más que solo texto. Para servir datos binarios (como imágenes o PDFs), el método debe devolver un ReadResourceResult. Esto nos permite establecer el tipo MIME explícitamente:

@McpResource(uri = "diagrams://{id}", name = "System Architecture Diagram")
public ReadResourceResult getDiagram(String id) {
    String base64Image = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
    
    return new ReadResourceResult(List.of(
        new BlobResourceContents(
            "diagrams://" + id, 
            "image/png", 
            base64Image
        )
    ));
}

6. Estandarizando Prompts con @McpPrompt*

La anotación @McpPrompt permite al servidor definir plantillas de prompt reutilizables. Esto es útil para compartir instrucciones estandarizadas o "mejores prácticas" para interactuar con los datos del servidor:

@Service
public class CodeReviewPrompts {

    @McpPrompt(
        name = "review_code", 
        description = "Generates a standard code review request"
    )
    public GetPromptResult generateReviewPrompt(
        @McpArg(name = "language", description = "The programming language", required = true) String language,
        @McpArg(name = "code", description = "The code snippet", required = true) String code
    ) {
        String template = """
            Please review the following %s code. 
            Focus on thread safety and performance:
            
            %s
            """;
            
        String content = String.format(template, language, code);
        
        return new GetPromptResult(
            "Code Review", 
            List.of(new PromptMessage(Role.USER, new TextContent(content)))
        );
    }
}

Aquí, la anotación @McpArg funciona de manera similar a @McpToolParam, definiendo las variables que el cliente debe proporcionar para rellenar la plantilla.

7. Conexión a Claude Desktop

La aplicación Claude Desktop actúa como un cliente MCP. Para conectarla a nuestro servidor Spring Boot, debemos configurarla para lanzar directamente nuestro archivo JAR.

7.1. Construyendo la Aplicación

Como estamos usando el transporte Stdio, necesitamos un archivo JAR ejecutable. Construiremos la aplicación usando Maven:

./mvnw clean package

Verifique que el archivo JAR exista en su directorio target/ (por ejemplo, target/mcp-demo-0.0.1-SNAPSHOT.jar).

7.2. Configurando Claude Desktop

Para configurar la conexión MCP, necesitamos abrir el archivo claude_desktop_config.json. Podemos acceder a este archivo fácilmente a través de la interfaz de Claude navegando a Configuración > Desarrollador y haciendo clic en Editar Config. Alternativamente, podemos localizar el archivo directamente en estas rutas:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Una vez abierto, necesitamos agregar nuestra configuración del servidor:

{
  "mcpServers": {
    "my-spring-calculator": {
      "command": "java",
      "args": [
        "-jar",
        "C:\Users\yourname\projects\mcp-demo\target\mcp-demo-0.0.1-SNAPSHOT.jar"
      ]
    }
  }
}

Si estamos en Windows, debemos escapar nuestras barras invertidas. Por ejemplo, si tu ruta real es C:\Users\me\app.jar, debes escribirla como C:\\Users\\me\\app.jar dentro del archivo JSON.

Después de guardar el archivo, debemos reiniciar la aplicación Claude Desktop completamente para que reconozca los cambios. Cuando volvamos, buscaremos los Conectores (icono de enchufe) en la barra de entrada, y deberíamos ver my-spring-calculator con un estado activo verde.

8. Conclusión

En este artículo, discutimos las anotaciones MCP de Spring AI que reducen significativamente la barrera de entrada para construir sistemas de IA agente. Al aprovechar conceptos familiares como @Service y @McpTool, los desarrolladores pueden exponer la lógica de negocio existente a los modelos de IA con mínima fricción. Exploramos cómo @McpTool convierte métodos en acciones llamables por IA, cómo @McpResource crea sistemas de archivos virtuales para el contexto de IA, y cómo @McpPrompt estandariza las interacciones. Además, dado que estos componentes siguen siendo POJOs, son fácilmente testeables usando prácticas estándar de Java.

Newsletter Semanal de Java

Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.

Sin spam. Cancela cuando quieras.

Compartir artículo