Quarkus extension for integrating Model Context Protocol (MCP) client capabilities with LangChain4j
Support for multiple MCP transport types: STDIO (local subprocess), HTTP with SSE, Streamable HTTP (recommended), and WebSocket. Each transport is suitable for different deployment scenarios and requirements.
Enumeration of supported transport types.
package io.quarkiverse.langchain4j.mcp.runtime.config;
public enum McpTransportType {
/**
* Local subprocess communication via stdin/stdout.
* Best for: npm packages, local scripts, development.
*/
STDIO,
/**
* HTTP with separate SSE channel (dual-channel).
* Best for: Legacy servers, specific SSE requirements.
*/
HTTP,
/**
* HTTP with inline SSE streaming (single-channel, recommended).
* Best for: Remote servers, production deployments, scalability.
*/
STREAMABLE_HTTP,
/**
* WebSocket transport (non-standard MCP extension).
* Best for: Bidirectional real-time communication.
*/
WEBSOCKET
}Single-connection HTTP transport with inline SSE streaming.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public class QuarkusStreamableHttpMcpTransport implements McpTransport {
public static Builder builder() { ... }
public static class Builder {
/**
* Set MCP server endpoint URL.
*/
public Builder url(String url) { ... }
/**
* Set Vert.x HttpClient instance.
*/
public Builder httpClient(HttpClient httpClient) { ... }
/**
* Set operation timeout.
*/
public Builder timeout(Duration timeout) { ... }
/**
* Enable request logging.
*/
public Builder logRequests(boolean logRequests) { ... }
/**
* Enable response logging.
*/
public Builder logResponses(boolean logResponses) { ... }
/**
* Set MCP client name for logging/metrics.
*/
public Builder mcpClientName(String mcpClientName) { ... }
/**
* Set authentication provider.
*/
public Builder authProvider(McpClientAuthProvider authProvider) { ... }
/**
* Build the transport instance.
*/
public QuarkusStreamableHttpMcpTransport build() { ... }
}
}Configuration:
quarkus.langchain4j.mcp.remote.transport-type=streamable-http
quarkus.langchain4j.mcp.remote.url=https://mcp-server.example.com/mcp
quarkus.langchain4j.mcp.remote.tool-execution-timeout=60sFeatures:
Mcp-Session-Id headerMcpClientAuthProviderUse Cases:
HTTP transport with separate SSE channel for server-to-client and POST for client-to-server.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public class QuarkusHttpMcpTransport implements McpTransport {
public static Builder builder() { ... }
public static class Builder {
/**
* Set SSE endpoint URL.
*/
public Builder sseUrl(String sseUrl) { ... }
/**
* Set operation timeout.
*/
public Builder timeout(Duration timeout) { ... }
/**
* Enable request logging.
*/
public Builder logRequests(boolean logRequests) { ... }
/**
* Enable response logging.
*/
public Builder logResponses(boolean logResponses) { ... }
/**
* Set TLS configuration.
*/
public Builder tlsConfiguration(TlsConfiguration tlsConfiguration) { ... }
/**
* Set MCP client name for logging/metrics.
*/
public Builder mcpClientName(String mcpClientName) { ... }
/**
* Set authentication provider.
*/
public Builder authProvider(McpClientAuthProvider authProvider) { ... }
/**
* Build the transport instance.
*/
public QuarkusHttpMcpTransport build() { ... }
}
}Configuration:
quarkus.langchain4j.mcp.api.transport-type=http
quarkus.langchain4j.mcp.api.url=https://api.example.com/mcp/sseFeatures:
McpClientAuthProviderUse Cases:
Local subprocess transport for spawning MCP servers.
Configuration:
quarkus.langchain4j.mcp.filesystem.transport-type=stdio
quarkus.langchain4j.mcp.filesystem.command=npm,exec,@modelcontextprotocol/server-filesystem,/path
# With environment variables
quarkus.langchain4j.mcp.database.transport-type=stdio
quarkus.langchain4j.mcp.database.command=python,/opt/mcp/server.py
quarkus.langchain4j.mcp.database.environment.DB_HOST=localhost
quarkus.langchain4j.mcp.database.environment.DB_PORT=5432Features:
Use Cases:
@modelcontextprotocol/server-filesystem)WebSocket-based transport (non-standard MCP extension).
Configuration:
quarkus.langchain4j.mcp.realtime.transport-type=websocket
quarkus.langchain4j.mcp.realtime.url=ws://localhost:8080/mcpFeatures:
Use Cases:
| Transport | Connection Model | Use Case | Production Ready |
|---|---|---|---|
| STDIO | Subprocess stdin/stdout | Local servers, development | Yes (local only) |
| Streamable HTTP | Single HTTP connection | Remote servers, scalability | Yes (recommended) |
| HTTP/SSE | Dual-channel (SSE + POST) | Legacy compatibility | Yes |
| WebSocket | Single WebSocket | Real-time bidirectional | Non-standard |
quarkus.langchain4j.mcp.filesystem.transport-type=stdio
quarkus.langchain4j.mcp.filesystem.command=npm,exec,@modelcontextprotocol/server-filesystem,/workspace
quarkus.langchain4j.mcp.filesystem.environment.NODE_ENV=productionquarkus.langchain4j.mcp.postgres.transport-type=stdio
quarkus.langchain4j.mcp.postgres.command=python,/opt/mcp-postgres/server.py
quarkus.langchain4j.mcp.postgres.environment.PGHOST=localhost
quarkus.langchain4j.mcp.postgres.environment.PGPORT=5432
quarkus.langchain4j.mcp.postgres.environment.PGDATABASE=mydb
quarkus.langchain4j.mcp.postgres.environment.PGUSER=admin
quarkus.langchain4j.mcp.postgres.environment.PGPASSWORD=${DB_PASSWORD}quarkus.langchain4j.mcp.custom.transport-type=stdio
quarkus.langchain4j.mcp.custom.command=/usr/local/bin/mcp-server,--config,/etc/mcp/config.json
quarkus.langchain4j.mcp.custom.environment.LOG_LEVEL=infoquarkus.langchain4j.mcp.github.transport-type=streamable-http
quarkus.langchain4j.mcp.github.url=https://mcp.github.example.com/api/mcp
quarkus.langchain4j.mcp.github.header.Authorization=Bearer ${GITHUB_TOKEN}
quarkus.langchain4j.mcp.github.tool-execution-timeout=30s
quarkus.langchain4j.mcp.github.ping-timeout=10squarkus.langchain4j.mcp.secure.transport-type=streamable-http
quarkus.langchain4j.mcp.secure.url=https://secure.example.com/mcp
quarkus.langchain4j.mcp.secure.tls-configuration-name=secure-tls
# TLS configuration
quarkus.tls.secure-tls.trust-store.p12.path=/certs/truststore.p12
quarkus.tls.secure-tls.trust-store.p12.password=changeit
quarkus.tls.secure-tls.key-store.p12.path=/certs/keystore.p12
quarkus.tls.secure-tls.key-store.p12.password=changeitquarkus.langchain4j.mcp.legacy.transport-type=http
quarkus.langchain4j.mcp.legacy.url=https://api.legacy-system.com/mcp/sse
quarkus.langchain4j.mcp.legacy.log-requests=true
quarkus.langchain4j.mcp.legacy.log-responses=truequarkus.langchain4j.mcp.ws-server.transport-type=websocket
quarkus.langchain4j.mcp.ws-server.url=ws://localhost:8080/mcp
quarkus.langchain4j.mcp.ws-server.tool-execution-timeout=120squarkus.langchain4j.mcp.wss-server.transport-type=websocket
quarkus.langchain4j.mcp.wss-server.url=wss://secure.example.com/mcp
quarkus.langchain4j.mcp.wss-server.tls-configuration-name=wss-tlsJAX-RS client interface for SSE endpoint.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public interface McpSseEndpoint {
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
Multi<SseEvent<String>> get();
}JAX-RS client interface for POST operations.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public interface McpPostEndpoint {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Uni<Response> post(McpClientMessage message);
}Logger for HTTP requests/responses.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public class McpHttpClientLogger implements ClientLogger {
// Logs HTTP method, URL, headers, and body at INFO level
}Handles SSE events from MCP server.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public class SseSubscriber implements Consumer<SseEvent<String>> {
/**
* Create subscriber for SSE events.
*
* @param operationHandler handler for MCP operations from server
* @param logEvents whether to log incoming events
* @param initializationFinished future completed when initialization is done
*/
public SseSubscriber(
McpOperationHandler operationHandler,
boolean logEvents,
CompletableFuture<String> initializationFinished
) { ... }
/**
* Process incoming SSE event.
* Handles "message" event type for MCP protocol messages.
* Handles "endpoint" event type for POST endpoint URL.
*
* @param event the SSE event
*/
void accept(SseEvent<String> event);
}HTTP client filter for adding authorization headers.
package io.quarkiverse.langchain4j.mcp.runtime.http;
public class McpClientAuthFilter implements ResteasyReactiveClientRequestFilter {
/**
* Create auth filter.
*
* @param authProvider the authentication provider
*/
public McpClientAuthFilter(McpClientAuthProvider authProvider) { ... }
/**
* Filter HTTP requests to add Authorization header.
* Calls authProvider.getAuthorization() and sets the header value.
*/
void filter(ResteasyReactiveClientRequestContext requestContext);
}@modelcontextprotocol/server-*)All transports support configurable timeouts:
# Tool execution timeout (how long to wait for tool execution)
quarkus.langchain4j.mcp.CLIENT_NAME.tool-execution-timeout=60s
# Resources timeout (how long to wait for resource operations)
quarkus.langchain4j.mcp.CLIENT_NAME.resources-timeout=60s
# Ping timeout (how long to wait for ping response)
quarkus.langchain4j.mcp.CLIENT_NAME.ping-timeout=10sFor HTTP-based transports, additional timeouts:
# Registry client timeouts
quarkus.langchain4j.mcp.registry-client.default.read-timeout=10s
quarkus.langchain4j.mcp.registry-client.default.connect-timeout=10sMcpClientAuthProviderInstall with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-mcp