Security Reference

This page covers security configuration for MCP servers, particularly when using HTTP transports.

Securing HTTP Endpoints

In case of using the HTTP transport, you can secure MCP Streamable HTTP and SSE endpoints using the Quarkus web security layer.

Example application.properties
quarkus.http.auth.permission.mcp-endpoints.paths=/mcp/* (1)
quarkus.http.auth.permission.mcp-endpoints.policy=authenticated (2)
1 Apply the mcp-endpoints policy to all requests targeting both Streamable HTTP and SSE MCP endpoints. All tools, resources and prompts that can be accessed via the Streamable HTTP and SSE MCP endpoints are controlled by this policy.
2 Permit only authenticated users.

Annotation-Based Security

Alternatively, you can also secure the annotated server feature methods with security annotations such as io.quarkus.security.Authenticated, jakarta.annotation.security.RolesAllowed and other annotations supported by Quarkus. However, in this case an MCP client will not receive an appropriate HTTP status code if authentication fails. Instead, an MCP error message with code -32001 is sent back to the client.

Annotation-based Security Example
package org.acme;

import jakarta.annotation.security.RolesAllowed;
import io.quarkus.security.Authenticated;

import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
import io.quarkiverse.mcp.server.ToolResponse;
import jakarta.inject.Inject;

@Authenticated (1)
public class MyTools {

    @Tool
    String up(String name, McpLog log) {
        log.info("UP name accepted %s", name); (1)
        return name.toUpperCase();
    }

    @Tool
    @RolesAllowed("admin") (2)
    String down(String name, McpLog log) {
        log.send(LogLevel.INFO, "DOWN name accepted %s", name); (2)
        return name.toLowerCase();
    }
}
1 Permit only authenticated users. All CDI business methods are protected.
2 Permit only user with role admin.

CORS Configuration

You are strongly encouraged to enable Cross-Origin Resource Sharing filter for Streamable HTTP MCP server endpoints to accept request from the trusted origins only, for example:

Example CORS configuration
quarkus.http.cors.enabled=true (1)
quarkus.http.cors.origins=http://localhost:6274 (2)
1 Enable CORS.
2 Accept requests from a Single-Page MCP Client running at http://localhost:6274.

DNS Rebinding Protection

DNS rebinding is an attack in which a malicious website causes a victim’s browser to send requests to a server running on the victim’s own machine, such as a local MCP server. Because the request originates from the attacker’s page, the browser attaches the attacker’s Origin header, which lets the server detect and reject the request. The Streamable HTTP transport validates this header to satisfy the DNS rebinding protection requirement of the MCP transport specification. For more information, see MCP Security Best Practices.

The check applies to the Streamable HTTP endpoint (/mcp by default) for all request methods. The deprecated SSE endpoint (/mcp/sse) and the WebSocket endpoint are not covered by this check; if you expose them, restrict access with the CORS filter and the authentication mechanisms described on this page.

The check is active when both of the following are true:

  • The quarkus.mcp.server.http.dns-rebinding-check.enabled property is true, which is the default.

  • The effective quarkus.http.host value is a local address (localhost, 127.0.0.1, [::1], or ::1), or is unset.

Quarkus binds to localhost in dev and test mode and to 0.0.0.0 in production mode. With the default configuration, the check is therefore active during development and inactive in production.

When the check rejects a request, the server returns an HTTP 403 response with the reason phrase Invalid origin and an empty body. Requests that carry no Origin header are never rejected, so command-line clients such as curl are unaffected unless you set the header explicitly. Each rejection is logged at DEBUG level in the io.quarkiverse.mcp.server.http.runtime.HttpMcpServerRecorder category as Non-localhost origin rejected: <origin>. Some MCP clients report any 403 response as an authentication failure, which can make an origin rejection look like a credentials problem. For help distinguishing the two, see Troubleshooting HTTP Connections.

To disable the check, set the property to false. You can also disable it for a single named server:

quarkus.mcp.server.http.dns-rebinding-check.enabled=false
quarkus.mcp.server."my-server".http.dns-rebinding-check.enabled=false

The property is read at startup, so you can override it at run time, for example with an environment variable or a system property.

Explicitly setting quarkus.http.host to a non-local address, such as 0.0.0.0, also deactivates the check. This value is read at startup, so it can be changed at run time. Any deployment that is reachable from outside localhost should enforce the authentication mechanisms described earlier on this page.

This check is independent of the CORS filter. The CORS filter relies on the browser to enforce access rules and does not reject same-origin requests, whereas this check is enforced by the server. Enabling CORS neither replaces nor disables the check, so configure both for browser-facing deployments.

OAuth2/OIDC Integration

Typically, to enforce the HTTP security policy configuration, you can use the Quarkus OIDC extension.

For example, to verify bearer access tokens against an OIDC provider such as Keycloak, you can add the following configuration:

Example Quarkus OIDC configuration
quarkus.oidc.auth-server-url=${keycloak.url}/realms/quarkus (1)
quarkus.oidc.token.audience=quarkus-mcp-server (2)
quarkus.oidc.resource-metadata.enabled=true (3)
1 Keycloak realm address. Replace it with your own provider’s address.
2 Require that only access tokens that have a quarkus-mcp-server audience can be accepted. Change this audience value to uniquely identify your Quarkus MCP HTTP Server deployment.
3 Allow MCP Clients to discover OAuth2 Protected Resource Metadata of this Quarkus MCP Server in order to meet the Protected Resource Metadata Discovery Requirements of the MCP Authorization specification. See also Quarkus OIDC Expanded Configuration Guide how to customize the protected resource metadata content.