Provides Model Context Protocol (MCP) server implementation patterns with LangChain4j. Use when building MCP servers to extend AI capabilities with custom tools, resources, and prompt templates.
54
68%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./plugins/developer-kit-java/skills/langchain4j-mcp-server-patterns/SKILL.mdThe canonical home for this skill is giuseppe-trisciuoglio/developer-kit
Implement Model Context Protocol (MCP) servers with LangChain4j to extend AI capabilities with standardized tools, resources, and prompt templates.
The Model Context Protocol (MCP) is a standardized protocol for connecting AI applications to external data sources and tools. LangChain4j provides MCP server implementation patterns that enable AI systems to dynamically discover and execute tools, access resources, and use prompt templates through a standardized interface.
Use this skill when building:
Follow these steps to implement an MCP server with LangChain4j:
Implement ToolProvider to define executable tools:
class WeatherToolProvider implements ToolProvider {
@Override
public List<ToolSpecification> listTools() {
return List.of(ToolSpecification.builder()
.name("get_weather")
.description("Get weather for a city")
.inputSchema(Map.of(
"type", "object",
"properties", Map.of(
"city", Map.of("type", "string", "description", "City name")
),
"required", List.of("city")
))
.build());
}
@Override
public String executeTool(String name, String arguments) {
// Parse arguments and execute tool logic
return "Weather data result";
}
}Create and start the MCP server:
MCPServer server = MCPServer.builder()
.server(new StdioServer.Builder())
.addToolProvider(new WeatherToolProvider())
.build();
server.start();Implement resource providers for data access:
class CompanyResourceProvider
implements ResourceListProvider, ResourceReadHandler {
@Override
public List<McpResource> listResources() {
return List.of(
McpResource.builder()
.uri("policies")
.name("Company Policies")
.mimeType("text/plain")
.build()
);
}
@Override
public String readResource(String uri) {
return loadResourceContent(uri);
}
}Configure MCP server in Spring Boot application:
@Bean
public MCPSpringConfig mcpServer(List<ToolProvider> tools) {
return MCPSpringConfig.builder()
.tools(tools)
.server(new StdioServer.Builder())
.build();
}Add tool filtering for access control:
McpToolProvider secureProvider = McpToolProvider.builder()
.mcpClients(mcpClient)
.filter((client, tool) -> {
if (tool.name().startsWith("admin_") && !isAdmin()) {
return false;
}
return true;
})
.build();Create a simple MCP server with one tool:
MCPServer server = MCPServer.builder()
.server(new StdioServer.Builder())
.addToolProvider(new SimpleWeatherToolProvider())
.build();
server.start();Configure MCP server in Spring Boot:
@Bean
public MCPSpringConfig mcpServer(List<ToolProvider> tools) {
return MCPSpringConfig.builder()
.tools(tools)
.server(new StdioServer.Builder())
.build();
}MCP standardizes AI application connections:
AI Application ←→ MCP Client ←→ Transport ←→ MCP Server ←→ External ServiceCreate tools with proper schema validation:
class WeatherToolProvider implements ToolProvider {
@Override
public List<ToolSpecification> listTools() {
return List.of(ToolSpecification.builder()
.name("get_weather")
.description("Get weather for a city")
.inputSchema(Map.of(
"type", "object",
"properties", Map.of(
"city", Map.of("type", "string", "description", "City name")
),
"required", List.of("city")
))
.build());
}
@Override
public String executeTool(String name, String arguments) {
// Parse arguments and execute tool logic
return "Weather data result";
}
}Provide static and dynamic resources:
class CompanyResourceProvider
implements ResourceListProvider, ResourceReadHandler {
@Override
public List<McpResource> listResources() {
return List.of(
McpResource.builder()
.uri("policies")
.name("Company Policies")
.mimeType("text/plain")
.build()
);
}
@Override
public String readResource(String uri) {
return loadResourceContent(uri);
}
}Create reusable prompt templates:
class PromptTemplateProvider
implements PromptListProvider, PromptGetHandler {
@Override
public List<Prompt> listPrompts() {
return List.of(
Prompt.builder()
.name("code-review")
.description("Review code for quality")
.build()
);
}
@Override
public String getPrompt(String name, Map<String, String> args) {
return applyTemplate(name, args);
}
}Local process communication:
McpTransport transport = new StdioMcpTransport.Builder()
.command(List.of("npm", "exec", "@modelcontextprotocol/server-everything@0.6.2"))
.logEvents(true)
.build();Remote server communication:
McpTransport transport = new HttpMcpTransport.Builder()
.sseUrl("http://localhost:3001/sse")
.logRequests(true)
.logResponses(true)
.build();Connect to MCP servers:
McpClient client = new DefaultMcpClient.Builder()
.key("my-client")
.transport(transport)
.cacheToolList(true)
.build();
// List available tools
List<ToolSpecification> tools = client.listTools();Bridge MCP servers to LangChain4j AI services:
McpToolProvider provider = McpToolProvider.builder()
.mcpClients(mcpClient)
.failIfOneServerFails(false)
.filter((client, tool) -> filterByPermissions(tool))
.build();
// Integrate with AI service
AIAssistant assistant = AiServices.builder(AIAssistant.class)
.chatModel(chatModel)
.toolProvider(provider)
.build();Implement secure tool filtering:
McpToolProvider secureProvider = McpToolProvider.builder()
.mcpClients(mcpClient)
.filter((client, tool) -> {
if (tool.name().startsWith("admin_") && !isAdmin()) {
return false;
}
return true;
})
.build();Apply access controls to resources:
public boolean canAccessResource(String uri, User user) {
return resourceService.hasAccess(uri, user);
}Implement robust error handling:
try {
String result = mcpClient.executeTool(request);
} catch (McpException e) {
log.error("MCP execution failed: {}", e.getMessage());
return fallbackResult();
}Configure multiple MCP servers:
@Bean
public List<McpClient> mcpClients(List<ServerConfig> configs) {
return configs.stream()
.map(this::createMcpClient)
.collect(Collectors.toList());
}
@Bean
public McpToolProvider multiServerProvider(List<McpClient> clients) {
return McpToolProvider.builder()
.mcpClients(clients)
.failIfOneServerFails(false)
.build();
}Runtime tool filtering based on context:
McpToolProvider contextualProvider = McpToolProvider.builder()
.mcpClients(clients)
.filter((client, tool) -> isToolAllowed(user, tool, context))
.build();Monitor MCP server health:
@Component
public class McpHealthChecker {
@Scheduled(fixedRate = 30000) // 30 seconds
public void checkServers() {
mcpClients.forEach(client -> {
try {
client.listTools();
markHealthy(client.key());
} catch (Exception e) {
markUnhealthy(client.key(), e.getMessage());
}
});
}
}Configure MCP servers in application.yml:
mcp:
servers:
github:
type: docker
command: ["/usr/local/bin/docker", "run", "-e", "GITHUB_TOKEN", "-i", "mcp/github"]
log-events: true
database:
type: stdio
command: ["/usr/bin/npm", "exec", "@modelcontextprotocol/server-sqlite@0.6.2"]
log-events: falseConfigure MCP with Spring Boot:
@Configuration
@EnableConfigurationProperties(McpProperties.class)
public class McpConfiguration {
@Bean
public MCPServer mcpServer(List<ToolProvider> providers) {
return MCPServer.builder()
.server(new StdioServer.Builder())
.addToolProvider(providers)
.enableLogging(true)
.build();
}
}Input:
// Client invokes the weather tool
Map<String, Object> args = Map.of("city", "Milan");
String result = mcpClient.executeTool("get_weather", mapper.writeValueAsString(args));Output:
{
"city": "Milan",
"temperature": 22,
"condition": "Partly Cloudy",
"humidity": 65,
"unit": "celsius"
}Input:
// Client requests a resource by URI
String content = mcpClient.readResource("policies");Output:
Company Remote Work Policy v2.0
Effective Date: January 1, 2025
1. Employees may work remotely up to 3 days per week...Input:
// List all tools from connected MCP servers
List<ToolSpecification> tools = mcpToolProvider.tools();
tools.forEach(t -> System.out.println(t.name() + ": " + t.description()));Output:
get_weather: Get current weather for a city
search_documents: Search company knowledge base
send_notification: Send notification to user
admin_backup: Create system backup (admin only)Refer to examples.md for comprehensive implementation examples including:
Complete API documentation is available in api-reference.md covering:
npm exec or HTTP/SSE endpoints) can expose untrusted tools, resources, and prompts that may influence agent behavior through indirect prompt injection.@modelcontextprotocol/server-everything@0.6.2) to prevent supply-chain attacks from unpinned dependencies.fernandezbaptiste/developer-kit
810297c
Canonical home
since Mar 15, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.