Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public final class MicronautDependencyUtils {
public static final String GROUP_ID_MICRONAUT_FLYWAY = "io.micronaut.flyway";
public static final String GROUP_ID_MICRONAUT_SPRING = "io.micronaut.spring";
public static final String GROUP_ID_MICRONAUT_VIEWS = "io.micronaut.views";
public static final String GROUP_ID_MICRONAUT_MCP = "io.micronaut.mcp";

private MicronautDependencyUtils() {

Expand Down Expand Up @@ -123,6 +124,11 @@ public static Dependency.Builder azureDependency() {
return micronautDependency(GROUP_ID_MICRONAUT_AZURE);
}

@NonNull
public static Dependency.Builder mcpDependency() {
return micronautDependency(GROUP_ID_MICRONAUT_MCP);
}

@NonNull
public static Dependency.Builder reactorDependency() {
return micronautDependency(GROUP_ID_MICRONAUT_REACTOR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class Category {
public static final String LANGUAGE_MODEL = "Language Models";
public static final String LOGGING = "Logging";
public static final String MANAGEMENT = "Management";

public static final String MCP = "Mcp";
public static final String MESSAGING = "Messaging";
public static final String METRICS = "Metrics";
public static final String OTHER = "Other";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2017-2025 original authors
*
* 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
*
* https://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.micronaut.starter.feature.mcp;

import io.micronaut.context.annotation.Requires;
import io.micronaut.starter.application.ApplicationType;
import io.micronaut.starter.application.generator.GeneratorContext;
import io.micronaut.starter.build.dependencies.Dependency;
import io.micronaut.starter.build.dependencies.MicronautDependencyUtils;
import io.micronaut.starter.feature.Feature;
import jakarta.annotation.Nullable;
import jakarta.inject.Singleton;

import static io.micronaut.core.util.StringUtils.TRUE;
import static io.micronaut.starter.feature.Category.MCP;

@Requires(property = "micronaut.starter.feature.mcp.client.langchain4j.enabled", value = TRUE, defaultValue = TRUE)
@Singleton
public class MicronautMcpClientLangchain4j implements Feature {

public static final String NAME = "mcp-client-langchain4j";
private static final String ARTIFACT_ID_MICRONAUT_MCP_CLIENT_LANGCHAIN4J = "micronaut-mcp-client-langchain4j";
private static final Dependency MICRONAUT_MCP_CLIENT_LANGCHAIN4J_DEPENDENCY =
MicronautDependencyUtils.mcpDependency()
.artifactId(ARTIFACT_ID_MICRONAUT_MCP_CLIENT_LANGCHAIN4J)
.test()
.build();

@Override
public String getName() {
return NAME;
}

@Override
public String getTitle() {
return "Micronaut MCP Client LangChain4j";
}

@Override
public String getDescription() {
return "Use LangChain4j MCP Clients" ;
}

@Nullable
@Override
public String getMicronautDocumentation() {
return "https://micronaut-projects.github.io/micronaut-mcp/latest/guide/#clientLangchain4j";
}

@Nullable
@Override
public String getThirdPartyDocumentation() {
return "https://docs.langchain4j.dev/tutorials/mcp/#mcp-client";
}

@Override
public String getCategory() {
return MCP;
}

@Override
public boolean supports(ApplicationType applicationType) {
return true;
}

@Override
public void apply(GeneratorContext generatorContext) {
generatorContext.addDependency(MICRONAUT_MCP_CLIENT_LANGCHAIN4J_DEPENDENCY);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.micronaut.starter.feature.mcp

import io.micronaut.starter.ApplicationContextSpec
import io.micronaut.starter.BuildBuilder
import io.micronaut.starter.application.ApplicationType
import io.micronaut.starter.build.BuildTestUtil
import io.micronaut.starter.build.BuildTestVerifier
import io.micronaut.starter.feature.Category
import io.micronaut.starter.fixture.CommandOutputFixture
import io.micronaut.starter.options.BuildTool
import spock.lang.Shared
import spock.lang.Subject

class MicronautMcpClientLangchain4jSpec extends ApplicationContextSpec implements CommandOutputFixture{

@Shared
@Subject
MicronautMcpClientLangchain4j feature = beanContext.getBean(MicronautMcpClientLangchain4j)

void "mcp-client-langchain4j belongs to MCP category"() {
expect:
Category.MCP == feature.category
}

void "mcp-client-langchain4j supports application type #appType"(ApplicationType appType) {
expect:
feature.supports(appType)

where:
appType << ApplicationType.values()
}

void "mcp-client-langchain4j dependencies #buildTool"(BuildTool buildTool) {
when:
String template = new BuildBuilder(beanContext, buildTool)
.features(['mcp-client-langchain4j'])
.render()
BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template)

then:
verifier.hasDependency("micronaut-mcp-client-langchain4j")

where:
buildTool << BuildTool.values()
}

void 'test readme.md with feature mcp-client-langchain4j contains links to docs'() {
when:
def output = generate(['mcp-client-langchain4j'])
def readme = output["README.md"]

then:
readme
readme.contains("https://micronaut-projects.github.io/micronaut-mcp/latest/guide/#clientLangchain4j")
readme.contains("https://docs.langchain4j.dev/tutorials/mcp/#mcp-client")
}
}
Loading