Skip to content

MCP Core Java SDK

A high-performance Java SDK for Model Context Protocol (MCP) registry integration, designed for seamless Spring Boot integration with annotation-driven endpoint registration.

๐Ÿš€ Features

  • โ˜• Java 8+ Compatible: Works with Java 8 through Java 21
  • ๐Ÿƒ Spring Boot Integration: Seamless integration with Spring Boot 2.x and 3.x
  • ๐Ÿ“ Annotation-Driven: Simple @EnableAutogentMcp and @AutogentTool annotations
  • ๐Ÿ”„ Auto-Registration: Automatic application and endpoint registration on startup
  • ๐Ÿ“Š Batch Operations: Efficient batch endpoint registration for performance
  • ๐Ÿ” Smart Discovery: Automatic HTTP method and parameter detection
  • ๐Ÿ›ก๏ธ Error Handling: Robust error handling and logging
  • โšก Production Ready: Optimized for enterprise production environments

๐Ÿ—๏ธ Architecture

graph TB
    subgraph "Your Spring Boot Application"
        A[@SpringBootApplication]
        B[@EnableAutogentMcp]
        C[@RestController]
        D[@AutogentTool]
    end

    subgraph "MCP Core Java SDK"
        E[AutogentMcpAutoConfiguration]
        F[RegistryClient]
        G[EndpointCollector]
        H[BeanPostProcessor]
    end

    subgraph "MCP Registry Server"
        I[Application Registration]
        J[Endpoint Registration]
        K[Health Monitoring]
    end

    A --> B
    C --> D
    B --> E
    E --> F
    E --> G
    E --> H
    F --> I
    F --> J
    F --> K

    style E fill:#e1f5fe
    style F fill:#f3e5f5
    style G fill:#fff3e0

๐Ÿ”ง Installation

Maven

Add to your pom.xml:

<dependency>
    <groupId>com.autogentmcp</groupId>
    <artifactId>mcp-core-java</artifactId>
    <version>0.0.2</version>
</dependency>

Gradle

Add to your build.gradle:

dependencies {
    implementation 'com.autogentmcp:mcp-core-java:0.0.2'
}

โš™๏ธ Configuration

Application Properties

Add to your application.properties:

# MCP Registry URL (required)
autogentmcp.registry-url=http://localhost:8000

# MCP API Key (required)
autogentmcp.api-key=your-api-key-here

# Application health check endpoint (required)
autogentmcp.app-healthcheck-endpoint=/actuator/health

# Environment (optional, default: production)
autogentmcp.environment=production

YAML Configuration

Or in application.yml:

autogentmcp:
  registry-url: http://localhost:8000
  api-key: your-api-key-here
  app-healthcheck-endpoint: /actuator/health
  environment: production

๐ŸŽฏ Quick Start

1. Enable MCP in Your Application

import com.autogentmcp.registry.EnableAutogentMcp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableAutogentMcp(
    key = "my-awesome-app", 
    description = "My Awesome Spring Boot Application"
)
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

2. Register Your Endpoints

import com.autogentmcp.registry.AutogentTool;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @AutogentTool(
        name = "Create User",
        uri = "/api/users",
        description = "Creates a new user in the system",
        method = "POST",
        isPublic = false
    )
    @PostMapping
    public User createUser(@RequestBody CreateUserRequest request) {
        // Your implementation
        return userService.createUser(request);
    }

    @AutogentTool(
        name = "Get User",
        uri = "/api/users/{id}",
        description = "Retrieves a user by their ID",
        method = "GET",
        isPublic = true
    )
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // Your implementation
        return userService.getUser(id);
    }

    @AutogentTool(
        name = "Search Users",
        uri = "/api/users/search",
        description = "Searches for users based on criteria",
        method = "GET"
    )
    @GetMapping("/search")
    public List<User> searchUsers(
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String email,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size
    ) {
        // Your implementation
        return userService.searchUsers(name, email, page, size);
    }
}

3. Run Your Application

mvn spring-boot:run

That's it! Your endpoints will be automatically registered with the MCP Registry on startup.

๐Ÿ“š Detailed Usage

@EnableAutogentMcp Annotation

The @EnableAutogentMcp annotation enables MCP integration and must be placed on your main application class.

@EnableAutogentMcp(
    key = "unique-app-key",          // Required: Unique application identifier
    description = "App description"   // Optional: Application description
)

Parameters: - key: Unique identifier for your application in the registry - description: Human-readable description of your application

@AutogentTool Annotation

The @AutogentTool annotation registers methods as MCP tools/endpoints.

@AutogentTool(
    name = "Tool Name",                    // Optional: Tool name (defaults to method name)
    uri = "/api/endpoint/{param}",         // Required: Endpoint URI with parameters
    description = "Tool description",      // Optional: Tool description
    method = "GET",                        // Optional: HTTP method (auto-detected if not specified)
    isPublic = true,                       // Optional: Public accessibility (default: false)
    contentType = "application/json",      // Optional: Content type (default: application/json)
    pathParams = "{\"id\":\"Long\"}",      // Optional: Path parameters (auto-detected)
    queryParams = "{\"page\":\"Integer\"}", // Optional: Query parameters (auto-detected)
    requestBody = "{\"name\":\"String\"}"  // Optional: Request body schema (auto-detected)
)

Automatic Parameter Detection

The SDK automatically detects parameters from your method signatures and Spring annotations:

@AutogentTool(uri = "/api/users/{id}")
@GetMapping("/{id}")
public User getUser(
    @PathVariable Long id,                    // Detected as path parameter
    @RequestParam(required = false) String include,  // Detected as query parameter
    @RequestHeader("X-Client-Version") String version // Detected as header
) {
    // Implementation
}

Generated metadata:

{
  "name": "getUser",
  "path": "/api/users/{id}",
  "method": "GET",
  "pathParams": {
    "id": {
      "type": "Long",
      "description": "User ID"
    }
  },
  "queryParams": {
    "include": {
      "type": "String",
      "description": "Fields to include"
    }
  }
}

Request Body Detection

For POST/PUT endpoints, the SDK automatically detects request body schemas:

@AutogentTool(
    uri = "/api/users",
    description = "Creates a new user"
)
@PostMapping
public User createUser(@RequestBody CreateUserRequest request) {
    // Implementation
}

Auto-generated request body schema:

{
  "requestBody": {
    "type": "object",
    "properties": {
      "name": {"type": "String"},
      "email": {"type": "String"},
      "age": {"type": "Integer"}
    }
  }
}

Custom Content Types

Support for different content types:

@AutogentTool(
    uri = "/api/users/upload",
    description = "Upload user profile picture",
    contentType = "multipart/form-data"
)
@PostMapping(value = "/upload", consumes = "multipart/form-data")
public ResponseEntity<String> uploadProfilePicture(
    @RequestParam("file") MultipartFile file,
    @RequestParam("userId") Long userId
) {
    // Implementation
}

๐Ÿ”ง Advanced Configuration

Custom Registry Client

For advanced scenarios, you can provide your own RegistryClient:

@Configuration
public class McpConfiguration {

    @Bean
    @Primary
    public RegistryClient customRegistryClient() {
        return new RegistryClient("http://localhost:8000", "api-key") {
            @Override
            protected CloseableHttpResponse executePost(HttpPost post) throws IOException {
                // Custom HTTP handling
                return super.executePost(post);
            }
        };
    }
}

Health Check Customization

Customize the health check endpoint:

@RestController
public class HealthController {

    @GetMapping("/health")
    public ResponseEntity<Map<String, Object>> health() {
        Map<String, Object> health = new HashMap<>();
        health.put("status", "UP");
        health.put("timestamp", Instant.now());
        health.put("version", "1.0.0");

        return ResponseEntity.ok(health);
    }
}

Error Handling

The SDK includes comprehensive error handling:

@ControllerAdvice
public class McpErrorHandler {

    @ExceptionHandler(RegistryException.class)
    public ResponseEntity<ErrorResponse> handleRegistryException(RegistryException e) {
        log.error("Registry error: {}", e.getMessage(), e);
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
            .body(new ErrorResponse("Registry temporarily unavailable"));
    }
}

๐Ÿฅ Health Monitoring

The SDK automatically registers your application's health endpoint with the registry for monitoring.

Health Check Flow

  1. SDK registers health endpoint during startup
  2. Registry periodically checks the health endpoint
  3. Registry updates application status based on health responses
  4. Failed health checks trigger alerts and status updates

Health Response Format

Your health endpoint should return:

{
  "status": "UP",
  "components": {
    "database": {
      "status": "UP"
    },
    "external-api": {
      "status": "UP"
    }
  }
}

๐Ÿ”„ Lifecycle Management

Application Startup

  1. Bean Processing: SDK scans for @AutogentTool annotations
  2. Application Registration: Registers application metadata with registry
  3. Endpoint Collection: Collects all annotated endpoints
  4. Batch Registration: Registers all endpoints in a single batch request
  5. Health Registration: Registers health check endpoint

Runtime Updates

  • Endpoint Updates: Changes to endpoints require application restart
  • Health Monitoring: Continuous health check monitoring
  • Error Recovery: Automatic retry on registry communication failures

Application Shutdown

  • Graceful Shutdown: SDK handles graceful shutdown
  • Registry Notification: Notifies registry of application shutdown
  • Resource Cleanup: Cleans up connections and resources

๐Ÿงช Testing

Unit Testing

@ExtendWith(MockitoExtension.class)
class UserControllerTest {

    @Mock
    private UserService userService;

    @InjectMocks
    private UserController userController;

    @Test
    void shouldCreateUser() {
        // Test your endpoint logic
        CreateUserRequest request = new CreateUserRequest("John", "john@example.com");
        User expectedUser = new User(1L, "John", "john@example.com");

        when(userService.createUser(request)).thenReturn(expectedUser);

        User result = userController.createUser(request);

        assertEquals(expectedUser, result);
        verify(userService).createUser(request);
    }
}

Integration Testing

@SpringBootTest
@AutoConfigureMockMvc
class McpIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private RegistryClient registryClient;

    @Test
    void shouldRegisterEndpoints() throws Exception {
        // Verify that endpoints are registered
        verify(registryClient).registerEndpointsBatch(
            eq("test-app"),
            eq("test"),
            argThat(endpoints -> endpoints.size() > 0)
        );
    }
}

Mock Registry for Testing

@TestConfiguration
public class TestMcpConfiguration {

    @Bean
    @Primary
    public RegistryClient mockRegistryClient() {
        return Mockito.mock(RegistryClient.class);
    }
}

๐Ÿ” Troubleshooting

Common Issues

Registry Connection Failures

// Check registry URL and API key
@Value("${autogentmcp.registry-url}")
private String registryUrl;

@Value("${autogentmcp.api-key}")
private String apiKey;

@PostConstruct
public void validateConfig() {
    if (registryUrl == null || apiKey == null) {
        throw new IllegalStateException("MCP configuration is missing");
    }
}

Endpoint Registration Failures

// Enable debug logging
logging.level.com.autogentmcp=DEBUG

// Check endpoint collection
@Component
public class EndpointDebugger {

    @EventListener
    public void onApplicationReady(ApplicationReadyEvent event) {
        List<Map<String, Object>> endpoints = EndpointCollector.getAll();
        log.info("Collected {} endpoints for registration", endpoints.size());
        endpoints.forEach(ep -> log.info("Endpoint: {}", ep));
    }
}

Authentication Issues

# Verify API key in registry
curl -H "X-Admin-Key: admin-key" http://localhost:8000/applications/your-app-key

# Check API key format
curl -X POST http://localhost:8000/register/endpoints \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -H "X-App-Key: your-app-key" \
  -d '{"app_key": "your-app-key", "environment": "production", "endpoints": []}'

Debug Logging

Enable comprehensive logging:

# Application properties
logging.level.com.autogentmcp=DEBUG
logging.level.org.apache.http=DEBUG

# Specific logger configuration
logging.level.com.autogentmcp.registry.spring.AutogentMcpAutoConfiguration=TRACE
logging.level.com.autogentmcp.registry.RegistryClient=DEBUG

๐Ÿš€ Production Best Practices

Configuration Management

# Use environment-specific configuration
autogentmcp.registry-url=${MCP_REGISTRY_URL:http://localhost:8000}
autogentmcp.api-key=${MCP_API_KEY}
autogentmcp.environment=${MCP_ENVIRONMENT:production}

Health Check Optimization

@Component
public class OptimizedHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        // Lightweight health check
        return Health.up()
            .withDetail("timestamp", Instant.now())
            .withDetail("version", getClass().getPackage().getImplementationVersion())
            .build();
    }
}

Error Recovery

@Component
public class RegistryErrorHandler {

    @Retryable(value = {RegistryException.class}, maxAttempts = 3)
    public void registerWithRetry() {
        // Registration logic with retry
    }

    @Recover
    public void recoverFromRegistryFailure(RegistryException ex) {
        log.error("Failed to register after retries: {}", ex.getMessage());
        // Fallback logic
    }
}

Monitoring and Metrics

@Component
public class McpMetrics {

    private final Counter registrationAttempts;
    private final Timer registrationTime;

    public McpMetrics(MeterRegistry meterRegistry) {
        this.registrationAttempts = Counter.builder("mcp.registration.attempts")
            .register(meterRegistry);
        this.registrationTime = Timer.builder("mcp.registration.time")
            .register(meterRegistry);
    }

    public void recordRegistrationAttempt() {
        registrationAttempts.increment();
    }

    public void recordRegistrationTime(Duration duration) {
        registrationTime.record(duration);
    }
}

๐Ÿ“‹ API Reference

Core Classes

@EnableAutogentMcp

Enables MCP integration for the application.

Attributes: - key(): Application key (required) - description(): Application description (optional)

@AutogentTool

Registers a method as an MCP tool.

Attributes: - name(): Tool name (optional, defaults to method name) - uri(): Endpoint URI (required) - description(): Tool description (optional) - method(): HTTP method (optional, auto-detected) - isPublic(): Public accessibility (optional, default: false) - contentType(): Content type (optional, default: application/json) - pathParams(): Path parameters JSON (optional, auto-detected) - queryParams(): Query parameters JSON (optional, auto-detected) - requestBody(): Request body schema JSON (optional, auto-detected)

RegistryClient

HTTP client for registry communication.

Methods: - registerEndpointsBatch(String appKey, String environment, List<Map<String, Object>> endpoints) - updateApplication(String appKey, Map<String, Object> updateData)

EndpointCollector

Collects and manages endpoint metadata.

Methods: - getAll(): Get all collected endpoints - add(Map<String, Object> endpoint): Add endpoint - clear(): Clear all endpoints

๐Ÿ”— Integration Examples

Spring Security Integration

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authz -> authz
                .antMatchers("/actuator/health").permitAll()
                .antMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt());

        return http.build();
    }
}

Database Integration

@AutogentTool(
    uri = "/api/users",
    description = "Get all users with pagination"
)
@GetMapping
@Transactional(readOnly = true)
public Page<User> getUsers(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "10") int size,
    @RequestParam(required = false) String search
) {
    Pageable pageable = PageRequest.of(page, size);

    if (search != null && !search.isEmpty()) {
        return userRepository.findByNameContainingIgnoreCase(search, pageable);
    }

    return userRepository.findAll(pageable);
}

Async Processing

@AutogentTool(
    uri = "/api/users/batch",
    description = "Process users in batch"
)
@PostMapping("/batch")
@Async
public CompletableFuture<BatchResult> processBatch(@RequestBody List<User> users) {
    return CompletableFuture.supplyAsync(() -> {
        // Async processing logic
        return batchProcessor.process(users);
    });
}

๐Ÿ“ˆ Performance Considerations

Startup Performance

  • Lazy Initialization: Use @Lazy for non-essential beans
  • Batch Operations: All endpoints registered in single batch request
  • Async Registration: Registration happens asynchronously after startup

Runtime Performance

  • Connection Pooling: HTTP client uses connection pooling
  • Caching: Registry responses are cached when appropriate
  • Error Resilience: Circuit breaker pattern for registry failures

Memory Management

  • Endpoint Metadata: Minimal memory footprint for metadata storage
  • Connection Management: Proper connection lifecycle management
  • Resource Cleanup: Automatic cleanup on application shutdown

๐Ÿค Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass: mvn test
  6. Submit a pull request

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Note: LICENSE file will be added to the repository soon. See the Contributing Guide for full license details.


Next Steps: - Explore the MCP Demo Apps for working examples - Set up the MCP Registry Server for your environment - Check out the Autogent MCP Server for orchestration