This is an automated email from the ASF dual-hosted git repository.

tsato pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 6c76d151b99 CAMEL-21508: Create a KServe component
6c76d151b99 is described below

commit 6c76d151b99f85818733c3f681834f623a95c5bd
Author: Tadayoshi Sato <[email protected]>
AuthorDate: Thu Jan 16 18:06:38 2025 +0900

    CAMEL-21508: Create a KServe component
---
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 components/camel-ai/camel-kserve/pom.xml           | 168 ++++++++++
 .../kserve/KServeComponentConfigurer.java          |  97 ++++++
 .../kserve/KServeConfigurationConfigurer.java      |  63 ++++
 .../component/kserve/KServeConverterLoader.java    |  64 ++++
 .../component/kserve/KServeEndpointConfigurer.java |  69 +++++
 .../component/kserve/KServeEndpointUriFactory.java |  75 +++++
 .../org/apache/camel/component/kserve/kserve.json  |  49 +++
 .../services/org/apache/camel/TypeConverterLoader  |   2 +
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/kserve     |   2 +
 .../org/apache/camel/configurer/kserve-component   |   2 +
 .../org/apache/camel/configurer/kserve-endpoint    |   2 +
 ...ache.camel.component.kserve.KServeConfiguration |   2 +
 .../org/apache/camel/urifactory/kserve-endpoint    |   2 +
 .../src/main/docs/kserve-component.adoc            | 243 +++++++++++++++
 .../camel/component/kserve/KServeComponent.java    |  59 ++++
 .../component/kserve/KServeConfiguration.java      |  93 ++++++
 .../camel/component/kserve/KServeConstants.java    |  32 ++
 .../camel/component/kserve/KServeConverter.java    |  63 ++++
 .../camel/component/kserve/KServeEndpoint.java     | 105 +++++++
 .../camel/component/kserve/KServeProducer.java     | 129 ++++++++
 .../src/main/proto/grpc_predict_v2.proto           | 342 +++++++++++++++++++++
 .../component/kserve/it/KServeEndpointIT.java      | 312 +++++++++++++++++++
 .../camel/component/kserve/it/KServeITSupport.java |  39 +++
 .../src/test/resources/log4j2.properties           |  28 ++
 components/camel-ai/pom.xml                        |   1 +
 .../modules/ROOT/examples/json/kserve.json         |   1 +
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../modules/ROOT/pages/kserve-component.adoc       |   1 +
 parent/pom.xml                                     |   5 +
 pom.xml                                            |   2 +
 test-infra/camel-test-infra-all/pom.xml            |   7 +-
 .../camel-test-infra-triton}/pom.xml               |  55 ++--
 .../test/infra/triton/common/TritonProperties.java |  27 ++
 .../infra/triton/services/TritonInfraService.java  |  28 ++
 .../services/TritonLocalContainerInfraService.java |  99 ++++++
 .../triton/services/TritonRemoteInfraService.java  |  55 ++++
 .../src/main/resources/META-INF/MANIFEST.MF        |   0
 .../main/resources/models/simple/1/model.graphdef  |  21 ++
 .../src/main/resources/models/simple/config.pbtxt  |  27 ++
 .../infra/triton/services/container.properties     |  17 +
 .../test/infra/triton/services/TritonService.java  |  26 ++
 .../triton/services/TritonServiceFactory.java      |  42 +++
 test-infra/pom.xml                                 |   1 +
 46 files changed, 2446 insertions(+), 29 deletions(-)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 92fd81e4287..51d41c5314f 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1287,6 +1287,11 @@
         <artifactId>camel-knative-http</artifactId>
         <version>4.10.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-kserve</artifactId>
+        <version>4.10.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-kubernetes</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml 
b/catalog/camel-allcomponents/pom.xml
index 3d614f91871..cdc3f1a434c 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1116,6 +1116,11 @@
             <artifactId>camel-knative-http</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-kserve</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-kubernetes</artifactId>
diff --git a/components/camel-ai/camel-kserve/pom.xml 
b/components/camel-ai/camel-kserve/pom.xml
new file mode 100644
index 00000000000..9733c21a54c
--- /dev/null
+++ b/components/camel-ai/camel-kserve/pom.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
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>
+        <artifactId>camel-ai-parent</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <version>4.10.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-kserve</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: AI :: KServe</name>
+    <description>Provide access to AI model servers with the KServe standard 
to run inference with remote models
+    </description>
+
+    <properties>
+        <!-- Triton Inference Server container is not available on these 
platforms -->
+        <skipITs.ppc64le>true</skipITs.ppc64le>
+        <skipITs.s390x>true</skipITs.s390x>
+    </properties>
+
+    <dependencies>
+        <!-- camel -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+
+        <!-- Dependencies required by the generated client -->
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>${protobuf-version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-netty-shaded</artifactId>
+            <version>${grpc-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-protobuf</artifactId>
+            <version>${grpc-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-stub</artifactId>
+            <version>${grpc-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <version>${jakarta-annotation-api-version}</version>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java-util</artifactId>
+            <version>${protobuf-version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- test infra -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-triton</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>io.github.ascopes</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>${protobuf-maven-plugin-version}</version>
+                <configuration>
+                    <protocVersion>${protobuf-version}</protocVersion>
+                    <sourceDirectories>
+                        <sourceDirectory>src/main/proto</sourceDirectory>
+                    </sourceDirectories>
+                    <binaryMavenPlugins>
+                        <binaryMavenPlugin>
+                            <groupId>io.grpc</groupId>
+                            <artifactId>protoc-gen-grpc-java</artifactId>
+                            <version>${grpc-version}</version>
+                        </binaryMavenPlugin>
+                    </binaryMavenPlugins>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                
<source>target/generated-sources/protobuf</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <!-- Remove it once 
https://github.com/grpc/grpc-java/issues/9179 is resolved -->
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>process-sources</phase>
+                        <configuration>
+                            <target>
+                                <replace token="@javax.annotation.Generated"
+                                    value="@jakarta.annotation.Generated"
+                                    dir="target/generated-sources/protobuf">
+                                    <include name="**/*.java" />
+                                </replace>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git 
a/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeComponentConfigurer.java
 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeComponentConfigurer.java
new file mode 100644
index 00000000000..032b117ee96
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeComponentConfigurer.java
@@ -0,0 +1,97 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.kserve;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class KServeComponentConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    private org.apache.camel.component.kserve.KServeConfiguration 
getOrCreateConfiguration(KServeComponent target) {
+        if (target.getConfiguration() == null) {
+            target.setConfiguration(new 
org.apache.camel.component.kserve.KServeConfiguration());
+        }
+        return target.getConfiguration();
+    }
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        KServeComponent target = (KServeComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
+        case "configuration": target.setConfiguration(property(camelContext, 
org.apache.camel.component.kserve.KServeConfiguration.class, value)); return 
true;
+        case "credentials": 
getOrCreateConfiguration(target).setCredentials(property(camelContext, 
io.grpc.ChannelCredentials.class, value)); return true;
+        case "healthcheckconsumerenabled":
+        case "healthCheckConsumerEnabled": 
target.setHealthCheckConsumerEnabled(property(camelContext, boolean.class, 
value)); return true;
+        case "healthcheckproducerenabled":
+        case "healthCheckProducerEnabled": 
target.setHealthCheckProducerEnabled(property(camelContext, boolean.class, 
value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
+        case "modelname":
+        case "modelName": 
getOrCreateConfiguration(target).setModelName(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "modelversion":
+        case "modelVersion": 
getOrCreateConfiguration(target).setModelVersion(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "target": 
getOrCreateConfiguration(target).setTarget(property(camelContext, 
java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": return boolean.class;
+        case "configuration": return 
org.apache.camel.component.kserve.KServeConfiguration.class;
+        case "credentials": return io.grpc.ChannelCredentials.class;
+        case "healthcheckconsumerenabled":
+        case "healthCheckConsumerEnabled": return boolean.class;
+        case "healthcheckproducerenabled":
+        case "healthCheckProducerEnabled": return boolean.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        case "modelname":
+        case "modelName": return java.lang.String.class;
+        case "modelversion":
+        case "modelVersion": return java.lang.String.class;
+        case "target": return java.lang.String.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        KServeComponent target = (KServeComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": return target.isAutowiredEnabled();
+        case "configuration": return target.getConfiguration();
+        case "credentials": return 
getOrCreateConfiguration(target).getCredentials();
+        case "healthcheckconsumerenabled":
+        case "healthCheckConsumerEnabled": return 
target.isHealthCheckConsumerEnabled();
+        case "healthcheckproducerenabled":
+        case "healthCheckProducerEnabled": return 
target.isHealthCheckProducerEnabled();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        case "modelname":
+        case "modelName": return 
getOrCreateConfiguration(target).getModelName();
+        case "modelversion":
+        case "modelVersion": return 
getOrCreateConfiguration(target).getModelVersion();
+        case "target": return getOrCreateConfiguration(target).getTarget();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConfigurationConfigurer.java
 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConfigurationConfigurer.java
new file mode 100644
index 00000000000..1afd4f2eeb1
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConfigurationConfigurer.java
@@ -0,0 +1,63 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.kserve;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.component.kserve.KServeConfiguration;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateConfigurerMojo")
+@SuppressWarnings("unchecked")
+public class KServeConfigurationConfigurer extends 
org.apache.camel.support.component.PropertyConfigurerSupport implements 
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        org.apache.camel.component.kserve.KServeConfiguration target = 
(org.apache.camel.component.kserve.KServeConfiguration) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": target.setCredentials(property(camelContext, 
io.grpc.ChannelCredentials.class, value)); return true;
+        case "modelname":
+        case "modelName": target.setModelName(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "modelversion":
+        case "modelVersion": target.setModelVersion(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "target": target.setTarget(property(camelContext, 
java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": return io.grpc.ChannelCredentials.class;
+        case "modelname":
+        case "modelName": return java.lang.String.class;
+        case "modelversion":
+        case "modelVersion": return java.lang.String.class;
+        case "target": return java.lang.String.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.component.kserve.KServeConfiguration target = 
(org.apache.camel.component.kserve.KServeConfiguration) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": return target.getCredentials();
+        case "modelname":
+        case "modelName": return target.getModelName();
+        case "modelversion":
+        case "modelVersion": return target.getModelVersion();
+        case "target": return target.getTarget();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConverterLoader.java
 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConverterLoader.java
new file mode 100644
index 00000000000..d5b7664e26c
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeConverterLoader.java
@@ -0,0 +1,64 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.kserve;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.util.DoubleMap;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class KServeConverterLoader implements TypeConverterLoader, 
CamelContextAware {
+
+    private CamelContext camelContext;
+
+    public KServeConverterLoader() {
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void load(TypeConverterRegistry registry) throws 
TypeConverterLoaderException {
+        registerConverters(registry);
+    }
+
+    private void registerConverters(TypeConverterRegistry registry) {
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ModelInferRequest.class, 
inference.GrpcPredictV2.ModelInferRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toModelInferRequest((inference.GrpcPredictV2.ModelInferRequest.Builder)
 value));
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ModelMetadataRequest.class, 
inference.GrpcPredictV2.ModelMetadataRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toModelMetadataRequest((inference.GrpcPredictV2.ModelMetadataRequest.Builder)
 value));
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ModelReadyRequest.class, 
inference.GrpcPredictV2.ModelReadyRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toModelReadyRequest((inference.GrpcPredictV2.ModelReadyRequest.Builder)
 value));
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ServerLiveRequest.class, 
inference.GrpcPredictV2.ServerLiveRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toServerLiveRequest((inference.GrpcPredictV2.ServerLiveRequest.Builder)
 value));
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ServerMetadataRequest.class, 
inference.GrpcPredictV2.ServerMetadataRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toServerMetadataRequest((inference.GrpcPredictV2.ServerMetadataRequest.Builder)
 value));
+        addTypeConverter(registry, 
inference.GrpcPredictV2.ServerReadyRequest.class, 
inference.GrpcPredictV2.ServerReadyRequest.Builder.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.kserve.KServeConverter.toServerReadyRequest((inference.GrpcPredictV2.ServerReadyRequest.Builder)
 value));
+    }
+
+    private static void addTypeConverter(TypeConverterRegistry registry, 
Class<?> toType, Class<?> fromType, boolean allowNull, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addTypeConverter(toType, fromType, new 
SimpleTypeConverter(allowNull, method));
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointConfigurer.java
 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointConfigurer.java
new file mode 100644
index 00000000000..4772486a476
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointConfigurer.java
@@ -0,0 +1,69 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.kserve;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class KServeEndpointConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        KServeEndpoint target = (KServeEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": 
target.getConfiguration().setCredentials(property(camelContext, 
io.grpc.ChannelCredentials.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
+        case "modelname":
+        case "modelName": 
target.getConfiguration().setModelName(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "modelversion":
+        case "modelVersion": 
target.getConfiguration().setModelVersion(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "target": 
target.getConfiguration().setTarget(property(camelContext, 
java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": return io.grpc.ChannelCredentials.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        case "modelname":
+        case "modelName": return java.lang.String.class;
+        case "modelversion":
+        case "modelVersion": return java.lang.String.class;
+        case "target": return java.lang.String.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        KServeEndpoint target = (KServeEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "credentials": return target.getConfiguration().getCredentials();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        case "modelname":
+        case "modelName": return target.getConfiguration().getModelName();
+        case "modelversion":
+        case "modelVersion": return 
target.getConfiguration().getModelVersion();
+        case "target": return target.getConfiguration().getTarget();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointUriFactory.java
 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointUriFactory.java
new file mode 100644
index 00000000000..555657e9d78
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/java/org/apache/camel/component/kserve/KServeEndpointUriFactory.java
@@ -0,0 +1,75 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.kserve;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class KServeEndpointUriFactory extends 
org.apache.camel.support.component.EndpointUriFactorySupport implements 
EndpointUriFactory {
+
+    private static final String BASE = ":api";
+
+    private static final Set<String> PROPERTY_NAMES;
+    private static final Set<String> SECRET_PROPERTY_NAMES;
+    private static final Set<String> MULTI_VALUE_PREFIXES;
+    static {
+        Set<String> props = new HashSet<>(6);
+        props.add("api");
+        props.add("credentials");
+        props.add("lazyStartProducer");
+        props.add("modelName");
+        props.add("modelVersion");
+        props.add("target");
+        PROPERTY_NAMES = Collections.unmodifiableSet(props);
+        SECRET_PROPERTY_NAMES = Collections.emptySet();
+        MULTI_VALUE_PREFIXES = Collections.emptySet();
+    }
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "kserve".equals(scheme);
+    }
+
+    @Override
+    public String buildUri(String scheme, Map<String, Object> properties, 
boolean encode) throws URISyntaxException {
+        String syntax = scheme + BASE;
+        String uri = syntax;
+
+        Map<String, Object> copy = new HashMap<>(properties);
+
+        uri = buildPathParameter(syntax, uri, "api", null, true, copy);
+        uri = buildQueryParameters(uri, copy, encode);
+        return uri;
+    }
+
+    @Override
+    public Set<String> propertyNames() {
+        return PROPERTY_NAMES;
+    }
+
+    @Override
+    public Set<String> secretPropertyNames() {
+        return SECRET_PROPERTY_NAMES;
+    }
+
+    @Override
+    public Set<String> multiValuePrefixes() {
+        return MULTI_VALUE_PREFIXES;
+    }
+
+    @Override
+    public boolean isLenientProperties() {
+        return false;
+    }
+}
+
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/org/apache/camel/component/kserve/kserve.json
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/org/apache/camel/component/kserve/kserve.json
new file mode 100644
index 00000000000..cda7067ee14
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/org/apache/camel/component/kserve/kserve.json
@@ -0,0 +1,49 @@
+{
+  "component": {
+    "kind": "component",
+    "name": "kserve",
+    "title": "KServe",
+    "description": "Provide access to AI model servers with the KServe 
standard to run inference with remote models",
+    "deprecated": false,
+    "firstVersion": "4.10.0",
+    "label": "ai",
+    "javaType": "org.apache.camel.component.kserve.KServeComponent",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-kserve",
+    "version": "4.10.0-SNAPSHOT",
+    "scheme": "kserve",
+    "extendsScheme": "",
+    "syntax": "kserve:api",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": true,
+    "lenientProperties": false,
+    "browsable": false,
+    "remote": true
+  },
+  "componentProperties": {
+    "configuration": { "index": 0, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": "org.apache.camel.component.kserve.KServeConfiguration", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
configuration." },
+    "modelName": { "index": 1, "kind": "property", "displayName": "Model 
Name", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The name of the model used for inference." },
+    "modelVersion": { "index": 2, "kind": "property", "displayName": "Model 
Version", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The version of the model used for inference." 
},
+    "target": { "index": 3, "kind": "property", "displayName": "Target", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "localhost:8001", "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The target URI of the client. See: 
https:\/\/grpc.github.io\/grpc-java\/javadoc\/io\/g [...]
+    "lazyStartProducer": { "index": 4, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 5, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
+    "healthCheckConsumerEnabled": { "index": 6, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
+    "healthCheckProducerEnabled": { "index": 7, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on producer [...]
+    "credentials": { "index": 8, "kind": "property", "displayName": 
"Credentials", "group": "security", "label": "security", "required": false, 
"type": "object", "javaType": "io.grpc.ChannelCredentials", "deprecated": 
false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The credentials of the client." }
+  },
+  "headers": {
+    "CamelKServeModelName": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The name of the model used for inference.", 
"constantName": "org.apache.camel.component.kserve.KServeConstants#MODEL_NAME" 
},
+    "CamelKServeModelVersion": { "index": 1, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The version of the model used for inference.", 
"constantName": 
"org.apache.camel.component.kserve.KServeConstants#MODEL_VERSION" }
+  },
+  "properties": {
+    "api": { "index": 0, "kind": "path", "displayName": "Api", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "enum": [ "infer", "model\/ready", "model\/metadata", 
"server\/ready", "server\/live", "server\/metadata" ], "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
KServe API" },
+    "modelName": { "index": 1, "kind": "parameter", "displayName": "Model 
Name", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The name of the model used for inference." },
+    "modelVersion": { "index": 2, "kind": "parameter", "displayName": "Model 
Version", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The version of the model used for inference." 
},
+    "target": { "index": 3, "kind": "parameter", "displayName": "Target", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "localhost:8001", "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The target URI of the client. See: 
https:\/\/grpc.github.io\/grpc-java\/javadoc\/io\/ [...]
+    "lazyStartProducer": { "index": 4, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "credentials": { "index": 5, "kind": "parameter", "displayName": 
"Credentials", "group": "security", "label": "security", "required": false, 
"type": "object", "javaType": "io.grpc.ChannelCredentials", "deprecated": 
false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.kserve.KServeConfiguration", "configurationField": 
"configuration", "description": "The credentials of the client." }
+  }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
new file mode 100644
index 00000000000..3cb278bf2aa
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+org.apache.camel.component.kserve.KServeConverterLoader
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component.properties
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 00000000000..fd082757d6b
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=kserve
+groupId=org.apache.camel
+artifactId=camel-kserve
+version=4.10.0-SNAPSHOT
+projectName=Camel :: AI :: KServe
+projectDescription=Provide access to AI model servers with the KServe standard 
to run inference with remote models
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component/kserve
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component/kserve
new file mode 100644
index 00000000000..62255ddd309
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/component/kserve
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kserve.KServeComponent
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-component
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-component
new file mode 100644
index 00000000000..8de8ef1ca0e
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kserve.KServeComponentConfigurer
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-endpoint
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-endpoint
new file mode 100644
index 00000000000..66f0b3890c9
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/kserve-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kserve.KServeEndpointConfigurer
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.kserve.KServeConfiguration
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.kserve.KServeConfiguration
new file mode 100644
index 00000000000..f141901179a
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.kserve.KServeConfiguration
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kserve.KServeConfigurationConfigurer
diff --git 
a/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/urifactory/kserve-endpoint
 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/urifactory/kserve-endpoint
new file mode 100644
index 00000000000..d0e4d52c7ee
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/generated/resources/META-INF/services/org/apache/camel/urifactory/kserve-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kserve.KServeEndpointUriFactory
diff --git 
a/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc 
b/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc
new file mode 100644
index 00000000000..e73d97b39ae
--- /dev/null
+++ b/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc
@@ -0,0 +1,243 @@
+= KServe Component
+:doctitle: KServe
+:shortname: kserve
+:artifactid: camel-kserve
+:description: Provide access to AI model servers with the KServe standard to 
run inference with remote models
+:since: 4.10
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:group: AI
+:camel-spring-boot-name: kserve
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The KServe component provides the ability to access various AI model servers 
using the 
https://kserve.github.io/website/latest/modelserving/data_plane/v2_protocol/[KServe
 Open Inference Protocl V2]. This allows Camel to remotely perform inference 
with AI models on various model servers that support the KServe V2 protocol.
+
+NOTE: Currently, this component only supports 
https://kserve.github.io/website/latest/reference/swagger-ui/#grpc[GRPC API].
+
+To use the KServe component, Maven users will need to add the following 
dependency to their `pom.xml`:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-kserve</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+== URI format
+
+----
+kserve:api[?options]
+----
+
+Where `api` represents one of the 
https://kserve.github.io/website/latest/reference/swagger-ui/#grpc[KServe Open 
Inference Protocol GRPC API].
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
+
+// component headers: START
+include::partial$component-endpoint-headers.adoc[]
+// component headers: END
+
+== Usage
+
+The component supports the following APIs.
+
+----
+kserve:<api>[?options]
+----
+
+[width="100%",cols="2,5,1,2,2",options="header"]
+|===
+| API | Description | Options | Input (Message Body) | Result (Message Body)
+
+| `infer`
+| Performs inference using the specified model.
+| `modelName` +
+  `modelVersion`
+| `ModelInferRequest` footnote:[`inference.GrpcPredictV2.ModelInferRequest`]
+| `ModelInferResponse` footnote:[`inference.GrpcPredictV2.ModelInferResponse`]
+
+| `model/ready`
+| Indicates if a specific model is ready for inferencing.
+| `modelName` +
+  `modelVersion`
+| `ModelReadyRequest` footnote:[`inference.GrpcPredictV2.ModelReadyRequest`] +
+  (optional)
+| `ModelReadyResponse` footnote:[`inference.GrpcPredictV2.ModelReadyResponse`]
+
+| `model/metadata`
+| Provides information about a model.
+| `modelName` +
+  `modelVersion`
+| `ModelMetadataRequest` 
footnote:[`inference.GrpcPredictV2.ModelMetadataRequest`] +
+  (optional)
+| `ModelMetadataResponse` 
footnote:[`inference.GrpcPredictV2.ModelMetadataResponse`]
+
+| `server/ready`
+| Indicates if the server is ready for inferencing.
+|
+|
+| `ServerReadyResponse` 
footnote:[`inference.GrpcPredictV2.ServerReadyResponse`]
+
+| `server/live`
+| Indicates if the inference server is able to receive and respond to metadata 
and inference requests.
+|
+|
+| `ServerLiveResponse` footnote:[`inference.GrpcPredictV2.ServerLiveResponse`]
+
+| `server/metadata`
+| Provides information about the server.
+|
+|
+| `ServerMetadataResponse` 
footnote:[`inference.GrpcPredictV2.ServerMetadataResponse`]
+|===
+
+== Examples
+
+=== Infer (ModelInfer) API
+
+.Perform inference
+[source,java]
+----
+from("direct:infer")
+    .setBody(constant(createRequest()))
+    .to("kserve:infer?modelName=simple&modelVersion=1")
+    .process(this::postprocess)
+    .log("Result: ${body}");
+
+// Helper methods
+
+ModelInferRequest createRequest() {
+    // How to create a request differs depending on the input types of the 
model.
+    var ints0 = IntStream.range(1, 17).boxed().collect(Collectors.toList());
+    var content0 = InferTensorContents.newBuilder().addAllIntContents(ints0);
+    var input0 = ModelInferRequest.InferInputTensor.newBuilder()
+            .setName("INPUT0").setDatatype("INT32").addShape(1).addShape(16)
+            .setContents(content0);
+    var ints1 = IntStream.range(0, 16).boxed().collect(Collectors.toList());
+    var content1 = InferTensorContents.newBuilder().addAllIntContents(ints1);
+    var input1 = ModelInferRequest.InferInputTensor.newBuilder()
+            .setName("INPUT1").setDatatype("INT32").addShape(1).addShape(16)
+            .setContents(content1);
+    return ModelInferRequest.newBuilder()
+            .addInputs(0, input0).addInputs(1, input1)
+            .build();
+}
+
+void postprocess(Exchange exchange) {
+    // How to post-process the response differs depending on the output types
+    // of the model.
+    var response = exchange.getMessage().getBody(ModelInferResponse.class);
+    var content = response.getRawOutputContents(0);
+    var buffer = 
content.asReadOnlyByteBuffer().order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
+    var ints = new ArrayList<Integer>(buffer.remaining());
+    while (buffer.hasRemaining()) {
+        ints.add(buffer.get());
+    }
+    exchange.getMessage().setBody(ints);
+}
+----
+
+.Specify the model name and version with headers
+[source,java]
+----
+from("direct:infer-with-headers")
+    .setBody(constant(createRequest()))
+    .setHeader(KServeConstants.MODEL_NAME, constant("simple"))
+    .setHeader(KServeConstants.MODEL_VERSION, constant("1"))
+    .to("kserve:infer")
+    .process(this::postprocess)
+    .log("Result: ${body}");
+
+// ... Same as the previous example
+----
+
+=== ModelReady API
+
+.Check if a model is ready
+[source,java]
+----
+from("direct:model-ready")
+    .to("kserve:model-ready?modelName=simple&modelVersion=1")
+    .log("Status: ${body.ready}");
+----
+
+.Specify the model name and version with headers
+[source,java]
+----
+from("direct:model-ready-with-headers")
+    .setHeader(KServeConstants.MODEL_NAME, constant("simple"))
+    .setHeader(KServeConstants.MODEL_VERSION, constant("1"))
+    .to("kserve:model-ready")
+    .log("Status: ${body.ready}");
+----
+
+=== ModelMetadata API
+
+.Fetch model metadata
+[source,java]
+----
+from("direct:model-metadata")
+    .to("kserve:model-metadata?modelName=simple&modelVersion=1")
+    .log("Metadata: ${body}");
+----
+
+.Specify the model name and version with headers
+[source,java]
+----
+from("direct:model-metadata-with-headers")
+    .setHeader(KServeConstants.MODEL_NAME, constant("simple"))
+    .setHeader(KServeConstants.MODEL_VERSION, constant("1"))
+    .to("kserve:model-metadata")
+    .log("Metadata: ${body}");
+----
+
+=== ServerReady API
+
+.Check if the server is ready
+[source,java]
+----
+from("direct:server-ready")
+    .to("kserve:server-ready")
+    .log("Status: ${body.ready}");
+----
+
+=== ServerLive API
+
+.Check if the server is live
+[source,java]
+----
+from("direct:server-live")
+    .to("kserve:server-live")
+    .log("Status: ${body.live}");
+----
+
+=== ServerMetadata API
+
+.Fetch server metadata
+[source,java]
+----
+from("direct:server-metadata")
+    .to("kserve:server-metadata")
+    .log("Metadata: ${body}");
+----
+
+include::spring-boot:partial$starter.adoc[]
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeComponent.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeComponent.java
new file mode 100644
index 00000000000..ea8aaccf019
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeComponent.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.HealthCheckComponent;
+
+@Component("kserve")
+public class KServeComponent extends HealthCheckComponent {
+
+    @Metadata
+    private KServeConfiguration configuration = new KServeConfiguration();
+
+    public KServeComponent() {
+        super();
+    }
+
+    public KServeComponent(CamelContext context) {
+        super(context);
+    }
+
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        KServeConfiguration configuration
+                = this.configuration != null ? this.configuration.copy() : new 
KServeConfiguration();
+        Endpoint endpoint = new KServeEndpoint(uri, this, remaining, 
configuration);
+        setProperties(endpoint, parameters);
+        return endpoint;
+    }
+
+    public KServeConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * The configuration.
+     */
+    public void setConfiguration(KServeConfiguration configuration) {
+        this.configuration = configuration;
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConfiguration.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConfiguration.java
new file mode 100644
index 00000000000..4fdda0a3241
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConfiguration.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import io.grpc.ChannelCredentials;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+@UriParams
+@Configurer
+public class KServeConfiguration implements Cloneable {
+
+    @UriParam(label = "common", defaultValue = "localhost:8001")
+    private String target = "localhost:8001";
+
+    @UriParam(label = "security")
+    private ChannelCredentials credentials;
+
+    @UriParam(label = "common")
+    private String modelName;
+
+    @UriParam(label = "common")
+    private String modelVersion;
+
+    public String getTarget() {
+        return target;
+    }
+
+    /**
+     * The target URI of the client. See:
+     * 
https://grpc.github.io/grpc-java/javadoc/io/grpc/Grpc.html#newChannelBuilder%28java.lang.String,io.grpc.ChannelCredentials%29
+     */
+    public void setTarget(String target) {
+        this.target = target;
+    }
+
+    public ChannelCredentials getCredentials() {
+        return credentials;
+    }
+
+    /**
+     * The credentials of the client.
+     */
+    public void setCredentials(ChannelCredentials credentials) {
+        this.credentials = credentials;
+    }
+
+    public String getModelName() {
+        return modelName;
+    }
+
+    /**
+     * The name of the model used for inference.
+     */
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public String getModelVersion() {
+        return modelVersion;
+    }
+
+    /**
+     * The version of the model used for inference.
+     */
+    public void setModelVersion(String modelVersion) {
+        this.modelVersion = modelVersion;
+    }
+
+    public KServeConfiguration copy() {
+        try {
+            return (KServeConfiguration) clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConstants.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConstants.java
new file mode 100644
index 00000000000..1465f834763
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConstants.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Constants used in Camel KServe component.
+ */
+public interface KServeConstants {
+
+    @Metadata(description = "The name of the model used for inference.", 
javaType = "String")
+    String MODEL_NAME = "CamelKServeModelName";
+
+    @Metadata(description = "The version of the model used for inference.", 
javaType = "String")
+    String MODEL_VERSION = "CamelKServeModelVersion";
+
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConverter.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConverter.java
new file mode 100644
index 00000000000..af9380d8d77
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeConverter.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import inference.GrpcPredictV2;
+import org.apache.camel.Converter;
+
+/**
+ * Converter methods to convert from / to KServe types.
+ */
+@Converter(generateLoader = true)
+public class KServeConverter {
+
+    @Converter
+    public static GrpcPredictV2.ModelInferRequest toModelInferRequest(
+            GrpcPredictV2.ModelInferRequest.Builder builder) {
+        return builder.build();
+    }
+
+    @Converter
+    public static GrpcPredictV2.ModelReadyRequest toModelReadyRequest(
+            GrpcPredictV2.ModelReadyRequest.Builder builder) {
+        return builder.build();
+    }
+
+    @Converter
+    public static GrpcPredictV2.ModelMetadataRequest toModelMetadataRequest(
+            GrpcPredictV2.ModelMetadataRequest.Builder builder) {
+        return builder.build();
+    }
+
+    @Converter
+    public static GrpcPredictV2.ServerReadyRequest toServerReadyRequest(
+            GrpcPredictV2.ServerReadyRequest.Builder builder) {
+        return builder.build();
+    }
+
+    @Converter
+    public static GrpcPredictV2.ServerLiveRequest toServerLiveRequest(
+            GrpcPredictV2.ServerLiveRequest.Builder builder) {
+        return builder.build();
+    }
+
+    @Converter
+    public static GrpcPredictV2.ServerMetadataRequest toServerMetadataRequest(
+            GrpcPredictV2.ServerMetadataRequest.Builder builder) {
+        return builder.build();
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeEndpoint.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeEndpoint.java
new file mode 100644
index 00000000000..74e6af43a9e
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeEndpoint.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import inference.GRPCInferenceServiceGrpc;
+import io.grpc.ChannelCredentials;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.ManagedChannel;
+import org.apache.camel.Category;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultEndpoint;
+
+@UriEndpoint(firstVersion = "4.10.0", scheme = "kserve", title = "KServe",
+             syntax = "kserve:api", producerOnly = true,
+             category = { Category.AI }, headersClass = KServeConstants.class)
+public class KServeEndpoint extends DefaultEndpoint {
+
+    /**
+     * The KServe API spec: <a href=
+     * 
"https://github.com/kserve/open-inference-protocol/blob/main/specification/protocol/inference_grpc.md";>open-inference-protocol/specification/protocol/inference_grpc.md</a>
+     */
+    @UriPath(enums = 
"infer,model/ready,model/metadata,server/ready,server/live,server/metadata",
+             description = "The KServe API")
+    @Metadata(required = true)
+    private final String api;
+
+    @UriParam
+    private KServeConfiguration configuration;
+
+    private ManagedChannel channel;
+    private GRPCInferenceServiceGrpc.GRPCInferenceServiceBlockingStub 
inferenceService;
+
+    public KServeEndpoint(String uri, KServeComponent component, String path,
+                          KServeConfiguration configuration) {
+        super(uri, component);
+        this.api = path;
+        this.configuration = configuration;
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+
+        ChannelCredentials credentials = configuration.getCredentials() != null
+                ? configuration.getCredentials()
+                : InsecureChannelCredentials.create();
+        channel = Grpc.newChannelBuilder(configuration.getTarget(), 
credentials).build();
+        inferenceService = GRPCInferenceServiceGrpc.newBlockingStub(channel);
+    }
+
+    @Override
+    public void doStop() throws Exception {
+        super.doStop();
+
+        // Close the channel
+        channel.shutdown();
+    }
+
+    @Override
+    public Producer createProducer() {
+        return new KServeProducer(this);
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) {
+        throw new UnsupportedOperationException("Consumer not supported");
+    }
+
+    public String getApi() {
+        return api;
+    }
+
+    public KServeConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(KServeConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public GRPCInferenceServiceGrpc.GRPCInferenceServiceBlockingStub 
getInferenceService() {
+        return inferenceService;
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeProducer.java
 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeProducer.java
new file mode 100644
index 00000000000..40ee8b259e0
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/main/java/org/apache/camel/component/kserve/KServeProducer.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve;
+
+import java.util.Optional;
+
+import com.google.protobuf.GeneratedMessageV3;
+import inference.GRPCInferenceServiceGrpc;
+import inference.GrpcPredictV2;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.support.DefaultProducer;
+
+public class KServeProducer extends DefaultProducer {
+
+    private final String api;
+    private final GRPCInferenceServiceGrpc.GRPCInferenceServiceBlockingStub 
inferenceService;
+
+    public KServeProducer(KServeEndpoint endpoint) {
+        super(endpoint);
+        this.api = endpoint.getApi();
+        this.inferenceService = endpoint.getInferenceService();
+    }
+
+    @Override
+    public KServeEndpoint getEndpoint() {
+        return (KServeEndpoint) super.getEndpoint();
+    }
+
+    @Override
+    public void process(Exchange exchange) {
+        GeneratedMessageV3 response = switch (api) {
+            case "infer" -> infer(exchange);
+            case "model/ready" -> modelReady(exchange);
+            case "model/metadata" -> modelMetadata(exchange);
+            case "server/ready" -> serverReady();
+            case "server/live" -> serverLive();
+            case "server/metadata" -> serverMetadata();
+            default -> throw new IllegalArgumentException("Unsupported API: " 
+ api);
+        };
+        exchange.getMessage().setBody(response);
+    }
+
+    private GrpcPredictV2.ModelInferResponse infer(Exchange exchange) {
+        Message message = exchange.getMessage();
+        GrpcPredictV2.ModelInferRequest request = 
message.getBody(GrpcPredictV2.ModelInferRequest.class);
+
+        KServeConfiguration configuration = getEndpoint().getConfiguration();
+        GrpcPredictV2.ModelInferRequest.Builder builder = 
GrpcPredictV2.ModelInferRequest.newBuilder();
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_NAME, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelName()))
+                .ifPresent(builder::setModelName);
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_VERSION, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelVersion()))
+                .ifPresent(builder::setModelVersion);
+        if (request != null) {
+            builder.mergeFrom(request);
+        }
+
+        return inferenceService.modelInfer(builder.build());
+    }
+
+    private GrpcPredictV2.ModelReadyResponse modelReady(Exchange exchange) {
+        Message message = exchange.getMessage();
+        GrpcPredictV2.ModelReadyRequest request = 
message.getBody(GrpcPredictV2.ModelReadyRequest.class);
+
+        KServeConfiguration configuration = getEndpoint().getConfiguration();
+        GrpcPredictV2.ModelReadyRequest.Builder builder = 
GrpcPredictV2.ModelReadyRequest.newBuilder();
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_NAME, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelName()))
+                .ifPresent(builder::setName);
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_VERSION, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelVersion()))
+                .ifPresent(builder::setVersion);
+        if (request != null) {
+            builder.mergeFrom(request);
+        }
+
+        return inferenceService.modelReady(builder.build());
+    }
+
+    private GrpcPredictV2.ModelMetadataResponse modelMetadata(Exchange 
exchange) {
+        Message message = exchange.getMessage();
+        GrpcPredictV2.ModelMetadataRequest request = 
message.getBody(GrpcPredictV2.ModelMetadataRequest.class);
+
+        KServeConfiguration configuration = getEndpoint().getConfiguration();
+        GrpcPredictV2.ModelMetadataRequest.Builder builder = 
GrpcPredictV2.ModelMetadataRequest.newBuilder();
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_NAME, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelName()))
+                .ifPresent(builder::setName);
+        Optional.ofNullable(message.getHeader(KServeConstants.MODEL_VERSION, 
String.class))
+                .or(() -> Optional.ofNullable(configuration.getModelVersion()))
+                .ifPresent(builder::setVersion);
+        if (request != null) {
+            builder.mergeFrom(request);
+        }
+
+        return inferenceService.modelMetadata(builder.build());
+    }
+
+    private GrpcPredictV2.ServerReadyResponse serverReady() {
+        GrpcPredictV2.ServerReadyRequest.Builder builder = 
GrpcPredictV2.ServerReadyRequest.newBuilder();
+        return inferenceService.serverReady(builder.build());
+    }
+
+    private GrpcPredictV2.ServerLiveResponse serverLive() {
+        GrpcPredictV2.ServerLiveRequest.Builder builder = 
GrpcPredictV2.ServerLiveRequest.newBuilder();
+        return inferenceService.serverLive(builder.build());
+    }
+
+    private GrpcPredictV2.ServerMetadataResponse serverMetadata() {
+        GrpcPredictV2.ServerMetadataRequest.Builder builder = 
GrpcPredictV2.ServerMetadataRequest.newBuilder();
+        return inferenceService.serverMetadata(builder.build());
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/main/proto/grpc_predict_v2.proto 
b/components/camel-ai/camel-kserve/src/main/proto/grpc_predict_v2.proto
new file mode 100644
index 00000000000..5605f8fdfa7
--- /dev/null
+++ b/components/camel-ai/camel-kserve/src/main/proto/grpc_predict_v2.proto
@@ -0,0 +1,342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Copyright 2020 kubeflow.org.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+package inference;
+
+// Inference Server GRPC endpoints.
+service GRPCInferenceService
+{
+  // The ServerLive API indicates if the inference server is able to receive 
+  // and respond to metadata and inference requests.
+  rpc ServerLive(ServerLiveRequest) returns (ServerLiveResponse) {}
+
+  // The ServerReady API indicates if the server is ready for inferencing.
+  rpc ServerReady(ServerReadyRequest) returns (ServerReadyResponse) {}
+
+  // The ModelReady API indicates if a specific model is ready for inferencing.
+  rpc ModelReady(ModelReadyRequest) returns (ModelReadyResponse) {}
+
+  // The ServerMetadata API provides information about the server. Errors are 
+  // indicated by the google.rpc.Status returned for the request. The OK code 
+  // indicates success and other codes indicate failure.
+  rpc ServerMetadata(ServerMetadataRequest) returns (ServerMetadataResponse) {}
+
+  // The per-model metadata API provides information about a model. Errors are 
+  // indicated by the google.rpc.Status returned for the request. The OK code 
+  // indicates success and other codes indicate failure.
+  rpc ModelMetadata(ModelMetadataRequest) returns (ModelMetadataResponse) {}
+
+  // The ModelInfer API performs inference using the specified model. Errors 
are
+  // indicated by the google.rpc.Status returned for the request. The OK code 
+  // indicates success and other codes indicate failure.
+  rpc ModelInfer(ModelInferRequest) returns (ModelInferResponse) {}
+}
+
+message ServerLiveRequest {}
+
+message ServerLiveResponse
+{
+  // True if the inference server is live, false if not live.
+  bool live = 1;
+}
+
+message ServerReadyRequest {}
+
+message ServerReadyResponse
+{
+  // True if the inference server is ready, false if not ready.
+  bool ready = 1;
+}
+
+message ModelReadyRequest
+{
+  // The name of the model to check for readiness.
+  string name = 1;
+
+  // The version of the model to check for readiness. If not given the
+  // server will choose a version based on the model and internal policy.
+  string version = 2;
+}
+
+message ModelReadyResponse
+{
+  // True if the model is ready, false if not ready.
+  bool ready = 1;
+}
+
+message ServerMetadataRequest {}
+
+message ServerMetadataResponse
+{
+  // The server name.
+  string name = 1;
+
+  // The server version.
+  string version = 2;
+
+  // The extensions supported by the server.
+  repeated string extensions = 3;
+}
+
+message ModelMetadataRequest
+{
+  // The name of the model.
+  string name = 1;
+
+  // The version of the model to check for readiness. If not given the
+  // server will choose a version based on the model and internal policy.
+  string version = 2;
+}
+
+message ModelMetadataResponse
+{
+  // Metadata for a tensor.
+  message TensorMetadata
+  {
+    // The tensor name.
+    string name = 1;
+
+    // The tensor data type.
+    string datatype = 2;
+
+    // The tensor shape. A variable-size dimension is represented
+    // by a -1 value.
+    repeated int64 shape = 3;
+  }
+
+  // The model name.
+  string name = 1;
+
+  // The versions of the model available on the server.
+  repeated string versions = 2;
+
+  // The model's platform. See Platforms.
+  string platform = 3;
+
+  // The model's inputs.
+  repeated TensorMetadata inputs = 4;
+
+  // The model's outputs.
+  repeated TensorMetadata outputs = 5;
+}
+
+message ModelInferRequest
+{
+  // An input tensor for an inference request.
+  message InferInputTensor
+  {
+    // The tensor name.
+    string name = 1;
+
+    // The tensor data type.
+    string datatype = 2;
+
+    // The tensor shape.
+    repeated int64 shape = 3;
+
+    // Optional inference input tensor parameters.
+    map<string, InferParameter> parameters = 4;
+
+    // The tensor contents using a data-type format. This field must
+    // not be specified if "raw" tensor contents are being used for
+    // the inference request.
+    InferTensorContents contents = 5;
+  }
+
+  // An output tensor requested for an inference request.
+  message InferRequestedOutputTensor
+  {
+    // The tensor name.
+    string name = 1;
+
+    // Optional requested output tensor parameters.
+    map<string, InferParameter> parameters = 2;
+  }
+
+  // The name of the model to use for inferencing.
+  string model_name = 1;
+
+  // The version of the model to use for inference. If not given the
+  // server will choose a version based on the model and internal policy.
+  string model_version = 2;
+
+  // Optional identifier for the request. If specified will be
+  // returned in the response.
+  string id = 3;
+
+  // Optional inference parameters.
+  map<string, InferParameter> parameters = 4;
+
+  // The input tensors for the inference.
+  repeated InferInputTensor inputs = 5;
+
+  // The requested output tensors for the inference. Optional, if not
+  // specified all outputs produced by the model will be returned.
+  repeated InferRequestedOutputTensor outputs = 6;
+
+  // The data contained in an input tensor can be represented in "raw"
+  // bytes form or in the repeated type that matches the tensor's data
+  // type. To use the raw representation 'raw_input_contents' must be
+  // initialized with data for each tensor in the same order as
+  // 'inputs'. For each tensor, the size of this content must match
+  // what is expected by the tensor's shape and data type. The raw
+  // data must be the flattened, one-dimensional, row-major order of
+  // the tensor elements without any stride or padding between the
+  // elements. Note that the FP16 and BF16 data types must be represented as
+  // raw content as there is no specific data type for a 16-bit float type.
+  //
+  // If this field is specified then InferInputTensor::contents must
+  // not be specified for any input tensor.
+  repeated bytes raw_input_contents = 7;
+}
+
+message ModelInferResponse
+{
+  // An output tensor returned for an inference request.
+  message InferOutputTensor
+  {
+    // The tensor name.
+    string name = 1;
+
+    // The tensor data type.
+    string datatype = 2;
+
+    // The tensor shape.
+    repeated int64 shape = 3;
+
+    // Optional output tensor parameters.
+    map<string, InferParameter> parameters = 4;
+
+    // The tensor contents using a data-type format. This field must
+    // not be specified if "raw" tensor contents are being used for
+    // the inference response.
+    InferTensorContents contents = 5;
+  }
+
+  // The name of the model used for inference.
+  string model_name = 1;
+
+  // The version of the model used for inference.
+  string model_version = 2;
+
+  // The id of the inference request if one was specified.
+  string id = 3;
+
+  // Optional inference response parameters.
+  map<string, InferParameter> parameters = 4;
+
+  // The output tensors holding inference results.
+  repeated InferOutputTensor outputs = 5;
+
+  // The data contained in an output tensor can be represented in
+  // "raw" bytes form or in the repeated type that matches the
+  // tensor's data type. To use the raw representation 'raw_output_contents'
+  // must be initialized with data for each tensor in the same order as
+  // 'outputs'. For each tensor, the size of this content must match
+  // what is expected by the tensor's shape and data type. The raw
+  // data must be the flattened, one-dimensional, row-major order of
+  // the tensor elements without any stride or padding between the
+  // elements. Note that the FP16 and BF16 data types must be represented as
+  // raw content as there is no specific data type for a 16-bit float type.
+  //
+  // If this field is specified then InferOutputTensor::contents must
+  // not be specified for any output tensor.
+  repeated bytes raw_output_contents = 6;
+}
+
+// An inference parameter value. The Parameters message describes a 
+// “name”/”value” pair, where the “name” is the name of the parameter
+// and the “value” is a boolean, integer, or string corresponding to 
+// the parameter.
+message InferParameter
+{
+  // The parameter value can be a string, an int64, a boolean
+  // or a message specific to a predefined parameter.
+  oneof parameter_choice
+  {
+    // A boolean parameter value.
+    bool bool_param = 1;
+
+    // An int64 parameter value.
+    int64 int64_param = 2;
+
+    // A string parameter value.
+    string string_param = 3;
+  }
+}
+
+// The data contained in a tensor represented by the repeated type
+// that matches the tensor's data type. Protobuf oneof is not used
+// because oneofs cannot contain repeated fields.
+message InferTensorContents
+{
+  // Representation for BOOL data type. The size must match what is
+  // expected by the tensor's shape. The contents must be the flattened,
+  // one-dimensional, row-major order of the tensor elements.
+  repeated bool bool_contents = 1;
+
+  // Representation for INT8, INT16, and INT32 data types. The size
+  // must match what is expected by the tensor's shape. The contents
+  // must be the flattened, one-dimensional, row-major order of the
+  // tensor elements.
+  repeated int32 int_contents = 2;
+
+  // Representation for INT64 data types. The size must match what
+  // is expected by the tensor's shape. The contents must be the
+  // flattened, one-dimensional, row-major order of the tensor elements.
+  repeated int64 int64_contents = 3;
+
+  // Representation for UINT8, UINT16, and UINT32 data types. The size
+  // must match what is expected by the tensor's shape. The contents
+  // must be the flattened, one-dimensional, row-major order of the
+  // tensor elements.
+  repeated uint32 uint_contents = 4;
+
+  // Representation for UINT64 data types. The size must match what
+  // is expected by the tensor's shape. The contents must be the
+  // flattened, one-dimensional, row-major order of the tensor elements.
+  repeated uint64 uint64_contents = 5;
+
+  // Representation for FP32 data type. The size must match what is
+  // expected by the tensor's shape. The contents must be the flattened,
+  // one-dimensional, row-major order of the tensor elements.
+  repeated float fp32_contents = 6;
+
+  // Representation for FP64 data type. The size must match what is
+  // expected by the tensor's shape. The contents must be the flattened,
+  // one-dimensional, row-major order of the tensor elements.
+  repeated double fp64_contents = 7;
+
+  // Representation for BYTES data type. The size must match what is
+  // expected by the tensor's shape. The contents must be the flattened,
+  // one-dimensional, row-major order of the tensor elements.
+  repeated bytes bytes_contents = 8;
+}
diff --git 
a/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeEndpointIT.java
 
b/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeEndpointIT.java
new file mode 100644
index 00000000000..4bfde361087
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeEndpointIT.java
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve.it;
+
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import com.google.protobuf.ByteString;
+import inference.GrpcPredictV2;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.kserve.KServeConstants;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class KServeEndpointIT extends KServeITSupport {
+
+    private static final String TEST_MODEL = "simple";
+    private static final String TEST_MODEL_VERSION = "1";
+
+    @Test
+    void testInfer() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelInferResponse.class)
+                .simple("${body.rawOutputContentsCount").isEqualTo(2);
+
+        var request = createInferRequest();
+        template.sendBody("direct:infer", request);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+
+        var response = 
mock.getReceivedExchanges().get(0).getMessage().getBody(GrpcPredictV2.ModelInferResponse.class);
+        assertInferResponse(response);
+    }
+
+    @Test
+    void testInfer_version() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelInferResponse.class)
+                .simple("${body.rawOutputContentsCount").isEqualTo(2);
+
+        var request = createInferRequest();
+        template.sendBody("direct:infer_version", request);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+
+        var response = 
mock.getReceivedExchanges().get(0).getMessage().getBody(GrpcPredictV2.ModelInferResponse.class);
+        assertInferResponse(response);
+    }
+
+    @Test
+    void testInfer_headers() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelInferResponse.class)
+                .simple("${body.rawOutputContentsCount").isEqualTo(2);
+
+        var request = createInferRequest();
+        template.send("direct:infer_headers", e -> {
+            e.getMessage().setHeader(KServeConstants.MODEL_NAME, TEST_MODEL);
+            e.getMessage().setHeader(KServeConstants.MODEL_VERSION, 
TEST_MODEL_VERSION);
+            e.getMessage().setBody(request);
+        });
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+
+        var response = 
mock.getReceivedExchanges().get(0).getMessage().getBody(GrpcPredictV2.ModelInferResponse.class);
+        assertInferResponse(response);
+    }
+
+    private GrpcPredictV2.ModelInferRequest createInferRequest() {
+        var ints0 = IntStream.range(1, 
17).boxed().collect(Collectors.toList());
+        var content0 = 
GrpcPredictV2.InferTensorContents.newBuilder().addAllIntContents(ints0);
+        var input0 = 
GrpcPredictV2.ModelInferRequest.InferInputTensor.newBuilder()
+                
.setName("INPUT0").setDatatype("INT32").addShape(1).addShape(16)
+                .setContents(content0);
+
+        var ints1 = IntStream.range(0, 
16).boxed().collect(Collectors.toList());
+        var content1 = 
GrpcPredictV2.InferTensorContents.newBuilder().addAllIntContents(ints1);
+        var input1 = 
GrpcPredictV2.ModelInferRequest.InferInputTensor.newBuilder()
+                
.setName("INPUT1").setDatatype("INT32").addShape(1).addShape(16)
+                .setContents(content1);
+
+        return GrpcPredictV2.ModelInferRequest.newBuilder()
+                .addInputs(0, input0).addInputs(1, input1)
+                .build();
+    }
+
+    private void assertInferResponse(GrpcPredictV2.ModelInferResponse 
response) {
+        var output0 = toList(response.getRawOutputContents(0));
+        // output0 = input0 + input1
+        assertEquals(List.of(1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 
27, 29, 31), output0);
+        var output1 = toList(response.getRawOutputContents(1));
+        // output1 = input0 - input1
+        assertEquals(List.of(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
output1);
+    }
+
+    private List<Integer> toList(ByteString content) {
+        var buffer = 
content.asReadOnlyByteBuffer().order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
+        var list = new ArrayList<Integer>(buffer.remaining());
+        while (buffer.hasRemaining()) {
+            list.add(buffer.get());
+        }
+        return list;
+    }
+
+    @Test
+    void testModelReady() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelReadyResponse.class)
+                .simple("${body.ready}").isEqualTo("true");
+
+        template.sendBody("direct:model-ready", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testModelReady_version() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelReadyResponse.class)
+                .simple("${body.ready}").isEqualTo("true");
+
+        template.sendBody("direct:model-ready_version", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testModelReady_headers() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ModelReadyResponse.class)
+                .simple("${body.ready}").isEqualTo("true");
+
+        template.send("direct:model-ready_headers", e -> {
+            e.getMessage().setHeader(KServeConstants.MODEL_NAME, TEST_MODEL);
+            e.getMessage().setHeader(KServeConstants.MODEL_VERSION, 
TEST_MODEL_VERSION);
+        });
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testModelMetadata() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
mock.expectedBodyReceived().body(GrpcPredictV2.ModelMetadataResponse.class);
+        mock.message(0).body().simple("${body.name}").isEqualTo(TEST_MODEL);
+        
mock.message(0).body().simple("${body.getVersions(0)}").isEqualTo(TEST_MODEL_VERSION);
+
+        template.sendBody("direct:model-metadata", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testModelMetadata_version() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
mock.expectedBodyReceived().body(GrpcPredictV2.ModelMetadataResponse.class);
+        mock.message(0).body().simple("${body.name}").isEqualTo(TEST_MODEL);
+        
mock.message(0).body().simple("${body.getVersions(0)}").isEqualTo(TEST_MODEL_VERSION);
+
+        template.sendBody("direct:model-metadata_version", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testModelMetadata_headers() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
mock.expectedBodyReceived().body(GrpcPredictV2.ModelMetadataResponse.class);
+        mock.message(0).body().simple("${body.name}").isEqualTo(TEST_MODEL);
+        
mock.message(0).body().simple("${body.getVersions(0)}").isEqualTo(TEST_MODEL_VERSION);
+
+        template.send("direct:model-metadata_headers", e -> {
+            e.getMessage().setHeader(KServeConstants.MODEL_NAME, TEST_MODEL);
+            e.getMessage().setHeader(KServeConstants.MODEL_VERSION, 
TEST_MODEL_VERSION);
+        });
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testServerReady() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ServerReadyResponse.class)
+                .simple("${body.ready}").isEqualTo("true");
+
+        template.sendBody("direct:server-ready", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testServerLive() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.expectedBodyReceived()
+                .body(GrpcPredictV2.ServerLiveResponse.class)
+                .simple("${body.live}").isEqualTo("true");
+
+        template.sendBody("direct:server-live", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testServerMetadata() throws Exception {
+        var mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
mock.expectedBodyReceived().body(GrpcPredictV2.ServerMetadataResponse.class);
+        // IT uses Triton Inference Server
+        mock.message(0).body().simple("${body.name}").isEqualTo("triton");
+        mock.message(0).body().simple("${body.version}").isNotNull();
+        
mock.message(0).body().simple("${body.extensionsCount}").isNotEqualTo(0);
+
+        template.sendBody("direct:server-metadata", null);
+
+        mock.await(1, TimeUnit.SECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:infer")
+                        .toF("kserve:infer?modelName=%s", TEST_MODEL)
+                        .to("mock:result");
+                from("direct:infer_version")
+                        .toF("kserve:infer?modelName=%s&modelVersion=%s", 
TEST_MODEL, TEST_MODEL_VERSION)
+                        .to("mock:result");
+                from("direct:infer_headers")
+                        .to("kserve:infer")
+                        .to("mock:result");
+                from("direct:model-ready")
+                        .toF("kserve:model/ready?modelName=%s", TEST_MODEL)
+                        .to("mock:result");
+                from("direct:model-ready_version")
+                        
.toF("kserve:model/ready?modelName=%s&modelVersion=%s", TEST_MODEL, 
TEST_MODEL_VERSION)
+                        .to("mock:result");
+                from("direct:model-ready_headers")
+                        .to("kserve:model/ready")
+                        .to("mock:result");
+                from("direct:model-metadata")
+                        .toF("kserve:model/metadata?modelName=%s", TEST_MODEL)
+                        .to("mock:result");
+                from("direct:model-metadata_version")
+                        
.toF("kserve:model/metadata?modelName=%s&modelVersion=%s", TEST_MODEL, 
TEST_MODEL_VERSION)
+                        .to("mock:result");
+                from("direct:model-metadata_headers")
+                        .to("kserve:model/metadata")
+                        .to("mock:result");
+                from("direct:server-ready")
+                        .toF("kserve:server/ready")
+                        .to("mock:result");
+                from("direct:server-live")
+                        .toF("kserve:server/live")
+                        .to("mock:result");
+                from("direct:server-metadata")
+                        .toF("kserve:server/metadata")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeITSupport.java
 
b/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeITSupport.java
new file mode 100644
index 00000000000..62db7c3c52a
--- /dev/null
+++ 
b/components/camel-ai/camel-kserve/src/test/java/org/apache/camel/component/kserve/it/KServeITSupport.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.kserve.it;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.kserve.KServeComponent;
+import org.apache.camel.test.infra.triton.services.TritonService;
+import org.apache.camel.test.infra.triton.services.TritonServiceFactory;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class KServeITSupport extends CamelTestSupport {
+
+    @RegisterExtension
+    static TritonService service = TritonServiceFactory.createService();
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        var context = super.createCamelContext();
+        var component = context.getComponent("kserve", KServeComponent.class);
+        var configuration = component.getConfiguration();
+        configuration.setTarget("localhost:" + service.grpcPort());
+        return context;
+    }
+}
diff --git 
a/components/camel-ai/camel-kserve/src/test/resources/log4j2.properties 
b/components/camel-ai/camel-kserve/src/test/resources/log4j2.properties
new file mode 100644
index 00000000000..552135d8f5c
--- /dev/null
+++ b/components/camel-ai/camel-kserve/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-kserve-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-ai/pom.xml b/components/camel-ai/pom.xml
index db94f0489a8..23c3e3c73d9 100644
--- a/components/camel-ai/pom.xml
+++ b/components/camel-ai/pom.xml
@@ -36,6 +36,7 @@
     <modules>
         <module>camel-chatscript</module>
         <module>camel-djl</module>
+        <module>camel-kserve</module>
         <module>camel-langchain4j-chat</module>
         <module>camel-langchain4j-core</module>
         <module>camel-langchain4j-embeddings</module>
diff --git a/docs/components/modules/ROOT/examples/json/kserve.json 
b/docs/components/modules/ROOT/examples/json/kserve.json
new file mode 120000
index 00000000000..71cc8ea13b2
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/kserve.json
@@ -0,0 +1 @@
+../../../../../../components/camel-ai/camel-kserve/src/generated/resources/META-INF/org/apache/camel/component/kserve/kserve.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc 
b/docs/components/modules/ROOT/nav.adoc
index 2a726e80bfa..48c93dc972b 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -7,6 +7,7 @@
 ** xref:ai-summary.adoc[AI]
 *** xref:chatscript-component.adoc[ChatScript]
 *** xref:djl-component.adoc[Deep Java Library]
+*** xref:kserve-component.adoc[KServe]
 *** xref:langchain4j-chat-component.adoc[LangChain4j Chat]
 *** xref:langchain4j-embeddings-component.adoc[LangChain4j Embeddings]
 *** xref:langchain4j-tools-component.adoc[LangChain4j Tools]
diff --git a/docs/components/modules/ROOT/pages/kserve-component.adoc 
b/docs/components/modules/ROOT/pages/kserve-component.adoc
new file mode 120000
index 00000000000..f1d9609220b
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/kserve-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index be164cc902f..77638a24229 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1746,6 +1746,11 @@
                 <artifactId>camel-knative-http</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-kserve</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-kubernetes</artifactId>
diff --git a/pom.xml b/pom.xml
index 7a87c2f02b8..0c8fdf695d4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -260,6 +260,7 @@
                                     <exclude>**/*.event</exclude>
                                     <exclude>**/*.gif</exclude>
                                     <exclude>**/*.gpg</exclude>
+                                    <exclude>**/*.graphdef</exclude>
                                     <exclude>**/*.graphql*</exclude>
                                     <exclude>**/*.ics</exclude>
                                     <exclude>**/*.joor</exclude>
@@ -276,6 +277,7 @@
                                     <exclude>**/*.params</exclude>
                                     <exclude>**/*.parquet</exclude>
                                     <exclude>**/*.pb</exclude>
+                                    <exclude>**/*.pbtxt</exclude>
                                     <exclude>**/*.pem</exclude>
                                     <exclude>**/*.pfx</exclude>
                                     <exclude>**/*.pgp</exclude>
diff --git a/test-infra/camel-test-infra-all/pom.xml 
b/test-infra/camel-test-infra-all/pom.xml
index 021950e7509..d66f3db70b2 100644
--- a/test-infra/camel-test-infra-all/pom.xml
+++ b/test-infra/camel-test-infra-all/pom.xml
@@ -246,6 +246,11 @@
             <artifactId>camel-test-infra-tensorflow-serving</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-triton</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -550,4 +555,4 @@
         </plugins>
     </build>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/components/camel-ai/pom.xml 
b/test-infra/camel-test-infra-triton/pom.xml
similarity index 50%
copy from components/camel-ai/pom.xml
copy to test-infra/camel-test-infra-triton/pom.xml
index db94f0489a8..68b88518cfe 100644
--- a/components/camel-ai/pom.xml
+++ b/test-infra/camel-test-infra-triton/pom.xml
@@ -17,37 +17,36 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-         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>
-
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
+        <artifactId>camel-test-infra-parent</artifactId>
         <groupId>org.apache.camel</groupId>
-        <artifactId>components</artifactId>
+        <relativePath>../camel-test-infra-parent/pom.xml</relativePath>
         <version>4.10.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>camel-ai-parent</artifactId>
-    <packaging>pom</packaging>
-    <name>Camel :: AI :: Parent</name>
-    <description>Camel AI parent</description>
-
-    <modules>
-        <module>camel-chatscript</module>
-        <module>camel-djl</module>
-        <module>camel-langchain4j-chat</module>
-        <module>camel-langchain4j-core</module>
-        <module>camel-langchain4j-embeddings</module>
-        <module>camel-langchain4j-tokenizer</module>
-        <module>camel-langchain4j-tools</module>
-        <module>camel-langchain4j-web-search</module>
-        <module>camel-milvus</module>
-        <module>camel-pinecone</module>
-        <module>camel-qdrant</module>
-        <module>camel-tensorflow-serving</module>
-        <module>camel-torchserve</module>
-    </modules>
-
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>camel-test-infra-triton</artifactId>
+
+    <name>Camel :: Test Infra :: Triton Inference Server</name>
+    <description>Triton Inference Server test infrastructure for 
Camel</description>
+
+    <properties>
+        <assembly.skipAssembly>false</assembly.skipAssembly>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-common</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>testcontainers</artifactId>
+            <version>${testcontainers-version}</version>
+        </dependency>
+    </dependencies>
 </project>
-
diff --git 
a/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/common/TritonProperties.java
 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/common/TritonProperties.java
new file mode 100644
index 00000000000..106d8289b10
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/common/TritonProperties.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.common;
+
+public class TritonProperties {
+    public static final String TRITON_HTTP_PORT = "triton.http.port";
+    public static final String TRITON_GPRC_PORT = "triton.grpc.port";
+    public static final String TRITON_METRICS_PORT = "triton.metrics.port";
+    public static final String TRITON_CONTAINER = "triton.container";
+
+    private TritonProperties() {
+    }
+}
diff --git 
a/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonInfraService.java
 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonInfraService.java
new file mode 100644
index 00000000000..b4e16901901
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonInfraService.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.services;
+
+import org.apache.camel.test.infra.common.services.InfrastructureService;
+
+public interface TritonInfraService extends InfrastructureService {
+
+    int httpPort();
+
+    int grpcPort();
+
+    int metricsPort();
+}
diff --git 
a/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonLocalContainerInfraService.java
 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonLocalContainerInfraService.java
new file mode 100644
index 00000000000..77a52680f68
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonLocalContainerInfraService.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.services;
+
+import org.apache.camel.test.infra.common.LocalPropertyResolver;
+import org.apache.camel.test.infra.common.services.ContainerService;
+import org.apache.camel.test.infra.triton.common.TritonProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+public class TritonLocalContainerInfraService implements TritonInfraService, 
ContainerService<GenericContainer<?>> {
+    private static final Logger LOG = 
LoggerFactory.getLogger(TritonLocalContainerInfraService.class);
+
+    public static final int HTTP_PORT = 8000;
+    public static final int GRPC_PORT = 8001;
+    public static final int METRICS_PORT = 8002;
+
+    private static final String CONTAINER_COMMAND = "tritonserver 
--model-repository=/models";
+
+    private final GenericContainer<?> container;
+
+    public TritonLocalContainerInfraService() {
+        String imageName = LocalPropertyResolver.getProperty(
+                TritonLocalContainerInfraService.class,
+                TritonProperties.TRITON_CONTAINER);
+
+        container = initContainer(imageName);
+    }
+
+    @SuppressWarnings("resource")
+    protected GenericContainer<?> initContainer(String imageName) {
+        return new GenericContainer<>(DockerImageName.parse(imageName))
+                .withExposedPorts(HTTP_PORT, GRPC_PORT, METRICS_PORT)
+                
.withCopyFileToContainer(MountableFile.forClasspathResource("models"), 
"/models")
+                .waitingFor(Wait.forListeningPorts(HTTP_PORT, GRPC_PORT, 
METRICS_PORT))
+                .withCommand(CONTAINER_COMMAND);
+    }
+
+    @Override
+    public void registerProperties() {
+        System.setProperty(TritonProperties.TRITON_HTTP_PORT, 
String.valueOf(httpPort()));
+        System.setProperty(TritonProperties.TRITON_GPRC_PORT, 
String.valueOf(grpcPort()));
+        System.setProperty(TritonProperties.TRITON_METRICS_PORT, 
String.valueOf(metricsPort()));
+    }
+
+    @Override
+    public void initialize() {
+        LOG.info("Trying to start the Triton Inference Server container");
+
+        container.start();
+        registerProperties();
+
+        LOG.info("Triton Inference Server instance running at {}, {} and {}", 
httpPort(), grpcPort(), metricsPort());
+    }
+
+    @Override
+    public void shutdown() {
+        LOG.info("Stopping the Triton Inference Server container");
+        container.stop();
+    }
+
+    @Override
+    public GenericContainer<?> getContainer() {
+        return container;
+    }
+
+    @Override
+    public int httpPort() {
+        return container.getMappedPort(HTTP_PORT);
+    }
+
+    @Override
+    public int grpcPort() {
+        return container.getMappedPort(GRPC_PORT);
+    }
+
+    @Override
+    public int metricsPort() {
+        return container.getMappedPort(METRICS_PORT);
+    }
+}
diff --git 
a/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonRemoteInfraService.java
 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonRemoteInfraService.java
new file mode 100644
index 00000000000..72c0fb49f08
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/java/org/apache/camel/test/infra/triton/services/TritonRemoteInfraService.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.services;
+
+import org.apache.camel.test.infra.triton.common.TritonProperties;
+
+public class TritonRemoteInfraService implements TritonInfraService {
+
+    @Override
+    public void registerProperties() {
+        // NO-OP
+    }
+
+    @Override
+    public void initialize() {
+        registerProperties();
+    }
+
+    @Override
+    public void shutdown() {
+        // NO-OP
+    }
+
+    @Override
+    public int httpPort() {
+        String value = System.getProperty(TritonProperties.TRITON_HTTP_PORT, 
"8000");
+        return Integer.parseInt(value);
+    }
+
+    @Override
+    public int grpcPort() {
+        String value = System.getProperty(TritonProperties.TRITON_GPRC_PORT, 
"8001");
+        return Integer.parseInt(value);
+    }
+
+    @Override
+    public int metricsPort() {
+        String value = 
System.getProperty(TritonProperties.TRITON_METRICS_PORT, "8002");
+        return Integer.parseInt(value);
+    }
+}
diff --git 
a/test-infra/camel-test-infra-triton/src/main/resources/META-INF/MANIFEST.MF 
b/test-infra/camel-test-infra-triton/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..e69de29bb2d
diff --git 
a/test-infra/camel-test-infra-triton/src/main/resources/models/simple/1/model.graphdef
 
b/test-infra/camel-test-infra-triton/src/main/resources/models/simple/1/model.graphdef
new file mode 100644
index 00000000000..d7409a44290
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/resources/models/simple/1/model.graphdef
@@ -0,0 +1,21 @@
+
+@
+INPUT0Placeholder*
+shape:���������*
+dtype0
+@
+INPUT1Placeholder*
+dtype0*
+shape:���������
+2
+ADDAddINPUT0INPUT1" /device:CPU:0*
+T0
+2
+SUBSubINPUT0INPUT1" /device:CPU:0*
+T0
+!
+OUTPUT0IdentityADD*
+T0
+!
+OUTPUT1IdentitySUB*
+T0"
\ No newline at end of file
diff --git 
a/test-infra/camel-test-infra-triton/src/main/resources/models/simple/config.pbtxt
 
b/test-infra/camel-test-infra-triton/src/main/resources/models/simple/config.pbtxt
new file mode 100644
index 00000000000..b33ac77a514
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/resources/models/simple/config.pbtxt
@@ -0,0 +1,27 @@
+name: "simple"
+platform: "tensorflow_graphdef"
+max_batch_size: 8
+input [
+  {
+    name: "INPUT0"
+    data_type: TYPE_INT32
+    dims: [ 16 ]
+  },
+  {
+    name: "INPUT1"
+    data_type: TYPE_INT32
+    dims: [ 16 ]
+  }
+]
+output [
+  {
+    name: "OUTPUT0"
+    data_type: TYPE_INT32
+    dims: [ 16 ]
+  },
+  {
+    name: "OUTPUT1"
+    data_type: TYPE_INT32
+    dims: [ 16 ]
+  }
+]
diff --git 
a/test-infra/camel-test-infra-triton/src/main/resources/org/apache/camel/test/infra/triton/services/container.properties
 
b/test-infra/camel-test-infra-triton/src/main/resources/org/apache/camel/test/infra/triton/services/container.properties
new file mode 100644
index 00000000000..73c0a101b80
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/main/resources/org/apache/camel/test/infra/triton/services/container.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+triton.container=nvcr.io/nvidia/tritonserver:24.12-py3
diff --git 
a/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonService.java
 
b/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonService.java
new file mode 100644
index 00000000000..f0762778350
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonService.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.services;
+
+import org.apache.camel.test.infra.common.services.ContainerTestService;
+import org.apache.camel.test.infra.common.services.TestService;
+
+/**
+ * Test infra service for Triton Inference Server
+ */
+public interface TritonService extends TestService, TritonInfraService, 
ContainerTestService {
+}
diff --git 
a/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonServiceFactory.java
 
b/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonServiceFactory.java
new file mode 100644
index 00000000000..9544f917657
--- /dev/null
+++ 
b/test-infra/camel-test-infra-triton/src/test/java/org/apache/camel/test/infra/triton/services/TritonServiceFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.infra.triton.services;
+
+import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;
+
+public final class TritonServiceFactory {
+    private TritonServiceFactory() {
+    }
+
+    public static SimpleTestServiceBuilder<TritonService> builder() {
+        return new SimpleTestServiceBuilder<>("triton");
+    }
+
+    public static TritonService createService() {
+        return builder()
+                .addLocalMapping(TritonLocalContainerService::new)
+                .addRemoteMapping(TritonRemoteService::new)
+                .build();
+    }
+
+    public static class TritonLocalContainerService extends 
TritonLocalContainerInfraService
+            implements TritonService {
+    }
+
+    public static class TritonRemoteService extends TritonRemoteInfraService 
implements TritonService {
+    }
+}
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index 6b8e7e08d1f..b79f7c84de1 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -89,6 +89,7 @@
         <module>camel-test-infra-hivemq</module>
         <module>camel-test-infra-torchserve</module>
         <module>camel-test-infra-tensorflow-serving</module>
+        <module>camel-test-infra-triton</module>
         <module>camel-test-infra-all</module>
     </modules>
 

Reply via email to