Class 1: Why Spring AI + MCP?
Duration: ~30 minutes | Level: Intermediate | Prerequisites: Completed MCP Fundamentals, and comfortable with Spring Boot. Building MCP Servers in Java is recommended for depth, but not required: Spring AI's starters cover the plumbing this course needs.
- MCP spec: the code here targets
2025-11-25, which is the revision Spring AI2.0.0and the Java MCP SDK2.0.0implement.2026-07-28is the current stable revision; where it changes something this course teaches, the lesson says so. - Spring AI:
2.0.0GA (generally available, the stable release). - Spring Boot:
4.1.0GA, which means Spring Framework 7, Jakarta EE 11, Jackson 3, and a Java 17+ baseline. - Java: 21.
- Node.js: 22.12 or later, needed from Class 9 onwards for one MCP server distributed on npm, and from this class for the optional React frontend. Node 20 is end of life, and Vite 7, which the frontend uses, accepts
^20.19.0 || >=22.12.0.
Versions here move quickly: check Maven Central and docs.spring.io before starting your own project.
What We'll Cover
- Which half of the MCP picture the Java SDK course covered, and which half it did not
- What Spring AI is and the specific problems it solves
- How Spring AI and MCP fit together
- The application we build across the remaining sixteen classes, and how to get it running
You will not write any code in this class, only clone an application and start it, which takes a few minutes.
The Half We Have Not Built Yet
The Java SDK course built MCP servers. A server takes some capability we have, describes it in the terms the protocol uses, and waits for someone to call it. That someone was always an application we did not write.
The other side of the protocol is the application doing the asking: our own code, which sends a question to a model, lets the model decide which tools it needs, and then uses the answers it gets back. An order-processing assistant, a document summariser, or a service answering support questions from internal data all work this way.
The difference is which box we write:
In the Java SDK course, the model's reasoning happened inside a client someone else wrote. Here it happens inside our own process, and we choose the model and the servers it can reach.
The MCP Java SDK does not help us here. It implements the protocol, client-side included, but it does not include any code for calling a model. This course uses Spring AI for that.
What Spring AI Provides
Spring AI is the Spring project for working with AI models from Java. It sits between application code and the provider, in the position JdbcTemplate occupies between application code and a database driver.
ChatClient
ChatClient is the entry point, and the same code works against whichever provider is configured:
@Service
public class DocumentService {
private final ChatClient chatClient;
DocumentService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
public String summarise(String document) {
return chatClient.prompt()
.user("Summarise the following document:\n" + document)
.call()
.content();
}
}
Changing provider means changing one dependency and one property. The service does not change.
The tool-use loop, handled
When a model decides to call a tool, it does not send back an answer. It sends back a request: run this tool with these arguments. Something then has to run the tool, add the result to the conversation, and call the model again, until the model produces text.
ChatClient does all of that in one call:
The middle four messages repeat as long as the model keeps asking for tools. One request and its reply is a round trip, and our code sees only the first message and the last. Class 7 covers what happens when a tool fails.
MCP support, on both sides
On the client side, the MCP client starter reads connection details from configuration, connects to each server, performs the handshake that 2025-11-25 defines, and calls tools/list. Every discovered tool is exposed through a ToolCallbackProvider bean, which ChatClient accepts directly:
spring:
ai:
mcp:
client:
stdio:
connections:
knowledge-base:
command: npx
args:
- -y
- "@modelcontextprotocol/server-filesystem"
- ./support-kb
Those lines start the filesystem MCP server as a child process and offer its tools to the model. The server refuses any path outside the directories it is given, so this one can only reach ./support-kb. In Class 9 we use exactly this configuration to give the support agent the team's own notes.
On the server side, a set of annotations turns Spring beans into MCP capabilities. A method annotated with @McpTool becomes a tool, and Spring AI builds the JSON Schema from the method signature:
@McpTool(name = "get_order", description = "Look up an order by its ID.")
public Order getOrder(@McpToolParam(description = "Order ID, ORD-XXXXX") String orderId) {
return orderService.findById(orderId)
.orElseThrow(() -> new IllegalArgumentException(
"No order with ID '%s'. Check the ID and try again.".formatted(orderId)));
}
Matching annotations cover the other things a server can expose, and we use all of them: @McpResource, @McpPrompt and @McpComplete.
How the Pieces Fit
Follow one request down from the user, and the results back up:
Our code talks only to ChatClient. The provider's message format and MCP's JSON-RPC are both below that line.
MCP is a protocol, so a tool written once can be used by any client that speaks it. Spring AI packages that protocol's Java implementation, the MCP Java SDK, for Spring Boot on both sides, and adds the model integration around it. MCP without Spring AI leaves us writing the model integration ourselves, and Spring AI without MCP means defining the tools again in every application that needs them.
What We Build: a Support Desk
The rest of the course builds one order support system, class by class. By the end it does this:
You: Where is order ORD-10001, and can the customer still return it?
Support Desk: It shipped on 12 May with DHL, tracking DHL-88213, and is due on 14 May. Ana Ruiz is a Gold-tier customer, so the returns window is 60 days from delivery rather than the usual 30, which takes her to mid-July.
The support desk answers from three sources, and only one is a server we did not write:
The order, the shipment and the returns policy above all come from order-service, the server we build in Classes 2 to 5. In Class 9 we connect the agent to the third, an npm package that serves the support team's own notes. Most MCP systems are built this way, so the course covers both sides.
The course also covers the rest of what the protocol offers. order-service exposes orders as resources, so they can be attached to a conversation without the model having to look for them. It also offers a prompt that drafts a refund email, reports progress while rechecking delivery estimates for every order still in transit, and asks a person to confirm before cancelling an order.
Where each part is built:
| Class | What we add |
|---|---|
| 2 | The first @McpTool and the MCP endpoint |
| 3 | The rest of the tools, their schemas, and their behavioural hints |
| 4 | Resources: order://{orderId}, policy://returns and policy://shipping |
| 5 | A prompt that drafts a refund email, with order-ID completion |
| 6 | A second application, support-agent, connecting as an MCP client |
| 7 | A model, so support-agent answers questions in English |
| 8 | Reading resources and prompts from the client side |
| 9 | An MCP server we did not write, serving the support team's notes |
| 10 | A second knowledge-base server, and colliding tool names |
| 11 | Progress and log messages during a long job |
| 12 | Asking a person to confirm before cancelling an order |
| 13 | Roots, change notifications and sampling |
| 14 | Tests without calling a model |
| 15 | The same service, reactive and stateless |
| 16 | Health, metrics, retries and timeouts |
| 17 | The same service in Claude Desktop |
Classes 2 to 6 do not need an API key or a model: order-service is a working MCP server long before a model is involved, and we check it with curl at every step.
Getting the Starter Running
The application already exists as a plain Spring Boot service without AI. Clone it and start it:
git clone https://github.com/the-mcp-guy/spring-ai-mcp-course.git
cd spring-ai-mcp-course
mvn -pl order-service spring-boot:run
The repository is a multi-module Maven build: the pom.xml at the top has <packaging>pom</packaging>, listing the modules and holding the versions they share, without any code of its own. The application lives in order-service. -pl is short for --projects, and it names the module the goal runs for instead of every project in the build.
Leaving it out stops at that top-level project, which does not contain an application class to start:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:4.1.0:run (default-cli) on project support-desk: Unable to find a suitable main class, please add a 'mainClass' property
That is why every run command in this course names a module. In Class 6 we add a second module, support-agent, and from there the two run simultaneously in separate terminals.
The starter is an order service with JPA entities, repositories, a business service, a REST controller, and seed data for 200 orders across 42 customers. None of it is taught in this course: it is here so the classes can spend their time on MCP.
Check that it started:
curl http://localhost:8080/api/orders/ORD-10001
{
"orderId": "ORD-10001",
"status": "SHIPPED",
"customer": {
"customerId": "CUST-42",
"name": "Ana Ruiz",
"email": "[email protected]",
"tier": "GOLD"
},
"items": [
{ "productId": "PROD-001", "productName": "Wireless Keyboard", "quantity": 1, "unitPrice": 89.99 },
{ "productId": "PROD-002", "productName": "USB-C Hub", "quantity": 2, "unitPrice": 45.00 }
],
"totalAmount": 179.99,
"createdAt": "2026-05-10T09:00:00Z",
"lastUpdated": "2026-05-12T14:30:00Z",
"shipment": {
"carrier": "DHL",
"trackingNumber": "DHL-88213",
"shippedOn": "2026-05-12",
"estimatedDelivery": "2026-05-14"
}
}
In Class 2, we expose the same order through MCP. The REST endpoint stays where it is, leaving two entry points: one for the applications that call it today, one for a model.
The browser view
The repository also has a small React frontend. Start it if you want it:
cd frontend
npm install
npm run dev
It runs on http://localhost:5173 and shows the orders, with a panel for asking questions, which starts working in Class 7.
We don't teach the frontend, and we don't change it. It ships with the course project to make the later classes easier to follow. The refund-email button on each order starts working in Class 8, the progress bar in Class 11, and the confirmation dialog before a cancellation in Class 12. Every class also works from the command line, so the browser is optional.
A Note on Providers
Class 7 is the first class that needs a model. The examples use Anthropic's Claude because Anthropic designed MCP and Claude's tool use is well documented. Spring AI's abstraction means the same code runs against OpenAI, Google, Mistral, or a model on your own machine.
In Class 7 we configure Anthropic, provide the OpenAI equivalent, and set up Ollama with qwen3:8b so the course can be followed without an account or API key. We then run the application against that local model and show what came back, including where a model of that size struggles.
Where anything is provider-specific, this course says so.
Next: Class 2: From a REST Application to an MCP Server. Add the server starter, write the first tool, and call it over curl.
Further Reading
- Chat Client API, Spring AI Reference: the full
ChatClientAPI, including the builder, default system prompts, entity mapping and streaming. - Tool Calling, Spring AI Reference: how Spring AI runs the tool-use loop drawn above, where the tool method is executed, and how to take that over yourself.
- MCP Client Boot Starter, Spring AI Reference: every property under
spring.ai.mcp.client, including the stdio connections block above and the tool-callback bean it produces. - MCP Server Boot Starter, Spring AI Reference: the server half of the picture, which we add in Class 2, with its transports and the properties that configure them.
- MCP Annotations Overview, Spring AI Reference: the full list of MCP annotations on both sides, with the parameter annotations the
@McpToolexample uses. - Specification: 2025-11-25, Model Context Protocol: the protocol revision this course targets, in full.
- Versioning, Model Context Protocol: how revisions are dated and negotiated, for a reader wondering how
2025-11-25relates to2026-07-28. - MCP Java SDK: Client: the client API underneath the Spring AI starter, for a reader who wants to see what the starter configures.
Sources
- Spring AI 2.0.0 GA Available Now: Spring AI
2.0.0as the GA release, shipping MCP Java SDK2.0.0for the2025-11-25revision. - Versioning, Model Context Protocol:
2026-07-28as the current stable revision. - Spring Boot 4.1.0 available now: the
4.1.0GA release named in the version baseline. - Spring Framework 7.0 General Availability: the Jakarta EE 11 API level, the Java 17 baseline and Jackson 3 support that Spring Boot 4.1 brings with it.
- Previous Releases, Node.js: Node.js 20 listed as end of life, with 22 and 24 as the supported LTS lines.
- Maven CLI Options Reference:
-plas the short form of--projects, and what it selects. - Introducing the Model Context Protocol: Anthropic as the creator of MCP, which is why Class 7's examples use Claude.
- qwen3, Ollama: the
qwen3:8btag Class 7 pulls for the local model. - Filesystem MCP Server, modelcontextprotocol/servers: the directory access control behind the note that the server refuses any path outside the directories it is given.