Restructure hawkbit-mcp into starter/server modules following the hawkbit conventions (#2923)
Signed-off-by: Denislav Prinov <denislav.prinov@bosch.com>
This commit is contained in:
62
hawkbit-mcp/hawkbit-mcp-server/pom.xml
Normal file
62
hawkbit-mcp/hawkbit-mcp-server/pom.xml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright (c) 2026 Contributors to the Eclipse Foundation
|
||||||
|
|
||||||
|
This program and the accompanying materials are made
|
||||||
|
available under the terms of the Eclipse Public License 2.0
|
||||||
|
which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-mcp-parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>hawkbit-mcp-server</artifactId>
|
||||||
|
<name>hawkBit :: MCP :: Server (Standalone)</name>
|
||||||
|
<description>Standalone MCP server that connects to hawkBit via REST API</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring.app.class>org.eclipse.hawkbit.mcp.server.McpServerStart</spring.app.class>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-mcp-starter</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${baseDir}</outputDirectory>
|
||||||
|
<mainClass>${spring.app.class}</mainClass>
|
||||||
|
<layout>JAR</layout>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -9,10 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.mcp.server;
|
package org.eclipse.hawkbit.mcp.server;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.mcp.server.config.HawkbitMcpProperties;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +21,6 @@ import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServic
|
|||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication(exclude = UserDetailsServiceAutoConfiguration.class)
|
@SpringBootApplication(exclude = UserDetailsServiceAutoConfiguration.class)
|
||||||
@EnableConfigurationProperties(HawkbitMcpProperties.class)
|
|
||||||
public class McpServerStart {
|
public class McpServerStart {
|
||||||
|
|
||||||
public static void main(final String[] args) {
|
public static void main(final String[] args) {
|
||||||
114
hawkbit-mcp/hawkbit-mcp-starter/pom.xml
Normal file
114
hawkbit-mcp/hawkbit-mcp-starter/pom.xml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright (c) 2026 Contributors to the Eclipse Foundation
|
||||||
|
|
||||||
|
This program and the accompanying materials are made
|
||||||
|
available under the terms of the Eclipse Public License 2.0
|
||||||
|
which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-mcp-parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>hawkbit-mcp-starter</artifactId>
|
||||||
|
<name>hawkBit :: MCP :: Spring Boot Starter</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- hawkBit SDK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-sdk-mgmt</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring AI MCP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-mcp-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Caching -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Copy hawkBit docs for MCP resources -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-hawkbit-docs</id>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.outputDirectory}/hawkbit-docs</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.basedir}/../../docs</directory>
|
||||||
|
<includes>
|
||||||
|
<include>README.md</include>
|
||||||
|
<include>what-is-hawkbit.md</include>
|
||||||
|
<include>quick-start.md</include>
|
||||||
|
<include>features.md</include>
|
||||||
|
<include>architecture.md</include>
|
||||||
|
<include>base-setup.md</include>
|
||||||
|
<include>hawkbit-sdk.md</include>
|
||||||
|
<include>feign-client.md</include>
|
||||||
|
<include>clustering.md</include>
|
||||||
|
<include>authentication.md</include>
|
||||||
|
<include>authorization.md</include>
|
||||||
|
<include>datamodel.md</include>
|
||||||
|
<include>rollout-management.md</include>
|
||||||
|
<include>targetstate.md</include>
|
||||||
|
<include>management-api.md</include>
|
||||||
|
<include>direct-device-integration-api.md</include>
|
||||||
|
<include>device-management-federation-api.md</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.autoconfigure.mcp;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.mcp.server.client.AuthenticationValidator;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.client.HawkbitAuthenticationValidator;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.HawkbitClientConfiguration;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.HawkbitMcpProperties;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.McpHttpClientConfiguration;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.McpSecurityConfiguration;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.McpStdioClientConfiguration;
|
||||||
|
import org.eclipse.hawkbit.mcp.server.config.McpToolConfiguration;
|
||||||
|
import org.eclipse.hawkbit.sdk.HawkbitClient;
|
||||||
|
import org.eclipse.hawkbit.sdk.Tenant;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-configuration for the hawkBit MCP server.
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@ConditionalOnClass(McpToolConfiguration.class)
|
||||||
|
@Import({
|
||||||
|
McpToolConfiguration.class,
|
||||||
|
HawkbitClientConfiguration.class,
|
||||||
|
McpHttpClientConfiguration.class,
|
||||||
|
McpStdioClientConfiguration.class,
|
||||||
|
McpSecurityConfiguration.class
|
||||||
|
})
|
||||||
|
@EnableConfigurationProperties(HawkbitMcpProperties.class)
|
||||||
|
public class McpAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(name = "hawkbit.mcp.validation.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public AuthenticationValidator hawkbitAuthenticationValidator(
|
||||||
|
final HawkbitClient hawkbitClient, final Tenant dummyTenant, final HawkbitMcpProperties properties) {
|
||||||
|
return new HawkbitAuthenticationValidator(hawkbitClient, dummyTenant, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,17 +22,13 @@ import org.eclipse.hawkbit.mcp.server.config.HawkbitMcpProperties;
|
|||||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi;
|
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi;
|
||||||
import org.eclipse.hawkbit.sdk.HawkbitClient;
|
import org.eclipse.hawkbit.sdk.HawkbitClient;
|
||||||
import org.eclipse.hawkbit.sdk.Tenant;
|
import org.eclipse.hawkbit.sdk.Tenant;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates authentication credentials against hawkBit REST API using the SDK.
|
* Validates authentication credentials against hawkBit REST API using the SDK.
|
||||||
* This validator is conditionally created when {@code hawkbit.mcp.validation.enabled=true}.
|
* This validator is conditionally created when {@code hawkbit.mcp.validation.enabled=true}.
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
|
||||||
@ConditionalOnProperty(name = "hawkbit.mcp.validation.enabled", havingValue = "true", matchIfMissing = true)
|
|
||||||
public class HawkbitAuthenticationValidator implements AuthenticationValidator {
|
public class HawkbitAuthenticationValidator implements AuthenticationValidator {
|
||||||
|
|
||||||
private final HawkbitClient hawkbitClient;
|
private final HawkbitClient hawkbitClient;
|
||||||
@@ -63,6 +63,7 @@ public class McpSecurityConfiguration {
|
|||||||
@SuppressWarnings("java:S4502") // CSRF protection is not needed for stateless REST APIs using Authorization header
|
@SuppressWarnings("java:S4502") // CSRF protection is not needed for stateless REST APIs using Authorization header
|
||||||
public SecurityFilterChain mcpSecurityFilterChain(final HttpSecurity http) throws Exception {
|
public SecurityFilterChain mcpSecurityFilterChain(final HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
|
.securityMatcher("/mcp/**")
|
||||||
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
|
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.eclipse.hawkbit.autoconfigure.mcp.McpAutoConfiguration
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
|
|
||||||
Copyright (c) 2025 Contributors to the Eclipse Foundation
|
Copyright (c) 2026 Contributors to the Eclipse Foundation
|
||||||
|
|
||||||
This program and the accompanying materials are made
|
This program and the accompanying materials are made
|
||||||
available under the terms of the Eclipse Public License 2.0
|
available under the terms of the Eclipse Public License 2.0
|
||||||
@@ -18,113 +18,12 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hawkbit-mcp-server</artifactId>
|
<artifactId>hawkbit-mcp-parent</artifactId>
|
||||||
<name>hawkBit :: MCP Server (Standalone)</name>
|
<name>hawkBit :: MCP</name>
|
||||||
<description>Standalone MCP server that connects to hawkBit via REST API</description>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<modules>
|
||||||
<spring.app.class>org.eclipse.hawkbit.mcp.server.McpServerStart</spring.app.class>
|
<module>hawkbit-mcp-starter</module>
|
||||||
</properties>
|
<module>hawkbit-mcp-server</module>
|
||||||
|
</modules>
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
|
||||||
<artifactId>hawkbit-sdk-mgmt</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springdoc</groupId>
|
|
||||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.ai</groupId>
|
|
||||||
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.ai</groupId>
|
|
||||||
<artifactId>spring-ai-mcp-annotations</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
|
||||||
<artifactId>caffeine</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-hawkbit-docs</id>
|
|
||||||
<phase>generate-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-resources</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.outputDirectory}/hawkbit-docs</outputDirectory>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>${project.basedir}/../docs</directory>
|
|
||||||
<includes>
|
|
||||||
<include>README.md</include>
|
|
||||||
<include>what-is-hawkbit.md</include>
|
|
||||||
<include>quick-start.md</include>
|
|
||||||
<include>features.md</include>
|
|
||||||
<include>architecture.md</include>
|
|
||||||
<include>base-setup.md</include>
|
|
||||||
<include>hawkbit-sdk.md</include>
|
|
||||||
<include>feign-client.md</include>
|
|
||||||
<include>clustering.md</include>
|
|
||||||
<include>authentication.md</include>
|
|
||||||
<include>authorization.md</include>
|
|
||||||
<include>datamodel.md</include>
|
|
||||||
<include>rollout-management.md</include>
|
|
||||||
<include>targetstate.md</include>
|
|
||||||
<include>management-api.md</include>
|
|
||||||
<include>direct-device-integration-api.md</include>
|
|
||||||
<include>device-management-federation-api.md</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${baseDir}</outputDirectory>
|
|
||||||
<mainClass>${spring.app.class}</mainClass>
|
|
||||||
<layout>JAR</layout>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
Reference in New Issue
Block a user