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

client.mddocs/

MCP Client

The MCP client is the core interface for communicating with MCP servers. It provides methods for listing and executing tools, accessing resources, managing prompts, and monitoring server health.

Quick Reference

// Create client
McpClient client = DefaultMcpClient.builder()
    .transport(transport)  // Required
    .key("my-server")      // Optional: unique identifier
    .toolExecutionTimeout(Duration.ofSeconds(60))
    .build();

// List and execute tools
List<ToolSpecification> tools = client.listTools();
ToolExecutionResult result = client.executeTool(request);

// Access resources
List<McpResource> resources = client.listResources();
McpReadResourceResult content = client.readResource("file:///path");

// Work with prompts
List<McpPrompt> prompts = client.listPrompts();
McpGetPromptResult prompt = client.getPrompt("name", args);

// Health check
client.checkHealth();

// Cleanup
client.close();

Imports

import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.transport.McpTransport;
import dev.langchain4j.invocation.InvocationContext;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.service.tool.ToolExecutionResult;
import java.time.Duration;
import java.util.List;
import java.util.Map;

McpClient Interface

The McpClient interface defines the contract for MCP server communication.

interface McpClient extends AutoCloseable {
    // Identity
    String key();

    // Tools
    List<ToolSpecification> listTools();
    List<ToolSpecification> listTools(InvocationContext invocationContext);
    ToolExecutionResult executeTool(ToolExecutionRequest executionRequest);
    ToolExecutionResult executeTool(ToolExecutionRequest executionRequest, InvocationContext invocationContext);

    // Resources
    List<McpResource> listResources();
    List<McpResource> listResources(InvocationContext invocationContext);
    List<McpResourceTemplate> listResourceTemplates();
    List<McpResourceTemplate> listResourceTemplates(InvocationContext invocationContext);
    McpReadResourceResult readResource(String uri);
    McpReadResourceResult readResource(String uri, InvocationContext invocationContext);

    // Prompts
    List<McpPrompt> listPrompts();
    List<McpPrompt> listPrompts(InvocationContext invocationContext);
    McpGetPromptResult getPrompt(String name, Map<String, Object> arguments);

    // Management
    void checkHealth();
    void setRoots(List<McpRoot> roots);
    void close();
}

Methods

key()

Returns the unique identifier for this client.

Returns: String - Client's unique key Nullability: Never null, defaults to generated value if not set Thread-safe: Yes

Usage:

String clientKey = client.key();
System.out.println("Client: " + clientKey);

listTools()

Retrieves the list of tools available on the MCP server. Results are cached by default.

Returns: List<ToolSpecification> - List of available tools (never null, may be empty) Throws: McpException - If the server returns an error Throws: IllegalResponseException - If the response structure is invalid Caching: Enabled by default, use evictToolListCache() to clear Thread-safe: Yes

When to use:

  • During initialization to discover available tools
  • After evictToolListCache() to refresh tool list
  • When tool provider needs current capabilities

Example:

List<ToolSpecification> tools = client.listTools();
for (ToolSpecification tool : tools) {
    System.out.println("Tool: " + tool.name());
    System.out.println("Description: " + tool.description());
}

listTools(InvocationContext)

Retrieves tools with invocation context for tracing and monitoring.

Parameters:

  • invocationContext (InvocationContext, nullable) - Context for the invocation

Returns: List<ToolSpecification> - List of available tools Throws: Same as listTools() Thread-safe: Yes

When to use:

  • When called from within AI service invocations
  • When distributed tracing is needed

executeTool(ToolExecutionRequest)

Executes a tool on the MCP server. Supports text-based results and JSON structured content.

Parameters:

  • executionRequest (ToolExecutionRequest, required) - Request containing tool name and arguments as JSON string

Returns: ToolExecutionResult - Result of tool execution (never null) Throws: McpException - If the tool execution fails or times out Throws: IllegalArgumentException - If request is null or tool name is missing Timeout: Configured via toolExecutionTimeout (default 60 seconds) Thread-safe: Yes

Important Notes:

  • Tool execution is synchronous and blocks until completion or timeout
  • Arguments must be valid JSON string (not a Java object)
  • Binary content in results is base64-encoded

Example:

ToolExecutionRequest request = ToolExecutionRequest.builder()
    .name("get_weather")
    .arguments("{\"location\": \"San Francisco\"}")
    .build();

try {
    ToolExecutionResult result = client.executeTool(request);
    System.out.println("Result: " + result.text());
} catch (McpException e) {
    System.err.println("Tool failed: " + e.errorMessage());
}

executeTool(ToolExecutionRequest, InvocationContext)

Executes a tool with invocation context for tracing.

Parameters:

  • executionRequest (ToolExecutionRequest, required)
  • invocationContext (InvocationContext, nullable) - Context for tracing

Returns: ToolExecutionResult Throws: Same as executeTool(ToolExecutionRequest) Thread-safe: Yes

listResources()

Retrieves the list of static resources available on the MCP server. Does not include resource templates.

Returns: List<McpResource> - List of static resources (never null, may be empty) Throws: McpException - If the server returns an error Throws: IllegalResponseException - If response is missing required fields Timeout: Configured via resourcesTimeout (default 60 seconds) Thread-safe: Yes

Example:

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

listResources(InvocationContext)

Retrieves resources with invocation context.

Parameters:

  • invocationContext (InvocationContext, nullable)

Returns: List<McpResource> Throws: Same as listResources()

listResourceTemplates()

Retrieves the list of resource templates (dynamic resources with URI patterns).

Returns: List<McpResourceTemplate> - List of templates (never null, may be empty) Throws: McpException - If the server returns an error Throws: IllegalResponseException - If response structure is invalid Thread-safe: Yes

URI Template Patterns:

  • Templates use placeholders: file:///{userId}/profile.json
  • To read, substitute placeholders: file:///12345/profile.json

Example:

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

// Read using template (substitute placeholders)
McpReadResourceResult result = client.readResource("file:///12345/profile.json");

listResourceTemplates(InvocationContext)

Retrieves resource templates with invocation context.

Parameters:

  • invocationContext (InvocationContext, nullable)

Returns: List<McpResourceTemplate>

readResource(String)

Retrieves the contents of a resource by its URI. Works for both static resources and dynamic resources (templates with placeholders substituted).

Parameters:

  • uri (String, required) - The URI of the resource (must not be null or empty)

Returns: McpReadResourceResult - Resource contents (never null, but may contain empty content list) Throws: McpException - If the resource cannot be read or does not exist Throws: IllegalArgumentException - If URI is null or empty Timeout: Configured via resourcesTimeout (default 60 seconds) Thread-safe: Yes

Content Types:

  • Text content: McpTextResourceContents with text() method
  • Binary content: McpBlobResourceContents with base64-encoded blob() method

Example:

McpReadResourceResult result = client.readResource("file:///path/to/file.txt");

for (McpResourceContents contents : result.contents()) {
    if (contents instanceof McpTextResourceContents text) {
        System.out.println("Text: " + text.text());
    } else if (contents instanceof McpBlobResourceContents blob) {
        System.out.println("Binary data (base64): " + blob.blob());
    }
}

readResource(String, InvocationContext)

Retrieves resource contents with invocation context.

Parameters:

  • uri (String, required)
  • invocationContext (InvocationContext, nullable)

Returns: McpReadResourceResult Throws: Same as readResource(String)

listPrompts()

Retrieves the list of prompt templates available on the MCP server.

Returns: List<McpPrompt> - List of prompts (never null, may be empty) Throws: McpException - If the server returns an error Throws: IllegalResponseException - If response structure is invalid Timeout: Configured via promptsTimeout (default 60 seconds) Thread-safe: Yes

Example:

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()) {
            String req = arg.required() ? "required" : "optional";
            System.out.println("  - " + arg.name() + " (" + req + ")");
        }
    }
}

listPrompts(InvocationContext)

Retrieves prompts with invocation context.

Parameters:

  • invocationContext (InvocationContext, nullable)

Returns: List<McpPrompt>

getPrompt(String, Map)

Renders a prompt template with the specified arguments.

Parameters:

  • name (String, required) - The name of the prompt (must not be null)
  • arguments (Map<String, Object>, nullable) - Arguments for rendering (null treated as empty map)

Returns: McpGetPromptResult - Rendered prompt messages (never null) Throws: McpException - If prompt not found, required arguments missing, or rendering fails Throws: IllegalArgumentException - If name is null Timeout: Configured via promptsTimeout (default 60 seconds) Thread-safe: Yes

Argument Requirements:

  • Required arguments must be present
  • Optional arguments can be omitted
  • Extra arguments are typically ignored by server

Example:

Map<String, Object> args = Map.of(
    "topic", "artificial intelligence",
    "length", "short",
    "style", "formal"
);

try {
    McpGetPromptResult promptResult = client.getPrompt("essay_prompt", args);

    System.out.println("Description: " + promptResult.description());

    for (McpPromptMessage message : promptResult.messages()) {
        System.out.println("Role: " + message.role());
        if (message.content() instanceof McpTextContent text) {
            System.out.println("Content: " + text.text());
        }
    }
} catch (McpException e) {
    System.err.println("Prompt error: " + e.errorMessage());
}

checkHealth()

Performs a health check by sending a ping request to the MCP server.

Returns: Nothing (void) - Returns normally if healthy Throws: Exception - If the server is not responding or unhealthy Timeout: Configured via pingTimeout (default 10 seconds) Thread-safe: Yes

When to use:

  • Before critical operations to verify server availability
  • In monitoring/health check endpoints
  • After connection issues to verify recovery

Example:

try {
    client.checkHealth();
    System.out.println("Server is healthy");
} catch (Exception e) {
    System.err.println("Server health check failed: " + e.getMessage());
    // Consider reconnection or failover
}

setRoots(List)

Sets the roots (directories/locations) made available to the server. After setting, automatically sends notifications/roots/list_changed to the server.

Parameters:

  • roots (List<McpRoot>, required) - List of roots (must not be null, but can be empty)

Returns: Nothing (void) Throws: McpException - If notification fails Side Effects: Sends notification to server Thread-safe: Yes

When to use:

  • During initialization to establish accessible locations
  • When available directories change dynamically

Example:

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

client.setRoots(roots);

close()

Closes the client connection and releases resources. After closing, the client cannot be reused.

Returns: Nothing (void) Throws: Exception - If error occurs during closing Idempotent: Safe to call multiple times Thread-safe: Yes

Important: Always close clients to prevent resource leaks.

Example:

// Explicit close
McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .build();

try {
    // Use client
    client.listTools();
} finally {
    client.close();
}

// Preferred: try-with-resources
try (McpClient client = DefaultMcpClient.builder()
        .transport(transport)
        .build()) {
    client.listTools();
} // Automatically closed

DefaultMcpClient

The default implementation of the McpClient interface.

class DefaultMcpClient implements McpClient {
    static Builder builder();
    void evictToolListCache();
}

Additional Methods

evictToolListCache()

Manually evicts the cached tool list, forcing the next listTools() call to fetch fresh data from the server.

Returns: Nothing (void) Thread-safe: Yes

When to use:

  • When server capabilities change and cache must be refreshed
  • After server restart or update
  • When tool filtering changes and fresh list is needed

Example:

// Cache is populated
List<ToolSpecification> tools1 = client.listTools(); // Fetches from server

// Subsequent call uses cache
List<ToolSpecification> tools2 = client.listTools(); // Returns cached

// Evict cache
client.evictToolListCache();

// Next call fetches fresh
List<ToolSpecification> tools3 = client.listTools(); // Fetches from server

Builder

The DefaultMcpClient.Builder provides a fluent API for configuring and creating MCP clients.

class Builder {
    Builder transport(McpTransport transport);
    Builder key(String key);
    Builder clientName(String clientName);
    Builder clientVersion(String clientVersion);
    Builder protocolVersion(String protocolVersion);
    Builder initializationTimeout(Duration initializationTimeout);
    Builder toolExecutionTimeout(Duration toolExecutionTimeout);
    Builder resourcesTimeout(Duration resourcesTimeout);
    Builder promptsTimeout(Duration promptsTimeout);
    Builder toolExecutionTimeoutErrorMessage(String message);
    Builder logHandler(McpLogMessageHandler logHandler);
    Builder pingTimeout(Duration pingTimeout);
    Builder reconnectInterval(Duration reconnectInterval);
    Builder autoHealthCheck(boolean autoHealthCheck);
    Builder autoHealthCheckInterval(Duration interval);
    Builder roots(List<McpRoot> roots);
    Builder cacheToolList(boolean cacheToolList);
    Builder listener(McpClientListener listener);
    DefaultMcpClient build();
}

Builder Methods

transport(McpTransport)

Sets the transport implementation for server communication. This is required.

Parameters:

  • transport (McpTransport, required) - The transport implementation

Returns: Builder Default: None (must be set)

Transport Options:

  • StdioMcpTransport - For local subprocess servers
  • WebSocketMcpTransport - For remote WebSocket servers
  • StreamableHttpMcpTransport - For remote HTTP servers

Example:

StdioMcpTransport transport = StdioMcpTransport.builder()
    .command(List.of("node", "server.js"))
    .build();

McpClient client = DefaultMcpClient.builder()
    .transport(transport)  // Required
    .build();

key(String)

Sets the unique identifier for this client. Used when managing multiple MCP clients.

Parameters:

  • key (String, nullable) - Unique client identifier

Returns: Builder Default: Auto-generated UUID if not set Uniqueness: Should be unique across all clients in your application

When to use:

  • When using multiple MCP clients to distinguish them
  • In tool name mapping to prefix tools by server
  • In logs and monitoring to identify client

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .key("weather-server")
    .build();

clientName(String)

Sets the client name sent during MCP handshake for server identification.

Parameters:

  • clientName (String, nullable) - Client name

Returns: Builder Default: "LangChain4j MCP Client"

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .clientName("MyApplication")
    .build();

clientVersion(String)

Sets the client version sent during MCP handshake.

Parameters:

  • clientVersion (String, nullable) - Client version

Returns: Builder Default: Library version

protocolVersion(String)

Sets the MCP protocol version to use.

Parameters:

  • protocolVersion (String, nullable) - Protocol version string

Returns: Builder Default: "2025-11-25" Compatibility: Must match or be compatible with server version

When to change:

  • When server requires specific protocol version
  • When testing against different MCP versions

initializationTimeout(Duration)

Sets the timeout for MCP connection initialization.

Parameters:

  • initializationTimeout (Duration, nullable) - Timeout duration

Returns: Builder Default: 30 seconds Valid Range: 1 second to 10 minutes recommended

When to adjust:

  • Increase for slow server startup
  • Decrease for fast-fail in production

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .initializationTimeout(Duration.ofSeconds(60))
    .build();

toolExecutionTimeout(Duration)

Sets the timeout for tool execution requests.

Parameters:

  • toolExecutionTimeout (Duration, nullable) - Timeout duration

Returns: Builder Default: 60 seconds Valid Range: 1 second to several minutes depending on tool

When to adjust:

  • Increase for long-running tools (data processing, file operations)
  • Decrease for quick tools (simple queries, calculations)

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .toolExecutionTimeout(Duration.ofMinutes(5))  // Long-running tools
    .build();

resourcesTimeout(Duration)

Sets the timeout for resource operations (list, read).

Parameters:

  • resourcesTimeout (Duration, nullable) - Timeout duration

Returns: Builder Default: 60 seconds

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .resourcesTimeout(Duration.ofSeconds(30))
    .build();

promptsTimeout(Duration)

Sets the timeout for prompt operations (list, get).

Parameters:

  • promptsTimeout (Duration, nullable) - Timeout duration

Returns: Builder Default: 60 seconds

toolExecutionTimeoutErrorMessage(String)

Sets a custom error message returned when tool execution times out.

Parameters:

  • message (String, nullable) - Custom timeout error message

Returns: Builder Default: Standard timeout message

When to use:

  • Provide user-friendly timeout messages
  • Include guidance on what to do when timeout occurs

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .toolExecutionTimeoutErrorMessage(
        "Tool execution timed out. Try again or check server status.")
    .build();

logHandler(McpLogMessageHandler)

Sets the handler for log messages received from the MCP server.

Parameters:

  • logHandler (McpLogMessageHandler, nullable) - Log message handler

Returns: Builder Default: No handler (logs ignored)

Handler Options:

  • DefaultMcpLogMessageHandler - Forwards to SLF4J
  • Custom implementation for specialized logging

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .logHandler(new DefaultMcpLogMessageHandler())
    .build();

pingTimeout(Duration)

Sets the timeout for ping requests used in health checks.

Parameters:

  • pingTimeout (Duration, nullable) - Ping timeout

Returns: Builder Default: 10 seconds

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .pingTimeout(Duration.ofSeconds(5))
    .build();

reconnectInterval(Duration)

Sets the interval for reconnection attempts after connection failure.

Parameters:

  • reconnectInterval (Duration, nullable) - Reconnect interval

Returns: Builder Default: 5 seconds

autoHealthCheck(boolean)

Enables or disables automatic periodic health checks.

Parameters:

  • autoHealthCheck (boolean) - Enable auto health checks

Returns: Builder Default: true (enabled)

When to disable:

  • When implementing custom health check logic
  • In testing environments

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .autoHealthCheck(true)
    .autoHealthCheckInterval(Duration.ofSeconds(30))
    .build();

autoHealthCheckInterval(Duration)

Sets the interval between automatic health checks.

Parameters:

  • interval (Duration, nullable) - Health check interval

Returns: Builder Default: 30 seconds

roots(List)

Sets the initial list of roots to make available to the server.

Parameters:

  • roots (List<McpRoot>, nullable) - Initial roots

Returns: Builder Default: Empty list

Example:

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

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .roots(roots)
    .build();

cacheToolList(boolean)

Enables or disables caching of the tool list.

Parameters:

  • cacheToolList (boolean) - Enable caching

Returns: Builder Default: true (enabled)

When to disable:

  • When server capabilities change frequently
  • In dynamic development environments
  • For testing

Example:

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .cacheToolList(false)  // Always fetch fresh
    .build();

listener(McpClientListener)

Sets the event listener for client lifecycle events.

Parameters:

  • listener (McpClientListener, nullable) - Event listener

Returns: Builder Default: No listener

Use Cases:

  • Performance monitoring
  • Error tracking
  • Distributed tracing
  • Audit logging

Example:

McpClientListener listener = new McpClientListener() {
    @Override
    public void beforeExecuteTool(McpCallContext context) {
        System.out.println("Executing tool...");
    }

    @Override
    public void afterExecuteTool(McpCallContext context,
                                 ToolExecutionResult result,
                                 Map<String, Object> rawResult) {
        System.out.println("Tool executed successfully");
    }

    @Override
    public void onExecuteToolError(McpCallContext context, Throwable error) {
        System.err.println("Tool failed: " + error.getMessage());
    }
};

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .listener(listener)
    .build();

build()

Builds and returns the configured DefaultMcpClient instance.

Returns: DefaultMcpClient Throws: IllegalArgumentException - If transport is not set

Example:

try {
    McpClient client = DefaultMcpClient.builder()
        .transport(transport)
        .build();
} catch (IllegalArgumentException e) {
    System.err.println("Invalid configuration: " + e.getMessage());
}

Complete Usage Examples

Basic Client Creation

import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
import java.util.List;

StdioMcpTransport transport = StdioMcpTransport.builder()
    .command(List.of("node", "mcp-server.js"))
    .build();

try (McpClient client = DefaultMcpClient.builder()
        .transport(transport)
        .build()) {

    List<ToolSpecification> tools = client.listTools();
    System.out.println("Available tools: " + tools.size());
}

Production-Ready Configuration

import java.time.Duration;

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .key("production-server")
    .clientName("MyApplication")
    .clientVersion("1.0.0")

    // Timeouts
    .initializationTimeout(Duration.ofSeconds(60))
    .toolExecutionTimeout(Duration.ofMinutes(5))
    .resourcesTimeout(Duration.ofSeconds(30))
    .promptsTimeout(Duration.ofSeconds(30))
    .pingTimeout(Duration.ofSeconds(10))

    // Health checks
    .autoHealthCheck(true)
    .autoHealthCheckInterval(Duration.ofSeconds(30))

    // Caching
    .cacheToolList(true)

    // Monitoring
    .listener(new PerformanceMonitoringListener())
    .logHandler(new DefaultMcpLogMessageHandler())

    // Initial roots
    .roots(List.of(
        new McpRoot("workspace", "file:///app/workspace"),
        new McpRoot("data", "file:///app/data")
    ))

    .build();

Error Handling Pattern

try (McpClient client = DefaultMcpClient.builder()
        .transport(transport)
        .build()) {

    // Execute tool with error handling
    ToolExecutionRequest request = ToolExecutionRequest.builder()
        .name("process_data")
        .arguments("{\"file\": \"data.csv\"}")
        .build();

    ToolExecutionResult result = client.executeTool(request);
    System.out.println("Success: " + result.text());

} catch (McpException e) {
    // MCP protocol error
    System.err.println("MCP Error " + e.errorCode() + ": " + e.errorMessage());

    if (e.errorCode() == -32601) {
        System.err.println("Tool not found");
    } else if (e.errorCode() == -32602) {
        System.err.println("Invalid parameters");
    }

} catch (IllegalResponseException e) {
    // Malformed response
    System.err.println("Invalid response: " + e.getMessage());

} catch (Exception e) {
    // Network, timeout, or other errors
    System.err.println("Client error: " + e.getMessage());
}

Dynamic Roots Management

McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .build();

// Set initial roots
client.setRoots(List.of(
    new McpRoot("workspace", "file:///home/user/workspace")
));

// Later, add more roots
List<McpRoot> updatedRoots = List.of(
    new McpRoot("workspace", "file:///home/user/workspace"),
    new McpRoot("projects", "file:///home/user/projects"),
    new McpRoot("documents", "file:///home/user/documents")
);

client.setRoots(updatedRoots);

Cache Management

// Client with caching enabled (default)
McpClient client = DefaultMcpClient.builder()
    .transport(transport)
    .cacheToolList(true)
    .build();

// First call fetches from server
List<ToolSpecification> tools1 = client.listTools();
System.out.println("Fetched from server: " + tools1.size());

// Second call returns cached result
List<ToolSpecification> tools2 = client.listTools();
System.out.println("From cache: " + tools2.size());

// Server capabilities changed, refresh cache
client.evictToolListCache();

// Next call fetches fresh data
List<ToolSpecification> tools3 = client.listTools();
System.out.println("Fresh from server: " + tools3.size());

Performance Best Practices

  1. Reuse Clients: Create client once and reuse for multiple operations
  2. Enable Caching: Keep tool list caching enabled unless dynamic changes expected
  3. Adjust Timeouts: Set appropriate timeouts for expected operation duration
  4. Close Resources: Always close clients to prevent resource leaks
  5. Monitor Health: Use auto health checks in long-running applications
  6. Connection Pooling: For HTTP transport, consider connection pooling at transport level

Thread Safety

  • All methods are thread-safe
  • Can call methods concurrently from multiple threads
  • Internal caching is thread-safe
  • Listeners are called synchronously in the calling thread

Common Pitfalls

  1. Not closing clients: Always use try-with-resources or explicit close
  2. Incorrect JSON arguments: Tool arguments must be valid JSON strings
  3. Ignoring exceptions: Always handle McpException and IllegalResponseException
  4. Short timeouts: Increase timeouts for long-running operations
  5. Missing transport: Builder requires transport to be set
  6. Reusing closed client: Create new client after closing

Related Documentation

  • Transports - Transport configuration options
  • Tool Provider - Integrating with LangChain4j
  • Data Models - Understanding resources, prompts, and content types
  • Exceptions - Error handling reference
  • Logging and Listeners - Monitoring and observability

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