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.

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](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization). See also Quarkus OIDC Expanded Configuration Guide how to customize the protected resource metadata content.