Building a Real-World AI Agent with Spring Boot and MCP Explained in 10 Minutes
AI models today are incredibly smart and capable. They can chat, write, summarize, and think almost like an actual human. However, if you only use them as chat applications, you'll find they are somewhat limited to just text-based interactions. But did you know that we can also enable them to interact with the real world and actually perform tasks?
This is where the Model Context Protocol (MCP) comes in. If an AI model is like a brain, then MCP provides the arms and legs. In practice, MCP acts as a protocol for AI models to interact with APIs, whether they are online or running on your local computer. This allows our AI to go from simply returning text responses to performing actual, tangible tasks.
In this article, we are going to build an MCP server using Spring Boot that an AI model can call to perform tasks on our system. We'll be using Claude Desktop as our MCP client, which internally uses the Claude Sonnet AI model. This client will call the MCP server we build to execute actions. As an example, our MCP server will function as a shopping cart service, allowing us to create a shopping list where we can add, remove, and list items. By the end of this guide, you'll be able to type something like, 'add two packets of milk to my shopping list,' and the AI application will call the application we've built to store the items on our system.
It's worth noting that while we use Claude Desktop for simplicity in this tutorial, there are numerous other MCP clients available, and you can even build your own.
Setting Up the Spring Boot Application in 5 Steps
Let's begin by setting up our Spring Boot application. 1. Navigate to the Spring Initializr page. 2. We'll choose the default options for our language and framework versions. 3. Give a name to your artifact or application. 4. For dependencies, the crucial one to add is the Model Context Protocol server. 5. After this is done, you can download the starter application code.
Configuring the Application
Now, let's examine the code.
pom.xml
In the pom.xml
file, you will see that the spring-mcp-server
dependency has been added.
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
application.properties
Next, let's look at the application.properties
file. This is essential for configuring our MCP server correctly. Here are the key settings:
-
spring.ai.mcp.server.type=sync
: We set the server type tosync
, meaning we're running a synchronous server for requests and responses. -
spring.ai.mcp.server.name=shopping-cart-server
andspring.ai.mcp.server.version=1.0.0
: These settings help the MCP client identify our server. -
spring.main.web-application-type=none
: We must set the web application type tonone
. This tells Spring Boot not to start a web server, as our MCP server will communicate using standard input/output (stdio) instead of HTTP or REST APIs. -
spring.main.banner-mode=off
andlogging.pattern.console=
: These two settings disable any other logs from Spring Boot from appearing in the standard output. This prevents interference with the messages exchanged between the MCP client and server during stdio communication. All other standard logs are redirected to a file to avoid interference.
Implementing the Core Logic
Now, let's dive into the core logic for our MCP server. We've created a class called ShoppingCart
, which we will annotate as a Spring Boot service. This class contains the actual logic for our shopping list.
First, we define a ShoppingItem
which consists of a name
and a quantity
. Then, we'll use a ConcurrentHashMap
to store all the shopping items in memory.
Exposing Methods to the AI
So, how does the AI or our MCP client discover the available methods in our MCP server? This is achieved through the @Tool
annotation. In this annotation, we provide a name
and a description
.
These parameters are very important: * Description: This text is given to the AI model to help it determine whether to use the tool. The value should comprehensively describe the method's functionality. * Input Parameter Names: These are also crucial because Spring AI typically uses these exact names to map the inputs extracted from the user's request to the tool's arguments. * Return Value: Whatever your Java method returns is often serialized and sent back to the AI model. The model then uses this information in its response to the user or to make further decisions.
The Shopping Cart Implementation
Now, returning to our ShoppingCart
, let's examine the first method, which adds an item to the shopping list. We've added a name
and description
that inform the AI model that this method is used to add items to the shopping list or update their quantity. It also signals that the client or AI model needs to specify the item's name
and quantity
.
Our parameters are named name
and quantity
to clearly indicate their purpose. As mentioned, these names are important, so ensure your argument variables are named descriptively.
Here is an example of the code:
java
@Tool(name = "addItem", description = "Add an item to the shopping list or update its quantity. The item name and quantity must be specified.")
public String addItem(@RequestParam(name = "name") String name, @RequestParam(name = "quantity") int quantity) {
// ... validation and logic ...
shoppingList.put(name, new ShoppingItem(name, quantity));
return "Added " + quantity + " of " + name + " to the shopping list.";
}
In this method, we perform some initial validation and add a new ShoppingItem
to the ConcurrentHashMap
shopping list. If an item already exists, we update its quantity. Finally, we return a string confirming the quantity and name of the item added.
We also have methods to get all items from the shopping list and to remove items. You can review these implementations as well.
The Main Application Class
Now, let's look at our main application class. We annotate it with @SpringBootApplication
, and the main
method starts the application. Additionally, we need to define a @Bean
method that returns a List<ToolCallback>
. This is how our MCP client gets the list of tools exposed by our MCP server. The ShoppingCart
service is autowired by Spring Boot, and we convert it into a list of callbacks to be returned.
Running the Application
Let's run the application. Open your terminal and execute the mvn spring-boot:run
command to check if everything is working. You can ignore any logging errors for now, as they are likely caused by the empty logging pattern we configured earlier. If there are no other errors, our application should be running correctly.
Setting Up the Server in Claude Desktop
Now, we can set up this server in our Claude Desktop application. If the application runs successfully with the spring-boot:run
command, we can compile it into a JAR file by running mvn package
. After this, you will find the JAR file in the target
folder.
To set up the server in Claude Desktop:
1. Open the Settings in Claude Desktop and edit the Developer Settings.
2. This will open a JSON configuration file.
3. Add the command to start your server. The command is simply java -jar
followed by the path to your JAR file.
Here is an example configuration:
json
{
"commands": [
{
"name": "shopping-cart-server",
"command": "java",
"args": ["-jar", "/path/to/your/project/target/your-app.jar"]
}
]
}
After saving the settings and restarting Claude Desktop, you should see our server appearing in the Tool menu, listing all the methods we defined in our code.
Testing the Integration
Let's test it out. For instance, if we want to add a few packets of milk to our shopping list, we can just state this in plain English. The AI model will determine that this request is best handled by our MCP server and will call the appropriate method to add the milk to our shopping list. You can try adding several other items in plain English, and you'll see it works quite well.
To see what's currently on the list, you can again just ask in plain English. This will trigger a call to our MCP server to get all items. The server responds with the current list, and the client uses the AI model to present the information back to you in a natural, conversational way.
What's particularly powerful about this setup is that it's not just a regular chat with an AI. The data is being stored on your local machine. This means if you start a new chat session and ask, 'What's on my shopping list?' it will again call the MCP server and retrieve the items you added previously.
Note: This worked well in our example because the application is quite simple. If you encounter issues, you can debug by inspecting the exact requests and responses being sent to the MCP server.
Endless Possibilities
We've explored a simple application, but as you can imagine, this is an incredibly powerful paradigm. It allows us to use any AI model as a reasoning 'brain' to decide what needs to be done, while the actual execution is handled by our MCP server. Our example was a simple shopping list, but you could implement more than 5+ other functionalities, like browsing the file system or even controlling a robot arm in the real world. The possibilities are vast, and frameworks like Spring AI make it remarkably easy to get started and create an MCP server from scratch.
Join the 10xdev Community
Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.