Transports

This page explains the transport mechanisms available for MCP communication.

Overview

The MCP specification currently defines two standard transports for client-server communication. The stdio transport starts an MCP server as a subprocess and communicates over standard in and out. The HTTP transport connects to a running HTTP server. The HTTP transport is defined in two variants: the "Streamable HTTP" variant (introduced in the protocol version 2025-03-26) replaces the "HTTP/SSE" transport (introduced in protocol version 2024-11-05). The "HTTP/SSE" transport is considered deprecated, but it’s still supported by most clients and servers.

This extension supports the stdio transport and both variants of the HTTP transport. Moreover, it also supports the unofficial websocket transport.

STDIO Transport

If you want to use the stdio transport you’ll need to add the io.quarkiverse.mcp:quarkus-mcp-server-stdio extension to your build file first. For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-stdio</artifactId>
    <version>2.0.0.Beta1</version>
</dependency>
If you use the stdio transport then your app should not write anything to the standard output. Quarkus console logging is automatically redirected to the standard error. And the standard output stream is set to "null" when the app is started by default.

See Getting Started with STDIO for a complete tutorial.

HTTP Transport

If you want to use the HTTP transport you’ll need to add the io.quarkiverse.mcp:quarkus-mcp-server-http extension to your build file first. For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-http</artifactId>
    <version>2.0.0.Beta1</version>
</dependency>
The artifactId has changed from quarkus-mcp-server-sse to quarkus-mcp-server-http in version 1.8.0. However, the old artifactId should still work because it’s relocated.

This artifact contains both versions of the HTTP transport. The MCP endpoint (as defined in 2025-03-26) is exposed at {rootPath}, i.e. /mcp by default. The SSE endpoint (as defined in 2024-11-05) is exposed at {rootPath}/sse, i.e. /mcp/sse by default. The {rootPath} is set to mcp by default, but it can be changed with the quarkus.mcp.server.http.root-path configuration property.

The Resumability and Redelivery for the Streamable HTTP is not supported yet.

Stateless Mode

Starting with protocol version 2026-07-28, MCP supports a stateless communication mode. The server automatically detects whether a client is stateless or stateful and handles both paradigms simultaneously on the same endpoint.

Stateless vs. Stateful

In the stateful mode (protocol versions 2025-11-25 and earlier), the client performs an initialize/initialized handshake, the server assigns a session via the Mcp-Session-Id header, and both sides maintain state across requests. In the stateless mode, there is no handshake and no session. Instead, each request is self-contained — the client provides its identity, protocol version, and capabilities via _meta fields and required HTTP headers.

How it works
  • A stateless client sends server/discover (instead of initialize) to learn the server’s capabilities, supported protocol versions, and server info.

  • Every subsequent request includes:

    • MCP-Protocol-Version header with the protocol version

    • Mcp-Method header matching the JSON-RPC method in the body

    • Mcp-Name header for tools/call, prompts/get, and resources/read (the tool name, prompt name, or resource URI)

    • _meta fields: io.modelcontextprotocol/protocolVersion, io.modelcontextprotocol/clientInfo, and optionally io.modelcontextprotocol/clientCapabilities

  • The server creates a transient connection for each request — no session is established and no Mcp-Session-Id header is returned.

  • Stateless connections are transient (McpConnection.isTransient() returns true).

  • The following methods are not available for stateless clients and will be rejected with a METHOD_NOT_FOUND error: ping, logging/setLevel, initialize, notifications/initialized, notifications/roots/list_changed, resources/subscribe, and resources/unsubscribe.

  • GET requests (subsidiary SSE streams) and DELETE requests (session termination) return HTTP 405 Method Not Allowed for stateless clients.

  • Server-initiated requests (sampling, elicitation, roots) are not available for stateless clients. The Multi Round-Trip Requests (MRTR) pattern is used instead — see Multi Round-Trip Request (MRTR).

  • Stateless clients use subscriptions/listen instead of resources/subscribe/resources/unsubscribe to receive notifications. The client specifies a filter for the notification types it wants (e.g. toolsListChanged, resourceSubscriptions), and the server delivers matching notifications on the subscription stream. See Subscription Notifications.

Per-request log level

Since logging/setLevel is not available for stateless clients, the log level can be set per-request using the io.modelcontextprotocol/logLevel _meta field. The value must be a valid log level string (e.g. debug, info, warning, error). The server returns an INVALID_PARAMS error (-32602) if the value is not recognized. The McpConnection.logLevel() method returns this per-request value for transient connections.

See Getting Started with HTTP for a complete tutorial.

WebSocket Transport

If you want to use the WebSocket transport you’ll need to add the io.quarkiverse.mcp:quarkus-mcp-server-websocket extension to your build file first. For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-websocket</artifactId>
    <version>2.0.0.Beta1</version>
</dependency>

The WebSocket endpoint is exposed at {endpointPath}. The {endpointPath} is set to /mcp/ws by default, but it can be changed with the quarkus.mcp.server.websocket.endpoint-path configuration property.

Using the BOM

You can also use the BOM (Bill Of Materials) to control the versions of all io.quarkiverse.mcp dependencies:

+

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.quarkiverse.mcp</groupId>
            <artifactId>quarkus-mcp-server-bom</artifactId>
            <version>2.0.0.Beta1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>