Menu

AI

Spring AI MCP Tutorial: MCP Client and Server Boot Starters in Java

Build MCP clients and servers in Spring Boot with Spring AI: the client starter, ToolCallbackProvider, @McpTool servers, Streamable HTTP, stdio and Windows fixes.

By: Irina ShvayaNovember 2, 2026

Spring AI MCP Tutorial: MCP Client and Server Boot Starters in Java

This tutorial is part of Build an MCP Server, within The MCP Guide. Want it built for you? See MCP development.

Spring AI brings MCP to Spring Boot through boot starters. Add the MCP client starter, list servers in application.yml, and every server's tools arrive as a ToolCallbackProvider you hand to a ChatClient. Add an MCP server starter, annotate methods with @McpTool, and your Spring app becomes an MCP server.

This tutorial builds both sides: a client that calls a local server, and a server with one annotated tool. Code was checked against the Spring AI MCP reference pages and the official spring-ai-examples repository on 2 November 2026. Maven Central's newest stable Spring AI release that day was 2.0.2, with 2.1.0-RC1 also published. The official examples target Spring Boot 4 and Spring AI 2.x.

Key Takeaways

  • Client: add spring-ai-starter-mcp-client and configure connections under spring.ai.mcp.client; tools become a ToolCallbackProvider bean.
  • Spring AI recommends the WebFlux-based client starter, spring-ai-starter-mcp-client-webflux, for production HTTP connections.
  • Server: annotate methods on a Spring bean with @McpTool and @McpToolParam; the starter registers them automatically.
  • Pick the server transport with spring.ai.mcp.server.protocol: STREAMABLE or STATELESS; SSE is deprecated since 2.0.0.
  • stdio servers must keep stdout clean: no web server, no banner, no console logging.

Prerequisites

  • Java 17 or later and Maven or Gradle.
  • A Spring Boot 4 project with the Spring AI BOM.
  • A chat model starter, such as spring-ai-starter-model-anthropic, plus its API key.
  • Node.js if you want to run npm-packaged MCP servers or the MCP Inspector.

Part 1: The MCP client

Add the starter

From the MCP Client Boot Starter docs:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

The docs say this starter connects over stdio, SSE, Streamable HTTP and Stateless Streamable HTTP, using the JDK HttpClient. "For production deployment, we recommend using the WebFlux-based" starter, spring-ai-starter-mcp-client-webflux.

Configure servers

spring:
  ai:
    mcp:
      client:
        type: SYNC
        request-timeout: 30s
        streamable-http:
          connections:
            notes:
              url: http://localhost:8080
              endpoint: /mcp
        stdio:
          connections:
            filesystem:
              command: npx
              args:
                - -y
                - "@modelcontextprotocol/server-filesystem"
                - /path/to/files

Notes:

  • streamable-http.connections.[name].url is the base URL; endpoint is the path and defaults to /mcp.
  • type is SYNC by default, or ASYNC for reactive apps. You "cannot mix sync and async clients."
  • You can point stdio.servers-configuration at a Claude Desktop style JSON file instead of listing connections in YAML.

Use the tools in a ChatClient

The default client example injects the auto-configured ToolCallbackProvider:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner ask(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) {
        return args -> {
            var chatClient = chatClientBuilder.defaultTools(tools).build();
            System.out.println(chatClient.prompt("What tools are available?").call().content());
        };
    }
}

The tool callback auto-configuration is on by default. Set spring.ai.mcp.client.toolcallback.enabled=false if you want the raw McpSyncClient beans without tool callbacks.

Filter tools and avoid name clashes

The client docs describe tool filtering and tool name prefix generation, so two servers' search tools do not collide. Filter down to the tools each ChatClient needs. Every tool you pass adds a description to every model call; see too many MCP tools.

Windows: the cmd.exe wrapper

The docs explain that on Windows, npx, npm and node are batch files, and "Java's ProcessBuilder cannot execute batch files directly." Wrap them:

{
  "mcpServers": {
    "filesystem": {
      "command": "cmd.exe",
      "args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\username\\Desktop"]
    }
  }
}

Part 2: An MCP server with @McpTool

Choose a starter and protocol

From the MCP Server Boot Starter docs:

TransportStarterProperty
stdiospring-ai-starter-mcp-serverspring.ai.mcp.server.stdio=true
Streamable HTTP (WebMVC)spring-ai-starter-mcp-server-webmvcspring.ai.mcp.server.protocol=STREAMABLE
Stateless (WebMVC)spring-ai-starter-mcp-server-webmvcspring.ai.mcp.server.protocol=STATELESS
Streamable HTTP (WebFlux)spring-ai-starter-mcp-server-webfluxspring.ai.mcp.server.protocol=STREAMABLE

SSE variants still exist but are marked "deprecated since 2.0.0, use STREAMABLE instead." The Streamable HTTP server's endpoint defaults to /mcp. Our stdio vs Streamable HTTP guide helps you choose.

Write a tool

Keep each tool small and specific. A tool that does one job, with a clear name and description, is easier for the model to pick correctly than a general tool with a mode parameter. Spring AI builds the input schema from the method parameters and their @McpToolParam descriptions, so write those descriptions for the model.

The MCP annotations docs show @McpTool on a Spring bean. The import path below comes from the official weather server example:

import org.springframework.ai.mcp.annotation.McpTool;
import org.springframework.ai.mcp.annotation.McpToolParam;
import org.springframework.stereotype.Component;

@Component
public class CalculatorTools {

    @McpTool(name = "add", description = "Add two numbers together")
    public int add(
            @McpToolParam(description = "First number", required = true) int a,
            @McpToolParam(description = "Second number", required = true) int b) {
        return a + b;
    }
}

The weather examples say the starter "discovers all @McpTool-annotated methods automatically," so no manual bean wiring is needed.

Add a second tool, with hints

@McpTool also takes a title, generateOutputSchema, and MCP tool annotations:

@McpTool(name = "calculate-area",
         description = "Calculate the area of a rectangle",
         title = "Rectangle Area Calculator",
         generateOutputSchema = true,
         annotations = @McpTool.McpAnnotations(
             title = "Rectangle Area Calculator",
             readOnlyHint = true,
             destructiveHint = false,
             idempotentHint = true
         ))
public AreaResult calculateRectangleArea(
        @McpToolParam(description = "Width", required = true) double width,
        @McpToolParam(description = "Height", required = true) double height) {
    return new AreaResult(width * height, "square units");
}

Mark read-only tools honestly. Clients may skip approval prompts for them. Our tool annotations guide explains how hints are used.

Configure a Streamable HTTP server

For an HTTP server on Spring MVC, add spring-ai-starter-mcp-server-webmvc and set the protocol:

spring.ai.mcp.server.name=calculator-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.protocol=STREAMABLE

The endpoint is /mcp unless you change mcp-endpoint. Use STATELESS for the simplest deployments; the docs describe stateless servers as "designed for simplified deployments where session state is not maintained between requests." Set spring.ai.mcp.server.type=ASYNC if the rest of your app is reactive.

Tools can also send progress and log messages. The annotations docs show a tool that takes an McpSyncRequestContext parameter and calls context.info(...) and context.progress(...) while it works, which helps clients show status on slow calls.

Keep stdout clean for stdio

For a stdio server, the official example sets:

spring.main.web-application-type=none
spring.main.banner-mode=off
logging.pattern.console=

spring.ai.mcp.server.name=my-weather-server
spring.ai.mcp.server.version=0.0.1

logging.file.name=./target/mcp-weather-stdio-server.log

stdout carries the protocol. A Spring banner or a console log line will corrupt it.

Test with the MCP Inspector

For a Streamable HTTP server on port 8080:

npx @modelcontextprotocol/inspector --cli http://localhost:8080/mcp --transport http --method tools/list

For a stdio server, pass the launch command instead:

npx @modelcontextprotocol/inspector --cli java -jar target/your-server.jar --method tools/list

Our MCP Inspector lesson shows how to call tools and script these checks.

Deploy notes

  • Use the WebFlux client starter for production HTTP connections, as the docs recommend.
  • Pick STATELESS for servers behind load balancers or on serverless platforms; the docs call stateless servers "ideal for microservices architectures and cloud-native deployments."
  • Protect HTTP servers with Spring Security or a gateway. Our OAuth for remote MCP servers guide covers the flow.

Pitfalls

  • Old artifact names. Some older READMEs still mention spring-ai-mcp-server-webmvc-spring-boot-starter. The current reference uses spring-ai-starter-mcp-server-webmvc.
  • Mixing SYNC and ASYNC. Pick one client type per app.
  • Copied server packages. Example configs name specific npm servers. Check that any server you copy is still published and maintained before you depend on it.
  • Logs on stdout in stdio mode. Redirect logging to a file.

Next step

Take the free MCP course for the protocol basics behind the starters. If you want a Java MCP server for your internal systems, built with auth and audit logging, see our MCP development service.

More in the MCP Guide

Free tools: server.json Validator · MCP Error Code Lookup

Latest research: State of MCP: October 2026

Frequently asked questions

Which Spring AI version should I use for MCP?

Use a current 2.x release. Maven Central listed 2.0.2 as the newest stable Spring AI release on 2 November 2026, and the official MCP examples target Spring Boot 4 and Spring AI 2.x.

Do I need the Java MCP SDK directly?

Usually not. The boot starters wrap it and auto-configure clients and servers from properties. Drop to the SDK only when you need manual control.

Can one Spring app be both an MCP client and server?

Yes. Add both starters. Keep the client's tool callbacks separate from the tools your server exposes, so you do not re-export third-party tools by accident.

Why does my stdio server fail when Claude Desktop starts it?

Usually stdout is not clean. Turn off the web server and banner, empty the console log pattern, and send logs to a file, as in the official stdio example.

You Might Also like to Read

Get a FREE Website Audit

Enter your website and get a 20–30 page SEO, GEO, AEO & CRO audit within 24 hours. Completely free.

Don't have a site yet? Get in touch →

Ready to speak with a marketing expert?
Give us a call! (916) 866-7893

Websites Launched
1407
Websites Launched
Marketing Experts
29
Marketing Experts
Hours of Dedicated Work
204533
Hours of Dedicated Work
Irina S.Benjamin G.Jeanette M.David G.