Skip to content

Commit 4a458c1

Browse files
committed
docs: simplify and streamline MCP annotations examples
- Simplify README documentation by removing verbose descriptions - Remove OpenAI/Anthropic API key dependencies from client examples - Update configuration examples to focus on core MCP functionality - Streamline server documentation with clearer examples - Remove unnecessary version properties from POM files - Add clarifying comments to application code - Update resource links to use current Spring AI documentation URLs - Focus examples on essential MCP features rather than comprehensive showcase Signed-off-by: Christian Tzolov <[email protected]>
1 parent d2d5845 commit 4a458c1

File tree

8 files changed

+232
-199
lines changed

8 files changed

+232
-199
lines changed

model-context-protocol/mcp-annotations/README.md

Lines changed: 50 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,25 @@
11
# Spring AI MCP Annotations Examples
22

3-
This directory contains comprehensive examples demonstrating the Model Context Protocol (MCP) using Spring AI's annotation-based approach. These examples showcase the full spectrum of MCP capabilities including tools, resources, prompts, completions, and client-side handlers using declarative annotations.
3+
This directory contains examples demonstrating the Model Context Protocol (MCP) using Spring AI's annotation-based approach. These examples showcase MCP capabilities including tools, resources, prompts, completions, and client-side handlers using declarative annotations.
44

55
## Overview
66

77
The MCP Annotations examples demonstrate:
88

9-
- **Complete MCP Feature Set**: Tools, resources, prompts, completions, and client handlers
109
- **Annotation-Driven Development**: Simplified MCP development using `@McpTool`, `@McpResource`, `@McpPrompt`, `@McpComplete`, and client annotations
1110
- **Declarative Configuration**: Automatic registration and configuration through annotations
12-
- **Multiple Data Sources**: Weather APIs, user profiles, and completion databases
1311
- **Client-Server Communication**: Full bidirectional MCP communication patterns
14-
- **Advanced MCP Features**: Progress tracking, logging, sampling, and elicitation
15-
16-
## What Makes This Special?
17-
18-
This is the most comprehensive MCP annotation example, showcasing:
19-
20-
### Server-Side Capabilities
21-
- **Multiple Tool Providers**: Weather data from different APIs (Open-Meteo and Weather.gov)
22-
- **Rich Resource System**: User profiles with various access patterns and URI templates
23-
- **Dynamic Prompts**: Contextual prompt generation with parameter validation
24-
- **Smart Completions**: Auto-completion for usernames, countries, and other data
12+
- **Multiple MCP Features**: Tools, resources, prompts, completions, and client handlers
2513
- **Mixed Annotation Styles**: Both MCP annotations and Spring AI `@Tool` annotations
2614

27-
### Client-Side Features
28-
- **Comprehensive Handlers**: Logging, progress, sampling, and elicitation support
29-
- **Annotation-Based Configuration**: Automatic handler registration
30-
- **Custom Client Customizers**: Advanced client configuration patterns
31-
3215
## Projects
3316

3417
### 1. mcp-annotations-server
35-
A comprehensive MCP server implementation showcasing all major MCP features:
18+
A comprehensive MCP server implementation showcasing all major MCP features using annotations.
3619

3720
#### Tools
38-
- **Weather Tools**: Temperature data from Open-Meteo API using `@McpTool`
39-
- **Weather Forecast**: Detailed forecasts from Weather.gov API using Spring AI `@Tool`
40-
- **Weather Alerts**: State-based weather alerts using Spring AI `@Tool`
21+
- **Weather Tool**: Temperature data from Open-Meteo API using `@McpTool`
22+
- **Additional Tools**: Weather forecast and alerts from Weather.gov API using Spring AI `@Tool`
4123

4224
#### Resources
4325
- **User Profiles**: Complete user information with multiple access patterns
@@ -46,20 +28,23 @@ A comprehensive MCP server implementation showcasing all major MCP features:
4628
- **User Connections**: Social connections and relationships
4729
- **User Notifications**: Dynamic notification generation
4830
- **User Avatars**: Binary data handling with custom MIME types
31+
- **User Location**: Simple location information
4932

5033
#### Prompts
5134
- **Greeting Prompts**: Simple parameterized greetings
5235
- **Personalized Messages**: Complex prompts with multiple parameters and logic
5336
- **Conversation Starters**: Multi-message conversation flows
5437
- **Dynamic Content**: Map-based argument handling
38+
- **Single Message**: Single message responses
39+
- **String List**: List-based responses
5540

5641
#### Completions
5742
- **Username Completion**: Auto-complete for user status URIs
43+
- **Name Completion**: Auto-complete for personalized message prompts
5844
- **Country Completion**: Travel-related country name completion
59-
- **Context-Aware**: Different completion strategies based on context
6045

6146
### 2. mcp-annotations-client
62-
A comprehensive MCP client implementation demonstrating all client-side MCP capabilities:
47+
A simple MCP client implementation demonstrating client-side MCP capabilities using annotations.
6348

6449
#### Handler Types
6550
- **Progress Handlers**: Track long-running operations with `@McpProgress`
@@ -74,30 +59,6 @@ A comprehensive MCP client implementation demonstrating all client-side MCP capa
7459
```java
7560
@SpringBootApplication
7661
public class McpServerApplication {
77-
// Automatic tool registration from multiple providers
78-
@Bean
79-
public List<SyncToolSpecification> toolSpecs(McpToolProvider toolProvider, McpToolProvider2 toolProvider2) {
80-
return SyncMcpAnnotationProvider.createSyncToolSpecifications(List.of(toolProvider, toolProvider2));
81-
}
82-
83-
// Resource specifications from annotation providers
84-
@Bean
85-
public List<SyncResourceSpecification> resourceSpecs(McpUserProfileResourceProvider userProfileResourceProvider) {
86-
return SyncMcpAnnotationProvider.createSyncResourceSpecifications(List.of(userProfileResourceProvider));
87-
}
88-
89-
// Prompt specifications
90-
@Bean
91-
public List<SyncPromptSpecification> promptSpecs(McpPromptProvider promptProvider) {
92-
return SyncMcpAnnotationProvider.createSyncPromptSpecifications(List.of(promptProvider));
93-
}
94-
95-
// Completion specifications
96-
@Bean
97-
public List<SyncCompletionSpecification> completionSpecs(McpCompletionProvider autocompleteProvider) {
98-
return SyncMcpAnnotationProvider.createSyncCompleteSpecifications(List.of(autocompleteProvider));
99-
}
100-
10162
// Traditional Spring AI tool integration
10263
@Bean
10364
public ToolCallbackProvider weatherTools(SpringAiToolProvider weatherService) {
@@ -106,41 +67,40 @@ public class McpServerApplication {
10667
}
10768
```
10869

70+
The server uses automatic annotation scanning to register MCP providers. All `@McpTool`, `@McpResource`, `@McpPrompt`, and `@McpComplete` annotated methods are automatically discovered and registered.
71+
10972
### Client Architecture
11073

11174
```java
11275
@SpringBootApplication
11376
public class McpClientApplication {
114-
// Automatic handler registration
115-
@Bean
116-
List<SyncLoggingSpecification> loggingSpecs(McpClientHandlers clientMcpHandlers) {
117-
return SyncMcpAnnotationProvider.createSyncLoggingSpecifications(List.of(clientMcpHandlers));
118-
}
119-
120-
@Bean
121-
List<SyncSamplingSpecification> samplingSpecs(McpClientHandlers clientMcpHandlers) {
122-
return SyncMcpAnnotationProvider.createSyncSamplingSpecifications(List.of(clientMcpHandlers));
123-
}
124-
125-
// Custom client configuration
12677
@Bean
127-
McpSyncClientCustomizer annotationMcpSyncClientCustomizer(
128-
List<SyncLoggingSpecification> loggingSpecs,
129-
List<SyncSamplingSpecification> samplingSpecs,
130-
List<SyncElicitationSpecification> elicitationSpecs,
131-
List<SyncProgressSpecification> progressSpecs) {
132-
return new AnnotationSyncClientCustomizer(samplingSpecs, loggingSpecs, elicitationSpecs, progressSpecs);
78+
public CommandLineRunner predefinedQuestions(List<McpSyncClient> mcpClients) {
79+
return args -> {
80+
for (McpSyncClient mcpClient : mcpClients) {
81+
// Call tools and interact with MCP servers
82+
CallToolRequest toolRequest = CallToolRequest.builder()
83+
.name("tool1")
84+
.arguments(Map.of("input", "test input"))
85+
.progressToken("test-progress-token")
86+
.build();
87+
88+
CallToolResult response = mcpClient.callTool(toolRequest);
89+
}
90+
};
13391
}
13492
}
13593
```
13694

95+
Client handlers are automatically registered through annotation scanning.
96+
13797
## Key Implementation Examples
13898

13999
### Tool Implementation
140100

141101
```java
142102
@Service
143-
public class McpToolProvider {
103+
public class ToolProvider {
144104
@McpTool(description = "Get the temperature (in celsius) for a specific location")
145105
public WeatherResponse getTemperature(
146106
@McpToolParam(description = "The location latitude") double latitude,
@@ -160,7 +120,7 @@ public class McpToolProvider {
160120

161121
```java
162122
@Service
163-
public class McpUserProfileResourceProvider {
123+
public class UserProfileResourceProvider {
164124
@McpResource(uri = "user-profile://{username}",
165125
name = "User Profile",
166126
description = "Provides user profile information for a specific user")
@@ -187,7 +147,7 @@ public class McpUserProfileResourceProvider {
187147

188148
```java
189149
@Service
190-
public class McpPromptProvider {
150+
public class PromptProvider {
191151
@McpPrompt(name = "personalized-message",
192152
description = "Generates a personalized message based on user information")
193153
public GetPromptResult personalizedMessage(
@@ -225,7 +185,7 @@ public class McpPromptProvider {
225185

226186
```java
227187
@Service
228-
public class McpCompletionProvider {
188+
public class CompletionProvider {
229189
@McpComplete(uri = "user-status://{username}")
230190
public List<String> completeUsername(String usernamePrefix) {
231191
String prefix = usernamePrefix.toLowerCase();
@@ -241,7 +201,7 @@ public class McpCompletionProvider {
241201
.toList();
242202
}
243203

244-
@McpComplete(prompt = "travel-planner")
204+
@McpComplete(prompt = "personalized-message")
245205
public CompleteResult completeCountryName(CompleteRequest request) {
246206
String prefix = request.argument().value().toLowerCase();
247207
String firstLetter = prefix.substring(0, 1);
@@ -260,20 +220,20 @@ public class McpCompletionProvider {
260220

261221
```java
262222
@Service
263-
public class McpClientHandlers {
264-
@McpProgress(clientId = "server1")
223+
public class McpClientHandlerProviders {
224+
@McpProgress(clients = "server1")
265225
public void progressHandler(ProgressNotification progressNotification) {
266226
logger.info("MCP PROGRESS: [{}] progress: {} total: {} message: {}",
267227
progressNotification.progressToken(), progressNotification.progress(),
268228
progressNotification.total(), progressNotification.message());
269229
}
270230

271-
@McpLogging
231+
@McpLogging(clients = "server1")
272232
public void loggingHandler(LoggingMessageNotification loggingMessage) {
273233
logger.info("MCP LOGGING: [{}] {}", loggingMessage.level(), loggingMessage.data());
274234
}
275235

276-
@McpSampling
236+
@McpSampling(clients = "server1")
277237
public CreateMessageResult samplingHandler(CreateMessageRequest llmRequest) {
278238
String userPrompt = ((McpSchema.TextContent) llmRequest.messages().get(0).content()).text();
279239
String modelHint = llmRequest.modelPreferences().hints().get(0).name();
@@ -283,7 +243,7 @@ public class McpClientHandlers {
283243
.build();
284244
}
285245

286-
@McpElicitation
246+
@McpElicitation(clients = "server1")
287247
public ElicitResult elicitationHandler(McpSchema.ElicitRequest request) {
288248
logger.info("MCP ELICITATION: {}", request);
289249
return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message()));
@@ -307,14 +267,6 @@ public class McpClientHandlers {
307267
<groupId>org.springframework.ai</groupId>
308268
<artifactId>spring-ai-starter-mcp-client</artifactId>
309269
</dependency>
310-
<dependency>
311-
<groupId>org.springframework.ai</groupId>
312-
<artifactId>spring-ai-starter-model-openai</artifactId>
313-
</dependency>
314-
<dependency>
315-
<groupId>org.springframework.ai</groupId>
316-
<artifactId>spring-ai-starter-model-anthropic</artifactId>
317-
</dependency>
318270
```
319271

320272
## Running the Examples
@@ -323,8 +275,6 @@ public class McpClientHandlers {
323275

324276
- Java 17 or later
325277
- Maven 3.6+
326-
- OpenAI API key (for client)
327-
- Anthropic API key (for client)
328278

329279
### Step 1: Start the MCP Annotations Server
330280

@@ -336,14 +286,7 @@ java -jar target/mcp-annotations-server-0.0.1-SNAPSHOT.jar
336286

337287
The server will start on `http://localhost:8080` with SSE transport enabled.
338288

339-
### Step 2: Set Environment Variables (for client)
340-
341-
```bash
342-
export OPENAI_API_KEY=your-openai-key
343-
export ANTHROPIC_API_KEY=your-anthropic-key
344-
```
345-
346-
### Step 3: Run the MCP Annotations Client
289+
### Step 2: Run the MCP Annotations Client
347290

348291
```bash
349292
cd mcp-annotations-client
@@ -355,8 +298,6 @@ java -jar target/mcp-annotations-client-0.0.1-SNAPSHOT.jar
355298

356299
### Tools
357300
- `getTemperature`: Get temperature data using Open-Meteo API
358-
- `getWeatherForecastByLocation`: Detailed weather forecast from Weather.gov
359-
- `getAlerts`: Weather alerts for US states
360301

361302
### Resources
362303
- `user-profile://{username}`: Complete user profile information
@@ -377,8 +318,8 @@ java -jar target/mcp-annotations-client-0.0.1-SNAPSHOT.jar
377318

378319
### Completions
379320
- Username completion for `user-status://` URIs
321+
- Name completion for `personalized-message` prompts
380322
- Country name completion for travel prompts
381-
- Context-aware completion strategies
382323

383324
## Configuration
384325

@@ -393,7 +334,7 @@ spring.ai.mcp.server.version=0.0.1
393334
spring.main.banner-mode=off
394335

395336
# Logging configuration
396-
logging.file.name=./model-context-protocol/weather/starter-webmvc-server/target/starter-webmvc-server.log
337+
logging.file.name=./model-context-protocol/mcp-annotations/mcp-annotations-server/target/mcp-annotations-server.log
397338

398339
# Uncomment for STDIO transport
399340
# spring.ai.mcp.server.stdio=true
@@ -410,10 +351,6 @@ logging.file.name=./model-context-protocol/weather/starter-webmvc-server/target/
410351
spring.application.name=mcp
411352
spring.main.web-application-type=none
412353

413-
# API keys for LLM providers
414-
spring.ai.openai.api-key=${OPENAI_API_KEY}
415-
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
416-
417354
# MCP client connection
418355
spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080
419356

@@ -465,17 +402,13 @@ Resources can specify custom MIME types for different content types, including b
465402
### Server Exchange Integration
466403
Methods can access `McpSyncServerExchange` for advanced server operations like logging notifications and progress tracking.
467404

468-
## Comparison with Other Examples
405+
## Sample Data
469406

470-
| Feature | Basic Examples | Sampling Examples | **Annotations Examples** |
471-
|---------|---------------|-------------------|---------------------------|
472-
| **Tools** | ✓ Basic | ✓ With Sampling |**Comprehensive** |
473-
| **Resources** |||**Full Featured** |
474-
| **Prompts** |||**Dynamic & Flexible** |
475-
| **Completions** |||**Context-Aware** |
476-
| **Client Handlers** || ✓ Sampling Only |**All Types** |
477-
| **Annotation Style** | Manual Config | Manual Config |**Declarative** |
478-
| **Mixed Approaches** |||**MCP + Spring AI** |
407+
The server includes sample user profiles for testing:
408+
- **john**: John Smith (New York, age 32)
409+
- **jane**: Jane Doe (London, age 28)
410+
- **bob**: Bob Johnson (Tokyo, age 45)
411+
- **alice**: Alice Brown (Sydney, age 36)
479412

480413
## Related Projects
481414

@@ -487,8 +420,8 @@ Methods can access `McpSyncServerExchange` for advanced server operations like l
487420
## Additional Resources
488421

489422
* [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/)
490-
* [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)
491-
* [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html)
423+
* [Spring AI MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)
424+
* [Spring AI MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html)
425+
* [Spring AI Annotations](https://docs.spring.io/spring-ai/reference/1.1-SNAPSHOT/api/mcp/mcp-annotations-overview.html)
426+
* [Java MCP Annotations](https://github.com/spring-ai-community/mcp-annotations)
492427
* [Model Context Protocol Specification](https://modelcontextprotocol.github.io/specification/)
493-
* [Spring Boot Documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/)
494-
* [Spring AI MCP Annotations](https://github.com/spring-projects-experimental/spring-ai-mcp-annotations)
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
spring.application.name=mcp
22
spring.main.web-application-type=none
33

4-
# Disable the chat client auto-configuration because we are using multiple chat models
5-
spring.ai.chat.client.enabled=false
6-
7-
spring.ai.openai.api-key=${OPENAI_API_KEY}
8-
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
94

105
# spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080
116
spring.ai.mcp.client.streamable-http.connections.server1.url=http://localhost:8080
127
# spring.ai.mcp.client.streamable-http.connections.server2.url=http://localhost:8081
8+
139
spring.ai.mcp.client.request-timeout=5m
1410

1511
logging.level.io.modelcontextprotocol.client=WARN
1612
logging.level.io.modelcontextprotocol.spec=WARN
1713

1814

19-
spring.ai.mcp.client.toolcallback.enabled=false
15+
# spring.ai.mcp.client.toolcallback.enabled=false

0 commit comments

Comments
 (0)