sandipanchakraborty2016/spring-ai-mcp-demo
If you are the rightful owner of spring-ai-mcp-demo and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Model Context Protocol (MCP) server is a robust platform designed to facilitate seamless communication between AI models and client applications through a standardized protocol.
Spring AI MCP Demo
A comprehensive demonstration of the Model Context Protocol (MCP) using Spring AI, featuring a fully-functional MCP server, client, and model-agnostic host implementations with multiple tool examples.
📘 Architecture Guide: See for detailed explanation of MCP protocol usage vs REST wrappers.
🎯 Project Overview
This project showcases Spring AI's MCP implementation with:
- MCP Server (Port 8080): Exposes multiple tools via Server-Sent Events (SSE) and
@McpToolannotations - MCP Client (Port 8081): REST API wrapper for direct tool access (convenience endpoints, not using MCP protocol)
- MCP Host OpenAI (Port 8082): ✅ TRUE MCP DEMO - AI chat using OpenAI GPT with tools via MCP protocol
- MCP Host Claude (Port 8083): ✅ TRUE MCP DEMO - AI chat using Anthropic Claude with tools via MCP protocol
- Spring Boot 3.4.12 and Spring AI 1.1.0-M2
- Docker support for containerized deployment
- Model-Agnostic Design: Same MCP tools work with different AI providers
🔍 MCP Protocol vs REST APIs
- MCP Protocol (SSE + JSON-RPC): Used in
mcp-hostwhere ChatModel calls tools ✅ - REST Wrapper APIs: Used in
mcp-clientfor direct tool testing (not MCP protocol) ⚠️
🌟 Key Feature: Model-Agnostic MCP
This demo proves MCP's model-agnostic nature:
- One MCP Server provides tools (calculator, time, files, storage)
- Multiple AI Models can use the same tools:
- OpenAI GPT models (mcp-host on port 8082)
- Anthropic Claude models (mcp-host-claude on port 8083)
- No server changes needed to support different models
- Same tools, different intelligence - compare how different models use identical tools
🏗️ Architecture
┌──────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ MCP Host │ │ MCP Host │ │ MCP Client │
│ (OpenAI) │ │ (Claude) │ │ (Port 8081) │
│ Port 8082 │ │ Port 8083 │ │ │
│ │ │ │ │ REST API │
│ GPT-4 + Tools │ │ Claude + Tools │ │ Endpoints │
└────────┬─────────┘ └────────┬─────────┘ └────────┬────────┘
│ │ │
│ │ │
│ Uses MCP Tools │ Uses MCP Tools │ Calls MCP Tools
│ │ │
└───────────────────────────┴───────────────────────────┘
│
│ SSE/HTTP
▼
┌─────────────────┐
│ MCP Server │
│ (Port 8080) │
└─────────────────┘
│
│ Exposes Tools
▼
┌──────────────────┐
│ • Time Service │
│ • Calculator │
│ • File Ops │
│ • Data Storage │
└──────────────────┘
Model-Agnostic Design: Both OpenAI and Claude hosts use the same MCP server and tools!
🚀 Available Tools
Time Service
getCurrentTime()- Returns current timestamp
Calculator Service
add(a, b)- Additionsubtract(a, b)- Subtractionmultiply(a, b)- Multiplicationdivide(a, b)- Divisionpower(base, exponent)- Exponentiationsqrt(number)- Square root
File Service
readFile(filename)- Read file contentswriteFile(filename, content)- Create or overwrite fileappendToFile(filename, content)- Append to existing filelistFiles()- List all files in workspacedeleteFile(filename)- Delete a filegetFileInfo(filename)- Get file size and metadatagetWorkspacePath()- Get workspace directory path
Data Storage Service
store(key, value)- Store key-value pairretrieve(key)- Retrieve value by keydelete(key)- Delete entrylistKeys()- List all keysclear()- Clear all datacount()- Count entries
📋 Prerequisites
- Java 21 JDK (not just JRE - includes compiler)
- Maven 3.6+
- Docker and Docker Compose (for containerized deployment)
Installing Java 21 JDK
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install openjdk-21-jdk
# Verify installation
javac -version # Should show: javac 21.x.x
🏃 Quick Start
Docker Compose (Recommended)
Start all services (MCP Server + Client + Both AI Hosts):
docker-compose up --build
This starts:
- MCP Server on port 8080
- MCP Client on port 8081
- MCP Host (OpenAI) on port 8082
- MCP Host (Claude) on port 8083
Environment Variables
Before starting, set your API keys:
# For OpenAI host
export SPRING_AI_OPENAI_API_KEY="your-openai-api-key"
# For Claude host
export ANTHROPIC_API_KEY="your-anthropic-api-key"
Or create a .env file:
SPRING_AI_OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
Local Development (Individual Services)
-
Build all projects
mvn clean package -f mcp-server/pom.xml mvn clean package -f mcp-client/pom.xml mvn clean package -f mcp-host/pom.xml mvn clean package -f mcp-host-claude/pom.xml -
Start services individually
# Terminal 1: MCP Server cd mcp-server && mvn spring-boot:run # Terminal 2: MCP Client cd mcp-client && mvn spring-boot:run # Terminal 3: MCP Host (OpenAI) cd mcp-host && mvn spring-boot:run # Terminal 4: MCP Host (Claude) cd mcp-host-claude && mvn spring-boot:run
🔌 API Examples
Comparing OpenAI vs Claude (Model-Agnostic Demo)
Both hosts provide identical endpoints - test with the same queries to compare!
MCP Host - OpenAI (Port 8082)
# Get host information
curl http://localhost:8082/
# Check available MCP tools
curl http://localhost:8082/api/mcp-info
# Simple calculation
curl "http://localhost:8082/api/demo?query=What+is+25+times+4"
MCP Host - Claude (Port 8083)
# Get host information
curl http://localhost:8083/
# Check available MCP tools (same tools, different model!)
curl http://localhost:8083/api/mcp-info
# Same calculation with Claude
curl "http://localhost:8083/api/demo?query=What+is+25+times+4"
Try both and compare: Ask the same question to OpenAI and Claude hosts - they use the same MCP tools but may respond differently!
MCP Client - Direct Tool Access
List Available Tools
curl http://localhost:8081/api/tools
Time Service
curl http://localhost:8081/api/time
Calculator Operations
# Addition
curl "http://localhost:8081/api/calculator/add?a=10&b=5"
# Division
curl "http://localhost:8081/api/calculator/divide?a=20&b=4"
# Power
curl "http://localhost:8081/api/calculator/power?base=2&exponent=8"
File Operations
# List files
curl "http://localhost:8081/api/files/list"
# Write a file
curl -X POST "http://localhost:8081/api/files/write?filename=test.txt&content=Hello%20World"
# Read a file
curl "http://localhost:8081/api/files/read?filename=test.txt"
# Append to file
curl -X POST "http://localhost:8081/api/files/append?filename=test.txt&content=%0ANew%20line"
# Get file info
curl "http://localhost:8081/api/files/info?filename=test.txt"
# Delete file
curl -X DELETE "http://localhost:8081/api/files/delete?filename=test.txt"
# Get workspace path
curl "http://localhost:8081/api/files/workspace"
Data Storage
# Store data
curl -X POST "http://localhost:8081/api/storage/store?key=username&value=john_doe"
# Retrieve data
curl "http://localhost:8081/api/storage/retrieve?key=username"
# List all keys
curl "http://localhost:8081/api/storage/list"
# Delete entry
curl -X DELETE "http://localhost:8081/api/storage/delete?key=username"
🌐 Deployment
See for detailed deployment instructions for:
- Render.com (Free tier)
- Railway.app
- Fly.io
- Other cloud platforms
📁 Project Structure
spring-ai-mcp-demo/
├── mcp-server/ # MCP Server (provides tools)
│ ├── src/main/java/
│ │ └── com/example/mcpserver/
│ │ ├── McpServerApplication.java
│ │ ├── TimeService.java # @McpTool
│ │ ├── CalculatorService.java # @McpTool
│ │ ├── FileService.java # @McpTool
│ │ ├── DataStorageService.java # @McpTool
│ │ └── HealthController.java
│ ├── Dockerfile
│ └── pom.xml
│
├── mcp-client/ # MCP Client (calls tools directly)
│ ├── src/main/java/
│ │ └── com/example/mcpclient/
│ │ ├── McpClientApplication.java
│ │ ├── ClientController.java
│ │ └── HealthController.java
│ ├── Dockerfile
│ └── pom.xml
│
├── mcp-host/ # MCP Host with OpenAI
│ ├── src/main/java/
│ │ └── com/example/mcphost/
│ │ ├── McpHostApplication.java
│ │ ├── ChatController.java # AI chat endpoints
│ │ └── HealthController.java
│ ├── Dockerfile
│ └── pom.xml
│
├── mcp-host-claude/ # MCP Host with Claude (Anthropic)
│ ├── src/main/java/
│ │ └── com/example/mcphostclaude/
│ │ ├── McpHostClaudeApplication.java
│ │ ├── ClaudeChatController.java
│ │ ├── ClaudeConfig.java
│ │ └── HealthController.java
│ ├── Dockerfile
│ └── pom.xml
│
├── docker-compose.yml # Orchestrates all 4 services
├── render.yaml # Deployment configuration
└── README.md
🔧 Configuration
MCP Server Configuration
mcp-server/src/main/resources/application.properties:
server.port=8080
spring.ai.mcp.server.transport=sse
spring.ai.mcp.server.sse.message-endpoint=/mcp/message
MCP Client Configuration
mcp-client/src/main/resources/application.properties:
server.port=8081
spring.ai.mcp.client.transport=sse
spring.ai.mcp.client.sse.base-url=http://localhost:8080
spring.ai.mcp.client.sse.message-endpoint=/mcp/message
MCP Host (OpenAI) Configuration
mcp-host/src/main/resources/application.properties:
server.port=8082
spring.ai.openai.api-key=${SPRING_AI_OPENAI_API_KEY:demo-key}
spring.ai.openai.chat.options.model=gpt-4
spring.ai.mcp.client.sse.base-url=${SPRING_AI_MCP_CLIENT_SSE_BASE_URL:http://localhost:8080}
MCP Host (Claude) Configuration
mcp-host-claude/src/main/resources/application.properties:
server.port=8083
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY:demo-key}
spring.ai.anthropic.chat.options.model=claude-3-5-sonnet-20241022
spring.ai.mcp.client.sse.base-url=${SPRING_AI_MCP_CLIENT_SSE_BASE_URL:http://localhost:8080}
🧪 Testing
Health Checks
# MCP Server health
curl http://localhost:8080/health
# MCP Client health
curl http://localhost:8081/health
# MCP Host (OpenAI) health
curl http://localhost:8082/health
# MCP Host (Claude) health
curl http://localhost:8083/health
Testing Model-Agnostic MCP
Same query to both AI models:
# Ask OpenAI
curl "http://localhost:8082/api/demo?query=What+time+is+it+and+calculate+50+divided+by+5"
# Ask Claude (same tools, different reasoning!)
curl "http://localhost:8083/api/demo?query=What+time+is+it+and+calculate+50+divided+by+5"
Tool Discovery
# List all available tools from MCP Client
curl http://localhost:8081/api/tools
# Check MCP info from OpenAI host
curl http://localhost:8082/api/mcp-info
# Check MCP info from Claude host
curl http://localhost:8083/api/mcp-info
📚 Learn More
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
This project is licensed under the MIT License.
🙋 Support
For issues and questions, please open an issue in the repository.