Hero image

Building an MCP Server with Spring AI

Sep 23, 2025
Java Spring Boot AI

In this article we’ll talk about building an Model Context Protocol (MCP) server using Spring AI.

Checkout the GitHub repository for the complete code.

Introduction to the MCP

As LLMs are becoming more popular there is a desire to expand their capabilities to be able to perform operations on external systems. For example, suppose we have created a referral system and we’d like prompts such as “What is the status of referral 0001?” or “List all pending referrals” to fetch the data from the database.

The MCP is a specification that allows LLMs to interact with external systems in a structured way. An LLM can query the MCP server to discover what capabilities it has and then invoke those capabilities by providing structured input.

An MCP server is an application that implements the MCP specification and expose additional capabilities to the LLM. The MCP server can be implemented in any programming language and can use any framework. In this article, we’ll use Java and Spring Boot to build an MCP server.

MCP Architecture

The MCP architecture follows a client-server model and consists of the following components:

  • MCP Host: This is the LLM or any application that wants to interact with the MCP server. The host is responsible for discovering the capabilities of the MCP server and invoking them.
  • MCP Client: The client sends requests to the server to discover its capabilities and invoke them.
  • MCP Server: This is the application that implements the MCP specification. The server exposes its capabilities to the client and processes the requests.
  • External System: These are the individual capabilities that the MCP server exposes. Each tool has a name, description, and input schema.

Spring Boot Project Example

To create an MCP server using Spring Boot, we can use the spring-ai-starter-mcp-server dependency. This starter provides the necessary components to build an MCP server.

implementation 'org.springframework.ai:spring-ai-starter-mcp-server'

For this demo we’ll also need to disable the Spring Boot startup banner by adding the following line to application.properties.

spring.main.bannerMode=off

The MCP server module provides the @Tool annotation to mark a method as a tool in Spring AI. The @Tool annotation can take a description parameter to provide a brief description of the tool which the LLM uses to understand its purpose.

@Service
public class ReferralService {
    private final ReferralRepository referralRepository;

    public ReferralService(ReferralRepository referralRepository) {
        this.referralRepository = referralRepository;
    }

    @Tool(description = "Find referral details for a specific referral id")
    public Optional<Referral> findReferral(UUID referralId) {
        return referralRepository.findReferral(referralId);
    }

    @Tool(description = "Find all referrals with a particular status")
    public List<Referral> findAllReferralsByStatus(ReferralStatus status) {
        return referralRepository.findAllReferralsByStatus(status);
    }
}

We need to register the tool methods with the MCP server using ToolCallbackProvider.

@Configuration
public class ApplicationConfig {
    @Bean
    public ToolCallbackProvider referralTools(ReferralService referralService) {
        return MethodToolCallbackProvider.builder().toolObjects(referralService).build();
    }
}

Integrating with Claude Desktop

To test our MCP server, we can use the Claude Desktop application. Claude Desktop allows us to configure MCP servers and interact with them. To configure the MCP server in Claude Desktop, we need to add the following configuration in the claude_desktop_config.json which can be opened File > Settings > Developers > Edit config

{
  "mcpServers": {
    "referral-system-mcp": {
      "command": "java",
      "args": [
        "-Dspring.ai.mcp.server.transport=STDIO",
        "-jar",
        "{path-to-project}/build/libs/referral-system-mcp-0.0.1-SNAPSHOT.jar"
      ]
    }
  }
}

This configures Claude Desktop to start the MCP server using the stdio transport, i.e. Claude starts the MCP server in a process then interacts with it via standard input/output. It is possible to use other transports such as HTTP for remote MCP servers however this is beyond the scope of this article.

If the prompt “What is the status of 44444444-4444-4444-4444-444444444444?” or “List all pending referrals” is entered then Claude will invoke the appropriate tool in the MCP server to fetch the data.

Viewing Logs and Debugging the MCP Server

Claude Desktop provides a way to view the logs of the MCP server. To view the logs, go to the directory containing claude_desktop_config.json then open logs/{mcp-name}.log.

The logs will show the requests and responses between Claude and the MCP server. This is useful for debugging and understanding how the MCP server is being used. For example, the following entry shows the initial request from Claude to discover the tools available in the MCP server.

{
  "tools": [
    {
      "name": "findAllReferralsByStatus",
      "description": "Find all referrals with a particular status",
      "inputSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "COMPLETED",
              "EXPIRED"
            ]
          }
        },
        "required": [
          "status"
        ],
        "additionalProperties": false
      }
    },
    {
      "name": "findReferral",
      "description": "Find referral details for a specific referral id",
      "inputSchema": {
        "type": "object",
        "properties": {
          "referralId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "referralId"
        ],
        "additionalProperties": false
      }
    }
  ]
}