CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-dev-langchain4j--langchain4j-mcp

Java implementation of the Model Context Protocol (MCP) client for the LangChain4j framework, enabling integration with MCP servers for tools, resources, and prompts

Overview
Eval results
Files

data-models.mddocs/

Data Models

The data models package provides classes representing MCP protocol entities including resources, prompts, roots, and their associated content types. These classes are primarily immutable data structures that map to the MCP protocol schema.

Quick Reference

// Resources
McpResource resource = new McpResource("file:///path", "name", "description", "text/plain");
McpResourceTemplate template = new McpResourceTemplate("user:///{id}", "User Profile", "...", "application/json");
McpReadResourceResult result = client.readResource("file:///path");

// Resource Contents
for (McpResourceContents contents : result.contents()) {
    switch (contents) {
        case McpTextResourceContents text -> System.out.println(text.text());
        case McpBlobResourceContents blob -> System.out.println(blob.blob());
    }
}

// Prompts
McpPrompt prompt = new McpPrompt("name", "description", List.of(argument));
McpGetPromptResult promptResult = client.getPrompt("name", args);
ChatMessage chatMessage = promptResult.messages().get(0).toChatMessage();

// Roots
McpRoot root = new McpRoot("workspace", "file:///home/user/workspace");
client.setRoots(List.of(root));

Imports

// Resources
import dev.langchain4j.mcp.client.McpResource;
import dev.langchain4j.mcp.client.McpResourceTemplate;
import dev.langchain4j.mcp.client.McpReadResourceResult;
import dev.langchain4j.mcp.client.McpResourceContents;
import dev.langchain4j.mcp.client.McpTextResourceContents;
import dev.langchain4j.mcp.client.McpBlobResourceContents;

// Prompts
import dev.langchain4j.mcp.client.McpPrompt;
import dev.langchain4j.mcp.client.McpPromptArgument;
import dev.langchain4j.mcp.client.McpGetPromptResult;
import dev.langchain4j.mcp.client.McpPromptMessage;
import dev.langchain4j.mcp.client.McpRole;

// Prompt Content
import dev.langchain4j.mcp.client.McpPromptContent;
import dev.langchain4j.mcp.client.McpTextContent;
import dev.langchain4j.mcp.client.McpImageContent;
import dev.langchain4j.mcp.client.McpEmbeddedResource;

// Other
import dev.langchain4j.mcp.client.McpRoot;
import dev.langchain4j.mcp.client.McpCallContext;

// LangChain4j integration
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.Content;
import dev.langchain4j.invocation.InvocationContext;

Resource Models

McpResource

Represents a static resource with a fixed URI.

record McpResource(String uri, String name, String description, String mimeType) {}

Constructor Parameters:

  • uri (String, required, never null) - The URI identifying this resource
  • name (String, required, never null) - Human-readable resource name
  • description (String, nullable) - Description of the resource
  • mimeType (String, nullable) - MIME type of the resource content

Methods: uri(), name(), description(), mimeType()

Example:

McpResource resource = new McpResource(
    "file:///config.json",
    "Application Configuration",
    "Main application configuration file",
    "application/json"
);

McpResourceTemplate

Represents a dynamic resource template with URI pattern containing placeholders.

record McpResourceTemplate(String uriTemplate, String name, String description, String mimeType) {}

Constructor Parameters:

  • uriTemplate (String, required, never null) - URI template with placeholders (e.g., "user:///{userId}")
  • name (String, required, never null) - Human-readable template name
  • description (String, nullable) - Description of the template
  • mimeType (String, nullable) - MIME type of resources from this template

Methods: uriTemplate(), name(), description(), mimeType()

Template Patterns:

  • user:///{userId} - Single placeholder
  • data:///{category}/{id} - Multiple placeholders
  • Placeholders use {name} syntax

Example:

McpResourceTemplate template = new McpResourceTemplate(
    "user:///{userId}/profile",
    "User Profile",
    "User profile by ID",
    "application/json"
);

// To read: substitute placeholders
McpReadResourceResult result = client.readResource("user:///12345/profile");

McpReadResourceResult

Result of reading a resource from an MCP server.

record McpReadResourceResult(List<McpResourceContents> contents) {}

Constructor Parameters:

  • contents (List<McpResourceContents>, required, never null) - List of content items (may be empty)

Methods: contents()

McpResourceContents

Sealed interface representing resource content. Can be either text or binary (blob).

sealed interface McpResourceContents permits McpTextResourceContents, McpBlobResourceContents {
    Type type();

    enum Type {
        TEXT,  // Text content
        BLOB   // Binary content (base64-encoded)
    }
}

Implementations:

  • McpTextResourceContents - Text content
  • McpBlobResourceContents - Binary content (base64-encoded)

Pattern Matching:

for (McpResourceContents contents : result.contents()) {
    switch (contents) {
        case McpTextResourceContents text ->
            System.out.println("Text: " + text.text());
        case McpBlobResourceContents blob ->
            System.out.println("Binary data length: " + blob.blob().length());
    }
}

McpTextResourceContents

Text content for a resource.

final record McpTextResourceContents(String uri, String text, String mimeType)
    implements McpResourceContents {
    Type type();
}

Constructor Parameters:

  • uri (String, required, never null) - Resource URI
  • text (String, required, never null) - Text content
  • mimeType (String, nullable) - MIME type

Methods: type() (returns Type.TEXT), uri(), text(), mimeType()

McpBlobResourceContents

Binary content for a resource, base64-encoded.

record McpBlobResourceContents(String uri, String blob, String mimeType)
    implements McpResourceContents {
    static McpBlobResourceContents create(String uri, String blob);
    static McpBlobResourceContents create(String uri, byte[] blob);
    Type type();
}

Constructor Parameters:

  • uri (String, required, never null) - Resource URI
  • blob (String, required, never null) - Base64-encoded binary content
  • mimeType (String, nullable) - MIME type

Static Factory Methods:

create(String, String)

Creates from already base64-encoded string.

Parameters: uri, blob (base64-encoded string) Returns: McpBlobResourceContents

create(String, byte[])

Creates from byte array, automatically base64-encodes.

Parameters: uri, blob (byte array) Returns: McpBlobResourceContents

Example:

// From byte array (auto-encodes)
byte[] imageData = Files.readAllBytes(Path.of("image.png"));
McpBlobResourceContents blobFromBytes =
    McpBlobResourceContents.create("file:///image.png", imageData);

// From base64 string
String base64Data = "SGVsbG8gV29ybGQ=";
McpBlobResourceContents blobFromString =
    McpBlobResourceContents.create("file:///data.bin", base64Data);

Prompt Models

McpPrompt

Represents a prompt template declaration. Contains metadata but not the actual rendered content.

record McpPrompt(String name, String description, List<McpPromptArgument> arguments) {}

Constructor Parameters:

  • name (String, required, never null) - Prompt name
  • description (String, nullable) - Prompt description
  • arguments (List<McpPromptArgument>, nullable) - List of prompt arguments (may be null or empty)

Methods: name(), description(), arguments()

Example:

McpPrompt prompt = new McpPrompt(
    "essay_prompt",
    "Generates an essay prompt",
    List.of(
        new McpPromptArgument("topic", "Essay topic", true),
        new McpPromptArgument("length", "Desired length", false)
    )
);

McpPromptArgument

Represents an argument for a prompt template.

record McpPromptArgument(String name, String description, boolean required) {}

Constructor Parameters:

  • name (String, required, never null) - Argument name
  • description (String, nullable) - Argument description
  • required (boolean) - Whether this argument is required

Methods: name(), description(), required()

McpGetPromptResult

Result of rendering a prompt with arguments. Contains the rendered messages.

record McpGetPromptResult(String description, List<McpPromptMessage> messages) {}

Constructor Parameters:

  • description (String, nullable) - Prompt description
  • messages (List<McpPromptMessage>, required, never null) - Rendered prompt messages (may be empty)

Methods: description(), messages()

McpPromptMessage

Represents a message in a prompt, with a role and content.

record McpPromptMessage(McpRole role, McpPromptContent content) {
    ChatMessage toChatMessage();
}

Constructor Parameters:

  • role (McpRole, required, never null) - Message role (USER or ASSISTANT)
  • content (McpPromptContent, required, never null) - Message content

Methods: role(), content(), toChatMessage()

toChatMessage()

Converts this MCP prompt message to a LangChain4j ChatMessage.

Returns: ChatMessage (UserMessage or AiMessage) Throws: UnsupportedOperationException - If role is ASSISTANT and content is not text Use Case: Convert MCP prompts to LangChain4j chat format

Example:

McpGetPromptResult promptResult = client.getPrompt("essay_prompt", args);
List<ChatMessage> chatMessages = new ArrayList<>();

for (McpPromptMessage message : promptResult.messages()) {
    try {
        chatMessages.add(message.toChatMessage());
    } catch (UnsupportedOperationException e) {
        logger.warn("Cannot convert message: {}", e.getMessage());
    }
}

McpRole

Enumeration of message roles in prompts.

enum McpRole {
    ASSISTANT,  // AI assistant message
    USER;       // User message

    static McpRole fromString(String key);
}

Constants:

  • ASSISTANT - Represents an AI assistant message
  • USER - Represents a user message

Methods:

fromString(String)

Parses a role from a string (case-insensitive).

Parameters: key (String) - Role string Returns: McpRole or null if unknown

Prompt Content Models

McpPromptContent

Sealed interface for prompt content types.

sealed interface McpPromptContent
    permits McpTextContent, McpEmbeddedResource, McpImageContent {
    Type type();
    Content toContent();
    String getType();

    enum Type {
        TEXT,      // Text content
        RESOURCE,  // Embedded resource
        IMAGE      // Image content
    }
}

Implementations:

  • McpTextContent - Text content
  • McpImageContent - Image content (base64-encoded)
  • McpEmbeddedResource - Embedded resource content

Methods:

  • type() - Returns the content type
  • toContent() - Converts to LangChain4j Content
  • getType() - Returns type as lowercase string

McpTextContent

Text content for prompts.

record McpTextContent(String text) implements McpPromptContent {
    Type type();
    Content toContent();
}

Constructor Parameters:

  • text (String, required, never null) - Text content

Methods: type() (returns Type.TEXT), toContent(), text()

McpImageContent

Image content for prompts, with base64-encoded data.

record McpImageContent(String data, String mimeType) implements McpPromptContent {
    Type type();
    Content toContent();
}

Constructor Parameters:

  • data (String, required, never null) - Base64-encoded image data
  • mimeType (String, required, never null) - Image MIME type

Methods: type() (returns Type.IMAGE), toContent(), data(), mimeType()

McpEmbeddedResource

Embedded resource content for prompts.

record McpEmbeddedResource(McpResourceContents resource) implements McpPromptContent {
    Type type();
    Content toContent();
}

Constructor Parameters:

  • resource (McpResourceContents, required, never null) - Resource contents

Methods: type() (returns Type.RESOURCE), toContent(), resource()

Limitations: toContent() only supports text resources, throws UnsupportedOperationException for binary

Other Models

McpRoot

Represents a root directory or location made available to an MCP server.

record McpRoot(String name, String uri) {}

Constructor Parameters:

  • name (String, required, never null) - Root name identifier
  • uri (String, required, never null) - Root URI (typically file:// scheme)

Methods: name(), uri()

Example:

List<McpRoot> roots = List.of(
    new McpRoot("workspace", "file:///home/user/workspace"),
    new McpRoot("documents", "file:///home/user/documents"),
    new McpRoot("config", "file:///etc/myapp")
);

client.setRoots(roots);

McpCallContext

Context information for MCP operation calls, including invocation context for tracing.

record McpCallContext(InvocationContext invocationContext, McpClientMessage message) {}

Constructor Parameters:

  • invocationContext (InvocationContext, nullable) - AI service invocation context for tracing
  • message (McpClientMessage, required, never null) - The MCP protocol message being sent

Methods: invocationContext(), message()

Use Cases:

  • Client listeners for monitoring
  • Headers suppliers for context-aware authentication
  • Distributed tracing integration

Complete Usage Examples

Working with Resources

// List static resources
List<McpResource> resources = client.listResources();
for (McpResource resource : resources) {
    System.out.println("Resource: " + resource.name());
    System.out.println("  URI: " + resource.uri());
    System.out.println("  Description: " + resource.description());
    System.out.println("  MIME Type: " + resource.mimeType());
}

// List resource templates
List<McpResourceTemplate> templates = client.listResourceTemplates();
for (McpResourceTemplate template : templates) {
    System.out.println("Template: " + template.name());
    System.out.println("  URI Pattern: " + template.uriTemplate());
}

// Read a static resource
McpReadResourceResult result = client.readResource("file:///config.json");
for (McpResourceContents contents : result.contents()) {
    if (contents instanceof McpTextResourceContents text) {
        System.out.println("Text: " + text.text());
        System.out.println("MIME Type: " + text.mimeType());
    } else if (contents instanceof McpBlobResourceContents blob) {
        System.out.println("Binary data (base64): " + blob.blob());
        System.out.println("MIME Type: " + blob.mimeType());
    }
}

// Read using template (substitute placeholders)
McpReadResourceResult templatedResult = client.readResource("user:///12345/profile");

Working with Prompts

// List available prompts
List<McpPrompt> prompts = client.listPrompts();
for (McpPrompt prompt : prompts) {
    System.out.println("Prompt: " + prompt.name());
    System.out.println("Description: " + prompt.description());

    if (prompt.arguments() != null) {
        for (McpPromptArgument arg : prompt.arguments()) {
            System.out.println("  Argument: " + arg.name());
            System.out.println("    Description: " + arg.description());
            System.out.println("    Required: " + arg.required());
        }
    }
}

// Render a prompt with arguments
Map<String, Object> args = Map.of(
    "topic", "artificial intelligence",
    "length", "short",
    "style", "formal"
);

McpGetPromptResult promptResult = client.getPrompt("essay_prompt", args);
System.out.println("Prompt description: " + promptResult.description());

for (McpPromptMessage message : promptResult.messages()) {
    System.out.println("Role: " + message.role());

    if (message.content() instanceof McpTextContent textContent) {
        System.out.println("Content: " + textContent.text());
    }
}

Converting to LangChain4j Types

// Convert prompt messages to chat messages
McpGetPromptResult promptResult = client.getPrompt("essay_prompt", args);
List<ChatMessage> chatMessages = new ArrayList<>();

for (McpPromptMessage message : promptResult.messages()) {
    try {
        ChatMessage chatMessage = message.toChatMessage();
        chatMessages.add(chatMessage);
    } catch (UnsupportedOperationException e) {
        logger.warn("Cannot convert message: {}", e.getMessage());
    }
}

// Use with LangChain4j
ChatLanguageModel model = /* ... */;
AiMessage response = model.generate(chatMessages).content();

Pattern Matching with Sealed Types

// Resource contents
for (McpResourceContents contents : result.contents()) {
    switch (contents) {
        case McpTextResourceContents text ->
            System.out.println("Text: " + text.text());
        case McpBlobResourceContents blob -> {
            byte[] data = Base64.getDecoder().decode(blob.blob());
            System.out.println("Binary data size: " + data.length);
        }
    }
}

// Prompt content
McpPromptContent content = message.content();
switch (content) {
    case McpTextContent text ->
        System.out.println("Text: " + text.text());
    case McpImageContent image ->
        System.out.println("Image: " + image.mimeType());
    case McpEmbeddedResource resource ->
        System.out.println("Resource: " + resource.resource());
}

Creating Binary Resource Contents

// From byte array (auto-encodes to base64)
byte[] imageData = Files.readAllBytes(Path.of("image.png"));
McpBlobResourceContents blobFromBytes =
    McpBlobResourceContents.create("file:///image.png", imageData);

// From base64 string
String base64Data = "SGVsbG8gV29ybGQ=";
McpBlobResourceContents blobFromString =
    McpBlobResourceContents.create("file:///data.bin", base64Data);

// Full constructor with MIME type
McpBlobResourceContents blobWithMime =
    new McpBlobResourceContents("file:///image.png", base64Data, "image/png");

// Decode base64 to byte array
byte[] decoded = Base64.getDecoder().decode(blobWithMime.blob());

Complex Prompt Structures

McpGetPromptResult complexPrompt = client.getPrompt("multi_modal_prompt", args);

for (McpPromptMessage message : complexPrompt.messages()) {
    System.out.println("Role: " + message.role());

    McpPromptContent content = message.content();
    switch (content.type()) {
        case TEXT -> {
            McpTextContent text = (McpTextContent) content;
            System.out.println("Text: " + text.text());
        }
        case IMAGE -> {
            McpImageContent image = (McpImageContent) content;
            System.out.println("Image MIME: " + image.mimeType());
            byte[] imageData = Base64.getDecoder().decode(image.data());
            System.out.println("Image size: " + imageData.length);
        }
        case RESOURCE -> {
            McpEmbeddedResource resource = (McpEmbeddedResource) content;
            System.out.println("Embedded resource: " + resource.resource());
        }
    }
}

Type Safety and Nullability

Never Null (Safe to Use Without Checks)

  • McpResource: uri(), name()
  • McpResourceTemplate: uriTemplate(), name()
  • McpReadResourceResult: contents() (list itself, may be empty)
  • McpTextResourceContents: uri(), text()
  • McpBlobResourceContents: uri(), blob()
  • McpPrompt: name()
  • McpPromptArgument: name(), required()
  • McpGetPromptResult: messages() (list itself)
  • McpPromptMessage: role(), content()
  • McpTextContent: text()
  • McpImageContent: data(), mimeType()
  • McpEmbeddedResource: resource()
  • McpRoot: name(), uri()
  • McpCallContext: message()

May Be Null (Check Before Using)

  • McpResource: description(), mimeType()
  • McpResourceTemplate: description(), mimeType()
  • McpTextResourceContents: mimeType()
  • McpBlobResourceContents: mimeType()
  • McpPrompt: description(), arguments()
  • McpPromptArgument: description()
  • McpGetPromptResult: description()
  • McpCallContext: invocationContext()

Immutability

All data model classes are immutable:

  • Record classes are inherently immutable
  • Lists in constructors are copied to prevent external modification
  • Thread-safe for concurrent access

Related Documentation

  • Client - Methods that work with these data models
  • Resources as Tools - Using resources as tools

Install with Tessl CLI

npx tessl i tessl/maven-dev-langchain4j--langchain4j-mcp

docs

client.md

data-models.md

exceptions.md

index.md

logging-listeners.md

registry.md

resources-as-tools.md

tool-provider.md

transports.md

tile.json