diff --git a/connector-sdk/element-template-generator-maven-plugin/README.md b/connector-sdk/element-template-generator-maven-plugin/README.md
new file mode 100644
index 0000000000..d0e33b86b7
--- /dev/null
+++ b/connector-sdk/element-template-generator-maven-plugin/README.md
@@ -0,0 +1,57 @@
+# Element Template Generator Maven Plugin
+
+This plugin generates [Connector Templates](https://docs.camunda.io/docs/components/connectors/custom-built-connectors/connector-templates/)
+based on Connector code.
+
+To use the plugin, your Connector must be annotated with `@ElementTemplate` annotation.
+See the [Element Template Generator](../element-template-generator) module for more information.
+
+## Usage
+
+Add the following plugin to your `pom.xml`:
+
+```xml
+
+ io.camunda.connector
+ element-template-generator-maven-plugin
+ ${version}
+
+
+
+ generate-templates
+
+
+
+
+
+ io.camunda.connector.MyConnector
+
+
+
+```
+
+Edit the `connectorClass` element to point to your Connector class. You can specify multiple
+classes if you have more than one Connector in one project.
+
+By default, the generated element template will be placed in `element-templates` directory inside
+your project's base directory. You can change the output directory by setting the `outputDirectory`
+configuration parameter.
+
+## Accessing classes from other modules
+
+If your Connector definition references classes from other modules, the plugin will not be able
+to find them automatically. You can add direct dependencies of your project to the plugin classpath
+by adding the following configuration to the plugin:
+
+```xml
+
+
+ io.camunda.connector.MyConnector
+
+
+ io.camunda.connector:my-connector-library
+
+
+```
+
+Note that the plugin will not resolve transitive dependencies of the specified dependencies.
diff --git a/connector-sdk/element-template-generator-maven-plugin/pom.xml b/connector-sdk/element-template-generator-maven-plugin/pom.xml
new file mode 100644
index 0000000000..ee29c31947
--- /dev/null
+++ b/connector-sdk/element-template-generator-maven-plugin/pom.xml
@@ -0,0 +1,63 @@
+
+ 4.0.0
+
+
+ io.camunda.connector
+ connector-parent
+ ../../parent/pom.xml
+ 0.23.0-SNAPSHOT
+
+
+ element-template-generator-maven-plugin
+ Maven plugin for generating connector templates
+ element-template-generator-maven-plugin
+ maven-plugin
+
+
+ 3.9.4
+ 3.9.0
+ 3.9.0
+ 2.2.1
+
+
+
+
+ io.camunda.connector
+ element-template-generator
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ ${version.maven-plugin-api}
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ ${version.maven-plugin-annotations}
+ provided
+
+
+ org.apache.maven
+ maven-project
+ ${version.maven-project}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ ${version.maven-plugin-plugin}
+
+
+ default-descriptor
+ process-classes
+
+
+
+
+
+
\ No newline at end of file
diff --git a/connector-sdk/element-template-generator-maven-plugin/src/main/java/io/camunda/connector/generator/ElementTemplateGeneratorMojo.java b/connector-sdk/element-template-generator-maven-plugin/src/main/java/io/camunda/connector/generator/ElementTemplateGeneratorMojo.java
new file mode 100644
index 0000000000..ec920fb301
--- /dev/null
+++ b/connector-sdk/element-template-generator-maven-plugin/src/main/java/io/camunda/connector/generator/ElementTemplateGeneratorMojo.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. Camunda licenses this file to you under the Apache License,
+ * Version 2.0; 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 io.camunda.connector.generator;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.camunda.connector.generator.core.OutboundElementTemplateGenerator;
+import io.camunda.connector.generator.dsl.OutboundElementTemplate;
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+
+@Mojo(
+ name = "generate-templates",
+ defaultPhase = LifecyclePhase.PROCESS_CLASSES,
+ requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
+public class ElementTemplateGeneratorMojo extends AbstractMojo {
+
+ @Parameter(defaultValue = "${project}", readonly = true, required = true)
+ private MavenProject project;
+
+ @Parameter(property = "connectorClasses", required = true)
+ private String[] connectorClasses;
+
+ @Parameter(property = "includeDependencies")
+ private String[] includeDependencies;
+
+ @Parameter(property = "outputDirectory", defaultValue = "${project.basedir}/element-templates")
+ private String outputDirectory;
+
+ private static final ObjectMapper mapper = new ObjectMapper();
+ private final OutboundElementTemplateGenerator generator = new OutboundElementTemplateGenerator();
+
+ private static final String COMPILED_CLASSES_DIR = "target" + File.separator + "classes";
+
+ @Override
+ public void execute() throws MojoFailureException {
+ if (connectorClasses.length == 0) {
+ getLog().warn("No connector classes specified. Skipping generation of element templates.");
+ return;
+ }
+
+ List classpathUrls = new ArrayList<>();
+
+ try {
+ String compiledClassesPath =
+ project.getFile().getParent() + File.separator + COMPILED_CLASSES_DIR;
+ classpathUrls.add(new File(compiledClassesPath).toURI().toURL());
+
+ for (String dependency : includeDependencies) {
+ Artifact dependencyArtifact = (Artifact) project.getArtifactMap().get(dependency);
+ if (dependencyArtifact == null) {
+ throw new IllegalArgumentException(
+ "Failed to find dependency " + dependency + " in project " + project.getName());
+ }
+ classpathUrls.add(dependencyArtifact.getFile().toURI().toURL());
+ }
+ } catch (Exception e) {
+ throw new MojoFailureException("Failed to load classpath: " + e.getMessage(), e);
+ }
+
+ try (URLClassLoader classLoader =
+ new URLClassLoader(
+ classpathUrls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader())) {
+
+ for (String className : connectorClasses) {
+ getLog().info("Generating element template for " + className);
+ Class> clazz = classLoader.loadClass(className);
+ OutboundElementTemplate template = generateElementTemplate(clazz);
+ writeElementTemplate(template);
+ }
+
+ } catch (ClassNotFoundException e) {
+ throw new MojoFailureException("Failed to find connector class: " + e.getMessage(), e);
+ } catch (TypeNotPresentException e) {
+ throw new MojoFailureException(
+ e.getMessage()
+ + "\nIf your connector references other packages, include them using the 'includeDependencies' parameter",
+ e);
+ } catch (Exception e) {
+ throw new MojoFailureException("Failed to generate element templates: " + e.getMessage(), e);
+ }
+ }
+
+ private OutboundElementTemplate generateElementTemplate(Class> clazz) {
+ return generator.generate(clazz);
+ }
+
+ private void writeElementTemplate(OutboundElementTemplate template) {
+ try {
+ String fileName = transformConnectorNameToTemplateFileName(template.name());
+ File file = new File(outputDirectory, fileName);
+ file.getParentFile().mkdirs();
+ mapper.writerWithDefaultPrettyPrinter().writeValue(file, template);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to write element template", e);
+ }
+ }
+
+ private String transformConnectorNameToTemplateFileName(String connectorName) {
+ // convert human-oriented name to kebab-case
+ connectorName = connectorName.replaceAll(" ", "-");
+ connectorName = connectorName.replaceAll("([a-z])([A-Z]+)", "$1-$2");
+ connectorName = connectorName.toLowerCase();
+ return connectorName + ".json";
+ }
+}
diff --git a/connectors/pom.xml b/connectors/pom.xml
index 6d83b35db6..eaf3fce052 100644
--- a/connectors/pom.xml
+++ b/connectors/pom.xml
@@ -112,6 +112,19 @@ except in compliance with the proprietary license.
+
+ io.camunda.connector
+ element-template-generator-maven-plugin
+ ${project.version}
+
+
+
+ generate-templates
+
+
+
+
+
org.apache.maven.plugins
maven-shade-plugin
diff --git a/pom.xml b/pom.xml
index e2b84008a9..ba9537d108 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
connector-sdk/test
connector-sdk/jackson-datatype-feel
connector-sdk/element-template-generator
+ connector-sdk/element-template-generator-maven-plugin
secret-providers/gcp-secret-provider
connector-runtime/connector-runtime-core
connector-runtime/connector-runtime-spring